GBrowse-2.56000755001750001750 013036764442 13006 5ustar00lsteinlstein000000000000GBrowse-2.56/Build.PL000444001750001750 1135313036764442 14462 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use warnings; use FindBin '$Bin'; use lib "$Bin/install_util"; use File::Copy; use GBrowseInstall; my $build = GBrowseInstall->new( module_name => 'GBrowse', dist_version_from => 'lib/Bio/Graphics/Browser2.pm', dist_author => 'Lincoln Stein ', dist_abstract => 'The GMOD Generic Genome Browser', license => 'perl', requires => { 'perl' => '5.008', 'Bio::Root::Version' => '1.007001', 'Bio::Graphics' => '2.34', 'CGI::Session' => '4.02', 'Digest::MD5' => 0, 'ExtUtils::CBuilder' => 0, 'File::Temp' => 0, 'GD' => '2.50', 'Text::ParseWords' => '3.27', 'IO::String' => 0, 'JSON' => 0, 'LWP' => 0, 'Statistics::Descriptive' => 0, 'Storable' => 0, 'Time::HiRes' => 0, 'Digest::SHA' => 0, 'Date::Parse' => 0, 'Term::ReadKey' => 0, 'HTTP::Daemon' => 0, 'parent' => 0, }, build_requires => {'Capture::Tiny' => 0,}, recommends => { 'Bio::Das' => 0, 'Bio::DB::Sam' => 1.36, 'Bio::DB::BigFile' => 1.00, 'Crypt::SSLeay' => 0, 'DB_File::Lock' => 0, 'DBI' => 0, 'DBD::mysql' => 0, 'DBD::Pg' => 0, 'DBD::SQLite' => 0, 'Digest::SHA' => 0, 'FCGI' => 0, 'File::NFSLock' => 0, 'GD::SVG' => 0, 'Math::BigInt' => 0, 'Net::OpenID::Consumer' => 0, 'Net::SMTP::SSL' => 0, $] <= 5.008 ? ('Safe::World' => 0) : () , 'Template' => 2.20, 'Term::ReadKey' => 0, 'VM::EC2' => 1.19, 'Parse::Apache::ServerStatus' => 0, }, script_files => [ 'bin/gbrowse_clean.pl', 'bin/gbrowse_set_admin_passwd.pl', 'bin/gbrowse_import_ucsc_db.pl', 'bin/gbrowse_create_account.pl', 'bin/gbrowse_change_passwd.pl', 'bin/gbrowse_aws_balancer.pl', 'bin/gbrowse_sync_aws_slave.pl', 'bin/gbrowse_configure_slaves.pl', 'bin/gbrowse_metadb_config.pl', 'bin/gbrowse_grow_cloud_vol.pl', 'bin/gbrowse_slave', 'bin/gbrowse_syn_load_alignment_database.pl', 'bin/gbrowse_syn_load_alignments_msa.pl', 'bin/make_das_conf.pl', 'bin/scan_gbrowse.pl', 'bin/wiggle2gff3.pl', 'bin/gtf2gff3.pl', 'bin/bed2gff3.pl', 'bin/ucsc_genes2gff.pl', 'bin/load_genbank.pl', ], create_makefile_pl => 'passthrough', ); print STDERR <; #exit 0 unless $line =~ /[yY]/; if(-e '/proc/filesystems' && `grep selinux /proc/filesystems`) { print STDERR <<'END'; **** WARNING ********************************************************* You appear to have SELinux installed on this computer. This can interfere with GBrowse operation. Please read the file README.fedora_and_selinux in order to perform additional configuration operations that may be necessary to run on this computer. ********************************************************************** END } if ($build->have_c_compiler()) { foreach ('CAlign.xs','CAlign.pm') { copy("./libalign/$_" => "./lib/Bio/Graphics/Browser/$_"); } $build->include_dirs(["$Bin/libalign"]); } my $argc=0; for my $arg (keys %{$build->private_props}) { my $value = $build->runtime_params($arg) or next; $build->config_data($arg=>$value); $argc++; } $build->config_data(OpenIDConsumerSecret=>int(1e15*rand())); $build->config_done(1) if $argc > 0; $build->add_build_element('conf'); $build->add_build_element('htdocs'); $build->add_build_element('cgibin'); $build->add_build_element('etc'); $build->add_build_element('database'); $build->create_build_script; print STDERR <1. 2.25 * Fixed broken image generation. * Made it easier to install GBrowse as an unprivileged user. * Allow searching for features with pipe symbols in their names. * Allow searching for features defined in uploaded tracks. 2.24 * Fixed gbrowse_metadb_config.pl script so that it no longer fails when creating a user database from scratch. 2.23 * Added an "example_scripts" directory that contains a perl scripts that show how to manipulate sessions, upload custom tracks, and get basic information about services. This directory accompanies new REST API documentation located at http://gmod.oicr.on.ca/wiki/GBrowse2_REST_API. * Fixed missing "registration" link in login dialog. This occurred when openid was unavailable. * Fixed popup dialogs in the "Help" menu so that they appear again. * Fixed file upload status display to prevent upload details section from disappearing when uploading very small files. * Tinkered with session settings to minimize session lock timeouts. * Removed some dangling warnings in the track sharing module. * Made SQLite the default user account database. * Fixed default SQLite user account database to be created in /var/www/gbrowse2/databases rather than in / (root) directory. 2.22 * Fixed gbrowse_img to reactivate documented ability to list multiple tracks with t=track1+track2+track3 * Fixed startup to avoid Javascript crashing on autocomplete initiation when user accounts turned off. This had caused the "eurl" param (used to import external data tracks via URL) to fail. 2.21 * Fix all references to File::Path 'remove_tree" to "rm_tree" in order to work with older versions of File::Path. * Fixed display bug in Safari (popup balloons not working after zooming into a track). * Fixed Internet Explorer crash when uploading new files. * Fixed 'eurl=url' remote feature addition. * Added basic ipad functionality. * Newly-added uploaded tracks appear on the top now. 2.20 * User uploads can be run in the usual file-based mode or with a new database-driven system that supports sharing files between users based on public, group, casual (with a sharing link) and private permissions. * Added the ability to load wider details images. Detail tracks can then be dragged left and right without having to load more data from the server. To enable, add a property to the conf file called "details multiplier" and give it a value greater than 1 (3 is recommended). * Overview and scale tracks now show markers for both the currently viewed segment and the entire segment that is loaded. The loaded segment colours can be set with the settings "loaded_segment_fill" and "loaded_segment_outline" * Currently viewed position markers are now drawn with javascript with opacity set to 0.5 (this was necessary so that position markers can move as the user drags tracks). Therefore the markers will show up as a lighter colour than before, so settings 'hilite fill' and 'hilite outline' may need to be updated * Internationalization has been updated so that almost all strings in GBrowse can now be translated, including strings in javascript. * Subtrack labels now float on top of the underlying image data so that they show even when scrolling around. * Added a ruler option, which shows a draggable vertical ruler floating over the details tracks which helps users to line things up. * Track configuration dialog handles the vista plot in addition to regular and quantitative tracks. * Added a simple authentication plugin framework that allows you to authenticate against external authentication systems. * Added the PamAuthenticator plugin, which will authenticate against any Pluggable Authentication Module compatible data source (e.g. Unix, NIS, LDAP, Kerberbos, AD). * The ability to register new accounts can be disabled by setting "user accounts registration=0" in GBrowse.conf. * Support for Open ID can be disabled by setting "user accounts openid=0" in GBrowse.conf. * Fixed bug that caused regions with identical start and end coordinates but different chromosomes to be inappropriately cached to the same location. * Fixed bug in which tracks with a "remote feature" did not display correctly the very first time they are added to the session. 2.17 * Track configuration dialog now allows for control of autoscaling behavior in quantitative glyphs. * Support for vista_plot glyph added to config dialog. * Fixed behavior of GBox balloons so that the scroll bar doesn't overrun the contents. 2.16 * Added code to recognize and strip whitespace from search coordinates. This allows "chr1:2,000 .. 1,180,000" to work as a search term. * Added code that allows callbacks to invoke Bio::Graphics::Browser2::Render->request() in order to get a hash that contains various information about the current state. Interesting keys include: search_str, ref, start, end, flip, tracks, features, userid, uploadid, h_feat, width, grid. (NOTE: please update documentation WIKI with some explanation of how to use this). * Disable track filters when in summary mode, since the summary features generated when this mode is active rarely have the structure and attributes expected by the writer of the filter. The downside of this is that if you use track filters to distinguish one set of features from another, this will not be reflected in the summary density plots, which will show all features of the matching type regardless of the filter. * Basic support for Google federated login via openid. * "unit label" and "unit divider" should now work as advertised. * Add commas to coordinates more liberally. * Maybe fixed failing t/00.compile.t test. * Fixed problem with subtrack selection tables producing empty tracks under some conditions. * Fixed SequenceDumper plugin to not crash on BigWig tracks. * added # to the list of acceptable characters in feature IDs * uploaded files won't use the summary mode unless the number of lines loaded exceeds 10,000 * Modified plugin base class to make it possible to get at the underlying renderer object by calling renderer() method. * Fixed regression in which database option wasn't propagating from base track to semantic zoom tracks. * Fixed SequenceDumper behavior on GFF dumping. * Removed brackets from list of naughty search characters to fix bug 3030462 2.15 Mon Sep 13 11:22:40 EDT 2010 * Set the "DNA accessor" for databases to the default database. Assuming that the backend supports the dna_accessor() method and that the default database has access to the underlying sequence, then this will enable glyphs and plugins to access the DNA for all features, even if the feature is contained in a database that does not have access to the DNA. * You can now override the "buttons" images path in individual datasource files. * You can now have an annotator plugin turned on by default by specifying it in the "default features" option using the syntax "plugin:RestrictionAnnotator". * Renderfarm slaves now honor the init_code directive. You will need Bio::Graphics version 2.13 in order to take advantage of this feature. * Added a description of the BED file format to the upload help page. * Fixed various problems in the ProteinDumper plugin. * Fixed problems with all regular expression tracks being cached to same directory. * Fixed issues with uploaded tracks not being displayed when renderfarm activated. * Fixed issues involving failure of render slaves to preload databases (slowing everything down). * Fixed incorrect sequence dumping in the sequence dumper when using the Bio::DB::GFF database backend. * Fixed problems with losing all default tracks when first loading the browser (this was a bug introduced in SVN and never released.) * You can now override the "buttons" images path in individual datasource files. 2.14 Fri Aug 27 11:05:08 EDT 2010 * Prevent a blank-screen crash when searching for chromosomes not in the database. * Added a "hide empty subtracks" option to suppress subtrack display when there are no features in the region of interest. Note that if there are no features in any subtracks, the entire track will be empty regardless of the subtracks (this may or may not be a bug). * Fixed bug in TrackDumper plugin to prevent "Can't locate object method print_gff3" error. Thanks to Prem Anand for the fix. * Fixed display problem in subtrack selection table when there are additional data row elements that are not listed among the selection criteria. * Fixed TrackDumper routines to dump out both the tracks and signal from vista tracks. * Added CORS capabilities to DAS server so that javascript clients don't have to use a proxy. * Precompile glyphs used in each datasource in parent process so that each child doesn't have to recompile them. * Renamed all the "userdb*" options to "upload_db_*" to avoid confusion with user_account_db. * Fixed uploaded tracks mysql backend so that server logs in with correct username and password. * simplified custom tracks interface by removing separate section for "import tracks" and adding a "From URL" link to the Upload Tracks section * 'eurl' parameter is now loaded asynchronously so that user can watch the process of the upload (useful from galaxy). * Fixed URL-based file uploads so that they work correctly even when the user has no session yet. * Added a datasource "seqid_prefix" option that allows you to add and strip "chr" style prefixes from all seqids; this allows for interoperability with UCSC, which always wants a "chr" to begin each chromosome. * Fixed loading of SAM files to avoid loading of incorrect fasta file when both .fa and .fa.fai files are present in the scaffolds directory. 2.13 * Fixed SAM file processing so as not to die on first line of SAM @SQ header. This requires Bio::DB::Sam 1.20 to work properly. * Fixed upload listing table so as not to duplicate track labels. * Fixed track importation via the eurl parameter so that it works when the user's uploadid is empty (due to clearing cache of cookies). * Fixed DAS server handling of the link option. 2.12 Wed Jun 30 15:28:16 EDT 2010 * Fixed FASTA dumping due to typo introduced just prior to 2.11 release. 2.11 Mon Jun 28 11:42:02 EDT 2010 * Fixed generation of mysql database names for user upload sets so that names do not exceed mysql's limits. * Speeded up execution speed when configuration files get large (>1000 tracks). * DAS server and client now functional. * Reenabled the "eurl" parameter to link to a data set from the URL. * Added "Get chromosome sizes" entry to the File menu (requires a developer's snapshot of bioperl to work with all data sources). * Fasta and GFF3 dumps working ok now. * You can now import a BigWig file by reference. * Uploaded WIG files will generate bigwig indexes if library is available. * action=scan now returns the category for each track. 2.10 Tue Jun 15 10:58:32 EDT 2010 * Fully generalized subtrack creation. 2.09 Mon May 24 18:45:48 PDT 2010 * To turn off caching of the config file (which is causing deparse errors for some callbacks) set the environment variable GBROWSE_NOCACHE to a true value (like "1" or "yes"). This must be done in the Apache config. * Fixed various bugs in the processing of SAM and BAM files. * BAM parser now creates BigWig indexes if library is available. * Fixed "no overloaded magic in Bio::DAS::Segment" error. * Made Menus and tabbed section labels larger (if you don't like, edit htdocs/css/dropdown/default-theme.css). * Moved track table into its own tabbed section. * TrackFinder plugin now hilights the matches in the track table. * New "subtrack table" and "subtrack select" options allow you to create nice sortable tables of potential subtracks. The old "select" option is still supported, but deprecated. * Added "kewl" blinds down effect when changing tabs. * Greatly improved track configuration. * From E.O. Stinson: added fixes for embedding GBrowse in other web pages. * From E.O. Stinson: Added support for regex-style datasources that let you define one data source that will pass different options to a script-based config depending on the URL. * From E.O. Stinson: Added a move_to_name function for navigating to a region in one step via a URL call. 2.08 Thu May 20 22:46:13 EDT 2010 * Added the ability to control the toggle state of each category and subcategory at startup time by using the "category state" and "category default state" options (see the GBROWSE2 HOWTO at http://gmod.org/wiki/GBrowse_2.0_HOWTO#Appearance_Settings) * Fixed searches on Bio::DB::GFF databases so that exact searches work again. * Fixed the busy spinner so that it doesn't stick in "on" state when region is empty and user turns on tracks. 2.07 Mon May 17 10:27:56 EDT 2010 ` * Tracked down the "let Lincoln know bug is not fixed" bug, and found a real solution. This was happening when user presses "back" button on browser after an unsuccessful search. This still triggers a log message until we know the bug is really and truly fixed. * BAM track download now works properly under both FastCGI and mod_perl. mod_perl download requires Bio-SamTools 1.19. * Requires Bio::Graphics version 2.09, which addresses a bug in which subroutines defined in init_code could not be referenced within callbacks. 2.06 Thu May 13 17:10:59 EDT 2010 * Fixed dangling references to GFFPrinter.pm module, which was renamed TrackDumper.pm * Requires Bio::Graphics version 2.08, in order to fix the init_code option, which stopped working when config file caching was introduced in Bio::Graphics 2.07. 2.05 * Implemented a new caching scheme for communicating with renderfarm slaves. This will improve performance, but requires Bio::Graphics version 1.05. * Experimental local rendering code -- each track is rendered in a separate process. * Reverted to older versions of prototype and scriptaculous due to Google Chrome incompatibilities. * Preferred way to separate labels is now to use the "l" option and separate labels with "%1E", as in "l=mdc-1%1Esma-23%1Eunknown genes" * Work around race conditions in the 05.deferredrendering regression tests. May still fail if system is under lots of load during test. * Fixed bug in change_track_order javascript that prevented track order change from "sticking" when track labels contained underscores. * Download icons now selectively download GFF3, SAM or WIG data. * Early support for a "show_summary" option in [TRACK DEFAULTS] and [TRACK] stanzas. If this is present and set to a length in bases, then when the user tries to display a region larger than the length the track will display feature density instead. For this to work, the database adaptor must support a feature_summary() method. This is being actively worked on in bioperl, but is not currently available. 2.04 * Can set the subtracks to be displayed by default using the new "select default" option. * New syntax for select option: select = type ; dpy-27 'dpy-27 chip' =101; htz-1 'htz-1 chip' =102; pol2 'polymerase II' =103; sdc-3 'sdc-3 chip' =104; Everything following the = sign is an optional comment (modencode uses it for the submission ID). The old syntax for this still works. * Added a TrackFinder plugin which will limit tracks according to their key, citation, or "keywords" option, based on keyword matches the user types in. * Prevent gbrowse_img zombie processes from accumulating under FastCGI. * Generate correct Galaxy callback URL and inhibit menu item when Galaxy not configured. * OligoFinder plugin now works with gbrowse2. * Updated js libraries to prototype 1.6.1 and scriptaculous 1.8.3. 2.03 * GBrowse_details: display of aligned sequences improved. * Can now paste remote BAM URLs into "import a track" field. * Private (authenticated) sessions never expire. * Fixed bug that led to a keyword search always returning multiple hits * Added a scalebar on top of the details ruler. * Fixed bug in installation paths of example databases (rbuels) * Bugfix to support for subroutines in user-defined 'head' configuration options (rbuels) * Bug fix to avoid hitting database each time the client checks on the status of a render request. * Bug fix to treat timed-out cache operations the same as timed-out render operations. * Bug fix to interrupt long system operations, like MySQL queries. 2.02 * Sheldon McKay rolled gbrowse_syn back into gbrowse2 * Fixed bug in parsing of configuration lines from cut-and-paste uploads * Added ability to look at current session's user and upload IDs. * Track dumper now accepts option to dump all chromosomes; however only works with local databases. * Fixed display of hard-clipped sequences in gbrowse_details. * Added a spinner that displays when tracks are updating. * Fixed appearance of subtrack selector. 2.01 * Fixed "multiple segment" exception in gbrowse_detail. * gbrowse_details now draws alignments correctly when both reference and target report "-" strand. This happens in samtools. * Fixed default location of users sqlite database; it now lives in /var/www/gbrowse2/databases * Fixed SMTP configuration for login script so that unencrypted connections to gateway now work. 2.00 * The "admin" user can upload public tracks. Use gbrowse_set_admin_passwd.pl to initialize the account. * If session arguments not specified in GBrowse.conf, software will pick the fastest version. * Brought tutorial into synch with new features and syntax. * "Build demo" now works correctly. * Install registration feature activated. 1.9990 * Re-added the ability to group tracks into NxM tables. * Fixed bug in which database ID was not filled in on the clickable imagemap when multiple features are shown. * Implemented the Finder plugin interface. * Balloon popups now work when gbrowse_img is embedded (from Xiaoqi Shi's patch). * Fixed track sharing client functionality. 1.9984 * gbrowse_img now shows karyotype display when multiple regions are selected. * Fixed install paths and verified that you can install into home directory. 1.9983 * Not released. 1.9982 * Undid some of the damage left by the upload code cleanup. * Can now upload gzipped and bzipp2ed files for all file types. * SAM and BAM file uploading supported, provided Bio::DB::BAM library is installed and there is a suitable FASTA file for the reference genome in one of the tracks. 1.9981 * The old-style upload code has been removed. 1.998 * WARNING: WIG FILE UPLOADING NOT WORKING. * New tabbed layout for browser, uploads & preferences. * Background uploading working well; will now resume automatically if window is closed and reopened. * Editing of uploaded files and config files now working properly. 1.9971 * Fixed bugs that were preventing name searches from working across BAM databases. * Fixed incorrect character sets returned from asynchronous calls. * Implemented asynchronous upload of files. 1.997 * Fixed bad bug in cookie handling that allowed cookies from one session to overwrite another when mod_perl or fastcgi in use. * Started working on redesign of data uploading and sharing. 1.996 * Add "feature_limit" option to keep very populous tracks under control. * Attempt to fix problem of FastCGI processes hanging around even after apache restarted. * Installer will no longer overwrite locally-modified configuration files. * Will now cache piped files and freshen cache at an interval set by "expire data sources". 1.995 * Install to an alternate location (e.g. home directory) by using --install_base argument when calling perl Build.PL. * Don't overwrite user's configuration files when doing an upgrade install! 1.994 * Fixed another bug in the cache expiration code that was causing session information to expire at end of user's browser session. * Added abiity to tag tracks by their "track source" and "data source" and to turn them on and off using this information. * Added a track filtering ability via plugins. * Fixed FastCGI support so that changes to GBROWSE_CONF are recognized each time the FastCGI server runs. This allows you to change GBROWSE_CONF on a per-directory basis using and SetEnv. 1.993 * Fixed bug in the cache expiration code that caused cache time to be set abnormally low and prevented cached data from being cached. 1.992 * Added the gbrowse_clean.pl script for cleaning up stale temp files * Normalized expiration and caching arguments. 1.991 * Added a variety of different session locking mechanisms after I discovered. that flock doesn't always work across NFS-mounted file systems. 1.990 * Fixed bug in which the hilighting of features got "stuck" on beige. * Fixed bug in which changing the chromosome of a region but leaving the coordinates the same caused redisplay of the previous region. 1.989 * Another attempted fix of Galaxy problems. The galaxy_incoming option was not handled correctly. * Fix track dumping/sharing so that uploaded files are dumped/shared correctly. 1.988 * Fix handling of DBI databases so that various intermittent SQL errors ("server went away") no longer occur. * Fixed Galaxy support to return correct MIME type. This should correct problems people have had with track data not loading into Galaxy. * fixed bug that was causing remote tracks that didn't happen to contain any features in current view to remain greyed out 1.90 * server farm rearchitecture introduced * big cleanup of defunct files; migrating to Module::Build 1.67 * Templates now the norm, use gbrowse_not to get the "no templates" version. * The das script now works (more or less) with Bio::DB::SeqFeature::Store adaptor. Not tested with chado adaptor. 1.66 * The popup zoom menu will never show a region larger than the overview. * Fixed collapsible sections so that they store their state in transient named cookies rather than in a single bit vector. 1.65 * Improved support for negative and fractional coordinates, such as those used in some genetic maps. 1.64 * Revamped state handling to use CGI::Session instead of cookies * Added Russian and Polish language translations * Fixed chado adaptor bug for older chado databases with both SO and SOFA loaded * Fixed bug to allow multple 'add' parameters * Added an option to turn on and off the background grid. * Fixed extraneous redirect when calling gbrowse_img. 1.63 * Added a new "region" panel which is intermediate in size between the overview and the detail panels. Thanks to Barry Healy for coding this. Use the new "region segment" configuration option to turn this feature on. * Added ability to open and close sections with a JavaScript toggle. * Added ability to group tracks logically. * Added the "initial landmark" configuration option to bring up a default region the first time user visits the web page. * Added the "quicklink plugins" option to add selected plugins to the links list underneath the instructions. * Added compatibility with mod_perl version 2 (via ModPerl::Registry) * Added the ability to highlight multiple features using URL arguments. * Added the ability to highlight multiple sequence regions using URL arguments. * Added the ability to turn off the autosearch feature which restores the previous region when the user revisits the browser. * Added sections on grouping tracks by category, defining region panels, and loading Berkeleydb databases to tutorial. * Added a "hide" option to use when semantic zooming should turn a track off altogether. * Added README-lucegene.pod, describing the Lucegene GFF adaptor * The link option in the config file can now be used to override the built-in linking rules from DAS sources. * Moved plugins menu to a more prominent position. * Uploaded features can now be placed in details panel, overview panel, or both panels. * init_code subroutines and anonymous callbacks are now placed in the same package so that one can refer to the other. * The feature name search now no longer does a wildcard PREFIX search (*foo*), which was killing performance. It still does a wildcard SUFFIX search (foo*). * You can now use the parameters "enable" and "disable" to selectively open or close a set of tracks without blowing away the settings for all the other tracks the way "label" does. * gbrowse_img now takes a "highlight" parameter that will highlight the indicated named feature(s) in yellow. * gbrowse_details will now evaluate URL options expressed as anonymous subroutines (contributed by Cyril Pommier). * gbrowse_details now accepts a general formatting rule syntax that allows the formatting of each tag value to be precisely controlled. * Changed mainform submission method from POST to GET when MSIE detected, in order to defeat evil "cache has expired" message. This hack is under the control of the "msie hack" option, and is false by default. 1.62 Mon Apr 5 09:43:25 EDT 2004 * Added request timeout option for very long requests. * Added additional padding to prevent scales of xyplot glyph from being cut off. * Added ability to search within external annotation files for uploaded features. You will need to CVS update bioperl-live to get this feature. * Fixed problem of external annotation files disappearing. * Fixed the problem of three-frame translation glyph showing wrong translation. HOWEVER, for the [x]flip feature to work properly, you will need to CVS update bioperl-live. * Fixed the problem of segments shrinking by 1 bp when the starting segment length was an odd number. * Fixed problem of gbrowse_img consuming all available memory when displaying 3d party features in absolute coordinates. * Fixed problem of only one feature being found during wildcard search and identically-named matches are on different reference sequences. * Fixed problem of track settings disappearing when "update image" is pressed when the track checkboxes are hidden. * Fixed cross-site scripting bug (security hole) reported by Toshiaki Katayama. * Added a pairwise_plot glyph for showing linkage disequilibrium, paired blast scores, and other pairwise feature data. * Use can now turn on and off the overview tracks. * Fixed chado adaptor to properly render the gbrowse_details page. * Patch from Eric Just to eliminate unecessary URL arguments. * Fixes from Jack Chen to get colors in multiple alignments "just right." * Several fixes, improvements to the chado adaptor. * added code to the chado adaptor to allow it to generate URLs to corresponding cmap features 1.61 Wed Mar 17 21:59:16 EST 2004 * Moved the BioSQL adaptor to 'experimental'. It is not guaranteed to work. * Really fixed the landmark problem (the 1.60 release was premature) * Quashed warnings from the GeneFinder plugin * Suppress warnings generated by coderefs in the link and window_target options. See make_map() to turn this back on - it might not be the greatest idea to turn off warnings 1.60 Tue Mar 16 16:36:45 EST 2004 * Fixed problem of some landmarks not being recognized using the Class:Name syntax. 1.59 Mon Feb 16 13:56:46 EST 2004 * Fixed security hole related to track level security * Fixed functioning related to arbitrary (non-base) units * Fixed a bug that caused hanging when fetching reference sequences * Updated BioSQL adaptor * Updated ImportFeatures.pm and ExportFeatures.pm to better support GFF3 and fascilitate Apollo import and export * Added support for 3rd party DAS anotations * Added a MOBY server * Added a proof-of-concept filter module * added allele_tower glyph 1.58 Wed Dec 31 10:49:20 EST 2003 * Fixed memory leak when used with mod_perl * Fixed bug with link URL when the same feature type occurred in more than one track * Added SVG "Publication quality image" option; as a result, GD 2.07 is the minimum version of GD required. * Added the ability to modify html display via callbacks utilizing segment and page setting objects. * Fixed alignment problems in gbrowse_details * Fixed several items with the chado/gmod adaptor * Added documentation for installing on MacOSX * Added a simple MOBY browser (see CONFIGURE_HOWTO for configuring it). * Fixed a long pathname bug with the Windows PPM install. 1.57 Sat Oct 4 21:59:19 EDT 2003 * Fixed formatting errors in gbrowse_details alignments. * Fixed bug in generation of interspersed HTML that prevented one from providing a code reference for the html1 option. * New idiogram glyph for putting images of Giemsa-stained chromosomes in the overview. * Added Icelandic translation * Updated French translation * GET syntax for invoking gbrowse now changed from http://localhost/cgi-bin/gbrowse?source=yeast to http://localhost/cgi-bin/gbrowse/yeast This will allow restriction by data sources using Apache's standard authentication/authorization techniques. * Default time for cookie expiration reduced to 7 days. This will avoid issues arising from previous change. * Added mechanisms to restrict individual tracks by username and password or by host, domain, or IP address. * Fixed ppm install utility script * Updated documentation to reflect the new GET syntax * Fixed sequence alignments in gbrowse_details when there are minus strand sequences. 1.55 * Removed hard coded paths in install scripts * Auto-open tracks that contain matches to the search term. This avoids nasty behavior in which someone searches for "collagen" and never sees what it was that matched. * Support for highlighting the matched feature in yellow. Highlighted feature is persistent across sessions (may annoy people - consider a selectable option) * Support for a "highlight" plugin class which will highlight features based on matching attributes or other queries. 1.54 Thu Aug 28 12:08:15 EDT 2003 * Really fixed the security hole that was only partially fixed in 1.53. * Fixed the config file associated with the tutorial. * Fixed the install scripts so that they work on Windows. * Added a patch to allow GBrowse to dump GenBank and EMBL formatted files while using BioPerl 1.2.2. * Modified GFFDumper to dump GFF from multiple sources, not just what is in the primary data source. This functionality is still experimental and not fully tested. * Added more complete documentation for using GBrowse with GenBank formated files 1.53 Thu Aug 21 14:40:54 EDT 2003 * Security hole that allowed the display of /etc/passwd and other files fixed * Documentation reworked as pod and which is converted to html on install. That documentation is then available at http://localhost/gbrowse * Added an extensive tutorial, also available at http://localhost/gbrowse * Added tools for making it easier to create a PPM package for Windows * Added a 'nascent' synteny browser. * Added gbrowse_details, a CGI that gives skeletal details on each feature * Added an optional 'flip mode' to flip the orientation of the display * Added a multiple alignment plugin * Added a GeneFinder plugin * Added support for the chado database schema * Added support for the PostgreSQL database server * Added a script for converting UCSC genome data to GFF3 * Added a script for loading Genbank/EMBL files to a GFF database 1.51 Thu Mar 6 13:40:09 EST 2003 * Number of search results returned by keyword search now configurable. * Made it possible for same feature to belong to multiple tracks. * Fixed HTML title so that Perl memory location of segment object won't sometimes appear. * Added new link to gbrowse_img, so that people can embed images of a region in other HTML pages. * Added option to hide the whole banner for those who prefer a minimal interface. 1.50 Thu Feb 27 09:05:37 EST 2003 * Added Dutch language support. * Added missing POXIX.pm file that was causing bizarre behavior for some browsers. * Fixed bug in label() subroutine that was causing crashes for some config files. * Added human GFF processor to installed scripts. * Fixed bug in htdocs_install.pl that created tmp directory with wrong permissions, resulting in permission failures the first time gbrowse run. 1.49 Thu Feb 13 17:25:20 EST 2003 * Version 1.48 was missing some .pl files needed to successfully install. 1.48 Sun Feb 9 12:55:48 EST 2003 * Added ability to group related features with dotted lines. * Added ability to pop up a new window when following links. * Preliminary Chado database support. * Added information on optimizing performance at SQL layer (see INSTALL). * Internationalization support: added Korean, Spanish, Chinese. * Flybase/Gadfly conversion script now works on Release 3 data format. 1.47 Tue Oct 8 14:44:44 EDT 2002 * Bug fix release. * Fixed source sorting so that lowest alphabetically-sorted configuration file is accepted by default. Otherwise, the default is BioSQL, which is not installed on most machines and causes an internal server error. * Fixed the plugins so that they are not turned on by default. * Changed the default empty track style from "suppress" to "key." * Better error reporting. * Changed passwd=>pass in all the sample config files. 1.46 Sun Oct 6 18:25:05 EDT 2002 * Major feature release. * Internationalization support: French, Italian, Japanese, English. * Some features need BioPerl 1.1; see patch file * Flexible support for semantic zooming. * Histograms in the overview and detailed views. * Multiple labeled features in overview. * Preliminary Oracle and BioSQL support. * Revamped and simplified stylesheet. * Hooks for adding HTML to display. * Track labels can now be between tracks. 1.45 Sun Jul 7 17:32:08 EDT 2002 * Major feature release. * Added conversion script for human genome annotations from NCBI. * New CDS/reading frame glyph. * New 3-frame translation glyph. * FASTA dumper now dumps out decorated FASTA files. * Sequence dumper supports output in GenBank, EMBL, GAME, BSML and other formats (thanks to magic of Bio::SeqIO). * Full set of restriction enzymes in restriction enzyme annotator plugin. * Support for named external feature tracks in popup menu. * External feature tracks are now highlighted in selection list. * Fixed uploaded files so that they are persistent. * Minor aesthetic improvements. * REQUIRES: BioPerl 1.02. * STILL PENDING: Internationalization/localization fixes 1.44 Mon May 6 19:14:45 EDT 2002 * Bug fix that caused keyword searches to fail on case mismatch. * Number of matches now printed at top of multiple-match page. 1.43 Mon May 6 14:38:40 EDT 2002 * Bug fix to correct a server error that occurred when multiple features match a search term. * Added very preliminary support for using GBrowse as a front end for GenBank and EMBL databases. 1.42 Sun May 5 11:35:22 EDT 2002 * Fixed a bad url in the help generated by gbrowse_img. 1.41 Sat May 4 16:19:20 EDT 2002 * Added gbrowse_img script; this allows local and remote HTML pages to inline the images generated by gbrowse. 1.40 Fri Apr 12 20:49:50 EDT 2002 * Minor documentation fixes. * Patch file now fixes a host of small display problems in bioperl 1.0 1.39 Fri Apr 12 00:18:10 EDT 2002 * Fixed problems compiling and installing on Solaris systems. * Added the wormbase_gene aggregator. Useful for the c. elegans gff file. * If you pick up the latest bioperl-live (or apply extras/bioperl-1.0.patch) there are fixes in Bio::Graphics that prevent genes from disappearing when zoomed all the way into an intron. 1.38 Mon Apr 8 21:16:12 EDT 2002 * Previous version would crash on vanilla Bioperl 1.0 installations. This problem has been fixed, but at the cost of disabling wildcard searches. To get wildcard searches, upgrade to Bioperl 1.01 using CVS or the patch file in extras/bioperl-1.0.patch. * Fixed aesthetic problems with a phantom "plugin:Restriction Sites" entry appearing on the key even when restriction sites are turned off. * Fixed intermittent "Couldn't open database" errors. * Fixed intermittent scrambling of user settings. 1.37 Sun Mar 31 16:10:11 EST 2002 * Plugin architecture completed see README-PLUGINS * Sample plugins provided: Restriction site annotator Find regions by searching for oligos GFF dumper FASTA dumper 1.36 Sat Mar 23 23:28:10 EST 2002 * Completely reworked the way that track options are stored. * Allow multiple files to be uploaded. * Added online help documentation. * Preparation for plug-in architecture. 1.35 Tue Mar 5 23:32:14 EST 2002 * Fixed mkpath bug in Browser.pm (wouldn't run without mods) * Fixed typos in sample .conf files. 1.34 Tue Feb 19 14:22:31 EST 2002 * Fixed JavaScript code so that the popup zoom menu works correctly with konqueror and old Netscape. * Robustified in the face of server timeout errors. 1.33 Mon Feb 18 17:41:28 EST 2002 * Made the zoom/scroll navigation bar more intuitive (in my opinion) * Zoom levels more configurable * Cleaned up the GIF buttons (install will overwrite the old ones) * Added GC and DNA content glyph to example config file 1.32 (intermediate version, do not use) 1.31 Thu Jan 24 15:44:40 EST 2002 * Fixed GFF and FASTA dumping problems. * Version number is now printed at bottom of page. 1.30 Thu Jan 24 12:01:52 EST 2002 * Clarified the method for installing in non-standard locations and gave an example for RedHat. 1.20 Mon Jan 21 17:43:06 EST 2002 * Fixed a bug that appeared with newer versions of Bio::DB::GFF in which features with multiple locations showed up with the same location repeated. 1.01 Fri Jan 11 13:12:36 EST 2002 Lincoln Stein * Better error reporting for when a database can't be opened for whatever reason. 1.00 2002-01-02 Lincoln Stein * Made GGB a project separate from Bio::Graphics * Wrote lots of documentation! GBrowse-2.56/DISCLAIMER000444001750001750 257213036764442 14510 0ustar00lsteinlstein000000000000The Generic Genome Browser package versions between 1.0 and 1.8 and all associated files are Copyright (c) 2002 Cold Spring Harbor Laboratory and University of California, Berkeley. Versions 1.9 and higher are copyright (c) 2010 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. CSHL makes no representations whatsoever as to the SOFTWARE contained herein. It is experimental in nature and is provided WITHOUT WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR IMPLIED. CSHL MAKES NO REPRESENTATION OR WARRANTY THAT THE USE OF THIS SOFTWARE WILL NOT INFRINGE ANY PATENT OR OTHER PROPRIETARY RIGHT. By downloading this SOFTWARE, your Institution hereby indemnifies CSHL against any loss, claim, damage or liability, of whatsoever kind or nature, which may arise from your Institution's respective use, handling or storage of the SOFTWARE. If publications result from research using this SOFTWARE, we ask that CSHL, University of California, Berkeley and the Ontario Institute for Cancer Research be acknowledged and/or credit be given to CSHL/Berkeley/OICR scientists, as scientifically appropriate. GBrowse-2.56/INSTALL000444001750001750 10322213036764442 14234 0ustar00lsteinlstein000000000000This document is out of date and only applies to pre-GBrowse2 releases. It will be removed from this distribution and replaced with a link to the GMOD wiki: http://gmod.org/wiki/GBrowse_2.0_Install_HOWTO ------------------------------------------------------------------------- Generic Genome Browser Installation GBrowse is distributed as binary packages for Windows and Macintosh OS X, and as source code for Unix systems. 1. WINDOWS INSTALL Before installing on Windows systems, you will need to install ActiveState Perl and the Apache web server. You may also wish to install a database management system such as MySQL. Install ActiveState Perl Go to http://www.activestate.com, and download the product "ActivePerl." This is a little confusing because web site tries to point you to the commercial product, ASPN Perl. At the current time, the full download URL for ActivePerl is: http://www.activestate.com/Products/Download/Download.plex?id=Active Perl Choose the "MSI" package for Windows. Once downloaded, launch the package, and it will install automatically. Install the Apache web server Go to http://httpd.apache.org/download.cgi . Select the most recent version of Apache, and choose the download marked "Win32 Binary (MSI Installer)." Once downloaded, launch the package and it will install automatically. Install the MySQL database (optional) Go to http://dev.mysql.com/downloads/mysql . Select and download the most recent version of the Windows package. Once the package is downloaded, you will need to unpack it with the WinZip program. Then launch the installer. Note that there have been problems reported with MySQL 4.1, therefore I suggest the newest release of 4.0. Install GBrowse Apache and ActiveState Perl must be installed before you try this step. Launch the Windows command shell by choosing "Run..." and then typing "cmd". Once the command shell appears, type the following commands: ppm> rep add gmod http://www.gmod.org/ggb/ppm ppm> rep up gmod ppm> rep up gmod ppm> install DBD::mysql (OPTIONAL) ppm> install Generic-Genome-Browser The binary distribution of GBrowse is at . Add this repository to the list of active repositories, and then move the repository to the top to ensure that you get the most up to date versions of the modules. If you wish to use a MySQL database, install DBD::mysql if you have not already done so. Then install Generic-Genome-Browser. At the end of the install, the automatic installation script will ask you to confirm the locations of your Apache conf (configuration), htdocs (document root) and cgi-bin (CGI executable) directories. Usually it will guess right, but if it doesn't, just type in the correct path. When this is done, go to step (5) below. 2. MACINTOSH OS X INSTALL NOTE: The MacOSX installer sited below is quite out of date. Until it is brought up to date, please use the SOURCE CODE INSTALL section below for Macs. Go to the following URL: ftp://dev.wormbase.org/pub/people/tharris/macosx/packages Find the most recent version of the GBrowse package. These files have the .dmg extension. Once the package is downloaded, double click on it. The installer will handle everything else. 3. SOURCE CODE INSTALL GBrowse runs on top of several software packages. These must be installed and configured before you can run GBrowse. Most preconfigured Linux systems will have some of these packages installed already. A) MySQL -- The MySQL database is a fast open source relational database that is widely used for web applications. It is required for most real-live genome annotation projects. For small projects (a few thousands of annotated features), you can skip installing MySQL and use an in-memory database instead. Note that there have been problems reported with MySQL 4.1, therefore I suggest the newest release of 4.0. B) Apache Web Server -- The Apache web server is the industry standard open source web server for Unix and Windows systems. C) Perl 5.005 -- The Perl language is widely used for web applications. Version 5.6 is preferred, but 5.00503 or higher will work. D) Standard Perl modules -- The following Perl modules must be installed for GBrowse to work. They can be found on the Comprehensive Perl Archive Network (CPAN): CGI (2.56 or higher) GD (2.07 or higher) DBI (any version) DBD::mysql (any version) Digest::MD5 (any version) Text::Shellwords (any version) E) Bioperl version 1.5 or higher -- GBrowse requires functionality that exists in bioperl-live (in the svn repository). Please either use bioperl-live or Bioperl 1.5 when it comes out. Until then, there is a release candidate of Bioperl 1.5 that is thought to be stable with regard to GBrowse. It can be found at . Other release candidates and the official 1.5 release of Bioperl can also be found in the directory when they are available. Optional modules: F) XML::Parser, XML::Writer, XML::Twig, XML::DOM If these modules are present, the "Sequence Dumper" plugin will be able to produce GAME and BSML output. They can be downloaded from CPAN. G) LWP To load remote 3d party annotations. Available from CPAN. H) Bio::Das To display remote annotations using the Distributed Annotation System. The current version can be obtained from CPAN. I) MOBY Needed by gbrowse_moby to fetch and display data from MOBY providers. Available from biomoby.org. Directions are at http://biomoby.open-bio.org/index.php/for-developers/get_code J) GD::SVG To save images as publication-quality editable images in Scalar Vector Graphics format. Available from CPAN. Once the prerequisites are installed, download the most recent version of the Generic-Genome-Browser source code from: http://prdownloads.sourceforge.net/gmod This will give you a .tar.gz file, which must be uncompressed and unpacked. Then run the following commands (in brief): perl Makefile.PL make make test (optional) make install This will install the software in the default location under /usr/local/apache. See "Details" to change this, or to install gbrowse into your home directory. To further configure GBrowse, see CONFIGURE_HOWTO. To run GBrowse on top of Oracle and PostgreSQL databases see ORACLE_AND_POSTGRESQL. To run on top of a BioSQL database, see BIOSQL_ADAPTER_HOWTO. To run GBrowse on top of Gadfly, see README-berkeley-gadfly. Details: The browser consists of a CGI script named "gbrowse", a Perl module that handles some of the gory details, a small number of static image files, and a configuration directory that contains configuration files for each data source. By default, these will be installed in the following locations: CGI script: /usr/local/apache/cgi-bin/gbrowse Static images: /usr/local/apache/htdocs/gbrowse Config files: /usr/local/apache/conf/gbrowse.conf The module: -standard site-specific Perl library location- You can change change the location of the installation by passing Makefile.PL one or more NAME=VALUE pairs, like so: perl Makefile.PL CONF=/etc HTDOCS=/home/html This will cause the configuration files to be installed in /etc/gbrowse.conf and the static files to be installed in /home/html/gbrowse. The following arguments are recognized: CONF Configuration file directory HTDOCS Static files directory CGIBIN CGI script directory APACHE Base directory for Apache's conf, htdocs and cgibin directories LIB Perl site-specific modules directory BIN Perl executable scripts directory NONROOT If set to a non-zero value (e.g. NONROOT=1) then install gbrowse in a way that does not require root access. DO_XS Compile fast alignment algorithm (XS C extension) For example, if you are on a RedHat system, where the default Apache installation uses /var/www/html for HTML files, /var/www/cgi-bin for CGI scripts, and /etc/httpd/conf for the configuration files, you should specify the following configuration: perl Makefile.PL HTDOCS=/var/www/html \ CONF=/etc/httpd/conf \ CGIBIN=/var/www/cgi-bin (The backslashes are there to split the command across multiple lines only). To make it easier when upgrading to new versions of the software, you can put this command into a shell script. As a convenience, you can use the configuration option APACHE, in which case the static and CGI files will be placed into APACHE/conf, APACHE/htdocs and APACHE/cgi-bin respectively, where APACHE is the location you specified on the command line: perl Makefile.PL APACHE=/home/www Note that the configuration files are always placed in a subdirectory named gbrowse.conf. You cannot change this. Similarly, the static files are placed in a directory named gbrowse. The install script will detect if there are already configuration files in the selected directory and not overwrite them if so. The same applies to the cascading stylesheet file (gbrowse.css) located in the gbrowse subdirectory. However, neither the GIF files in the "buttons" subdirectory nor the plugin modules in the gbrowse.conf/plugins directory are checked before overwriting them, so be careful to copy the new copies somewhere safe if you have modified them. The DO_XS flag, if true (perl Makefile.PL DO_XS=1), will compile a small C subroutine for nucleotide alignments. This will vastly improve the performance of the gbrowse_details script when displaying alignments. To use this feature, you will need a C compiler. You can always manually move the files around after install. See CONFIGURE_HOWTO for details. When installing the static files, the install script also creates an empty directory named "tmp". This directory is set to be world writable so that the GBrowse server can use it to manage temporary image files that it creates on the fly. If you would prefer not to have a world writable directory on your system, simply change the ownership and permissions to allow the web server account to write into it. The directory is located in /usr/local/apache/htdocs/gbrowse/tmp by default. The first time you run Makefile.PL, a file named GGB.def will be created your file path settings. When Makefile.PL is run again, it will ask you whether you wish to reuse the settings stored in the file. 4. INSTALLING INTO YOUR HOME DIRECTORY Read this section only if you are on a Unix system and do not have root privileges. You will need to configure Apache to run out of your home directory. One way to do this is to install Apache from source code and to specify your home directory when you first configure it: % cd apache_x.xx.xx % ./configure --prefix=$HOME/apache % make % make install This will place Apache into your home directory under ~/apache. You should then edit ~/apache/conf/httpd.conf and replace the directive: Listen 80 with Listen 8000 so that Apache will listen for connections to the unprivileged port 8000 rather than the usual port 80. If you also see a "Port 80" directive, change it to read "Port 8000." You'll now be able to talk to Apache using URLs like http://your.host.edu:8000/. You may not need to install Apache from scratch if your Unix distribution already has Apache installed. What you will do is to create an Apache directory tree in your home directory and then start Apache using command-line arguments that tell it to start up from the home directory rather than its default system-wide directory. Create an Apache directory and its subdirectories using the following series of commands: % cd ~ % mkdir apache % mkdir apache/conf % mkdir apache/logs % mkdir apache/htdocs % mkdir apache/cgi-bin Now copy the system-wide httpd.conf into ~/apache/conf. You may need to search around a bit to find out where the system-wide httpd.conf lives (try running the command "locate httpd.conf): % cp /etc/httpd/conf/httpd.conf ~/apache/conf Now open up ~/apache/conf/httpd.conf with a text editor and add the following four directives, replacing $HOME with the full path to your home directory (for example "/home/fred"): Listen 8000 ServerRoot $HOME/apache DocumentRoot $HOME/apache/htdocs SetEnv PERL5LIB $HOME/lib You should search the httpd.conf file for older versions of these directives, and delete them if they're there. If you see a Port directive, change it to read "Port 8000". Somewhere in httpd.conf there will be a ScriptAlias directives, as well as a section that refers to "cgi-bin". Delete the ScriptAlias directive and the entire section through to the line. Replace both these sections with the following: ScriptAlias /cgi-bin/ "cgi-bin/" AllowOverride None Options None Order allow,deny Allow from all You can now start Apache from the command line using the "apachectl" script: % /usr/sbin/apachectl -d ~/apache -k start If Apache starts successfully, then this command will return silently. Otherwise, it will print an error message. More error messages may be found in ~/apache/logs/error_log. To confirm that Apache is running from your home directory, create a file named index.html and copy it into ~/apache/htdocs. You should then be able to open a browser, connect to http://localhost:8000/, and see the index.html file that you just created. Now you can build and install gbrowse with the following incantation: % cd Generic-Genome-Browser-X.XX % perl Makefile.PL APACHE=~/apache LIB=~/lib BIN=~/bin NONROOT=1 % make % make install When you are prompted to load gbrowse using http://localhost/gbrowse, use http://localhost:8000/gbrowse instead. 5. TRY THE BROWSER OUT The installation procedure will create a small in-memory database of yeast chromosome 1 for you to play with. To try the browser out, use your favorite browser to open: http://localhost/cgi-bin/gbrowse Try searching for "I" (the name of the first chromosome of yeast), or a gene such as NUT21 or TCF3. Then try searching for "membrane trafficking." For your interest, the feature and DNA files for this database is located in the web server's document root at gbrowse/databases/yeast_chr1. The configuration file is in the web server's configuration directory under gbrowse.conf/yeast1.conf. More configuration information and a short tutorial are located at: http://localhost/gbrowse 6. POPULATING THE DATABASE (MySQL) This step takes you through populating the database with the full yeast genome. You can skip this step if you use the in-memory database for small projects (see section 6). Synopsis: mysql -uroot -p password -e 'create database yeast' mysql -uroot -p password -e 'grant all privileges on yeast.* to me@localhost' mysql -uroot -p password -e 'grant file on *.* to me@localhost' mysql -uroot -p password -e 'grant select on yeast.* to nobody@localhost' bp_bulk_load_gff.pl -d yeast sample_data/yeast_data.gff Details: Note for RedHat Linux users: note that if you are using the default installed Apache, the user that apache runs as is 'apache' as opposed to the otherwise standard 'nobody'. Therefore, everywhere 'nobody' occurs in these directions, replace it with 'apache'. In Bioperl versions 1.3 or later (not released as of August 2003), this script is named bp_bulk_load_gff.pl. You will need a MySQL database in order to start using GBrowse. Using the mysql command line, create a database (called "yeast" in the synopsis above), and ensure that you have update and file privileges on it. The example above assumes that you have a username of "me" and that you will allow updates from the local machine only. It also gives all privileges to "me". You may be comfortable with a more restricted set of privileges, but be sure to provide at least SELECT, UPDATE and INSERT privileges. You will need to provide the administrator's name and correct password for these commands to succeed. In addition, grant the "nobody" user the SELECT privilege. The web server usually runs as nobody, and must be able to make queries on the database. Modify this as needed if the web server runs under a different account. The next step is to load the database with data. This is accomplished by loading the database from a tab-delimited file containing the genomic annotations in GFF format. The Bioperl distribution comes with three tools for loading Bio::DB::GFF databases: 1 bp_load_gff.pl This will incrementally load a database, optionally initializing it if it does not already exist. This script will work correctly even if the MySQL server is located on another host. 2 bp_bulk_load_gff.pl This Perl script will initialize a new Bio::DB::GFF database with a fresh schema, deleting anything that was there before. It will then load the file. Only suitable for use the very first time you create a database, or when you want to start from scratch! The bulk loader is as much as 10x faster than bp_load_gff.pl, but does not work in the situation in which the MySQL database is running on a remote host. 3 bp_fast_load_gff.pl This will incrementally load a database. On UNIX systems, it will activate a fast loader that makes the speed almost the same as the bulk loader. Be careful, though, because this is an experimental piece of software. You will find these scripts in the Bioperl distribution, in the subdirectory scripts/Bio-DB-GFF. Earlier versions of the distribution will have these files directly in the scripts/ subdirectory. For testing purposes, this distribution includes a GFF file with yeast genome annotations. The file can be found in the test_data subdirectory. If the load is successful, you should see a message indicating that 13298 features were successfully loaded. Provided that the yeast load was successful, you may now run "make test". This invokes a small test script that tests that the database is accessible by the "nobody" user and that the basic feature retrieval functions are working. You may also wish to load the yeast DNA, so that you can test the three-frame translation and GC content features of the browser. Because of its size, the file containing the complete yeast genome is distributed separately and can be downloaded from: http://prdownloads.sourceforge.net/gmod/yeast.fasta.gz?download Load the file with this command: bp_load_gff.pl -d yeast -fasta yeast.fasta.gz ). By configuring an Apache::Registry directory and placing gbrowse inside it (rather than in the default cgi-bin directory). The overhead for loading Perl and its libraries are eliminated, thereby increasing the performance of the script noticeably. Be aware that there is a bad interaction between the Apache::DBI module (often used to speed up database accesses) and Bio::DB::GFF. This will cause the GFF dumper plugin to fail intermittently. GBrowse does not need Apache::DBI to achieve performance increases under mod_perl and it is suggested that you disable Apache::DBI. If you cannot do this, then you should remove the file GFFDumper.pm from the gbrowse.conf/plugins directory. Database query performance (2) is also a major factor. If you are using MySQL as the backend, you will see dramatic performance increases by increasing the amount of memory available to the key buffer, sort buffer, table cache and other in-memory data structures. I suggest that you replace the default MySQL configuration file (usually stored in /etc/my.cnf) with one of the large-memory sample configuration files provided in the support-files subdirectory of the MySQL distribution. Of course, if you tell MySQL to use more memory than you have, then performance will degrade again. Finally, there is a slowdown when gbrowse converts the results of database SQL queries into renderable biological objects. This becomes particularly noticeable when there are lots of multi-segment objects to be displayed. You can work around this slowdown by using semantic zooming (see CONFIGURE_HOWTO). Otherwise, there's not much that can be done about this short of buying a faster machine. The GMOD team is working hard to reduce this performance hit. 11. MAKING THE SERVER RUN SAFER Whenever you are running a server-side Web script using information provided by a web client, there is a risk that maliciously-formatted data provided by the use will trick the server-side script into performing some unintentional action, such as modifying a file on the server. Perl's "taint" checks are designed to catch places in the code where such malicious data could cause harm, and GBrowse has been tested extensively with these taint checks activated. Because of taint checks' noticeable impact on performance, they have been turned off in the distributed version of gbrowse. If you wish to reactivate the extra checking (at the expense of a performance hit), go to the file "gbrowse" located in the Web scripts directory and edit the top line of the file to read: #!/usr/bin/perl -w -T The -T switch turns on taint checks. If you are running GBrowse under mod_perl, add the following line to the httpd.conf configuration file: PerlTaintCheck On This will affect all mod_perl scripts globally. 12. BIOPERL VERSIONS GBrowse is evolving quickly, and some of its features are dependent on new features in Bioperl 1.4.0. If you are having trouble making GBrowse run, make sure you are using Bioperl 1.4.0! 13. THE GBROWSE_IMG SCRIPT The gbrowse_img CGI script (a new feature as of version 1.41), is a stripped-down version of gbrowse which just generates images. It is suitable for incorporating into tags in order to make a thumbnail of a region of interest. The thumbnail can then be linked to the full-featured gbrowse. Here is an example of how this works using the WormBase site: This will generate a 200-pixel inline image of the region. Clicking on the image will link to the fully-navigable gbrowse script. You can also use gbrowse_img to superimpose temporary features (like BLAST hits) on the existing genome features. Read docs/gbrowse_img.txt DOES NOT EXIST for the CGI parameters and other instructions. A copy of these instructions in HTML form will be generated when gbrowse_img is called without any arguments. Type http://your.host/cgi-bin/gbrowse_img into your favorite web browser. 14. PLUGINS Gbrowse has a plugin architecture which makes it easy for third-party developers to expand its functionality. The plugins are Perl .pm files located in the directory gbrowse.conf/plugins/. To install plugins, simply copy them into this directory. To uninstall, remove them. If you wish to install your own or third party plugins, it is suggested that you create a separate directory outside the gbrowse.conf/ hierarchy in which to store them and then to indicate the location of these plugins using the plugin_path setting: plugin_path = /usr/local/gbrowse_plugins This setting should be somewhere in the [GENERAL] section of the relevant gbrowse configuration file. 15. THE GENBANK/EMBL PROXY Sample configuration number 5 ("05.embl.conf") corresponds to an experimental pass-through proxy for Genbank. At least in theory, if you enter a landmark that isn't recognized, gbrowse will go to EMBL using the bioperl BioFetch facility, parse the record, and enter it into the local database. This allows you to browse arbitrary Genbank/EMBL/Refseq entries. You are free to experiment with this, but don't expect it to be entirely reliable. To get it to work, you must: 1 Make sure you are using Bioperl 1.02 (or a patched version of 1.01) 2 Create a local database named "embl" and initialize it this way: 3 Set up permissions for this database so that "nobody@localhost" has SELECT, INSERT, UPDATE and DELETE privileges 4 Initialize the database for use with this command: % bp_load_gff.pl -c -d embl Have fun! Lincoln Stein & the GMOD team lstein@cshl.org GBrowse-2.56/LICENSE000444001750001750 5702613036764442 14202 0ustar00lsteinlstein000000000000This package and its accompanying libraries is free software; you may redistribute it and/or modify it under the terms of either of these licenses: a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License 2.0" ---------------------------------------------------------------------------- The General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ---------------------------------------------------------------------------- Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. GBrowse-2.56/MANIFEST000444001750001750 5722713036764442 14331 0ustar00lsteinlstein000000000000bin/auto_install_databases.pl bin/bed2gff3.pl bin/bp_load_gff.pl bin/gbrowse_aws_balancer.pl bin/gbrowse_change_passwd.pl bin/gbrowse_clean.pl bin/gbrowse_configure_slaves.pl bin/gbrowse_create_account.pl bin/gbrowse_grow_cloud_vol.pl bin/gbrowse_import_ucsc_db.pl bin/gbrowse_metadb_config.pl bin/gbrowse_netinstall.pl bin/gbrowse_netinstall2.pl bin/gbrowse_set_admin_passwd.pl bin/gbrowse_slave bin/gbrowse_slave_start_aws.sh bin/gbrowse_syn_load_alignment_database.pl bin/gbrowse_syn_load_alignments_msa.pl bin/gbrowse_sync_aws_slave.pl bin/gtf2gff3.pl bin/load_genbank.pl bin/make_das_conf.pl bin/process_bamfiles.pl bin/process_gadfly.pl bin/process_ncbi_human.pl bin/process_sgd.pl bin/report_missing_language_tags.pl bin/scan_gbrowse.pl bin/split_wig.pl bin/ucsc_genes2gff.pl bin/wiggle2gff3.pl Build.PL cgi-bin/das cgi-bin/gbgff cgi-bin/gbrowse cgi-bin/gbrowse_details cgi-bin/gbrowse_gmap cgi-bin/gbrowse_img cgi-bin/gbrowse_key_img cgi-bin/gbrowse_login cgi-bin/gbrowse_syn Changes conf/aws_balancer.conf conf/detail_select_menu.conf conf/enzymes.txt conf/GBrowse.conf conf/languages/de.pm conf/languages/en.pm conf/languages/es.pm conf/languages/fr.pm conf/languages/is.pm conf/languages/it.pm conf/languages/ja.pm conf/languages/ko.pm conf/languages/nl.pm conf/languages/pl.pm conf/languages/POSIX.pm conf/languages/ru.pm conf/languages/zh.pm conf/languages/zh_cn.pm conf/log4perl.conf conf/MobyServices/b64_encoded_gif_renderer.pm conf/MobyServices/b64_encoded_jpeg_renderer.pm conf/MobyServices/GbrowseServices.pm conf/MobyServices/GbrowseServices.PMS conf/MobyServices/moby.conf conf/MobyServices/text_formatted_renderer.pm conf/MobyServices/text_html_renderer.pm conf/MobyServices/text_plain_renderer.pm conf/MobyServices/text_xml_renderer.pm conf/plugins/Aligner.pm conf/plugins/AlignTwoSequences.pm conf/plugins/AttributeHiliter.pm conf/plugins/BatchDumper.pm conf/plugins/Blat.pm conf/plugins/CMapDumper.pm conf/plugins/CreateBlastDB.pm conf/plugins/FastaDumper.pm conf/plugins/FBTableDumper.pm conf/plugins/FilterTest.pm conf/plugins/GeneFinder.pm conf/plugins/LDAPAuthenticate.pm conf/plugins/OligoFinder.pm conf/plugins/PamAuthenticate.pm conf/plugins/PrimerDesigner.pm conf/plugins/ProteinDumper.pm conf/plugins/RandomGene.pm conf/plugins/RestrictionAnnotator.pm conf/plugins/SequenceDumper.pm conf/plugins/SimpleTrackFinder.pm conf/plugins/SinWave.pm conf/plugins/SourceTrackFinder.pm conf/plugins/Spectrogram.pm conf/plugins/Submitter.pm conf/plugins/test.pm conf/plugins/TestAuthenticator.pm conf/plugins/TestFinder.pm conf/plugins/TrackDumper.pm conf/plugins/TrackFinder.pm conf/pop_demo.conf conf/renderfarm.conf conf/slave_preload.conf conf/submitter_plugin.conf conf/synteny/oryza.synconf.disabled.conf conf/synteny/rice_synteny.conf conf/synteny/wild_rice_synteny.conf conf/themes/solid_gray_colors conf/themes/transparent_colors conf/themes/warm_colors conf/volvox.conf conf/yeast_chr1+2.conf conf/yeast_renderfarm.conf conf/yeast_simple.conf contrib/ace2gff.pl contrib/AxtPairwise_convert/axt2phy.pl contrib/blast2gff.pl contrib/conf_files/01.yeast.conf contrib/conf_files/02.wormbase.conf contrib/conf_files/03.fly.conf contrib/conf_files/04.human.conf contrib/conf_files/05.embl_proxy.conf contrib/conf_files/06.biosql.conf contrib/conf_files/07.chado.conf contrib/conf_files/08.genbank.conf contrib/conf_files/09.human_karyotype.conf contrib/conf_files/index.html contrib/conf_files/wormbase.syn contrib/Coverage/INSTALL contrib/Coverage/plugin/Coverage.pm contrib/Coverage/README contrib/gdump.pl contrib/GeneFinder/genefinder/gfcode.c contrib/GeneFinder/genefinder/README contrib/GeneFinder/genefinder/readseq.c contrib/GeneFinder/genefinder/readseq.h contrib/GeneFinder/nematode_gftables/cds.hex contrib/GeneFinder/nematode_gftables/gftables contrib/GeneFinder/nematode_gftables/newnem.atg contrib/GeneFinder/nematode_gftables/newnem.codon contrib/GeneFinder/nematode_gftables/newnem.gene contrib/GeneFinder/nematode_gftables/newnem.intron3 contrib/GeneFinder/nematode_gftables/newnem.intron5 contrib/GeneFinder/nematode_gftables/ref.hist contrib/GeneFinder/nematode_gftables/zk637.atg contrib/GeneFinder/nematode_gftables/zk637.intron3 contrib/GeneFinder/nematode_gftables/zk637.intron5 contrib/GeneFinder/nematode_gftables/zk637.trinuc contrib/import_ncbi_mv_hs.pl contrib/install_macosx/BuildConfig.pm contrib/install_macosx/README.html contrib/install_macosx/README.pod contrib/install_macosx/scripts/build-gbrowse.pl contrib/install_macosx/scripts/build-libraries.pl contrib/README contrib/SynView/cgi-lib/DAS/GUS.pm contrib/SynView/cgi-lib/DAS/GUS/Segment.pm contrib/SynView/cgi-lib/DAS/GUS/Segment/Feature.pm contrib/SynView/cgi-lib/DAS/Util/SqlParser.pm contrib/SynView/gbrowse.conf/plasmodb.conf contrib/SynView/gbrowse.conf/plasmodb.xml contrib/SynView/MAL11/MAL11.conf contrib/SynView/MAL11/MAL11.fa contrib/SynView/MAL11/MAL11.gff3 contrib/SynView/README contrib/TextDumper/README contrib/TextDumper/TextDumper.pm DISCLAIMER docs/developer_notes/README.rearchitecture docs/developer_notes/README.sharing_tracks docs/example_remote_configs/volvox_local.conf docs/example_remote_configs/volvox_remote.conf docs/example_remote_configs/volvox_slave.conf docs/Gbrowse_Color_Palette.pdf docs/login.sql docs/pod/BIOSQL_ADAPTER_HOWTO.pod docs/pod/CONFIGURE_HOWTO.pod docs/pod/CONTROLLER.pod docs/pod/DAS_HOWTO.pod docs/pod/FAQ.pod docs/pod/GBROWSE_IMG.pod docs/pod/GENBANK_HOWTO.pod docs/pod/INSTALL.MacOSX.pod docs/pod/INSTALL.pod docs/pod/MAKE_IMAGES_HOWTO.pod docs/pod/ORACLE_AND_POSTGRESQL.pod docs/pod/PLUGINS_HOWTO.pod docs/pod/README-berkeley-gadfly.pod docs/pod/README-chado.pod docs/pod/README-gff-files.pod docs/pod/README-lucegene.pod docs/README.AWS docs/README.tutorial etc/default/gbrowse-aws-balancer etc/default/gbrowse-slave etc/init.d/gbrowse-aws-balancer etc/init.d/gbrowse-slave htdocs/annotation_help.html htdocs/cloud_index.html htdocs/css/dropdown/default_theme.css htdocs/css/dropdown/dropdown.css htdocs/css/dropdown/helper.css htdocs/css/dropdown/images/favicon.ico htdocs/css/dropdown/images/icon.png htdocs/css/dropdown/images/nav-arrow-down-on.png htdocs/css/dropdown/images/nav-arrow-down-open.png htdocs/css/dropdown/images/nav-arrow-down.png htdocs/css/dropdown/images/nav-arrow-left-on.png htdocs/css/dropdown/images/nav-arrow-left-open.png htdocs/css/dropdown/images/nav-arrow-left.png htdocs/css/dropdown/images/nav-arrow-right-on.png htdocs/css/dropdown/images/nav-arrow-right-open.png htdocs/css/dropdown/images/nav-arrow-right.png htdocs/css/dropdown/images/nav-arrow-up-on.png htdocs/css/dropdown/images/nav-arrow-up-open.png htdocs/css/dropdown/images/nav-arrow-up.png htdocs/css/dropdown/images/pattern1.png htdocs/css/dropdown/images/pattern2.png htdocs/css/dropdown/images/pattern3.png htdocs/css/gbrowse.css htdocs/css/gbrowse_autocomplete.css htdocs/css/gbrowse_elements.css htdocs/css/gbrowse_solid.css htdocs/css/gbrowse_transparent.css htdocs/css/gbrowse_warm.css htdocs/css/karyotype.css htdocs/css/menulink.png htdocs/css/menulink_active.png htdocs/css/snapshots.css htdocs/css/subtracktable.css htdocs/css/titlebar-default.css htdocs/css/titlebar-safari.css htdocs/css/tracks.css htdocs/example_scripts/gbrowse_get_sessionid.pl htdocs/example_scripts/gbrowse_new_sessionid.pl htdocs/example_scripts/gbrowse_upload_data.pl htdocs/example_scripts/gbrowse_upload_file.pl htdocs/example_scripts/index.html htdocs/example_scripts/README htdocs/example_scripts/test_file.bed htdocs/gbrowse_karyotype_help.html htdocs/gbrowse_syn_help.html htdocs/general_help.html htdocs/general_help.html.zh htdocs/gmod_cog.jpeg htdocs/images/backgrounds/cloud.jpg htdocs/images/backgrounds/lrock005.jpg htdocs/images/backgrounds/steel.jpg htdocs/images/balloons/GBubble/balloon.png htdocs/images/balloons/GBubble/balloon_ie.png htdocs/images/balloons/GBubble/close.png htdocs/images/balloons/GBubble/down_left.png htdocs/images/balloons/GBubble/down_right.png htdocs/images/balloons/GBubble/up_left.png htdocs/images/balloons/GBubble/up_right.png htdocs/images/balloons/GPlain/balloon.png htdocs/images/balloons/GPlain/close.png htdocs/images/balloons/GPlain/down_left.png htdocs/images/balloons/GPlain/down_right.png htdocs/images/balloons/GPlain/up_left.png htdocs/images/balloons/GPlain/up_right.png htdocs/images/buttons/ajax-loader.gif htdocs/images/buttons/blue_peaks.png htdocs/images/buttons/check.png htdocs/images/buttons/cursor-ewmove.ico htdocs/images/buttons/dark_0.4_pixel.png htdocs/images/buttons/download.png htdocs/images/buttons/empty.png htdocs/images/buttons/ex.png htdocs/images/buttons/ficon.png htdocs/images/buttons/ficon_2.png htdocs/images/buttons/fmini.png htdocs/images/buttons/fmini_2.png htdocs/images/buttons/green.gif htdocs/images/buttons/green1.gif htdocs/images/buttons/green2.gif htdocs/images/buttons/green3.gif htdocs/images/buttons/green4.gif htdocs/images/buttons/green5.gif htdocs/images/buttons/green6.gif htdocs/images/buttons/green7.gif htdocs/images/buttons/green8.gif htdocs/images/buttons/green_l1.gif htdocs/images/buttons/green_l2.gif htdocs/images/buttons/green_r1.gif htdocs/images/buttons/green_r2.gif htdocs/images/buttons/grey.png htdocs/images/buttons/grey_0.4_pixel.png htdocs/images/buttons/menu.png htdocs/images/buttons/minus.gif htdocs/images/buttons/minus.png htdocs/images/buttons/minus12.png htdocs/images/buttons/mminus.png htdocs/images/buttons/mplus.gif htdocs/images/buttons/mplus.png htdocs/images/buttons/opacity_thumb.png htdocs/images/buttons/open_open.png htdocs/images/buttons/panleft.png htdocs/images/buttons/panleft2.png htdocs/images/buttons/panright.png htdocs/images/buttons/panright2.png htdocs/images/buttons/plus.gif htdocs/images/buttons/plus.png htdocs/images/buttons/pop_in.png htdocs/images/buttons/pop_out.png htdocs/images/buttons/query.png htdocs/images/buttons/red.gif htdocs/images/buttons/red1.gif htdocs/images/buttons/red2.gif htdocs/images/buttons/red3.gif htdocs/images/buttons/red4.gif htdocs/images/buttons/red5.gif htdocs/images/buttons/red6.gif htdocs/images/buttons/red7.gif htdocs/images/buttons/red8.gif htdocs/images/buttons/red_peaks.png htdocs/images/buttons/ruler-icon.png htdocs/images/buttons/ruler.png htdocs/images/buttons/share.png htdocs/images/buttons/snap_check.png htdocs/images/buttons/snap_down.png htdocs/images/buttons/snap_ex.png htdocs/images/buttons/snap_mail.png htdocs/images/buttons/snap_share.png htdocs/images/buttons/snap_trash.png htdocs/images/buttons/sortable.gif htdocs/images/buttons/sorted_down.gif htdocs/images/buttons/sorted_up.gif htdocs/images/buttons/spinner.gif htdocs/images/buttons/square.png htdocs/images/buttons/square.xpm htdocs/images/buttons/tools.png htdocs/images/buttons/trash.gif htdocs/images/buttons/trash.png htdocs/images/help/detail.gif htdocs/images/help/detail.png htdocs/images/help/detail_scale.gif htdocs/images/help/detail_scale.png htdocs/images/help/landmark.gif htdocs/images/help/landmark.png htdocs/images/help/multiple_hits.png htdocs/images/help/navbar.gif htdocs/images/help/navbar.png htdocs/images/help/numeric+data.gif htdocs/images/help/overview+detail.gif htdocs/images/help/overview+detail.png htdocs/images/help/overview.gif htdocs/images/help/remote.png htdocs/images/help/search+settings.gif htdocs/images/help/sugarcane_sorghum_synteny.png htdocs/images/help/track+settings.gif htdocs/images/help/upload+edit.gif htdocs/images/help/upload+remote.gif htdocs/images/help/upload.gif htdocs/images/help/upload.png htdocs/images/help/upload_field.png htdocs/images/help/upload_list.png htdocs/images/help/worm_exons_spec.png htdocs/images/help/worm_telomeric_spec.png htdocs/images/help/yeast_I_genes_spec.png htdocs/images/openid/aim-logo.png htdocs/images/openid/blogspot-logo.png htdocs/images/openid/google-logo.gif htdocs/images/openid/livejournal-logo.png htdocs/images/openid/myopenid-logo.png htdocs/images/openid/openid-logo.gif htdocs/images/openid/yahoo-logo.png htdocs/index.html htdocs/js/ajax_upload.js htdocs/js/autocomplete.js htdocs/js/balloon.config.js htdocs/js/balloon.js htdocs/js/box.js htdocs/js/builder.js htdocs/js/buttons.js htdocs/js/controller.js htdocs/js/controls.js htdocs/js/detailSelect.js htdocs/js/dragdrop.js htdocs/js/effects.js htdocs/js/GBox.js htdocs/js/karyotype.js htdocs/js/login.js htdocs/js/menu.js htdocs/js/overviewSelect.js htdocs/js/prototype.js htdocs/js/regionSelect.js htdocs/js/rubber.js htdocs/js/ruler.js htdocs/js/scriptaculous.js htdocs/js/scrollfix.js htdocs/js/slider.js htdocs/js/snapshotManager.js htdocs/js/sound.js htdocs/js/subtracktable.css htdocs/js/subtracktable.js htdocs/js/tabs.js htdocs/js/toggle.js htdocs/js/track.js htdocs/js/track_configure.js htdocs/js/track_pan.js htdocs/js/trackFavorites.js htdocs/js/unittest.js htdocs/js/x_cook.js htdocs/tutorial/bin/expression_levels.pl htdocs/tutorial/bin/make_exon.pl htdocs/tutorial/bin/random_dna.pl htdocs/tutorial/bin/random_feature.pl htdocs/tutorial/bin/random_segments.pl htdocs/tutorial/bin/reformat.pl htdocs/tutorial/conf_files/elegans_core.conf htdocs/tutorial/conf_files/elegans_extra.conf htdocs/tutorial/conf_files/HEADER.html htdocs/tutorial/conf_files/volvox.conf htdocs/tutorial/conf_files/volvox_final.conf htdocs/tutorial/conf_files/volvox_final_withPhylo.conf htdocs/tutorial/conf_files/volvox_halfway.conf htdocs/tutorial/conf_files/volvox_Phylo.conf htdocs/tutorial/conf_files/volvox_quarter.conf htdocs/tutorial/conf_files/volvox_refactored.conf htdocs/tutorial/data_files/dog1_1700.wig htdocs/tutorial/data_files/elegans.fa htdocs/tutorial/data_files/elegans_acceptor.gff3 htdocs/tutorial/data_files/elegans_core.gff3 htdocs/tutorial/data_files/elegans_deletion.gff3 htdocs/tutorial/data_files/elegans_expression.gff3 htdocs/tutorial/data_files/elegans_extra.gff3 htdocs/tutorial/data_files/elegans_repeats.gff3 htdocs/tutorial/data_files/elegans_sts.gff3 htdocs/tutorial/data_files/ests.fa htdocs/tutorial/data_files/HEADER.html htdocs/tutorial/data_files/species.tre htdocs/tutorial/data_files/volvox.fa htdocs/tutorial/data_files/volvox.gff3 htdocs/tutorial/data_files/volvox_all.fa htdocs/tutorial/data_files/volvox_all.gff3 htdocs/tutorial/data_files/volvox_array.gff3 htdocs/tutorial/data_files/volvox_bacs.gff3 htdocs/tutorial/data_files/volvox_domains.gff3 htdocs/tutorial/data_files/volvox_est.gff3 htdocs/tutorial/data_files/volvox_est_targets.gff3 htdocs/tutorial/data_files/volvox_geneproducts.gff3 htdocs/tutorial/data_files/volvox_genes.gff3 htdocs/tutorial/data_files/volvox_genes_simple.gff3 htdocs/tutorial/data_files/volvox_matches.gff3 htdocs/tutorial/data_files/volvox_microarray.gff3 htdocs/tutorial/data_files/volvox_microarray.wig htdocs/tutorial/data_files/volvox_phyloalign.fa htdocs/tutorial/data_files/volvox_phyloalign.gff3 htdocs/tutorial/data_files/volvox_phyloalign_wigentries.gff3 htdocs/tutorial/data_files/volvox_remarks.gff3 htdocs/tutorial/data_files/volvox_trace.gff3 htdocs/tutorial/data_files/volvox_trace.scf htdocs/tutorial/dbgff/data_files/elegans_acceptor.gff htdocs/tutorial/dbgff/data_files/elegans_core.gff htdocs/tutorial/dbgff/data_files/elegans_deletion.gff htdocs/tutorial/dbgff/data_files/elegans_expression.gff htdocs/tutorial/dbgff/data_files/elegans_extra.gff htdocs/tutorial/dbgff/data_files/elegans_repeats.gff htdocs/tutorial/dbgff/data_files/elegans_sts.gff htdocs/tutorial/dbgff/data_files/volvox1.gff htdocs/tutorial/dbgff/data_files/volvox2.gff htdocs/tutorial/dbgff/data_files/volvox3.gff htdocs/tutorial/dbgff/data_files/volvox4.gff htdocs/tutorial/dbgff/data_files/volvox4a.gff htdocs/tutorial/dbgff/data_files/volvox4b.gff htdocs/tutorial/dbgff/data_files/volvox5.gff htdocs/tutorial/dbgff/data_files/volvox6.gff htdocs/tutorial/dbgff/data_files/volvox7.gff htdocs/tutorial/dbgff/data_files/volvox8.gff htdocs/tutorial/dbgff/data_files/volvox9.gff htdocs/tutorial/dbgff/data_files/volvox_all.gff htdocs/tutorial/figures/adding_dna_to_alignments1.gif htdocs/tutorial/figures/aliases.gif htdocs/tutorial/figures/basic_conf1.gif htdocs/tutorial/figures/basic_conf2.gif htdocs/tutorial/figures/basics1.gif htdocs/tutorial/figures/canonical_gene1.gif htdocs/tutorial/figures/canonical_gene2.gif htdocs/tutorial/figures/canonical_gene3.gif htdocs/tutorial/figures/categorytable.png htdocs/tutorial/figures/cds1.gif htdocs/tutorial/figures/config_editing.png htdocs/tutorial/figures/custom_aggregators1.gif htdocs/tutorial/figures/DAS1.gif htdocs/tutorial/figures/descriptions1.gif htdocs/tutorial/figures/dna1.gif htdocs/tutorial/figures/dna1.png htdocs/tutorial/figures/dna2.gif htdocs/tutorial/figures/dna2.png htdocs/tutorial/figures/enhancements1.gif htdocs/tutorial/figures/enhancements2.gif htdocs/tutorial/figures/enhancements3.gif htdocs/tutorial/figures/figure1.gif htdocs/tutorial/figures/figure10.gif htdocs/tutorial/figures/figure11.gif htdocs/tutorial/figures/figure12.gif htdocs/tutorial/figures/figure13a.gif htdocs/tutorial/figures/figure13b.gif htdocs/tutorial/figures/figure14.gif htdocs/tutorial/figures/figure15.gif htdocs/tutorial/figures/figure16.gif htdocs/tutorial/figures/figure17.gif htdocs/tutorial/figures/figure18.gif htdocs/tutorial/figures/figure19.gif htdocs/tutorial/figures/figure2.gif htdocs/tutorial/figures/figure20.gif htdocs/tutorial/figures/figure21.gif htdocs/tutorial/figures/figure22.gif htdocs/tutorial/figures/figure23.gif htdocs/tutorial/figures/figure24.gif htdocs/tutorial/figures/figure25.gif htdocs/tutorial/figures/figure26.gif htdocs/tutorial/figures/figure27.gif htdocs/tutorial/figures/figure28.gif htdocs/tutorial/figures/figure29.gif htdocs/tutorial/figures/figure3.gif htdocs/tutorial/figures/figure30.gif htdocs/tutorial/figures/figure4.gif htdocs/tutorial/figures/figure5.gif htdocs/tutorial/figures/figure6.gif htdocs/tutorial/figures/figure7.gif htdocs/tutorial/figures/figure7a.gif htdocs/tutorial/figures/figure7b.gif htdocs/tutorial/figures/figure8.gif htdocs/tutorial/figures/figure9.gif htdocs/tutorial/figures/graph1.gif htdocs/tutorial/figures/multiple_alignments1.gif htdocs/tutorial/figures/multiple_alignments2.gif htdocs/tutorial/figures/multiple_alignments3.gif htdocs/tutorial/figures/overview1.gif htdocs/tutorial/figures/phylo_align1.gif htdocs/tutorial/figures/phylo_align2.gif htdocs/tutorial/figures/phylo_align3.gif htdocs/tutorial/figures/plugins1.gif htdocs/tutorial/figures/plugins2.gif htdocs/tutorial/figures/predicted_genes.gif htdocs/tutorial/figures/segmented_features1.gif htdocs/tutorial/figures/segmented_features2.gif htdocs/tutorial/figures/semantic_zooming1.gif htdocs/tutorial/figures/setting_popup.png htdocs/tutorial/figures/third_party1.gif htdocs/tutorial/figures/third_party2.gif htdocs/tutorial/figures/third_party3.gif htdocs/tutorial/figures/third_party4.gif htdocs/tutorial/figures/third_party5.gif htdocs/tutorial/figures/trace1.png htdocs/tutorial/figures/trace2.png htdocs/tutorial/figures/wiggle_density.gif htdocs/tutorial/figures/wiggle_density.png htdocs/tutorial/tutorial.css htdocs/tutorial/tutorial.html htdocs/tutorial/tutorial.phyTreeEdit.html htdocs/vbox_index.html INSTALL install_util/cgi_install.pl install_util/conf_install.pl install_util/gbrowse_ppm_install.pl install_util/GBrowseGuessDirectories.pm install_util/GBrowseInstall.pm install_util/htdocs_install.pl install_util/InstallUtil.pm install_util/make_clean_add.pl install_util/pod2docs.pl install_util/sync-bioperl.sh install_util/tag.pl lib/Bio/DB/GFF/Aggregator/match_gap.pm lib/Bio/DB/GFF/Aggregator/reftranscript.pm lib/Bio/DB/GFF/Aggregator/waba_alignment.pm lib/Bio/DB/GFF/Aggregator/wormbase_gene.pm lib/Bio/DB/SeqFeature/Store/Alias.pm lib/Bio/DB/SeqFeature/Store/BedLoader.pm lib/Bio/DB/SeqFeature/Store/LoadHelper.pm lib/Bio/DB/Tagger.pm lib/Bio/DB/Tagger/mysql.pm lib/Bio/DB/Tagger/Tag.pm lib/Bio/Graphics/Browser2.pm lib/Bio/Graphics/Browser2/Action.pm lib/Bio/Graphics/Browser2/AuthorizedFeatureFile.pm lib/Bio/Graphics/Browser2/CachedTrack.pm lib/Bio/Graphics/Browser2/CAlign.pm lib/Bio/Graphics/Browser2/CAlign.xs lib/Bio/Graphics/Browser2/DataBase.pm lib/Bio/Graphics/Browser2/DataLoader.pm lib/Bio/Graphics/Browser2/DataLoader/archive.pm lib/Bio/Graphics/Browser2/DataLoader/bam.pm lib/Bio/Graphics/Browser2/DataLoader/bed.pm lib/Bio/Graphics/Browser2/DataLoader/bigbed.pm lib/Bio/Graphics/Browser2/DataLoader/bigwig.pm lib/Bio/Graphics/Browser2/DataLoader/featurefile.pm lib/Bio/Graphics/Browser2/DataLoader/generic.pm lib/Bio/Graphics/Browser2/DataLoader/gff.pm lib/Bio/Graphics/Browser2/DataLoader/gff3.pm lib/Bio/Graphics/Browser2/DataLoader/sam.pm lib/Bio/Graphics/Browser2/DataLoader/useq.pm lib/Bio/Graphics/Browser2/DataLoader/wig2bigwig.pm lib/Bio/Graphics/Browser2/DataLoader/wiggle.pm lib/Bio/Graphics/Browser2/DataSource.pm lib/Bio/Graphics/Browser2/ExternalData.pm lib/Bio/Graphics/Browser2/GFFhelper.pm lib/Bio/Graphics/Browser2/I18n.pm lib/Bio/Graphics/Browser2/Markup.pm lib/Bio/Graphics/Browser2/OptionPick.pm lib/Bio/Graphics/Browser2/PadAlignment.pm lib/Bio/Graphics/Browser2/Plugin.pm lib/Bio/Graphics/Browser2/Plugin/AuthPlugin.pm lib/Bio/Graphics/Browser2/PluginSet.pm lib/Bio/Graphics/Browser2/Realign.pm lib/Bio/Graphics/Browser2/Region.pm lib/Bio/Graphics/Browser2/RegionSearch.pm lib/Bio/Graphics/Browser2/RemoteSet.pm lib/Bio/Graphics/Browser2/Render.pm lib/Bio/Graphics/Browser2/Render/HTML.pm lib/Bio/Graphics/Browser2/Render/HTML/TrackListing.pm lib/Bio/Graphics/Browser2/Render/HTML/TrackListing/Categories.pm lib/Bio/Graphics/Browser2/Render/Login.pm lib/Bio/Graphics/Browser2/Render/Slave.pm lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm lib/Bio/Graphics/Browser2/Render/Slave/Status.pm lib/Bio/Graphics/Browser2/Render/SnapshotManager.pm lib/Bio/Graphics/Browser2/Render/TrackConfig.pm lib/Bio/Graphics/Browser2/RenderPanels.pm lib/Bio/Graphics/Browser2/SendMail.pm lib/Bio/Graphics/Browser2/Session.pm lib/Bio/Graphics/Browser2/Shellwords.pm lib/Bio/Graphics/Browser2/SubtrackTable.pm lib/Bio/Graphics/Browser2/TrackDumper.pm lib/Bio/Graphics/Browser2/TrackDumper/RichSeqMaker.pm lib/Bio/Graphics/Browser2/UserDB.pm lib/Bio/Graphics/Browser2/UserTracks.pm lib/Bio/Graphics/Browser2/UserTracks/Database.pm lib/Bio/Graphics/Browser2/UserTracks/Filesystem.pm lib/Bio/Graphics/Browser2/Util.pm lib/Bio/Graphics/GBrowseFeature.pm lib/Bio/Graphics/Karyotype.pm lib/CGI/Toggle.pm lib/Legacy/DB/SyntenyBlock.pm lib/Legacy/DB/SyntenyIO.pm lib/Legacy/Graphics/Browser.pm lib/Legacy/Graphics/Browser/I18n.pm lib/Legacy/Graphics/Browser/PageSettings.pm lib/Legacy/Graphics/Browser/Synteny.pm lib/Legacy/Graphics/Browser/Util.pm libalign/CAlign.pm libalign/CAlign.xs libalign/Changes libalign/README libalign/realign.h LICENSE Makefile.PL MANIFEST README README.fedora_and_selinux README.gff3 README.IF.GBROWSE.ISNT.WORKING sample_data/admin_uploads/README sample_data/gbrowse_syn/alignments/rice.aln.gz sample_data/gbrowse_syn/rice/rice.gff3 sample_data/gbrowse_syn/wild_rice/wild_rice.gff3 sample_data/ideograms/human_cytobands.gff sample_data/ideograms/mouse_cytobands.gff sample_data/ideograms/rat_cytobands.gff sample_data/pop_demo/pop_demo.gff3 sample_data/yeast_chr1+2/dummy.fa sample_data/yeast_chr1+2/yeast_chr1+2.gff3 sample_data/yeast_scaffolds/chr1.fa sample_data/yeast_scaffolds/chr2.fa sample_data/yeast_scaffolds/chromosomes.gff3 t/00.compile.t t/01.yeast.t t/02.rearchitecture.t t/03.render.t t/04.remoteserver.t t/05.deferredrendering.t t/06.featuresearch.t t/07.balancer.t t/07.karyotype.t t/08.calign.t t/Test.pm t/testdata/conf/aws_slave.conf t/testdata/conf/enzymes.txt t/testdata/conf/GBrowse.conf t/testdata/conf/languages/fr.pm t/testdata/conf/languages/POSIX.pm t/testdata/conf/templates/volvox_final.conf t/testdata/conf/templates/yeast_chr1.conf t/testdata/conf/WHERE_ARE_THE_CONF_FILES.txt t/testdata/data/volvox/dummy.fa t/testdata/data/volvox/volvox.gff t/testdata/data/volvox2/dummy.fa t/testdata/data/volvox2/volvox2.gff t/testdata/data/volvox3/dummy.fa t/testdata/data/volvox3/volvox3.gff t/testdata/data/volvox4/dummy.fa t/testdata/data/volvox4/volvox4.gff t/testdata/phylo_align/phyloalign.fa t/testdata/phylo_align/readme.txt t/testdata/phylo_align/species.tre t/testdata/phylo_align/volvox_alignment.conf t/testdata/phylo_align/volvox_phyloalign.gff t/testdata/TemplateCopy.pm META.yml META.json GBrowse-2.56/META.json000444001750001750 3165713036764442 14620 0ustar00lsteinlstein000000000000{ "abstract" : "The GMOD Generic Genome Browser", "author" : [ "Lincoln Stein " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4216", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "GBrowse", "prereqs" : { "build" : { "requires" : { "Capture::Tiny" : "0", "ExtUtils::CBuilder" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0.42" } }, "runtime" : { "recommends" : { "Bio::DB::BigFile" : "1", "Bio::DB::Sam" : "1.36", "Bio::Das" : "0", "Crypt::SSLeay" : "0", "DBD::Pg" : "0", "DBD::SQLite" : "0", "DBD::mysql" : "0", "DBI" : "0", "DB_File::Lock" : "0", "Digest::SHA" : "0", "FCGI" : "0", "File::NFSLock" : "0", "GD::SVG" : "0", "Math::BigInt" : "0", "Net::OpenID::Consumer" : "0", "Net::SMTP::SSL" : "0", "Parse::Apache::ServerStatus" : "0", "Template" : "2.2", "Term::ReadKey" : "0", "VM::EC2" : "1.19" }, "requires" : { "Bio::Graphics" : "2.34", "Bio::Root::Version" : "1.007001", "CGI::Session" : "4.02", "Date::Parse" : "0", "Digest::MD5" : "0", "Digest::SHA" : "0", "ExtUtils::CBuilder" : "0", "File::Temp" : "0", "GD" : "2.50", "HTTP::Daemon" : "0", "IO::String" : "0", "JSON" : "0", "LWP" : "0", "Statistics::Descriptive" : "0", "Storable" : "0", "Term::ReadKey" : "0", "Text::ParseWords" : "3.27", "Time::HiRes" : "0", "parent" : "0", "perl" : "5.008" } } }, "provides" : { "Bio::DB::GFF::Aggregator::match_gap" : { "file" : "lib/Bio/DB/GFF/Aggregator/match_gap.pm" }, "Bio::DB::GFF::Aggregator::reftranscript" : { "file" : "lib/Bio/DB/GFF/Aggregator/reftranscript.pm", "version" : "0.10" }, "Bio::DB::GFF::Aggregator::waba_alignment" : { "file" : "lib/Bio/DB/GFF/Aggregator/waba_alignment.pm", "version" : "0.20" }, "Bio::DB::GFF::Aggregator::wormbase_gene" : { "file" : "lib/Bio/DB/GFF/Aggregator/wormbase_gene.pm", "version" : "0.30" }, "Bio::DB::SeqFeature::Store::Alias" : { "file" : "lib/Bio/DB/SeqFeature/Store/Alias.pm" }, "Bio::DB::SeqFeature::Store::Alias::Iterator" : { "file" : "lib/Bio/DB/SeqFeature/Store/Alias.pm" }, "Bio::DB::SeqFeature::Store::Alias::Segment" : { "file" : "lib/Bio/DB/SeqFeature/Store/Alias.pm" }, "Bio::DB::SeqFeature::Store::BedLoader" : { "file" : "lib/Bio/DB/SeqFeature/Store/BedLoader.pm" }, "Bio::DB::SeqFeature::Store::LoadHelper" : { "file" : "lib/Bio/DB/SeqFeature/Store/LoadHelper.pm", "version" : "1.10" }, "Bio::DB::Tagger" : { "file" : "lib/Bio/DB/Tagger.pm", "version" : "1.00" }, "Bio::DB::Tagger::Iterator" : { "file" : "lib/Bio/DB/Tagger.pm" }, "Bio::DB::Tagger::Tag" : { "file" : "lib/Bio/DB/Tagger/Tag.pm" }, "Bio::DB::Tagger::mysql" : { "file" : "lib/Bio/DB/Tagger/mysql.pm" }, "Bio::Graphics::Browser2" : { "file" : "lib/Bio/Graphics/Browser2.pm", "version" : "2.56" }, "Bio::Graphics::Browser2::Action" : { "file" : "lib/Bio/Graphics/Browser2/Action.pm" }, "Bio::Graphics::Browser2::AdminTracks" : { "file" : "lib/Bio/Graphics/Browser2/UserTracks.pm" }, "Bio::Graphics::Browser2::AuthorizedFeatureFile" : { "file" : "lib/Bio/Graphics/Browser2/AuthorizedFeatureFile.pm" }, "Bio::Graphics::Browser2::CAlign" : { "file" : "lib/Bio/Graphics/Browser2/CAlign.pm" }, "Bio::Graphics::Browser2::CachedTrack" : { "file" : "lib/Bio/Graphics/Browser2/CachedTrack.pm" }, "Bio::Graphics::Browser2::DataBase" : { "file" : "lib/Bio/Graphics/Browser2/DataBase.pm" }, "Bio::Graphics::Browser2::DataLoader" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader.pm" }, "Bio::Graphics::Browser2::DataLoader::archive" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/archive.pm" }, "Bio::Graphics::Browser2::DataLoader::bam" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/bam.pm" }, "Bio::Graphics::Browser2::DataLoader::bed" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/bed.pm" }, "Bio::Graphics::Browser2::DataLoader::bigbed" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/bigbed.pm" }, "Bio::Graphics::Browser2::DataLoader::bigwig" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/bigwig.pm" }, "Bio::Graphics::Browser2::DataLoader::featurefile" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/featurefile.pm" }, "Bio::Graphics::Browser2::DataLoader::generic" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/generic.pm" }, "Bio::Graphics::Browser2::DataLoader::gff" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/gff.pm" }, "Bio::Graphics::Browser2::DataLoader::gff3" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/gff3.pm" }, "Bio::Graphics::Browser2::DataLoader::sam" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/sam.pm" }, "Bio::Graphics::Browser2::DataLoader::useq" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/useq.pm" }, "Bio::Graphics::Browser2::DataLoader::wig2bigwig" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/wig2bigwig.pm" }, "Bio::Graphics::Browser2::DataLoader::wiggle" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/wiggle.pm" }, "Bio::Graphics::Browser2::DataSource" : { "file" : "lib/Bio/Graphics/Browser2/DataSource.pm" }, "Bio::Graphics::Browser2::ExternalData" : { "file" : "lib/Bio/Graphics/Browser2/ExternalData.pm" }, "Bio::Graphics::Browser2::GFFhelper" : { "file" : "lib/Bio/Graphics/Browser2/GFFhelper.pm" }, "Bio::Graphics::Browser2::I18n" : { "file" : "lib/Bio/Graphics/Browser2/I18n.pm" }, "Bio::Graphics::Browser2::Markup" : { "file" : "lib/Bio/Graphics/Browser2/Markup.pm" }, "Bio::Graphics::Browser2::MetaDB" : { "file" : "lib/Bio/Graphics/Browser2/RegionSearch.pm" }, "Bio::Graphics::Browser2::MetaSegment" : { "file" : "lib/Bio/Graphics/Browser2/RegionSearch.pm" }, "Bio::Graphics::Browser2::MetaSegment::Iterator" : { "file" : "lib/Bio/Graphics/Browser2/RegionSearch.pm" }, "Bio::Graphics::Browser2::OptionPick" : { "file" : "lib/Bio/Graphics/Browser2/OptionPick.pm" }, "Bio::Graphics::Browser2::PadAlignment" : { "file" : "lib/Bio/Graphics/Browser2/PadAlignment.pm" }, "Bio::Graphics::Browser2::Plugin" : { "file" : "lib/Bio/Graphics/Browser2/Plugin.pm", "version" : "0.30" }, "Bio::Graphics::Browser2::Plugin::AuthPlugin" : { "file" : "lib/Bio/Graphics/Browser2/Plugin/AuthPlugin.pm" }, "Bio::Graphics::Browser2::PluginSet" : { "file" : "lib/Bio/Graphics/Browser2/PluginSet.pm" }, "Bio::Graphics::Browser2::Realign" : { "file" : "lib/Bio/Graphics/Browser2/Realign.pm" }, "Bio::Graphics::Browser2::Region" : { "file" : "lib/Bio/Graphics/Browser2/Region.pm" }, "Bio::Graphics::Browser2::RegionSearch" : { "file" : "lib/Bio/Graphics/Browser2/RegionSearch.pm" }, "Bio::Graphics::Browser2::RemoteSet" : { "file" : "lib/Bio/Graphics/Browser2/RemoteSet.pm" }, "Bio::Graphics::Browser2::Render" : { "file" : "lib/Bio/Graphics/Browser2/Render.pm" }, "Bio::Graphics::Browser2::Render::HTML" : { "file" : "lib/Bio/Graphics/Browser2/Render/HTML.pm" }, "Bio::Graphics::Browser2::Render::HTML::TrackListing" : { "file" : "lib/Bio/Graphics/Browser2/Render/HTML/TrackListing.pm" }, "Bio::Graphics::Browser2::Render::HTML::TrackListing::Categories" : { "file" : "lib/Bio/Graphics/Browser2/Render/HTML/TrackListing/Categories.pm" }, "Bio::Graphics::Browser2::Render::Login" : { "file" : "lib/Bio/Graphics/Browser2/Render/Login.pm" }, "Bio::Graphics::Browser2::Render::Slave" : { "file" : "lib/Bio/Graphics/Browser2/Render/Slave.pm" }, "Bio::Graphics::Browser2::Render::Slave::AWS_Balancer" : { "file" : "lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm" }, "Bio::Graphics::Browser2::Render::Slave::StagingServer" : { "file" : "lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm" }, "Bio::Graphics::Browser2::Render::Slave::Status" : { "file" : "lib/Bio/Graphics/Browser2/Render/Slave/Status.pm" }, "Bio::Graphics::Browser2::Render::SnapshotManager" : { "file" : "lib/Bio/Graphics/Browser2/Render/SnapshotManager.pm" }, "Bio::Graphics::Browser2::Render::TrackConfig" : { "file" : "lib/Bio/Graphics/Browser2/Render/TrackConfig.pm" }, "Bio::Graphics::Browser2::RenderPanels" : { "file" : "lib/Bio/Graphics/Browser2/RenderPanels.pm" }, "Bio::Graphics::Browser2::SendMail" : { "file" : "lib/Bio/Graphics/Browser2/SendMail.pm" }, "Bio::Graphics::Browser2::Session" : { "file" : "lib/Bio/Graphics/Browser2/Session.pm" }, "Bio::Graphics::Browser2::Shellwords" : { "file" : "lib/Bio/Graphics/Browser2/Shellwords.pm" }, "Bio::Graphics::Browser2::SubtrackTable" : { "file" : "lib/Bio/Graphics/Browser2/SubtrackTable.pm" }, "Bio::Graphics::Browser2::TrackDumper" : { "file" : "lib/Bio/Graphics/Browser2/TrackDumper.pm" }, "Bio::Graphics::Browser2::TrackDumper::RichSeqMaker" : { "file" : "lib/Bio/Graphics/Browser2/TrackDumper/RichSeqMaker.pm" }, "Bio::Graphics::Browser2::UserConf" : { "file" : "lib/Bio/Graphics/Browser2/UserTracks.pm" }, "Bio::Graphics::Browser2::UserDB" : { "file" : "lib/Bio/Graphics/Browser2/UserDB.pm", "version" : "0.5" }, "Bio::Graphics::Browser2::UserTracks" : { "file" : "lib/Bio/Graphics/Browser2/UserTracks.pm" }, "Bio::Graphics::Browser2::UserTracks::Database" : { "file" : "lib/Bio/Graphics/Browser2/UserTracks/Database.pm" }, "Bio::Graphics::Browser2::UserTracks::Filesystem" : { "file" : "lib/Bio/Graphics/Browser2/UserTracks/Filesystem.pm" }, "Bio::Graphics::Browser2::Util" : { "file" : "lib/Bio/Graphics/Browser2/Util.pm" }, "Bio::Graphics::GBrowseFeature" : { "file" : "lib/Bio/Graphics/GBrowseFeature.pm" }, "Bio::Graphics::Karyotype" : { "file" : "lib/Bio/Graphics/Karyotype.pm" }, "Bio::Graphics::Wiggle::Loader::Nosample" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/wiggle.pm" }, "CGI::Toggle" : { "file" : "lib/CGI/Toggle.pm" }, "FakeHomol" : { "file" : "lib/Bio/Graphics/Browser2/GFFhelper.pm" }, "LRUCache" : { "file" : "lib/Bio/Graphics/Browser2/DataBase.pm" }, "Legacy::DB::SyntenyBlock" : { "file" : "lib/Legacy/DB/SyntenyBlock.pm" }, "Legacy::DB::SyntenyIO" : { "file" : "lib/Legacy/DB/SyntenyIO.pm" }, "Legacy::Graphics::Browser" : { "file" : "lib/Legacy/Graphics/Browser.pm", "version" : "1.17" }, "Legacy::Graphics::Browser::I18n" : { "file" : "lib/Legacy/Graphics/Browser/I18n.pm", "version" : "1.01" }, "Legacy::Graphics::Browser::PageSettings" : { "file" : "lib/Legacy/Graphics/Browser/PageSettings.pm" }, "Legacy::Graphics::Browser::Synteny" : { "file" : "lib/Legacy/Graphics/Browser/Synteny.pm", "version" : "0.01" }, "Legacy::Graphics::Browser::Util" : { "file" : "lib/Legacy/Graphics/Browser/Util.pm" }, "Legacy::Graphics::BrowserConfig" : { "file" : "lib/Legacy/Graphics/Browser.pm" }, "MyFeatureFileLoader" : { "file" : "lib/Bio/Graphics/Browser2/DataLoader/featurefile.pm" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "2.56" } GBrowse-2.56/META.yml000444001750001750 2271413036764442 14442 0ustar00lsteinlstein000000000000--- abstract: 'The GMOD Generic Genome Browser' author: - 'Lincoln Stein ' build_requires: Capture::Tiny: '0' ExtUtils::CBuilder: '0' configure_requires: Module::Build: '0.42' dynamic_config: 1 generated_by: 'Module::Build version 0.4216, CPAN::Meta::Converter version 2.150001' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: GBrowse provides: Bio::DB::GFF::Aggregator::match_gap: file: lib/Bio/DB/GFF/Aggregator/match_gap.pm Bio::DB::GFF::Aggregator::reftranscript: file: lib/Bio/DB/GFF/Aggregator/reftranscript.pm version: '0.10' Bio::DB::GFF::Aggregator::waba_alignment: file: lib/Bio/DB/GFF/Aggregator/waba_alignment.pm version: '0.20' Bio::DB::GFF::Aggregator::wormbase_gene: file: lib/Bio/DB/GFF/Aggregator/wormbase_gene.pm version: '0.30' Bio::DB::SeqFeature::Store::Alias: file: lib/Bio/DB/SeqFeature/Store/Alias.pm Bio::DB::SeqFeature::Store::Alias::Iterator: file: lib/Bio/DB/SeqFeature/Store/Alias.pm Bio::DB::SeqFeature::Store::Alias::Segment: file: lib/Bio/DB/SeqFeature/Store/Alias.pm Bio::DB::SeqFeature::Store::BedLoader: file: lib/Bio/DB/SeqFeature/Store/BedLoader.pm Bio::DB::SeqFeature::Store::LoadHelper: file: lib/Bio/DB/SeqFeature/Store/LoadHelper.pm version: '1.10' Bio::DB::Tagger: file: lib/Bio/DB/Tagger.pm version: '1.00' Bio::DB::Tagger::Iterator: file: lib/Bio/DB/Tagger.pm Bio::DB::Tagger::Tag: file: lib/Bio/DB/Tagger/Tag.pm Bio::DB::Tagger::mysql: file: lib/Bio/DB/Tagger/mysql.pm Bio::Graphics::Browser2: file: lib/Bio/Graphics/Browser2.pm version: '2.56' Bio::Graphics::Browser2::Action: file: lib/Bio/Graphics/Browser2/Action.pm Bio::Graphics::Browser2::AdminTracks: file: lib/Bio/Graphics/Browser2/UserTracks.pm Bio::Graphics::Browser2::AuthorizedFeatureFile: file: lib/Bio/Graphics/Browser2/AuthorizedFeatureFile.pm Bio::Graphics::Browser2::CAlign: file: lib/Bio/Graphics/Browser2/CAlign.pm Bio::Graphics::Browser2::CachedTrack: file: lib/Bio/Graphics/Browser2/CachedTrack.pm Bio::Graphics::Browser2::DataBase: file: lib/Bio/Graphics/Browser2/DataBase.pm Bio::Graphics::Browser2::DataLoader: file: lib/Bio/Graphics/Browser2/DataLoader.pm Bio::Graphics::Browser2::DataLoader::archive: file: lib/Bio/Graphics/Browser2/DataLoader/archive.pm Bio::Graphics::Browser2::DataLoader::bam: file: lib/Bio/Graphics/Browser2/DataLoader/bam.pm Bio::Graphics::Browser2::DataLoader::bed: file: lib/Bio/Graphics/Browser2/DataLoader/bed.pm Bio::Graphics::Browser2::DataLoader::bigbed: file: lib/Bio/Graphics/Browser2/DataLoader/bigbed.pm Bio::Graphics::Browser2::DataLoader::bigwig: file: lib/Bio/Graphics/Browser2/DataLoader/bigwig.pm Bio::Graphics::Browser2::DataLoader::featurefile: file: lib/Bio/Graphics/Browser2/DataLoader/featurefile.pm Bio::Graphics::Browser2::DataLoader::generic: file: lib/Bio/Graphics/Browser2/DataLoader/generic.pm Bio::Graphics::Browser2::DataLoader::gff: file: lib/Bio/Graphics/Browser2/DataLoader/gff.pm Bio::Graphics::Browser2::DataLoader::gff3: file: lib/Bio/Graphics/Browser2/DataLoader/gff3.pm Bio::Graphics::Browser2::DataLoader::sam: file: lib/Bio/Graphics/Browser2/DataLoader/sam.pm Bio::Graphics::Browser2::DataLoader::useq: file: lib/Bio/Graphics/Browser2/DataLoader/useq.pm Bio::Graphics::Browser2::DataLoader::wig2bigwig: file: lib/Bio/Graphics/Browser2/DataLoader/wig2bigwig.pm Bio::Graphics::Browser2::DataLoader::wiggle: file: lib/Bio/Graphics/Browser2/DataLoader/wiggle.pm Bio::Graphics::Browser2::DataSource: file: lib/Bio/Graphics/Browser2/DataSource.pm Bio::Graphics::Browser2::ExternalData: file: lib/Bio/Graphics/Browser2/ExternalData.pm Bio::Graphics::Browser2::GFFhelper: file: lib/Bio/Graphics/Browser2/GFFhelper.pm Bio::Graphics::Browser2::I18n: file: lib/Bio/Graphics/Browser2/I18n.pm Bio::Graphics::Browser2::Markup: file: lib/Bio/Graphics/Browser2/Markup.pm Bio::Graphics::Browser2::MetaDB: file: lib/Bio/Graphics/Browser2/RegionSearch.pm Bio::Graphics::Browser2::MetaSegment: file: lib/Bio/Graphics/Browser2/RegionSearch.pm Bio::Graphics::Browser2::MetaSegment::Iterator: file: lib/Bio/Graphics/Browser2/RegionSearch.pm Bio::Graphics::Browser2::OptionPick: file: lib/Bio/Graphics/Browser2/OptionPick.pm Bio::Graphics::Browser2::PadAlignment: file: lib/Bio/Graphics/Browser2/PadAlignment.pm Bio::Graphics::Browser2::Plugin: file: lib/Bio/Graphics/Browser2/Plugin.pm version: '0.30' Bio::Graphics::Browser2::Plugin::AuthPlugin: file: lib/Bio/Graphics/Browser2/Plugin/AuthPlugin.pm Bio::Graphics::Browser2::PluginSet: file: lib/Bio/Graphics/Browser2/PluginSet.pm Bio::Graphics::Browser2::Realign: file: lib/Bio/Graphics/Browser2/Realign.pm Bio::Graphics::Browser2::Region: file: lib/Bio/Graphics/Browser2/Region.pm Bio::Graphics::Browser2::RegionSearch: file: lib/Bio/Graphics/Browser2/RegionSearch.pm Bio::Graphics::Browser2::RemoteSet: file: lib/Bio/Graphics/Browser2/RemoteSet.pm Bio::Graphics::Browser2::Render: file: lib/Bio/Graphics/Browser2/Render.pm Bio::Graphics::Browser2::Render::HTML: file: lib/Bio/Graphics/Browser2/Render/HTML.pm Bio::Graphics::Browser2::Render::HTML::TrackListing: file: lib/Bio/Graphics/Browser2/Render/HTML/TrackListing.pm Bio::Graphics::Browser2::Render::HTML::TrackListing::Categories: file: lib/Bio/Graphics/Browser2/Render/HTML/TrackListing/Categories.pm Bio::Graphics::Browser2::Render::Login: file: lib/Bio/Graphics/Browser2/Render/Login.pm Bio::Graphics::Browser2::Render::Slave: file: lib/Bio/Graphics/Browser2/Render/Slave.pm Bio::Graphics::Browser2::Render::Slave::AWS_Balancer: file: lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm Bio::Graphics::Browser2::Render::Slave::StagingServer: file: lib/Bio/Graphics/Browser2/Render/Slave/AWS_Balancer.pm Bio::Graphics::Browser2::Render::Slave::Status: file: lib/Bio/Graphics/Browser2/Render/Slave/Status.pm Bio::Graphics::Browser2::Render::SnapshotManager: file: lib/Bio/Graphics/Browser2/Render/SnapshotManager.pm Bio::Graphics::Browser2::Render::TrackConfig: file: lib/Bio/Graphics/Browser2/Render/TrackConfig.pm Bio::Graphics::Browser2::RenderPanels: file: lib/Bio/Graphics/Browser2/RenderPanels.pm Bio::Graphics::Browser2::SendMail: file: lib/Bio/Graphics/Browser2/SendMail.pm Bio::Graphics::Browser2::Session: file: lib/Bio/Graphics/Browser2/Session.pm Bio::Graphics::Browser2::Shellwords: file: lib/Bio/Graphics/Browser2/Shellwords.pm Bio::Graphics::Browser2::SubtrackTable: file: lib/Bio/Graphics/Browser2/SubtrackTable.pm Bio::Graphics::Browser2::TrackDumper: file: lib/Bio/Graphics/Browser2/TrackDumper.pm Bio::Graphics::Browser2::TrackDumper::RichSeqMaker: file: lib/Bio/Graphics/Browser2/TrackDumper/RichSeqMaker.pm Bio::Graphics::Browser2::UserConf: file: lib/Bio/Graphics/Browser2/UserTracks.pm Bio::Graphics::Browser2::UserDB: file: lib/Bio/Graphics/Browser2/UserDB.pm version: '0.5' Bio::Graphics::Browser2::UserTracks: file: lib/Bio/Graphics/Browser2/UserTracks.pm Bio::Graphics::Browser2::UserTracks::Database: file: lib/Bio/Graphics/Browser2/UserTracks/Database.pm Bio::Graphics::Browser2::UserTracks::Filesystem: file: lib/Bio/Graphics/Browser2/UserTracks/Filesystem.pm Bio::Graphics::Browser2::Util: file: lib/Bio/Graphics/Browser2/Util.pm Bio::Graphics::GBrowseFeature: file: lib/Bio/Graphics/GBrowseFeature.pm Bio::Graphics::Karyotype: file: lib/Bio/Graphics/Karyotype.pm Bio::Graphics::Wiggle::Loader::Nosample: file: lib/Bio/Graphics/Browser2/DataLoader/wiggle.pm CGI::Toggle: file: lib/CGI/Toggle.pm FakeHomol: file: lib/Bio/Graphics/Browser2/GFFhelper.pm LRUCache: file: lib/Bio/Graphics/Browser2/DataBase.pm Legacy::DB::SyntenyBlock: file: lib/Legacy/DB/SyntenyBlock.pm Legacy::DB::SyntenyIO: file: lib/Legacy/DB/SyntenyIO.pm Legacy::Graphics::Browser: file: lib/Legacy/Graphics/Browser.pm version: '1.17' Legacy::Graphics::Browser::I18n: file: lib/Legacy/Graphics/Browser/I18n.pm version: '1.01' Legacy::Graphics::Browser::PageSettings: file: lib/Legacy/Graphics/Browser/PageSettings.pm Legacy::Graphics::Browser::Synteny: file: lib/Legacy/Graphics/Browser/Synteny.pm version: '0.01' Legacy::Graphics::Browser::Util: file: lib/Legacy/Graphics/Browser/Util.pm Legacy::Graphics::BrowserConfig: file: lib/Legacy/Graphics/Browser.pm MyFeatureFileLoader: file: lib/Bio/Graphics/Browser2/DataLoader/featurefile.pm recommends: Bio::DB::BigFile: '1' Bio::DB::Sam: '1.36' Bio::Das: '0' Crypt::SSLeay: '0' DBD::Pg: '0' DBD::SQLite: '0' DBD::mysql: '0' DBI: '0' DB_File::Lock: '0' Digest::SHA: '0' FCGI: '0' File::NFSLock: '0' GD::SVG: '0' Math::BigInt: '0' Net::OpenID::Consumer: '0' Net::SMTP::SSL: '0' Parse::Apache::ServerStatus: '0' Template: '2.2' Term::ReadKey: '0' VM::EC2: '1.19' requires: Bio::Graphics: '2.34' Bio::Root::Version: '1.007001' CGI::Session: '4.02' Date::Parse: '0' Digest::MD5: '0' Digest::SHA: '0' ExtUtils::CBuilder: '0' File::Temp: '0' GD: '2.50' HTTP::Daemon: '0' IO::String: '0' JSON: '0' LWP: '0' Statistics::Descriptive: '0' Storable: '0' Term::ReadKey: '0' Text::ParseWords: '3.27' Time::HiRes: '0' parent: '0' perl: '5.008' resources: license: http://dev.perl.org/licenses/ version: '2.56' GBrowse-2.56/Makefile.PL000444001750001750 233313036764442 15116 0ustar00lsteinlstein000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.4216 require 5.008; unless (eval "use Module::Build::Compat 0.02; 1" ) { print "This module requires Module::Build to install itself.\n"; require ExtUtils::MakeMaker; my $yn = ExtUtils::MakeMaker::prompt (' Install Module::Build now from CPAN?', 'y'); unless ($yn =~ /^y/i) { die " *** Cannot install without Module::Build. Exiting ...\n"; } require Cwd; require File::Spec; require CPAN; # Save this 'cause CPAN will chdir all over the place. my $cwd = Cwd::cwd(); CPAN::Shell->install('Module::Build::Compat'); CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate or die "Couldn't install Module::Build, giving up.\n"; chdir $cwd or die "Cannot chdir() back to $cwd: $!"; } eval "use Module::Build::Compat 0.02; 1" or die $@; use lib 'install_util'; Module::Build::Compat->run_build_pl(args => \@ARGV); my $build_script = 'Build'; $build_script .= '.com' if $^O eq 'VMS'; exit(0) unless(-e $build_script); # cpantesters convention require GBrowseInstall; Module::Build::Compat->write_makefile(build_class => 'GBrowseInstall'); GBrowse-2.56/README000444001750001750 1361013036764442 14044 0ustar00lsteinlstein000000000000GBROWSE README The Generic Genome Browser (GBrowse) is a simple but highly configurable web-based genome browser. It is a component of the Generic Model Organism Systems Database project (GMOD). ******* DOWNLOADING ****** The 2.X versions are now considered stable. You may download it from CPAN at http://search.cpan.org/~lds/GBrowse/ or get the developer's version via SVN: Checkout read-only git clone git://github.com/GMOD/GBrowse.git The older 1.X version is still available for download here: http://sourceforge.net/projects/gmod/files/Generic%20Genome%20Browser/GBrowse-1.70/Generic-Genome-Browser-1.70.tar.gz/download or via SVN here: svn co https://gmod.svn.sourceforge.net/svnroot/gmod/Generic-Genome-Browser/branches/stable Generic-Genome-Browser ************************** SYNOPSIS: perl Build.PL ./Build distmeta ./Build test ./Build config ./Build demo (optional) ./Build install (will need to become superuser) ./Build apache_conf TO INSTALL: Detailed install and configure instructions are available at http://gmod.org/wiki/GBrowse_2.0_HOWTO and we suggest you follow that. What follows here is a brief synopsis. 1) You will need a bunch of Perl prerequisites: Module Version ---------------------+---------- perl 5.008 Bio::Perl 1.007001 CGI::Session 4.02 Bio::Graphics 2.09 GD 2.07 Digest::MD5 any File::Temp any IO::String any JSON any LWP any Storable any Statistics::Descriptive any The Build script will tell you if you are missing any prerequisites. All of these are available on CPAN (www.cpan.org), or by using the CPAN shell ("perl -MCPAN -e shell"). - If you wish to take advantage of user accounts (which lets users share tracks with each other), you must have: Module Version ---------------------+---------- DBI any Net::SMTP any -and either- DBD::mysql any -or- DBD::SQLite any - You should install BioPerl from CPAN (currently version 1.7.1) or, to take advantage of additional features and performance boosts, get a snapshot of the current developer version: http://github.com/bioperl/bioperl-live/tarball/master 2) Run the command: perl Build.PL This will create a script named "Build" in the current directory. If you have downloaded and unpacked, but not installed Bioperl, then you should specify its location using the -I option: perl -I /home/fred/build/bioperl-live Build.PL To install in a custom location, pass the --install_base (preferred) or --prefix argument (deprecated): perl Build.PL --install_base=/home/fred/gbrowse perl Build.PL --prefix=/home/fred/gbrowse 3) Run the command: ./Build test This will run a series of tests on the distribution. If one or more tests fail please inform the author. 4) Run the command: ./Build config This will ask you a series of questions about where Apache and its support files are located, and will allow you to choose where to install GBrowse's configuration files. If you change your mind and want to reconfigure GBrowse, simply run "./Build reconfig". 5) Run the command: ./Build demo This will launch configure an instance of Apache to run on a local port and give you the URL for a GBrowse demo database. This allows you to try out the system before you install it. 6) Run the command: ./Build install You will probably need to be the superuser to do this. If you have "sudo" installed the invocation will be: % sudo ./Build install [sudo] password for jdoe: ***** Otherwise % su Password: ***** # ./Build install 7) Run the command: ./Build apache_config This will print out a fragment of an Apache configuration file that contains all the information needed to run GBrowse. Cut and paste this into your system's Apache configuration file and restart the server. Usually you will find GBrowse running at http://localhost/gbrowse2. Support is available from the discussion groups and mailing lists at www.gmod.org. Lincoln Stein & the GMOD team lincoln.stein@gmail.com July 2010 --- COPYRIGHT AND LICENSING --- Copyright (c) 2002 Cold Spring Harbor Laboratory and University of California, Berkeley Copyright (c) 2010 Ontario Institute for Cancer Research This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. --- AUTHORS --- This project has had many authors. Some of the most prominent are: Scott Cain Ben Faga Vsevolod (Simon) Ilyushchenko Marc Logghe Aaron Mackey Sheldon McKay Nathan O. Siemers Ian Davies Lincoln Stein Peter Ruzanov Chris Vandevelde Tony deCatanzaro Sukhwinder Lall Ahmed Einalem Special thanks go to the authors of the translations, who include: Franck Aniere (French) Nansheng Chen (Chinese) Toshiaki Katayama (Japanese) Marc Logghe (Dutch) Marco Mangone (Italian) Linus Taejoon Kwon bawi org> (Korean) Marcela Tello-Ruiz (Spanish) Gudmundur Thorisson (Icelandic) GBrowse-2.56/README.IF.GBROWSE.ISNT.WORKING000444001750001750 124613036764442 17325 0ustar00lsteinlstein000000000000==NOTE THIS FILE OUT OF DATE== This file appears out of data since the code is now in Github. ==Old Message == If you got an svn checkout of GBrowse and it isn't working, it is probably because you checked out from the svn HEAD, which is the main development branch. Unfortunately, that branch is often unstable due to some major reworking which will make GBrowse much better. In the mean time (that is, until this README disappears), please check out from the stable branch. You can use almost the same svn command: svn co https://gmod.svn.sourceforge.net/svnroot/gmod/Generic-Genome-Browser/branches/stable Generic-Genome-Browser Thanks, Scott Cain cain@cshl.edu GBrowse-2.56/README.fedora_and_selinux000444001750001750 266213036764442 17661 0ustar00lsteinlstein000000000000If you have SELinux installed, typically as part of Fedora Core 3 or higher, then you may experience difficulties getting GBrowse to work. The default security parameters for SELinux prevent GBrowse from performing some fundamental tasks, including reading its configuration file in $CONF/GBrowse.conf (where $CONF is typically /etc/httpd/conf or /usr/local/apache/conf). The symptom of the problem is that you will see "Permission denied" errors in your server error log. To fix the problem: 1. Make sure your security policy is up to date: % yum update selinux-policy-targeted 2. Open System Settings->Security Level and click on the SELinux tab. Click on the HTTPD Service triangle to get the httpd settings, and select "Disable SELinux protection for httpd daemon". 2a. Alternatively, uncheck "Enforcing" to set the enforcement level to permissive. 2b. If you don't have X11, you can do the same as step 2 via the command line: % setsebool -P httpd_disable_trans 1 % system httpd restart 3. Make sure that all directories in the path to the gbrowse config directory are set to be world readable and executable. Either run: % chmod +rx -R /etc/httpd/conf or % chmod +rx -R /usr/local/apache/conf 4. After you do this, add the --SELINUX=1 tag when exectuting perl Makefile.PL: % perl Makefile.PL --SELINUX=1 Please let me know if you have any difficulties with this procedure. Scott Cain cain@cshl.org 2/16/05 GBrowse-2.56/README.gff3000444001750001750 1071713036764442 14675 0ustar00lsteinlstein000000000000GFF3 is the successor to the GFF2 feature file format. Its main advantage is that it uses the Sequence Ontology to describe features on the genome in a standard and predictable way. For details, see http://song.sourceforge.net/ and http://song.sourceforge.net/gff3.shtml The GBrowse Bio::DB::GFF adaptor was developed for GFF2 and its support for GFF3 is poor. The main issue is that Bio::DB::GFF is only able to support features that have two levels, for example an mRNA transcript and its exons, while GFF3 allows features to contain unlimited levels of features and subfeatures. This feature is most commonly used to describe genes: gene A mRNA A.1 CDS A.1.1 CDS A.1.2 CDS A.1.3 mRNA A.2 CDS A.2.1 CDS A.2.2 CDS A.2.3 This data model is encouraged by GFF3 and is used by FlyBase; unfortunately Bio::DB::GFF cannot store such gene features without hacking the FlyBase GFF3 files. The most recent (1.6.x) series of Bioperl releases have support for the GFF3 format via the Bio::DB::SeqFeature::Store. Here are instructions for bringing up the Fly GFF3 annotations. 1) Get the most recent version of Bioperl from CPAN: cpan Bio::DB::SeqFeature::Store or sudo cpan Bio::DB::SeqFeature::Store 2) perl Makefile.PL, make and make install in the bioperl-live directory. 3) Download the GFF3 files and FASTA files to load and put them in a directory somewhere. 4) Create a mysql database to hold the data, and set up the appropriate privileges: mysqladmin -uroot -p create database flygff3 mysql -uroot -p -e 'grant all privileges on flygff3.* to @localhost' mysql -uroot -p -e 'grant select on flygff3.* to nobody@localhost' 5) Use the bp_seqfeature_load.pl script to load the GFF3 and FASTA data: cd bp_seqfeature_load.pl -d flygff3 -c -f *.gff.gz *.fasta The -d option gives the name of the database to load ("flygff3"). The -c flag tells the script to initialize the database. The -f flag tells the script to use "fast" loading. You may see a small number of warnings about features with the same IDs not occurring in contiguous order. You can safely ignore these warnings. 6) Copy the 09.fly.gff3.conf config file into your gbrowse.conf directory. This file can be found in the Generic-Genome-Browser distribution directory under contrib/conf_files/. The distributed conf file expects the database to be named "flygff3" and to require no password to be readable by the "nobody" user. Please modify it if necessary. For example, to add a username and password: db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor DBI::mysql -dsn dbi:mysql:database=flygff3 -user fred -pass secretpassword You should be able to browse the database now! 7) To use the IN-MEMORY GFF3 database adaptor (very preliminary!) do the following: mkdir /var/www/htdocs/gbrowse/databases/volvox_gff3 cp docs/tutorial/data_files/volvox.gff3 /var/www/htdocs/gbrowse/databases/volvox_gff3 and edit the volvox.gff3.conf file to read: db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn /var/www/htdocs/gbrowse/databaess/volvox_gffe Be sure to change the database path to be appropriate for the location of the gbrowse document directory on your system. If you use the memory adaptor for large sequences, you will see better performance if you separate out the DNA part of the GFF3 file from the annotation part (the volvox.gff3 file has both annotations and DNA). Put the DNA into one or more .fasta files in the same directory as the .gff3 file(s). This is the same as the traditional way of creating a GFF2 in-memory database. 8) For more information: The 09.fly.gff3.conf file contains brief comments describing the changes needed to make GBrowse work well with Bio::DB::SeqFeature::Store, the most important of which is the lack of aggregators in the latter. A version of the tutorial files adapted for GFF3 use can be found in docs/tutorial/data_files/volvox.gff3 and docs/tutorial/conf_files/volvox.gff3.conf. To load the data, simply: bp_seqfeature_load.pl -d volvoxgff3 -c -f docs/tutorial/data_files/volvox.gff3 and install the volvox.gff3.conf file. This file is heavily annotated with instructions on how to use the GFF3 database with GBrowse. Please report all problems to gmod-gbrowse@lists.sourceforge.net. Good luck! Lincoln Stein 19 June 2006 GBrowse-2.56/bin000755001750001750 013036764442 13556 5ustar00lsteinlstein000000000000GBrowse-2.56/bin/auto_install_databases.pl000555001750001750 1734113036764442 21006 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w =head1 NAME auto_install_databases.pl - Download and install GFF data sets =head1 SYNOPSYS % auto_install_databases.pl --rdms pg --user scott =head1 DESCRIPTION This program queries a web server to determine what data sets are available and presents the user with a list to choose from, with the option of getting several data sets at once. The chosen data sets are downloaded and they are used as inputs for the bulk loader of the specified relational database management system (either MySQL or PostgreSQL) to initialize and load the GFF and optionally fasta data. =head2 NOTES This program uses the bulk loader for its database (bp_bulk_load_gff.pl for mysql, bp_pg_bulk_load_gff.pl for postgres); read the documentation for those programs for caveats with their use. Like the bulk loaders, this program uses \$TMPDIR to transiently store downloaded data, therefore, \$TMPDIR must have enough free space to store all of the raw data and the processed files for importation to the database. To create your own web server data source, carefully copy the syntax and file structure of the default data source, as this program is very inflexible with regard to the obtaining information from the web server. Since the data is being downloaded uncompressed from web server, it may take a very long time for the download and database load to complete. An hour or more is not out of the question for a large data set like wormbase. =head1 COMMAND-LINE OPTIONS Options can be abbreviated. For example, you can use -s for --server. --server URL of web server to obtain datasets Default = 'http://brie4.cshl.org:8000/' --rdms RDMS to use (mysql or pg (Postgres)) Default = 'mysql' --user Username to log into database server as Default = '' --password Password associated with username Default = '' =head1 SEE ALSO L, L, L =head1 AUTHOR Scott Cain, cain@cshl.org Copyright (c) 2003 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use LWP::UserAgent; use Getopt::Long; my $bWINDOWS = ($^O =~ /MSWin32/i) ? 1 : 0; my ($USER,$PASS,$RDMS,$SERVER); GetOptions ('server:s' => \$SERVER, 'rdms:s' => \$RDMS, 'user:s' => \$USER, 'password:s' => \$PASS) or die <new; my $req = HTTP::Request->new(GET => $SERVER); my $res = $ua->request($req); die "Failed to connect to gbrowse data source server $SERVER\n" unless ($res->is_success); my $result = $res->content; my @result = split /\n/, $result; my %available_data; # note that since I control both the page being retrieved and # this script, I can parse the html "by hand". Were that not # the case, I would certainly use HTML::Parser (or something # like that). foreach (@result) { if (/
  • .*href=\"(.*)\">(.*)<.*<\/li>/) { $available_data{$2} = $1; } } my $i = 0; my @keys; $keys[0] = ''; foreach my $key (reverse sort keys %available_data) { $i++; push @keys, $key; print "[$i] $key\n"; } print "Choose data sets to install (comma delimited list) [0]:"; my $answer; chomp($answer = ); die "OK, won't install anything\n" unless $answer; my @data_sets = split /\,\s*/, $answer; print "\nInstall these datasets?\n"; foreach my $set (@data_sets) { print "$keys[$set]\n"; } print "answer yes to confirm, no to quit [y]?"; chomp($answer = ); die "ok, nothing will be installed\n" if ($answer =~ /^n/i); #do arg building and error checking here my @args; push @args, $bulkloader; push @args, '--create'; if (defined $USER) { push @args, "--user"; push @args, $USER; if (defined $PASS) { push @args, "--password"; push @args, $PASS; } } #figure out which data sets, and if they include fastas #don't allow loading fasta without gff #this loop is really taking advantage of my control of the download site #it assumes that for every gff file there is a fasta, and than they are named #with the same prefix (eg, yeast_), and that the gff file comes second #alphabetically (ie, first when reverse sorted). warn "retrieving data (this could take a while) ...\n"; for ($i=0;$i < scalar @data_sets;$i++) { my $set = $data_sets[$i]; if ($set % 2 == 0) { warn "Importing of fasta without gff is not permitted from this interface\n"; unlink "$tmpdir/$keys[$set].$$"; next; } if (defined $data_sets[$i+1] && $set + 1 == $data_sets[$i+1]) { # fasta is to be imported too my $gff = "$tmpdir/$keys[$set].$$"; my $fasta = "$tmpdir/$keys[$set+1].$$"; download_data($keys[$set]); download_data($keys[$set+1]); $keys[$set] =~ /^(.+)_/; my $db = $1; push @args, "--fasta"; push @args, $fasta; push @args, "--database"; push @args, $db; push @args, $gff; warn "executing @args\n"; system (@args); unlink $gff; unlink $fasta; $i++; } else { # don't import fasta my $gff = "$tmpdir/$keys[$set].$$"; download_data($keys[$set]); $keys[$set] =~ /^(.+)_/; my $db = $1; push @args, "--database"; push @args, $db; push @args, $gff; warn "executing @args\n"; system (@args); unlink $gff; } } sub download_data { my $set = shift; warn "getting $set ...\n"; $req = HTTP::Request->new(GET => $available_data{$set}); $res = $ua->request($req,"$tmpdir/$set.$$" ); } __END__ GBrowse-2.56/bin/bed2gff3.pl000555001750001750 2001413036764442 15652 0ustar00lsteinlstein000000000000#!/usr/bin/perl # convert UCSC gene files into GFF3 data use strict; use File::Basename 'basename'; use Getopt::Long; my $executable = basename($0); my ($SRC,$ORIGIN); GetOptions('src:s' => \$SRC, 'origin:i' => \$ORIGIN, ) or die < Choose a source for the gene, default "UCSC" -origin Choose a relative position to number from, default is "1" The resulting file is in GFF3 format and should be loaded into a Bio::DB::GFF database using the following command: bp_bulk_load_gff.pl -c -d db1 --maxfeature 1000000000 --gff3_munge file.gff USAGE $SRC ||= 'UCSC'; $ORIGIN ||= 1; print "##gff-version 3\n"; # automatically uncompress varous compression formats foreach (@ARGV) { $_ = "gunzip -c $_ |" if /\.gz$/; $_ = "uncompress -c $_ |" if /\.Z$/; $_ = "bunzip2 -c $_ |" if /\.bz2$/; } while (<>) { chomp; next if /^\#/;; next if /random/; ## added line my ($chrom,$txStart,$txEnd,$id,$score,$strand,$cdsStart,$cdsEnd, $itemRGB,$exonCount,$exonSizes,$exonStarts) = split /\t/; my ($utr5_start,$utr5_end,$utr3_start,$utr3_end); # adjust for Jim's 0-based coordinates $txStart++; $cdsStart++; $txStart -= $ORIGIN; $txEnd -= $ORIGIN; $cdsStart -= $ORIGIN; $cdsEnd -= $ORIGIN; # print the transcript print join("\t",$chrom,$SRC,'mRNA',$txStart,$txEnd,'.',$strand,'.',"ID=$id;Name=$id"),"\n"; # now handle the CDS entries -- the tricky part is the need to keep # track of phase my $phase = 0; my @exon_starts = map {$_-$ORIGIN+$txStart} split ',',$exonStarts; my @exon_sizes = map {$_-$ORIGIN} split ',',$exonSizes; my @exon_ends = map {$exon_starts[$_]+$exon_sizes[$_]+1} (0..@exon_sizes); if ($strand eq '+') { for (my $i=0;$i<@exon_starts;$i++) { # for each exon start my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_start < $cdsStart) { # in a 5' UTR push (@utr_start, $exon_start); } elsif ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } elsif ($exon_end > $cdsEnd) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 5' end $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 3' end $utr_start[0]= $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if (defined $utr_start[0] == defined $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] < $cdsStart) { print join ("\t",$chrom,$SRC,"five_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } # end of if } # end of foreach if (defined $cds_start && $cds_start <= $cds_end) { print join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$id"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { print join ("\t",$chrom,$SRC,"three_prime_UTR",,$utr_start[$i], $utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } } # end of for each exon } # matches if strand = + if ($strand eq '-') { my @lines; for (my $i=@exon_starts-1; $i>=0; $i--) { # count backwards my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_end > $cdsEnd) { # in a 5' UTR push (@utr_end, $exon_end); } elsif ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } elsif ($exon_start < $cdsStart) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 3' end $utr_end[0] = $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 5' end $utr_start[0] = $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if (defined $utr_start[0] == defined $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { unshift @lines,join ("\t",$chrom,$SRC,"five_prime_UTR",,$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } # end of for if (defined $cds_start && $cds_start <= $cds_end) { unshift @lines,join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$id"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_end[$i] < $cdsStart) { unshift @lines,join ("\t",$chrom,$SRC,"three_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } # end for } print @lines; } } # end while <> __END__ =head1 NAME ucsc_genes2gff.pl - Convert UCSC Genome Browser-format gene files into GFF files suitable for loading into gbrowse =head1 SYNOPSIS % uscsc_genes2gff.pl [options] ucsc_file1 ucsc_file2... Options: -src Choose a source for the gene, default "UCSC" -origin Choose a relative position to number from, default is "1" =head1 DESCRIPTION This script massages the gene files available from the "tables" link of the UCSC genome browser (genome.ucsc.edu) into a form suitable for loading of gbrowse. Warning: it only works with the gene tables. Other tables, such as EST alignments, contours and repeats, have their own formats which will require other scripts to parse. To use this script, get one or more UCSC tables, either from the "Tables" link on the browser, or from the UCSC Genome Browser FTP site. Give the table file as the argument to this script. You may want to provide an alternative "source" field. Otherwise this script defaults to "UCSC". % pucsc_genes2gff.pl -src RefSeq refseq_data.ucsc > refseq.gff The resulting GFF file can then be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d refseq.gff =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2003 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut GBrowse-2.56/bin/bp_load_gff.pl000555001750001750 1251513036764442 16521 0ustar00lsteinlstein000000000000#!/usr/bin/perl # $Id: bp_load_gff.pl,v 1.1 2008-10-16 17:01:27 lstein Exp $ use strict; use Bio::DB::GFF; use Getopt::Long; =head1 NAME bp_load_gff.pl - Load a Bio::DB::GFF database from GFF files. =head1 SYNOPSIS % bp_load_gff.pl -d testdb dna1.fa dna2.fa features1.gff features2.gff ... =head1 DESCRIPTION This script loads a Bio::DB::GFF database with the features contained in a list of GFF files and/or FASTA sequence files. You must use the exact variant of GFF described in L. Various command-line options allow you to control which database to load and whether to allow an existing database to be overwritten. This script uses the Bio::DB::GFF interface, and so works with all database adaptors currently supported by that module (MySQL, Oracle, PostgreSQL soon). However, it is slow. For faster loading, see the MySQL-specific L and L scripts. =head2 NOTES If the filename is given as "-" then the input is taken from standard input. Compressed files (.gz, .Z, .bz2) are automatically uncompressed. FASTA format files are distinguished from GFF files by their filename extensions. Files ending in .fa, .fasta, .fast, .seq, .dna and their uppercase variants are treated as FASTA files. Everything else is treated as a GFF file. If you wish to load -fasta files from STDIN, then use the -f command-line swith with an argument of '-', as in gunzip my_data.fa.gz | bp_fast_load_gff.pl -d test -f - On the first load of a database, you will see a number of "unknown table" errors. This is normal. About maxfeature: the default value is 100,000,000 bases. If you have features that are close to or greater that 100Mb in length, then the value of maxbin should be increased to 1,000,000,000. =head1 COMMAND-LINE OPTIONS Command-line options can be abbreviated to single-letter options. e.g. -d instead of --database. --dsn Data source (default dbi:mysql:test) --adaptor Schema adaptor (default dbi::mysqlopt) --user Username for mysql authentication --pass Password for mysql authentication --fasta Fasta file or directory containing fasta files for the DNA --create Force creation and initialization of database --maxfeature Set the value of the maximum feature size (default 100 Mb) --group A list of one or more tag names (comma or space separated) to be used for grouping in the 9th column. --upgrade Upgrade existing database to current schema --gff3_munge Activate GFF3 name munging (see Bio::DB::GFF) --quiet No progress reports =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein, lstein@cshl.org Copyright (c) 2002 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut my ($DSN,$ADAPTOR,$CREATE,$USER,$PASSWORD,$FASTA,$UPGRADE,$MAX_BIN,$GROUP_TAG,$MUNGE,$QUIET); GetOptions ('dsn:s' => \$DSN, 'adaptor:s' => \$ADAPTOR, 'user:s' => \$USER, 'password:s' => \$PASSWORD, 'fasta:s' => \$FASTA, 'upgrade' => \$UPGRADE, 'maxbin|maxfeature:s' => \$MAX_BIN, 'group:s' => \$GROUP_TAG, 'gff3_munge' => \$MUNGE, 'quiet' => \$QUIET, create => \$CREATE) or (system('pod2text',$0), exit -1); # some local defaults $DSN ||= 'dbi:mysql:test'; $ADAPTOR ||= 'dbi::mysqlopt'; my @args; push @args,(-user=>$USER) if defined $USER; push @args,(-pass=>$PASSWORD) if defined $PASSWORD; push @args,(-preferred_groups=>[split(/[,\s+]+/,$GROUP_TAG)]) if defined $GROUP_TAG; push @args,(-create=>1) if $CREATE; push @args,(-write=>1); my $db = Bio::DB::GFF->new(-adaptor=>$ADAPTOR,-dsn => $DSN,@args) or die "Can't open database: ",Bio::DB::GFF->error,"\n"; $db->gff3_name_munging(1) if $MUNGE; if ($CREATE) { $MAX_BIN ? $db->initialize(-erase=>1,-MAX_BIN=>$MAX_BIN) : $db->initialize(1); } elsif ($UPGRADE) { warn qq(expect to see several "table already exists" messages\n); $db->initialize(0); my $dbi = $db->dbh; # get the raw database handle my ($count) = $dbi->selectrow_array('SELECT COUNT(*) FROM fnote'); if (defined($count) && $count > 0) { warn qq(fnote table detected. Translating into fattribute table. This may take a while.\n); $dbi->do("INSERT INTO fattribute VALUES (1,'Note')") or die "failed: ",$dbi->errstr; $dbi->do("INSERT INTO fattribute_to_feature (fid,fattribute_id,fattribute_value) SELECT fnote.fid,1,fnote FROM fnote") or die "failed: ",$dbi->errstr; warn qq(Schema successfully upgraded. You might want to drop the fnote table when you're sure everything's working.\n); } } my (@gff,@fasta); foreach (@ARGV) { if (/\.(fa|fasta|dna|seq|fast)$/i) { push @fasta,$_; } else { push @gff,$_; } } for my $file (@gff) { warn "$file: loading...\n"; my $loaded = $db->load_gff($file,!$QUIET); warn "$file: $loaded records loaded\n"; } unshift @fasta,$FASTA if defined $FASTA; for my $file (@fasta) { warn "Loading fasta ",(-d $file?"directory":"file"), " $file\n"; my $loaded = $db->load_fasta($file,!$QUIET); warn "$file: $loaded records loaded\n"; } GBrowse-2.56/bin/gbrowse_aws_balancer.pl000555001750001750 5033513036764442 20452 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME gbrowse_aws_balancer.pl Load balance GBrowse using Amazon Web Service instances =head1 SYNOPSIS Launch the balancer in the foreground % gbrowse_aws_balancer.pl --conf /etc/gbrowse2/aws_balancer.conf \ --access_key XYZZY \ --secret_key Plugh Launch the balancer in the background as a daemon: % gbrowse_aws_balancer.pl --background \ --conf /etc/gbrowse2/aws_balancer.conf \ --access_key XYZZY \ --secret_key Plugh \ --logfile /var/log/gbrowse/aws_balancer.log \ --pidfile /var/run/aws_balancer.pid \ --user nobody Kill a running balancer daemon: % gbrowse_aws_balancer.pl --kill \ --conf /etc/gbrowse2/aws_balancer.conf \ --access_key XYZZY \ --secret_key Plugh \ --logfile /var/log/gbrowse/aws_balancer.log \ --pidfile /var/run/aws_balancer.pid \ --user nobody Use the init script: % sudo /etc/init.d/gbrowse-aws-balancer start % sudo /etc/init.d/gbrowse-aws-balancer restart % sudo /etc/init.d/gbrowse-aws-balancer stop % sudo /etc/init.d/gbrowse-aws-balancer status Synchronize the master with the slave image: % sudo gbrowse_sync_aws_slave.pl -c /etc/gbrowse2/aws_balancer.conf syncing data....done data stored in snapshot(s) snap-12345 updated conf file, previous version in /etc/gbrowse2/aws_balancer.conf.bak =head1 DESCRIPTION This script launches a process that monitors the load on the local GBrowse instance. If the load exceeds certain predefined levels, then it uses Amazon web services to launch one or more GBrowse slave instances. The work of rendering tracks is then handed off to these instances, reducing the load on the local instance. Slave instances are implemented using Amazon's spot instance mechanism, which allows you to run EC2 instances at a fraction of the price of a standard on-demand instance. Load balancing is most convenient to run in conjunction with a GBrowse instance running within the Amazon Web Service EC2 cloud, but it can also be used to supplement an instance running on local hardware. The sections below describe the configuration needed for these two scenarios. Note that this script requires you to have an Amazon Web Services account, and for the VM::EC2 Perl module to be installed on the machine that is running this script. =head1 COMMAND-LINE OPTIONS Options can be abbreviated. For example, you can use -a for --access_key: --access_key EC2 access key --secret_key EC2 secret key --conf Path to balancer configuration file --pidfile Path to file that holds daemon process ID --logfile Path to file that records log messages --user User to run daemon under (script must be started as root) --verbosity Logging verbosity. 0=least, 3=most. --background Go into the background and run as daemon. --kill Kill a previously-launched daemon. Must provide the same --pidfile argument as used when the daemon was started. --ssh_key Enable ssh login on the slave(s) using the specified AWS ssh keypair. Login will only be available from the host this script is run on. =head1 PREREQUISITES 1. You must have the Perl modules VM::EC2 (v1.21 or later), and Parse::Apache::ServerStatus installed on the machine you intend to run the balancer on. The balancer must run on the same machine that GBrowse is running on. To install these modules, run: perl -MCPAN -e 'install VM::EC2; install Parse::Apache::ServerStatus' 2. You must have an account on Amazon Web Services and must be familiar with using the AWS Console to launch and terminate EC2 instances. If you run GBrowse on local hardware, then you will need to provide the script with your access key and secret access key when launching it. It may be safer to create and use an IAM user (Identity and Access Management) who has more limited privileges. See L below for some suggestions. 3. GBrowse must be running under Apache. 4. Apache must be configured to enable the mod_status module and to allow password-less requests to this module from localhost (http://httpd.apache.org/docs/2.2/mod/mod_status.html). This is the recommended configuration: ExtendedStatus on SetHandler server-status Order deny,allow Deny from all Allow from 127.0.0.1 ::1 5. If you are running GBrowse on local hardware, the local hardware must be connected to the Internet or have a Virtual Private Cloud (VPC) connection to Amazon. =head1 THE CONFIGURATION FILE The balancer requires a configuration file, ordinarily named aws_balancer.conf and located in the GBrowse configuration directory (e.g. /etc/gbrowse2). The configuration file has three sections: =head2 [LOAD TABLE] This section describes the number of slave instances to launch for different load levels. It consists of a three-column space-delimited table with the following columns: For example, the first few rows of the default table reads: 0.1 0 1 0.5 0 2 1.0 1 3 2.0 2 4 This is read as meaning that when the number of requests per second on the GBrowse server is greater than 0.1 but less than 0.5, run at least 0 slave servers but no more than 1 slave server. When the number of requests is between 0.5 and 1.0, run between 0 and 2 slave instances. When the rate is between 1.0 and 2.0, run at least 1 slave instance, but no more than 3. Load levels below the lowest value on the table (0.1 in this case) will run no slave servers, while levels above the highest value on the table (2.0) will launch the minimum and maximum number of slaves for that load value (between 2 and 4 in this case). The reason for having a range of instance counts for each load range is to avoid unecessarily launching and killing slaves repeatedly when the load fluctuates around the boundary. You may wish to tune the values in this table to maximize the performance of your GBrowse installation. Note that the server load includes both GBrowse requests and all other requests on the web server. If this is a problem, you may wish to run GBrowse on a separate Apache port or virtual host. =head2 [MASTER] The options in this sections configure the master GBrowse instance. Three options are recognized: =over 4 =item external_ip (optional) This controls the externally-visible IP address of the GBrowse master, which is needed by the firewall rule for master/slave communications. This option can usually be left blank: when the master is running on EC2, then the IP address is known; when the master is running on a local machine, the externally-visible IP address is looked up using a web service. It is only in the rare case that this lookup is incorrect that you will need to configure this option yourself. The external IP that the balancer script finds can be seen in a log message when verbosity is 2 or higher. =item poll_interval (required) This is the interval, in minutes, that the balancer script will periodically check the Apache load and adjust the number of slave instances. The suggested value is 0.5 (30s intervals). =item server_status_url (required) This is the URL to call to fetch the server load from Apache's server_status module. =back =head2 [SLAVE] The options in this section apply to the render slaves launched by the balancer. =over 4 =item instance_type (required) This is the EC2 instance type. Faster instances give better performance. High-IO instances give the best performance, but cost more. =item spot_bid (required) This is the maximum, in US dollars, that you are willing to pay per hour to run a slave spot instance. Typically you will pay less than the bid price. If the spot price increases beyond the maximum bid, then the spot instances will be terminated and the balancer will wait until the spot price decreases below the maximum bid before launching additional slaves. =item ports (required) This is a space-delimited list of TCP port numbers on which the render slaves should listen for incoming render requests from the master. Generally it is only necessary to listen on a single port; multiple ports were supported for performance reasons in earlier single-threaded versions of the slave. =item region (required for local masters) The Amazon region in which to launch slaves. When the master is running in EC2, this is automatically chosen to be the same as the master's region and can be left blank. =item image_id (required for local masters) This is the ID of the AMI that will be used to launch slaves. The correct value will be filled in when you run the gbrowse_sync_aws_slave.pl. You can leave this value blank if the GBrowse master is being run within an EC2 instance, in which case the slave will be launched using the same AMI that was used to launch the master. =item data_snapshots (required for local masters) Before launching the slave, attach EBS volumes created from one or more volume snapshots listed in this option. Multiple snapshots can be attached by providing a space-delimited list: data_snapshots = snap-12345 snap-abcdef The gbrowse_sync_aws_slave.pl script will automatically maintain this option for you. =item availability_zone (optional) This option will force the slave into the named availability zone. If not specified, an availability zone in the current region will be chosen at random. =item subnet (optional) If you are in a VPC environment, then this option will force the slave into the named subnet. Ordinarily the balancer script will launch slaves into non-VPC instances if the master is running on local hardware or a non-VPC EC2 instance. The balancer will launch slaves into the same VPC subnet as the master if the master is running on a VPC instance. =item security_group (optional) This specifies the security group to assign the slaves to. If not specified, a properly-configured security group will be created as needed and destroyed when the balancer script exits. If you choose to manage the security group manually, be sure to configure the firewall ingress rule to allow access to the slave port(s) (see the "ports" option) from the master's group or IP address. =back =head1 CONFIGURING AWS CREDENTIALS To work, the balancer script must be able to make spot instance requests and to monitor and terminate instances. To perform these operations the script must have access to the appropriate AWS credentials (access key and secret key) on the command line or as environment variables. While the script does its best to shield the credentials from prying eyes, there is still a chance that the credentials can be intercepted by another party with login access to the machine that the master runs on and use the credentials to run up your AWS bill. For this reason some people will prefer to create an EC2 account or role with limited access to AWS resources. =over 4 =item 1. Your personal EC2 credentials You may provide the balancer script with --access_key and --secret_key command line arguments using your personal EC2 credentials or set the environment variables EC2_ACCESS_KEY and EC2_SECRET_KEY. If not provided, the script will interactively prompt for one or both of these values. This is the simplest method, but has the risk that if the credentials are intercepted by a malicious third party, he or she gains access to all your EC2 resources. =item 2. The credentials of a restricted IAM account You may use the Amazon AWS console to create an IAM (Identity Access and Management) user with restricted permissions, and provide that user's credentials to the script on the command line or with environment variables. The following IAM permission policy is the minimum needed for the balancer script to work properly: { "Statement": [ { "Sid": "BalancerPolicy", "Action": [ "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateSecurityGroup", "ec2:DeleteSecurityGroup", "ec2:DescribeAvailabilityZones", "ec2:DescribeImageAttribute", "ec2:DescribeImages", "ec2:DescribeInstances", "ec2:DescribeInstanceAttribute", "ec2:DescribeInstanceStatus", "ec2:DescribeSecurityGroups", "ec2:DescribeVolumes", "ec2:DescribeSnapshots", "ec2:DescribeSpotInstanceRequests", "ec2:RequestSpotInstances", "ec2:CreateKeyPair", "ec2:DescribeKeyPairs", "ec2:DeleteKeyPair", "ec2:RunInstances", "ec2:TerminateInstances", "ec2:CreateSnapshot", "ec2:CreateVolume", "ec2:CreateTags", "ec2:DeleteTags" ], "Effect": "Allow", "Resource": [ "*" ] } ] } Note that even with these restrictions, an unauthorized user with access to the credentials could still launch a large number of spot instances or terminate bona fide instances. This is just a fundamental limitation of the granularity of EC2's permissions system. =item 3. Create an IAM role If the master is running on an EC2 instance, then the most convenient way to pass credentials is by assigning the instance an IAM role. The balancer script can then obtain temporary credentials by making internal EC2 calls. The credentials do not need to be provided on the command line or in environment variables, and are only valid for short periods of time, limiting the effect of theft. First, create an IAM role using the Amazon Console. Select IAM->Roles->Create New Role, and give the role the name "GBrowseMaster" (or whatever you prefer). Next, when prompted for the role type, select AWS Service Roles->Amazon EC2. On the Select Role Permissions screen, choose "Custom Policy". Give the policy a name like "GBrowseBalancer" and cut and paste into the Policy Document text field the permission policy listed above in the instructions for creating a restriced IAM account. Be sure to remove the whitespace before the beginning of the first curly brace, or the console will complain about an invalid policy. You only need to do this once. After this, whenever you launch an instance that will run the GBrowse master (typically from a GBrowse AMI), specify the "GBrowseMaster" IAM role name. This can be done from the AWS console's instance launch wizard, or by passing the -p option to the ec2-run-instances command-line tool. =back =head1 USING THE INIT SCRIPT The gbrowse-aws-balancer init script can be used on Ubuntu and Debian-based systems to simplify launching the balancer at boot time. It can be found in /etc/init.d by default, and is called in the following manner: start the service % sudo /etc/init.d/gbrowse-aws-balancer start stop the service % sudo /etc/init.d/gbrowse-aws-balancer stop stop and restart the service % sudo /etc/init.d/gbrowse-aws-balancer restart show the status of the service (running, stopped) % sudo /etc/init.d/gbrowse-aws-balancer status The various script options are all set in a single configuration file named /etc/default/gbrowse-aws-balancer. The distribution contents of this file looks like this: DAEMON=/usr/local/bin/gbrowse_aws_balancer.pl USER=www-data RUNDIR=/var/run/gbrowse LOGDIR=/var/log/gbrowse CONFFILE=/etc/gbrowse2/aws_balancer.conf ACCESS_KEY=YOUR_EC2_ACCESS_KEY_HERE SECRET_KEY=YOUR_EC2_SECRET_KEY_HERE VERBOSITY=3 The variables in this file set the location of the balancer script, the location of its configuration file, the verbosity to run with, and where to write the script's process ID and log information. In addition, you can place your (or another authorized user's) EC2 access and secret key in this file. Please make sure that this file is only readable by root. =head1 DEBUGGING SLAVE PROBLEMS If slaves are returning track renderinge errors, then there is likely an issue with data synchronization. This typically happens when the data on the master differs from the data on the slave, or path names are different on the two systems. To debug this, launch the script with the -ssh_key option: % gbrowse_aws_balancer.pl --conf /etc/gbrowse2/aws_balancer.conf \ --access_key XYZZY \ --secret_key Plugh \ --ssh_key John_Doe_default You may then ssh into the slave using the specified ssh key and the username "admin". A useful thing to do is to tail the slave log file: ssh -i .ssh/John_Doe_default admin@54.280.19.203 \ tail -f /var/log/gbrowse/gbrowse_slave Replace the IP number with the correct IP number of one of the running slaves, which you can find in /etc/gbrowse2/renderfarm.conf. =head1 THE GBROWSE_SYNC_AWS_SLAVE.PL SCRIPT The gbrowse_sync_aws_script.pl script should be run on the master each time you add a new database to an existing data source, or if you add a whole new data source. What it does is to prepare a new Amazon EBS snapshot containing a copy of all the data needed for the GBrowse slave to run. This snapshot is then attached to new slave instances. After running, it updates the conf file with the current versions of the slave AMI and the data snapshot. % sudo gbrowse_sync_aws_script.pl --conf /etc/gbrowse2/aws_balancer.conf \ --mysql /var/lib/mysql \ --postgres /var/lib/postgresql The --conf argument is required. The script will create a snapshot of the appropriate size, mount it on a temporary staging instance, and rsync a copy of your gbrowse databases directory (e.g. /var/lib/gbrowse2/databases) to the snapshot. If you have created mysql or postgres databases, you must also give the paths to their database file directories, as shown in the example. Note that ALL your mysql and postgres data files located on the server will be copied; not just those used for track display. =head1 ENVIRONMENT VARIABLES The following environment variables are used if the corresponding command line options are not present: EC2_ACCESS_KEY AWS EC2 access key EC2_SECRET_KEY AWS EC2 secret key =head1 SEE ALSO L, L =head1 AUTHOR Lincoln Stein, lincoln.stein@gmail.com Copyright (c) 2012 Ontario Institute for Cancer Research This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use Getopt::Long; use GBrowse::ConfigData; use File::Spec; use Bio::Graphics::Browser2::Render::Slave::AWS_Balancer; my $balancer; # this obscures the AWS secrets from ps; it is not 100% effective my $program = $0; ($0 = "$0 @ARGV") =~ s/(\s--?[as]\S*?)(=|\s+)\S+/$1$2xxxxxxxxxx/g; $SIG{TERM} = sub {exit 0}; $SIG{INT} = sub {exit 0}; my($ConfFile,$AccessKey,$SecretKey,$PidFile,$LogFile,$Daemon,$User,$Verbosity,$Kill,$SshKey); GetOptions( 'access_key=s' => \$AccessKey, 'secret_key=s' => \$SecretKey, 'conf=s' => \$ConfFile, 'pidfile=s' => \$PidFile, 'logfile=s' => \$LogFile, 'user=s' => \$User, 'verbosity=i' => \$Verbosity, 'kill' => \$Kill, 'background' => \$Daemon, 'ssh_key' => \$SshKey, ) or exec 'perldoc',$program; $ConfFile ||= File::Spec->catfile(GBrowse::ConfigData->config('conf'),'aws_balancer.conf'); $balancer = Bio::Graphics::Browser2::Render::Slave::AWS_Balancer->new( -conf => $ConfFile, -access_key => $AccessKey||'', -secret_key => $SecretKey||'', -logfile => $LogFile||'', -pidfile => $PidFile||'', -user => $User||'', -daemon => $Daemon||0, -ssh_key => $SshKey||undef, ); $Verbosity = 3 unless defined $Verbosity; $balancer->verbosity($Verbosity); if ($Kill) { $balancer->stop_daemon(); } else { $balancer->run(); } exit 0; GBrowse-2.56/bin/gbrowse_change_passwd.pl000555001750001750 301613036764442 20611 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use FindBin '$Bin'; use lib "$Bin/../lib"; use GBrowse::ConfigData; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::UserDB; use Getopt::Long; my @ORIGINAL_ARGV = @ARGV; use constant USAGE => <config('wwwuser'); my $uid = (getpwnam($wwwuser))[2]; unless ($uid == $<) { print STDERR "Not running as $wwwuser. Trying to use sudo to remedy. You may be asked for your login password.\n"; my @args = ('sudo','-u',$wwwuser,$0, @ORIGINAL_ARGV); exec @args; exit 0; } my $globals = Bio::Graphics::Browser2->open_globals or die "Couldn't open GBrowse.conf"; my $userdb = Bio::Graphics::Browser2::UserDB->new($globals); my $name = shift or die "Please provide a username. Run $0 --help for help\n"; my $pass = shift || get_random_password(); my $uid = $userdb->userid_from_username($name); $uid || die "unknown user: $name\n"; $userdb->set_password($uid,$pass); warn "Account \"$name\": password successfully set to $pass.\n"; exit 0; sub get_random_password { my $p = ''; my @a = ('a'..'z','A'..'Z',0..9); for (1..10) { $p .= $a[rand @a]; } return $p; } __END__ GBrowse-2.56/bin/gbrowse_clean.pl000555001750001750 2014713036764442 17111 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Getopt::Long; use Pod::Usage; use File::Find (); use File::Basename 'basename','dirname'; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::Util 'shellwords'; use POSIX 'ENOTEMPTY'; use CGI::Session; my ($man,$help,$verbose) = (0,0,0); GetOptions( 'help|?' => \$help, 'man' => \$man, 'verbose'=> \$verbose, ) or pod2usage(2); pod2usage(1) if $help; pod2usage(-verbose=>2) if $man; # for the convenience of &wanted calls, including -eval statements: use vars qw/*name *dir *prune/; *name = *File::Find::name; *dir = *File::Find::dir; *prune = *File::Find::prune; use constant DEFAULT_MASTER => 'GBrowse.conf'; use constant SECS_PER_DAY => 60*60*24; my $conf_dir = Bio::Graphics::Browser2->config_base; my $conf_file = $ENV{GBROWSE_MASTER} || DEFAULT_MASTER; my $globals = Bio::Graphics::Browser2->new(File::Spec->catfile($conf_dir, $conf_file) ) or die "Couldn't read globals"; my $tmpdir = $globals->tmpdir(); my $cache_dir = $globals->cache_dir; my $locks_dir = $globals->session_locks; my $images_dir = $globals->tmpimage_dir; my $user_dir = $globals->user_dir(); my $uploads_db = $globals->user_account_db; my $cache_secs = $globals->time2sec($globals->cache_time); my $uploads_secs = $globals->time2sec($globals->upload_time); logit("***",scalar localtime,basename($0),"starting ***\n"); #################################### # first we clean up expired sessions #################################### my $remember_settings_time = $globals->remember_settings_time; logit("Expiring sessions older than $remember_settings_time...\n"); my $dsn = $globals->code_setting(general=>'session driver'); my %dsn = shellwords($globals->code_setting(general=>'session args')); my $rst = $globals->time2sec($remember_settings_time); my $now = time(); my $deleted = 0; CGI::Session->find($dsn, sub { my $session = shift; return if $session->is_empty; return if $session->atime + $rst > $now; verbose("session ",$session->id," deleted\n"); $session->delete(); $session->flush(); $deleted++; },\%dsn); logit("$deleted sessions deleted.\n"); ############################################ # now we remove old cache files and userdata ############################################ my ($files,$directories) = (0,0); my $wanted = sub { my ($dev,$ino,$mode,$nlink,$uid,$gid, $rdev,$size,$atime,$mtime,$ctime) = stat($_); next if $name =~ m!$tmpdir/[^/]+$!; # don't remove toplevel! next if $name eq $tmpdir; next if $name eq $user_dir; my $is_userdata = $name =~ m/^$user_dir/; if (-d _ ) { # attempt to remove directories - will have no effect unless empty if (rmdir($name)) { verbose("rmdir $name\n"); $directories++; } else { warn "couldn't rmdir $name: $!\n" unless $!==ENOTEMPTY; } return; } my $secs = $name =~ m/^($cache_dir|$locks_dir|$images_dir)/ ? $cache_secs :$is_userdata ? $uploads_secs :0; return unless $secs; my $time = $is_userdata ? -A _ : -M _; my $days = $secs/SECS_PER_DAY; return unless -f _ && $time > $days; if (unlink($name)) { $files++; verbose("unlinked $name\n"); } else { warn "couldn't unlink $name: $!\n"; } }; # Traverse desired filesystems logit("Deleting cache files and directories older than ".$globals->cache_time." (see GBrowse.conf \"expire cache\" option)...\n"); File::Find::finddepth( {wanted=>$wanted}, $tmpdir); logit("Deleting unaccessed user uploads older than ".$globals->upload_time." (see GBrowse.conf \"expire uploads\" option)...\n"); File::Find::finddepth( {wanted=>$wanted}, $user_dir); logit("Deleted $directories directories and $files files.\n"); if ($uploads_db) { logit("Cleaning uploads db...\n"); clean_uploads(); } logit("*** ",scalar localtime,"$0 done ***\n\n"); exit 0; sub clean_uploads { eval {require DBI; 1} or return; my $db = DBI->connect($globals->user_account_db) or return; my $query = $db->prepare('select uploadsid,data_source,path,trackid from uploads,session where uploads.userid=session.userid') or return; $query->execute or return; my %flag_for_deletion; while (my ($uploadsid,$dsn,$path,$trackid) = $query->fetchrow_array) { my $full_path = "$user_dir/$dsn/$uploadsid/$path"; next if -e $full_path; $flag_for_deletion{$trackid}++; } my @delete = keys %flag_for_deletion or return; my $to_remove = join ',',map {"'$_'"}@delete; $db->do("delete from uploads where trackid in ($to_remove)") or warn $db->errstr; logit("Deleted ".scalar @delete." dangling uploads.\n"); } sub verbose { my @mess = @_; return unless $verbose; print " @mess"; } sub logit { my @mess = @_; print "@mess"; } __END__ =head1 NAME gbrowse_clean.pl - Clean up sessions and other temporary gbrowse2 files =head1 SYNOPSIS From the command line: sudo -u www-data gbrowse_clean.pl Replace "www-data" with the web server account name on your system. To run automatically under cron, create a crontab file for the web server user that contains a line like the following: # m h dom mon dow command 5 0 * * /usr/bin/gbrowse_clean.pl >>/var/log/gbrowse2/gbrowse_clean.log =head1 OPTIONS =over 4 =item B<-verbose> Report actions verbosely, printing out each session, file and directory deleted. =item B<-help> Print a brief help message and exits. =item B<-man> Prints the manual page and exits. =back =head1 DESCRIPTION GBrowse2 generates a number of temporary files during its operations. These files include session data, data cache files, and temporary image files, as well as user upload data from custom tracks. This script expires these temporary files, releasing unneeded space. The script honors the following options from the GBrowse.conf master configuration file: Name Default Description ---- ------- ----------- exire session 1M How long to keep session data expire cache 2h How long to keep cache data expire uploads 6w How long to keep user track data Time intervals are indicated using a count and a unit: Suffix Time Unit ------ --------- s seconds m minutes h hours d days w weeks M months y years B controls how long before user session data expires. Once a session expires, the user's saved settings, such as his preferred data source, track visibility settings, and custom track uploads are purged. The expiration interval is measured since the last time the user I his session, so simply loading a region in the browser without changing settings is sufficient to prevent a session from expiring. B controls how long before cached track data is purged from the system. Caching for up to a few hours increases performance because users frequently reload the same region. Caching for longer periods increases the time between updating the database and tracks displaying those changes. B controls how long to keep user uploaded data for custom tracks on disk. It makes sense to keep it on disk for as long or longer than the session. Even if the user's session expires, he can still get at the uploaded data if he bookmarked his session or shared the uploaded track at any point. This script should be run periodically, ideally under cron. Once per day should be adequate for most uses, but heavily-used sites may wish to run the script more frequently. It is important to run the script under the same user account as the web server; otherwise the script will be unable to delete the files created by the web server user during gbrowse execution. B =head1 AUTHOR Lincoln D. Stein Copyright 2009 Ontario Institute for Cancer Research This script is available under either the GNU General Public License or the Perl Artistic License version 2.0. See LICENSE in the GBrowse source code distribution for details. =head1 SEE ALSO L GBrowse-2.56/bin/gbrowse_configure_slaves.pl000555001750001750 454313036764442 21347 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Bio::Graphics::Browser2; use File::Spec; use Text::ParseWords 'shellwords'; use Getopt::Long; my (@to_add,@to_remove,@to_set); GetOptions( 'add=s' => \@to_add, 'remove=s' => \@to_remove, 'set=s' => \@to_set ) or die <open_globals; my $render_conf = File::Spec->catfile($globals->config_base,'renderfarm.conf'); -e $render_conf or system 'touch',$render_conf; my $conf = Bio::Graphics::FeatureFile->new(-file=>$render_conf) or die "Couldn't open $render_conf: $!"; my $use_renderfarm = $conf->setting(general=>'renderfarm'); my @remote_renderers = shellwords($conf->setting(general=>'remote renderer')); my %remote_renderers = map {$_=>1} @remote_renderers; my %original_renderers = %remote_renderers; for my $add (@to_add) { next unless $add; $remote_renderers{$add}++; } for my $sub (@to_remove) { next unless $sub; delete $remote_renderers{$sub}; } if (@to_set) { %remote_renderers = map {$_=>1} grep {$_} @to_set; } my $orig = join ' ',sort keys %original_renderers; my $new = join ' ',sort keys %remote_renderers; my $changed = $orig ne $new; if ($changed) { # write out $use_renderfarm = keys %remote_renderers > 0 ? 1 : 0; open my $f,'>',"$render_conf.new" or die "Couldn't open $conf.new: $!"; print $f "[GENERAL]\n"; print $f "renderfarm = $use_renderfarm\n"; print $f "remote renderer = \n"; for my $s (keys %remote_renderers) { print $f "\t",$s,"\n" or die "Couldn't write: $!"; } close $f or die "Couldn't write: $!"; rename "$render_conf.new",$render_conf; system "sudo /etc/init.d/apache2 graceful"; } exit 0; GBrowse-2.56/bin/gbrowse_create_account.pl000555001750001750 575413036764442 20775 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use FindBin '$Bin'; use lib "$Bin/../lib"; use GBrowse::ConfigData; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::UserDB; use Getopt::Long; my ($name,$pass,$fullname,$email); my @ORIGINAL_ARGV = @ARGV; use constant USAGE => < \$pass, 'fullname=s' => \$fullname, 'email-s' => \$email, ) or die USAGE; my $wwwuser = GBrowse::ConfigData->config('wwwuser'); my $uid = (getpwnam($wwwuser))[2]; unless ($uid == $<) { print STDERR "Not running as $wwwuser. Trying to use sudo to remedy. You may be asked for your login password.\n"; my @args = ('sudo','-u',$wwwuser,$0, @ORIGINAL_ARGV); exec @args; exit 0; } my $globals = Bio::Graphics::Browser2->open_globals or die "Couldn't open GBrowse.conf"; my $userdb = Bio::Graphics::Browser2::UserDB->new($globals); $name=shift or die "Please provide a username. Run $0 --help for help\n"; unless ($pass) { print STDERR "New password for $name: "; system "stty -echo"; $pass = ; chomp($pass); print STDERR "\n"; my $newpass; print STDERR "New password for $name (confirm): "; $newpass = ; chomp($newpass); print STDERR "\n"; system "stty echo"; die "Passwords don't match!\n" unless $pass eq $newpass; } $fullname ||= prompt("Enter user's full name (optional)"); $email ||= prompt("Enter user's email address (optional)"); $fullname ||= $name; $email ||= "$name\@nowhere.net"; my $uid = $userdb->userid_from_username($name); unless ($uid) { # this creates a new session for the admin user my $session = $globals->session; my $sessionid = $session->id; my $uploadsid = $session->uploadsid; $session->flush(); my ($status,undef,$message) = $userdb->do_add_user($name,$email,$fullname,$pass,$sessionid); warn $message,"\n"; $userdb->set_confirmed_from_username($name); warn "Account \"$name\": now registered with sessionid=$sessionid, uploadsid=$uploadsid.\n" if $message =~ /success/i; } else { $userdb->set_password($uid,$pass); warn "Account \"$name\": password successfully set.\n"; } exit 0; sub prompt { my $msg = shift; print STDERR "$msg: "; my $response = ; chomp $response; return $response; } __END__ GBrowse-2.56/bin/gbrowse_grow_cloud_vol.pl000555001750001750 1116213036764442 21050 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME gbrowse_grow_cloud-vol.pl Grow the GBrowse volume by the requested amount =head1 SYNOPSYS Grow /opt/gbrowse by another 100 gigabytes % gbrowse_grow_cloud_vol.pl 100 =head1 DESCRIPTION This script grows /opt/gbrowse by the requested number of gigabytes. The single argument must be a number between 1 and 1000, which indicates the number of GB to grow the volume by (not the new size of the volume). It works by creating a new EBS volume and adding it to the logical volume manager (LVM2) for this machine. The filesystem is then extended to the desired size. =head1 COMMAND-LINE OPTIONS Options can be abbreviated. For example, you can use -a for --access_key: --access_key EC2 access key --secret_key EC2 secret key =head1 ENVIRONMENT VARIABLES The following environment variables are used if the corresponding options are not present: EC2_ACCESS_KEY your access key EC2_SECRET_KEY your secret key =head1 SEE ALSO L, L =head1 AUTHOR Lincoln Stein, lincoln.stein@gmail.com Copyright (c) 2012 Ontario Institute for Cancer Research This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use lib '../lib'; use VM::EC2; use File::Basename 'basename'; use Getopt::Long; my($Access_key,$Secret_key,$Endpoint); my $Program_name = basename($0); GetOptions( 'access_key=s' => \$Access_key, 'secret_key=s' => \$Secret_key, ) or exec 'perldoc',$0; my $extra_size = shift or die "Please provide size to grow /opt/gbrowse by. Use --help for details."; #setup defaults $ENV{EC2_ACCESS_KEY} = $Access_key if defined $Access_key; $ENV{EC2_SECRET_KEY} = $Secret_key if defined $Secret_key; my $meta = VM::EC2->instance_metadata; my $zone = $meta->availabilityZone; (my $region = $zone) =~ s/[a-z]$//; # hack my $instance = $meta->instanceId; my ($ebs_device,$local_device) = unused_block_device() or die "Couldn't find a suitable device to attach to"; my $ec2 = VM::EC2->new(-region=>$region) or die VM::EC2->error_str; print STDERR "Creating $extra_size EBS volume.\n"; my $vol = $ec2->create_volume(-availability_zone => $zone, -size => $extra_size) or die "Couldn't create EBS volume: ",$ec2->error_str; $vol->add_tag(Name=>"GBrowse lvm disk $local_device"); print STDERR "Attaching volume.\n"; my $a = $vol->attach($instance=>$ebs_device) or die "Couldn't attach EBS volume to $ebs_device: ",$ec2->error_str; $ec2->wait_for_attachments($a); $a->deleteOnTermination(1); -e $local_device or die "EBS volume did not appear at $local_device as expected"; print STDERR "Creating lvm physical device.\n"; system("sudo pvcreate $local_device") == 0 or die "pvcreate failed"; print STDERR "Extending 'volumes' volume group.\n"; system("sudo vgextend volumes $local_device") == 0 or die "vgextend failed"; my $result = `sudo vgdisplay -c volumes` or die "vgdisplay filed"; my @result = split /:/,$result; my $free = $result[15] or die "volume group has no free extents"; print STDERR "Extending 'gbrowse' logical volume.\n"; system("sudo lvextend -l +$free /dev/volumes/gbrowse") == 0 or die "lvextend failed"; print STDERR "Extending /opt/gbrowse filesystem.\n"; system("sudo resize2fs /dev/volumes/gbrowse") == 0 or die "resize2fs failed"; print STDERR "Volume resized successfully\n"; exit 0; sub unused_block_device { my $major_start = shift || 'g'; my @devices = `ls -1 /dev/sd?* /dev/xvd?* 2>/dev/null`; chomp(@devices); return unless @devices; my %used = map {$_ => 1} @devices; my $base = $used{'/dev/sda1'} ? "/dev/sd" : $used{'/dev/xvda1'} ? "/dev/xvd" : ''; die "Device list contains neither /dev/sda1 nor /dev/xvda1; don't know how blocks are named on this system" unless $base; my $ebs = '/dev/sd'; for my $major ($major_start..'p') { for my $minor (1..15) { my $local_device = "${base}${major}${minor}"; next if $used{$local_device}++; my $ebs_device = "/dev/sd${major}${minor}"; return ($ebs_device,$local_device); } } return; } GBrowse-2.56/bin/gbrowse_import_ucsc_db.pl000555001750001750 5076113036764442 21030 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use warnings; use Carp 'croak'; use GBrowse::ConfigData; use DBI; use Bio::DB::Fasta; use LWP::Simple 'mirror','is_error','is_success'; use File::Basename 'dirname'; use Getopt::Long; use constant HOST=>'genome-mysql.cse.ucsc.edu'; use constant USER=>'genome'; my $host = HOST; my $dbh = DBI->connect( "DBI:mysql::host=$host;mysql_use_result=1", USER,'', {PrintError=>0,RaiseError=>0} ); my $USAGE = < [] Example: $0 hg19 'Human genome (hg19)' This creates a framework data source for one of the genomes known to the UCSC Genome Browser. You can then modify the data source configuration file, add your own data, and so forth. Provide the name of a UCSC genome build and optionally a description to display in GBrowse. To get started, find the desired data source by going to http://genome.ucsc.edu/cgi-bin/hgGateway and using the "clade" and "genome" menus to navigate to the desired species and build number. You will find the data source name in the blue box below the navigation controls. Look for something like this: D. melanogaster Genome Browser – dm3 assembly (sequences) The data source name appears before the word "assembly", in this case "dm3". To get a list of all sources recognized by UCSC appears type: $0 --list Options: --remove-chr Remove the 'chr' prefix from all chromosome names --list List data sources END ; my ($REMOVE_CHR,$LIST); GetOptions( 'remove-chr' => \$REMOVE_CHR, 'list' => \$LIST, ) or die $USAGE; if ($LIST) { print_sources($dbh); exit -1; } my $dsn = shift; my $description = shift || "Imported $dsn genome from UCSC"; unless ($dsn) { print STDERR "usage: $0 \n"; print STDERR "Run $0 --help for details.\n"; print STDERR "Run $0 --list for list of data sources.\n"; exit -1; } else { $dbh->do("use $dsn") or die "Could not access $dsn database. Run this script with --list to see valid database names.\n"; } my $conf_dir = GBrowse::ConfigData->config('conf'); my $data_dir = GBrowse::ConfigData->config('databases'); print STDERR "** During database creation, you may be asked for your password in order to set file permissions correctly.\n\n"; my $dir = create_database_dir($data_dir,$dsn); my $scaffolds = create_scaffold_db($dir,$dsn); my $genes = create_gene_db($dir,$dsn); create_conf_file($conf_dir,$dsn,$description,$scaffolds,$genes); create_source($conf_dir,$dsn,$description); print STDERR <selectcol_arrayref('show databases'); print STDERR join("\n",grep {!/information_schema/} @$s),"\n"; } sub create_database_dir { my ($data_dir,$dsn) = @_; my $uid = $<; my ($gid) = $( =~ /^(\d+)/; my $dir = "$data_dir/$dsn"; unless (-d $dir) { print STDERR "Creating database directory for $dsn. You may be prompted for your password.\n"; system "sudo mkdir -p $dir"; } unless (-w $dir) { system "sudo chown $uid $dir"; system "sudo chgrp $gid $dir"; } return $dir; } sub create_scaffold_db { my ($dir,$dsn) = @_; my $path = "$dir/chromosomes"; mkdir $path unless -e $path; open my $db,">$path/chrom_sizes.gff3" or die "$path: $!"; print $db <prepare('select chrom,size from chromInfo order by size') or die $dbh->errstr; $query->execute; my @chroms; while (my($chrom,$size) = $query->fetchrow_array) { $chrom =~ s/^chr// if $REMOVE_CHR; print $db join("\t", $chrom, $dsn, 'chromosome', 1, $size, '.','.','.', "ID=$chrom;Name=$chrom"),"\n"; push @chroms,$chrom; } $query->finish; close $db; print STDERR "Fetching FASTA files..."; $ENV{FTP_PASSIVE}=1 unless exists $ENV{FTP_PASSIVE}; my $prefix = $REMOVE_CHR ? 'chr' : ''; for my $chr (sort @chroms) { my $url = "ftp://hgdownload.cse.ucsc.edu/goldenPath/$dsn/chromosomes/$prefix$chr.fa.gz"; my $file = "$path/$prefix$chr.fa.gz"; print STDERR "$chr..."; my $code = mirror($url=>$file); warn "Fetch of $url returned error code $code\n" if is_error($code); } print STDERR "done\n"; print STDERR "Unpacking FASTA files..."; unlink "$path/chromosomes.fa"; for my $chr (sort @chroms) { my $command = $REMOVE_CHR ? "gunzip -c $path/$prefix$chr.fa.gz | perl -p -e 's/^>chr/>/' >> $path/chromosomes.fa" : "gunzip -c $path/$prefix$chr.fa.gz >> $path/chromosomes.fa" unless -e "$path/$chr.fa" && -M "$path/chromosomes.fa" > -M "$path/$prefix$chr.fa.gz"; system $command; } print STDERR "done\n"; print STDERR "Creating FASTA index..."; my $index = Bio::DB::Fasta->new($path) or die "Couldn't create index"; print "done\n"; my $wwwuser = GBrowse::ConfigData->config('wwwuser'); system "sudo chown -R $wwwuser $path"; return $path; } sub create_gene_db { my ($dir,$dsn) = @_; my $path = "$dir/refGenes"; mkdir $path unless -e $path; my $src_path = "$path/genes.gff3"; my $db_path = "$path/genes.sqlite"; open my $db,'>',$src_path or die "$path: $!"; print $db <prepare('select * from refFlat order by geneName') or die $dbh->errstr; $query->execute or die $dbh->errorstr; } || eval { $query = $dbh->prepare('select name2,name,chrom,strand,txStart,txEnd,cdsStart,cdsEnd,exonCount,exonStarts,exonEnds from ensGene order by name2') or die $dbh->errstr; $query->execute or die $dbh->errorstr; }; die $@ if $@; my $writer = GFFWriter->new($db,$dsn); while (my $row = $query->fetchrow_arrayref) { $writer->write_transcript($row); } $query->finish; $writer->finish; print STDERR "done\n"; close $db; print STDERR "Indexing..."; system "bp_seqfeature_load.pl -f -c -a DBI::SQLite -d $db_path $src_path"; print STDERR "done\n"; return $db_path; } sub log10 { log(shift())/log(10)} sub create_conf_file { my ($conf_dir,$dsn,$description,$scaffolds,$genes) = @_; my $conf_path = "$conf_dir/${dsn}.conf"; create_writable_file($conf_path); # figure size of chromosomes open my $fh1,"$scaffolds/chrom_sizes.gff3" or die "$scaffolds/chrom_sizes.gff3: $!"; my $max_chrom = 0; my ($first_chrom,$first_size); while (<$fh1>) { my ($chr,undef,undef,undef,$size) = split /\s+/; next unless $size; $max_chrom = $size if $max_chrom < $size; $first_chrom ||= $chr; $first_size ||= $size; } close $fh1; # from the max chromosome, figure out reasonable default sizes and zoom levels my $log = int log10($max_chrom); my $max_segment = $max_chrom; my $default_segment = 10**($log-3); my $region_segment = $default_segment*10; my @zoom_levels = qw(100 200 1000 2000 5000 10000 20000 50000 100000 200000 500000); for (my $i=6; $i<=$log; $i++) { push @zoom_levels,10**$i; } my @region_sizes = @zoom_levels; my $default_region = $default_segment * 10; my $summary_boundary= $default_segment * 100; my $start = int(rand($first_size)); my $end = $start + $default_segment -1; my $initial_landmark = "$first_chrom:$start..$end"; # pick some random examples from the gff3 file my @names; my $dir = dirname($genes); open my $fh2,"$dir/genes.gff3" or die "$dir/genes.gff3: $!"; while (<$fh2>) { my ($name) = /Name=([^;]+)/ or next; for (0..3) { $names[$_] = $name if rand($.) < 4; } } close $fh2; my $examples = "@names"; open my $fh3,'>',$conf_path or die "$conf_path: $!"; print $fh3 <strand > 0 ? 'red' : 'blue'} label_transcripts = 1 label = sub { my \$f = shift; my \$name = \$f->display_name; my \@aliases = sort \$f->attributes('Alias'); \$name .= " (\@aliases)" if \@aliases; \$name; } height = 10 description = 0 key = Known Genes [Genes:200000] glyph = box stranded = 1 [Genes:500000] glyph = box bump = 0 [ncRNA] database = genes feature = noncoding_transcript fgcolor = orange glyph = generic description = 1 key = Noncoding RNAs [CDS] database = genes feature = mRNA glyph = cds description = 0 height = 26 sixframe = 1 label = sub {shift->name . " reading frame"} key = CDS citation = This track shows CDS reading frames. [CDS:200000] glyph = box stranded = 1 [Translation] glyph = translation global feature = 1 database = scaffolds height = 40 fgcolor = purple strand = +1 translation = 6frame key = 6-frame translation [Translation:1000000] hide = 1 [TranslationF] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = purple strand = +1 translation = 3frame key = 3-frame translation (forward) [TranslationF:1000000] hide = 1 [DNA/GC Content] glyph = dna global feature = 1 database = scaffolds height = 40 do_gc = 1 gc_window = auto strand = both fgcolor = red axis_color = blue [DNA/GC Content:1000000] hide = 1 [TranslationR] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = blue strand = -1 translation = 3frame key = 3-frame translation (reverse) [TranslationR:1000000] hide = 1 END close $fh3; } sub create_source { my ($conf_dir,$dsn,$description) = @_; my $path = "$conf_dir/GBrowse.conf"; open my $fh,$path or die "$path: $!"; my $foundit; while (<$fh>) { $foundit++ if /\[$dsn\]/; } close $fh; return if $foundit; create_writable_file($path); open my $fh2,'>>',$path or die "$path: $!"; print $fh2 "\n"; print $fh2 < $fh, dsn => $dsn, gene_id => 'g000000', transcript_id => 't00000', last_gene_name => '', last_gene_id => '', last_gene => {}, },ref $class || $class; } # This subroutine is amazingly long and complicated looking, but probably correct sub write_transcript { my $self = shift; my $fields = shift; my ($gene_name,$accession,$chrom,$strand,$txStart,$txEnd,$cdsStart,$cdsEnd,$exons,$exonStarts,$exonEnds) = @$fields; my ($utr5_start,$utr5_end,$utr3_start,$utr3_end,$gid,$tid); $gene_name ||= $accession; $chrom =~ s/^chr// if $REMOVE_CHR; if ($self->{last_gene_name} ne $gene_name || $self->{last_gene}{chr} ne $chrom # avoid some gene name collisions || abs($self->{last_gene}{start} - $txStart) > 6_000_000 # avoid some gene name collisions || $self->{last_gene}{strand} ne $strand) { $self->write_last_gene; $self->{last_gene} = {}; $self->{last_gene_name} = ''; $gid = $self->{last_gene_id} = $self->{gene_id}++; } elsif ($self->{last_gene_id}) { $gid = $self->{last_gene_id}; } else { $gid = $self->{last_gene_id} = $self->{gene_id}++; } $tid = $self->{transcript_id}++; my $ORIGIN = 1; my $SRC = $self->{dsn}; my $fh = $self->{fh}; # adjust for Jim's 0-based coordinates $txStart++; $cdsStart++; $txStart -= $ORIGIN; $txEnd -= $ORIGIN; $cdsStart -= $ORIGIN; $cdsEnd -= $ORIGIN; # this is how noncoding genes are expressed (?!!!) my $is_noncoding = $cdsStart >= $cdsEnd; unless ($is_noncoding) { $self->{last_gene_name} ||= $gene_name; $self->{last_gene}{chr} ||= $chrom; $self->{last_gene}{strand} ||= $strand; $self->{last_gene}{start} = $txStart if !$self->{last_gene}{start} || $self->{last_gene}{start} > $txStart; $self->{last_gene}{end} = $txEnd if !$self->{last_gene}{end} || $self->{last_gene}{end} < $txEnd; } # print the transcript my $id = $is_noncoding ? "ID=$tid;Name=$gene_name;Alias=$accession" : "ID=$tid;Name=$accession;Parent=$gid"; print $fh join ("\t",$chrom,$SRC,($is_noncoding ? 'noncoding_transcript' : 'mRNA'),$txStart,$txEnd,'.',$strand,'.',$id),"\n"; # now handle the CDS entries -- the tricky part is the need to keep # track of phase my $phase = 0; my @exon_starts = map {$_-$ORIGIN} split ',',$exonStarts; my @exon_ends = map {$_-$ORIGIN} split ',',$exonEnds; if ($is_noncoding) { for (my $i=0;$i<@exon_starts;$i++) { # for each exon start print $fh join("\t", $chrom,$SRC,'exon',$exon_starts[$i],$exon_ends[$i],'.',$strand,'.',"Parent=$tid" ),"\n"; } } elsif ($strand eq '+') { for (my $i=0;$i<@exon_starts;$i++) { # for each exon start my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_start < $cdsStart) { # in a 5' UTR push (@utr_start, $exon_start); } elsif ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } elsif ($exon_end > $cdsEnd) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 5' end $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 3' end $utr_start[0]= $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if ($utr_start[0] && $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] < $cdsStart) { print $fh join ("\t",$chrom,$SRC,"five_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$tid"),"\n" } # end of if } # end of foreach if (defined $cds_start && $cds_start <= $cds_end) { print $fh join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$tid"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { print $fh join ("\t",$chrom,$SRC,"three_prime_UTR",,$utr_start[$i], $utr_end[$i],'.',$strand,'.',"Parent=$tid"),"\n" } } } # end of for each exon } # matches if strand = + elsif ($strand eq '-') { my @lines; for (my $i=@exon_starts-1; $i>=0; $i--) { # count backwards my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_end > $cdsEnd) { # in a 5' UTR push (@utr_end, $exon_end); } elsif ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } elsif ($exon_start < $cdsStart) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 3' end $utr_end[0] = $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 5' end $utr_start[0] = $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if ($utr_start[0] && $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { unshift @lines,join ("\t",$chrom,$SRC,"five_prime_UTR",,$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$tid"),"\n" } } # end of for if (defined $cds_start && $cds_start <= $cds_end) { unshift @lines,join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$tid"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_end[$i] < $cdsStart) { unshift @lines,join ("\t",$chrom,$SRC,"three_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$tid"),"\n" } } # end for } print $fh @lines; } } sub write_last_gene { my $self = shift; my $name = $self->{last_gene_name} or return; my $chr = $self->{last_gene}{chr}; my $start = $self->{last_gene}{start}; my $end = $self->{last_gene}{end}; my $strand = $self->{last_gene}{strand}; my $id = $self->{last_gene_id}; my $fh = $self->{fh}; print $fh join("\t", $chr, $self->{dsn}, 'gene', $start, $end, '.', $strand, '.', "ID=$id;Name=$name"),"\n"; $self->{last_gene_name} = ''; } sub finish { my $self = shift; $self->write_last_gene if defined fileno($self->{fh}); } sub DESTROY { shift->finish } GBrowse-2.56/bin/gbrowse_metadb_config.pl000555001750001750 10106613036764442 20630 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w # This script checks the schemas and required fields of the Users Database. use strict; use FindBin '$Bin'; use lib "$Bin/../blib/lib"; use Bio::Graphics::Browser2 "open_globals"; use CGI::Session; use Digest::MD5 qw(md5_hex); use Getopt::Long; use GBrowse::ConfigData; use List::Util; use File::Spec; use File::Basename 'dirname','basename'; use File::Path 'rmtree'; use File::Spec; use POSIX 'strftime'; use constant SCHEMA_VERSION => 4; # First, collect all the flags - or output the correct usage, if none listed. my @argv = @ARGV; my ($dsn, $admin); GetOptions('dsn=s' => \$dsn, 'admin=s' => \$admin) or die < Initializes an empty GBrowse user accounts and uploads metadata database. Options: -dsn Provide a custom DBI connection string, overriding what is set in Gbrowse.conf. Note that if there are semicolons in the string (like most MySQL connection DSNs will), you WILL have to escape it with quotes. -admin Provide an administrator username and password (in the form 'user:pass') to skip the prompts if the database does not exist. Currently mysql and SQLite databases are supported. When creating a mysql database you must provide the -admin option to specify a user and password that has database create privileges on the server. EOF ; my $www_user = GBrowse::ConfigData->config('wwwuser'); my ($current_user) = getpwuid($<); unless ($www_user eq $current_user or $< == 0) { print STDERR <open_globals; $dsn ||= $globals->user_account_db; if (!$dsn || ($dsn =~ /filesystem|memory/i) || !$globals->user_accounts) { print "No need to run database metadata configuration script, filesystem-backend will be used."; exit 0; } fix_sqlite_permissions() if $dsn =~ /sqlite/i; create_mysql_database() if $dsn =~ /mysql/i; eval "require DBI" or die "DBI module not installed. Cannot continue."; my $database = DBI->connect($dsn) or die "Error: Could not open users database, please check your credentials.\n" . DBI->errstr; my $type = $database->{Driver}->{Name}; my $autoincrement = $type =~ /mysql/i ? 'auto_increment' :$type =~ /sqlite/i ? 'autoincrement' :''; my $last_id = $type =~ /mysql/i ? 'mysql_insertid' :$type =~ /sqlite/i ? 'last_insert_rowid' :''; # Database schema. To change the schema, update/add the fields here, and run this script. my $users_columns = { userid => "integer PRIMARY KEY $autoincrement", email => "varchar(64) not null UNIQUE", pass => "varchar(44) not null", gecos => "varchar(64)", remember => "boolean not null", openid_only => "boolean not null", confirmed => "boolean not null", cnfrm_code => "varchar(32) not null", last_login => "timestamp not null", created => "datetime not null" }; my $session_columns = { userid => "integer PRIMARY KEY $autoincrement", username => "varchar(32)", sessionid => 'char(32) not null UNIQUE', uploadsid => 'char(32) not null UNIQUE', }; my $openid_columns = { userid => "integer not null", openid_url => "varchar(128) PRIMARY KEY" }; my $uploads_columns = { trackid => "varchar(32) not null PRIMARY key", userid => "integer not null", path => "text", title => "text", description => "text", imported => "boolean not null", creation_date => "datetime not null", modification_date => "datetime", sharing_policy => "ENUM('private', 'public', 'group', 'casual') not null", public_count => "int", data_source => "text", }; my $sharing_columns = { trackid => "varchar(32) not null", userid => "integer not null", public => "boolean", }; my $dbinfo_columns = { schema_version => 'int(10) not null UNIQUE' }; my $old_users_columns = { userid => "varchar(32) not null UNIQUE PRIMARY KEY", uploadsid => "varchar(32) not null UNIQUE", username => "varchar(32) not null UNIQUE", email => "varchar(64) not null UNIQUE", pass => "varchar(32) not null", remember => "boolean not null", openid_only => "boolean not null", confirmed => "boolean not null", cnfrm_code => "varchar(32) not null", last_login => "timestamp not null", created => "datetime not null" }; my $old_uploads_columns = { uploadid => "varchar(32) not null PRIMARY key", userid => "varchar(32) not null", path => "text", title => "text", description => "text", imported => "boolean not null", creation_date => "datetime not null", modification_date => "datetime", sharing_policy => "ENUM('private', 'public', 'group', 'casual') not null", users => "text", public_users => "text", public_count => "int", data_source => "text", }; upgrade_schema(SCHEMA_VERSION); check_table("users", $users_columns); check_table("session", $session_columns); check_table("openid_users", $openid_columns); check_table("uploads", $uploads_columns); check_table("sharing", $sharing_columns); check_sessions(); check_uploads_ids(); check_all_files(); check_data_sources(); fix_session_permissions(); fix_sqlite_permissions() if $type =~ /sqlite/i; $database->disconnect; print STDERR "Done!\n"; exit 0; # Check Table (Name, Columns) - Makes sure the named table is there and follows the schema needed. sub check_table { my $name = shift or die "No table name given, please check the gbrowse_metadb_config.pl script.\n"; my $columns = shift or die "No table schema given, please check the gbrowse_metadb_config.pl script.\n"; # If the database doesn't exist, create it. local $database->{PrintError} = 0; unless (eval {$database->do("SELECT * FROM $name LIMIT 1")}) { $database->{PrintError} = 1; print STDERR ucfirst $name . " table didn't exist, creating...\n"; my @column_descriptors = map { "$_ " . escape_enums($$columns{$_}) } keys %$columns; # This simply outputs %columns as "$key $value, "; my $creation_sql = "CREATE TABLE $name (" . (join ", ", @column_descriptors) . ")" . (($type =~ /mysql/i)? " ENGINE=InnoDB;" : ";"); $database->do($creation_sql) or die "Could not create $name database.\n"; } my $sth = $database->prepare("SELECT * from $name LIMIT 1"); $sth->execute; my %existing_columns = map {$_=>1} @{$sth->{NAME_lc}}; # If an extra column exists, drop it. my @columns_to_drop = grep {!$columns->{$_}} keys %existing_columns; if (@columns_to_drop) { print STDERR "Dropping the following columns from $name: ",join(',',@columns_to_drop),".\n"; if ($type !~ /sqlite/i) { for my $c (@columns_to_drop) { $database->do("ALTER TABLE $name DROP $c"); } } } # If a required column doesn't exist, add it. my @columns_to_create = grep {!$existing_columns{$_}} keys %$columns; if (@columns_to_create) { print STDERR ucfirst $name . " table schema is incorrect, adding " . @columns_to_create . " missing column" . ((@columns_to_create > 1)? "s." : "."); # SQLite doesn't support altering to add multiple columns or ENUMS, # so it gets special treatment. if ($type =~ /sqlite/i) { # If we don't find a specific column, add its SQL to the columns_to_create array. foreach (@columns_to_create) { $$columns{$_} = escape_enums($$columns{$_}); # Now add each column individually my $alter_sql = "ALTER TABLE $name ADD COLUMN $_ " . $$columns{$_} . ";"; $database->do($alter_sql) or die "While adding column $_ to $name: ", $database->errstr; } } else { @columns_to_create = map { "$_ " . $$columns{$_} } @columns_to_create; # Now add all the columns my $alter_sql; if ($type =~ /mysql/) { $alter_sql .= "ALTER TABLE $name"; $alter_sql .= " ADD COLUMN " . shift @columns_to_create; $alter_sql .= ", ADD COLUMN $_" foreach @columns_to_create; $alter_sql .= ";"; } else { $alter_sql = "ALTER TABLE $name ADD (" . (join ", ", @columns_to_create) . ");" ; } $database->do($alter_sql) or die $database->errstr; } } return $database; } # iterate through each session and make sure that there is a # corresponding user in the session table sub check_sessions { my $session_driver = $globals->session_driver; my $session_args = $globals->session_args; my $users_updated = 0; local $database->{PrintError} = 0; my $do_session_check = sub { my $session = shift; my $session_id = $session->id; my $source = $session->param('.source') or return; my $config_hash = $session->param($source) or return; my $uploadsid = $session->param('.uploadsid') || $config_hash->{page_settings}{uploadid}; $uploadsid or return; my $sql = "SELECT count(*) FROM session WHERE sessionid=? AND uploadsid=?"; my $rows = $database->selectrow_array($sql,undef,$session_id,$uploadsid); return if $rows == 0; $sql = "UPDATE session SET uploadsid=? WHERE sessionid=? AND uploadsid!=?"; $rows = $database->do($sql,undef,$uploadsid,$session_id,$uploadsid); $users_updated += $rows; }; eval { CGI::Session->find($session_driver,$do_session_check,$session_args); }; if ($users_updated) { print STDERR "$users_updated users had their session/upload IDs updated.\n"; } } # Check Uploads IDs () - Makes sure every user ID has an uploads ID corresponding to it. sub check_uploads_ids { print STDERR "Checking uploads IDs in database..."; my $ids_in_db = $database->selectcol_arrayref("SELECT userid, uploadsid FROM session", { Columns=>[1,2] }); my $missing = 0; if ($ids_in_db) { my %uploads_ids = @$ids_in_db; foreach my $userid (keys %uploads_ids) { unless ($uploads_ids{$userid}) { print STDERR "missing uploads ID found.\n" unless $missing; print STDERR "- Uploads ID not found for $userid, "; my $session = $globals->session($userid); my $settings= $session->page_settings; my $uploadsid = $session->param('.uploadsid') || $settings->{uploadid}; $database->do("UPDATE session SET uploadsid = ? WHERE sessionid = ?", undef, $uploadsid, $userid) or print STDERR "could not add to database.\n" . DBI->errstr; print STDERR "added to database.\n" unless DBI->errstr; $missing = 1; } } } print STDERR "all uploads IDs are present.\n" unless $missing; } # Check Data Sources () - Checks to make sure the data sources are there for each file. sub check_data_sources { print STDERR "Checking for any files with missing data sources..."; my $missing = 0; # Since we can't access the Database.pm access without the data source, we'll have to go in the back door, # and manually get the uploads ID, file path, and data source from the userdata folder. my $userdata_folder = $globals->user_dir; unless (-e $userdata_folder) { print STDERR "No files, no checks needed.\n"; return; } my @data_sources; opendir U, $userdata_folder; while (my $dir = readdir(U)) { next if $dir =~ /^\.+$/; next unless -d $dir; push @data_sources, $dir; } closedir(U); foreach my $data_source (@data_sources) { # Within each data source, get a list of users with uploaded files. my @users; my $source_path = File::Spec->catfile($userdata_folder, $data_source); opendir DS, $source_path; while (my $folder = readdir(DS)) { next if $folder =~ /^\.+$/; next unless -d $folder; my $user_path = File::Spec->catfile($userdata_folder, $data_source, $folder); opendir USER, $user_path if -d $user_path; next unless readdir(USER); push @users, $folder; closedir(USER); } closedir(DS); foreach my $uploadsid (@users) { # For each user, get the list of their files. my @files; my $user_path = File::Spec->catfile($userdata_folder, $data_source, $uploadsid); opendir FILE, $user_path; while (my $file = readdir(FILE)) { next if $file =~ /^\.+$/; next unless -d $file; push @files, $file; } closedir(FILE); # For each file, we have the data source and user - make sure the data source is present. foreach my $file (@files) { my @data_source_in_db = $database->selectrow_array("SELECT data_source FROM uploads WHERE path = ? AND userid = ?", undef, $file, $uploadsid); unless (@data_source_in_db) { print STDERR "missing source found.\n" unless $missing; print STDERR "- Data Source not found for $file (owned by $uploadsid), "; $database->do("UPDATE uploads SET data_source = ? WHERE path = ? AND userid = ?", undef, $data_source, $file, $uploadsid) or print STDERR "could not add to database.\n" . DBI->errstr; print STDERR "added to database.\n" unless DBI->errstr; $missing = 1; } } } } print STDERR "all data sources are present.\n" unless $missing; } # Check All Files () - Checks the integrity of the file data for every user. sub check_all_files { print STDERR "Checking for any files not in the database..."; $line_counter = 0; # Get all data sources my $userdata_folder = $globals->user_dir; unless (-e $userdata_folder) { print STDERR "no uploaded files to check.\n"; return; } my @data_sources; opendir U, $userdata_folder; while (my $dir = readdir(U)) { next if $dir =~ /^\.+$/; push @data_sources, $dir; } closedir(U); my $all_ok = 1; foreach my $data_source (@data_sources) { # Within each data source, get a list of users with uploaded files. my @uploads_ids; my $source_path = File::Spec->catfile($userdata_folder, $data_source); opendir DS, $source_path; while (my $folder = readdir(DS)) { next if $folder =~ /^\.+$/; my $user_path = File::Spec->catfile($userdata_folder, $data_source, $folder); opendir USER, $user_path; next unless readdir(USER); push @uploads_ids, $folder; closedir(USER); } closedir(DS); foreach my $uploadsid (@uploads_ids) { my $userid = check_uploadsid($source_path,$uploadsid) or next; my $this_ok = check_files($userid,$uploadsid, $data_source); $all_ok = $this_ok if $all_ok; } } print STDERR "all files are accounted for.\n" if $all_ok; } # remove dangling upload directories sub check_uploadsid { my ($source_path,$uploadsid) = @_; return if $uploadsid eq 'shared_remote_tracks'; my ($userid) = $database->selectrow_array('select (userid) from session where uploadsid=?', undef,$uploadsid); unless ($userid) { print STDERR "\n" unless $line_counter++; print STDERR "Uploadsid $uploadsid has no corresponding user. Removing.\n"; rmtree(File::Spec->catfile($source_path,$uploadsid)); return; } return $userid; } # Check Files (Uploads ID, Data Source) - Makes sure a user's files are in the database, add them if not. sub check_files { my $userid = shift or die "No user ID given, please check the gbrowse_metadb_config.pl script.\n"; my $uploadsid = shift or die "No uploads ID given, please check the gbrowse_metadb_config.pl script.\n"; my $data_source = shift or die "No data source given, please check the gbrowse_metadb_config.pl script.\n"; # Get the files from the database. my $files_in_db = $database->selectcol_arrayref("SELECT path FROM uploads WHERE userid=? AND data_source=?", undef, $userid, $data_source); my @files_in_db = @$files_in_db; # Get the files in the folder. my $path = $globals->user_dir($data_source, $uploadsid); my @files_in_folder; opendir D, $path; while (my $dir = readdir(D)) { next if $dir =~ /^\.+$/; push @files_in_folder, $dir; } closedir(D); my $all_ok = 1; foreach my $file (@files_in_folder) { my $found = grep(/$file/, @files_in_db); unless ($found) { print STDERR "\n" unless $line_counter++; add_file($file, $userid, $uploadsid, $data_source, $file) && print STDERR "- File \"$file\" found in the \"$data_source/$uploadsid\" folder without metadata, added to database.\n"; $all_ok = 0; } } return $all_ok; } # Fix Permissions () - Grants the web user the required privileges on all databases. sub fix_permissions { my (undef, $db_name) = $dsn =~ /.*:(database=)?([^;]+)/; $db_name ||= "gbrowse_login"; ($type) = $dsn =~ /^dbi:([^:]+)/i unless defined $type; if ($type =~ /mysql/i) { my ($db_user) = $dsn =~ /user=([^;]+)/i; my ($db_pass) = $dsn =~ /password=([^;]+)/i; $db_pass ||= ''; warn "GRANT ALL PRIVILEGES on $db_name.* TO '$db_user'\@'%' IDENTIFIED BY '$db_pass'"; $database->do("GRANT ALL PRIVILEGES on $db_name.* TO '$db_user'\@'%' IDENTIFIED BY '$db_pass'") or die DBI->errstr; } } sub fix_session_permissions { print STDERR "Fixing permissions in sessions directory\n"; my $globals = Bio::Graphics::Browser2->open_globals; my $session_dir = $globals->session_dir; my $webuser = GBrowse::ConfigData->config('wwwuser'); system "sudo chown -R $webuser $session_dir"; } sub fix_sqlite_permissions { my (undef, $db_name) = $dsn =~ /.*:(database=)?([^;]+)/; $db_name ||= "gbrowse_login"; my ($path) = $dsn =~ /dbname=([^;]+)/i; ($path) = $dsn =~ /DBI:SQLite:([^;]+)/i unless $path; die "Couldn't figure out location of database index from $dsn" unless $path; my $user = GBrowse::ConfigData->config('wwwuser'); my $group = get_group_from_user($user); my $dir = dirname($path); unless (-e $dir) { my $parent = dirname($dir); if (-w $parent) { mkdir $parent; } else { print STDERR "Using sudo to create $parent directory. You may be prompted for your login password now.\n"; system "sudo mkdir $parent"; } } my $file_owner = -e $path ? getpwuid((stat($path))[4]) : ''; my $dir_owner = -e $dir ? getpwuid((stat($dir))[4]) : ''; # Check if we need to, to avoid unnecessary printing/sudos. unless ($group) { print STDERR "Unable to look up group for $user. Will not change ownerships on $path.\n"; print STDERR "You should do this manually to give the Apache web server read/write access to $path.\n"; return; } if (-e $path && $user ne $file_owner) { print STDERR "Using sudo to set $path ownership to $user:$group. You may be prompted for your login password now.\n"; system "sudo chown $user $path" ; system "sudo chgrp $group $path"; system "sudo chmod 0644 $path"; } if (-e $dir && $user ne $dir_owner) { print STDERR "Using sudo to set $dir ownership to $user:$group. You may be prompted for your login password now.\n"; system "sudo chown $user $dir"; system "sudo chgrp $group $dir"; system "sudo chmod 0755 $dir"; } } # Create Database() - Creates the database specified (or the default gbrowse_login database). sub create_mysql_database { my (undef, $db_name) = $dsn =~ /.*:(database=)?([^;]+)/; $db_name ||= "gbrowse_login"; unless (DBI->connect($dsn)) { if ($dsn =~ /mysql/i) { print STDERR "Could not log into $db_name database, creating and/or fixing login permissions...\n"; my ($admin_user, $admin_pass); if ($admin) { ($admin_user) = $admin =~ /^(.*):/; ($admin_pass) = $admin =~ /:(.*)$/; } $admin_user ||= prompt("Please enter the MySQL administrator user", "root"); $admin_pass ||= prompt("Please enter the MySQL administrator password", "",1); my ($db_user) = $dsn =~ /user=([^;]+)/i; my ($db_pass) = $dsn =~ /password=([^;]+)/i; $db_pass ||= ''; my $test_dbi = DBI->connect("DBI:mysql:database=mysql;user=$admin_user;password=$admin_pass;"); $test_dbi->do("CREATE DATABASE IF NOT EXISTS $db_name"); $test_dbi->do("GRANT ALL PRIVILEGES on $db_name.* TO '$db_user'\@'%' IDENTIFIED BY '$db_pass'"); print STDERR "Database created!\n" unless DBI->errstr; } } # SQLite will create the file/database upon first connection. } # Add File (Full Path, Owner's Uploads ID, Data Source) - Adds $file to the database under a specified owner. # Database.pm's add_file() is dependant too many outside variables, not enough time to re-structure. sub add_file { my $filename = shift; my $userid = shift; my $uploadsid = shift; my $data_source = shift; my $full_path = shift; my $imported = ($filename =~ /^(ftp|http|das)_/)? 1 : 0; my $description = ""; my $shared = "private"; my $trackid = md5_hex($uploadsid.$filename.$data_source); my $now = nowfun(); $database->do("INSERT INTO uploads (trackid, userid, path, description, imported, creation_date, modification_date, sharing_policy, data_source) VALUES (?, ?, ?, ?, ?, $now, $now, ?, ?)", undef, $trackid, $userid, $filename, $description, $imported, $shared, $data_source); return $trackid; } # Now Function - return the database-dependent function for determining current date & time sub nowfun { return ($type =~ /sqlite/i)? "datetime('now','localtime')" : 'NOW()'; } # Escape Enums (type string) - If the string contains an ENUM, returns a compatible data type that works with SQLite. sub escape_enums { my $string = shift; # SQLite doesn't support ENUMs, so convert to a varchar. if ($string =~ /^ENUM\(/i) { #Check for any suffixes - "NOT NULL" or whatever. my @options = ($string =~ m/^ENUM\('(.*)'\)/i); my @suffix = ($string =~ m/([^\)]+)$/); my @values = split /',\w*'/, $options[0]; my $length = List::Util::max(map length $_, @values); $string = "varchar($length)" . $suffix[0]; } return $string; } # Asks q question and sets a default - blatantly stolen (& modified) from Module::Build. sub prompt { my $mess = shift or die "prompt() called without a prompt message"; my ($default,$hide) = @_; print STDERR "$mess [$default] "; my $ans; if ($hide) { eval { use Term::ReadKey; ReadMode('noecho'); $ans = ReadLine(0); ReadMode('normal'); print STDERR "\n"; }; } $ans ||= ; chomp $ans if defined $ans; if (!defined($ans) || !length($ans)) { print STDERR "$default\n"; $ans = $default; } return $ans; } sub get_group_from_user { my $user = shift; my (undef,undef,undef,$gid) = $user =~ /^\d+$/ ? getpwuid($user) : getpwnam($user); $gid or return; my $group = getgrgid($gid); return $group; } sub upgrade_schema { my $new_version = shift; # probe whether this is a completely empty database { local $database->{PrintWarn} = 0; local $database->{PrintError} = 0; my ($count) = $database->selectrow_array('select count(*) from users'); if (!defined $count) { check_table('dbinfo',$dbinfo_columns); set_schema_version('dbinfo',$new_version); return; } } my ($old_version) = $database->selectrow_array('SELECT MAX(schema_version) FROM dbinfo LIMIT 1'); unless ($old_version) { # table is missing, so add it check_table('dbinfo',$dbinfo_columns); $old_version = 0; } backup_database() unless $old_version == $new_version; for (my $i=$old_version;$i<$new_version;$i++) { my $function = "upgrade_from_${i}_to_".($i+1); eval "$function();1" or die "Can't upgrade from version $i to version ",$i+1; } set_schema_version('dbinfo',$new_version); } sub backup_database { my $temp = File::Spec->tmpdir; if ($type =~ /sqlite/i) { my ($src) = $dsn =~ /dbname=([^;]+)/i; unless ($src) { ($src) = $dsn =~ /DBI:SQLite:([^;]+)/i; } my $time = localtime; my $basename = basename($src); my $dest = strftime("$temp/${basename}_%d%b%Y.%H:%M",localtime); warn "backing up existing users database to $dest"; system ('cp',$src,$dest); } elsif ($type =~ /mysql/i) { my $dest = strftime("$temp/gbrowse_users_%d%b%Y.%H:%M",localtime); warn "backing up existing users database to ./$dest"; my ($src) = $dsn =~ /dbname=([^;]+)/i; unless ($src) { (undef, $src) = $dsn =~ /.*:(database=)?([^;]+)/i; } my ($db_user) = $dsn =~ /user=([^;]+)/i; my ($db_pass) = $dsn =~ /password=([^;]+)/i; $db_pass ||= ''; no warnings; open SAVEOUT,">&STDOUT"; open STDOUT,">$dest" or die "$dest: $!"; system('mysqldump',"--user=$db_user","--password=$db_pass",$src); open STDOUT,">&SAVEOUT"; } else { die "Don't know how to backup this driver"; } } sub set_schema_version { my ($table,$version) = @_; local $database->{AutoCommit} = 0; local $database->{RaiseError} = 1; eval { $database->do("delete from $table"); $database->do("insert into $table (schema_version) values ($version)"); $database->commit(); }; if ($@) { warn "update failed due to $@. Rolling back"; eval {$database->rollback()}; die "Can't continue"; } } ############################## one function to upgrade each level sub upgrade_from_0_to_1 { # create dbinfo table check_table("dbinfo", $dbinfo_columns); local $database->{AutoCommit} = 0; local $database->{RaiseError} = 1; eval { # this upgrades the original users table to the last version # before the session table was added check_table('users',$old_users_columns); # this creates the new session table check_table("session", $session_columns); check_table("users_new", $users_columns); # query to pull old data out of original users table my $select = $database->prepare(<errstr; SELECT userid,uploadsid,username,email,pass,remember,openid_only, confirmed,cnfrm_code,last_login,created FROM users END ; # query to insert data into new session table my $insert_session = $database->prepare(<errstr; REPLACE INTO session (username,sessionid,uploadsid) VALUES (?,?,?) END ; # query to insert data into new users table my $insert_user = $database->prepare(<errstr; REPLACE INTO users_new (userid, email, pass, remember, openid_only, confirmed, cnfrm_code, last_login, created) VALUES (?,?,?,?,?,?,?,?,?) END ; $select->execute() or die $database->errstr; my %uploadsid_to_userid; while (my ($sessionid,$uploadsid,$username,@rest) = $select->fetchrow_array()) { $insert_session->execute($username,$sessionid,$uploadsid) or die $database->errstr; my $userid = $database->last_insert_id('','','','') or die "Didn't get an autoincrement ID!"; $insert_user->execute($userid,@rest) or die $database->errstr; $uploadsid_to_userid{$uploadsid}=$userid; } $select->finish; $insert_session->finish; $insert_user->finish; # rename the current users table $database->do('drop table users') or die "Couldn't drop old users table"; $database->do('alter table users_new rename to users') or die "Couldn't rename new users table"; $database->do('create index index_session on session(username)') or die "Couldn't index sessions table"; # now do the uploads table # this upgrades to latest version 0 check_table('uploads', $old_uploads_columns); check_table("uploads_new", $uploads_columns); $select = $database->prepare(<errstr; SELECT uploadid,userid,path,title,description,imported, creation_date,modification_date,sharing_policy,users, public_users,public_count,data_source FROM uploads END ; my $insert = $database->prepare(<errstr; REPLACE INTO uploads_new (trackid,userid,path,title,description,imported, creation_date,modification_date,sharing_policy,users, public_users,public_count,data_source) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?) END ; $select->execute(); while (my ($trackid,$uploadsid,@rest) = $select->fetchrow_array()) { my $uid = $uploadsid_to_userid{$uploadsid}; unless ($uid) { print STDERR "Found an upload from uploadsid=$uploadsid, but there is no corresponding user. Skipping...\n"; next; } $insert->execute($trackid,$uid,@rest) or die $database->errstr; } $select->finish(); $insert->finish(); $database->do('drop table uploads') or die "Couldn't drop old uploads table"; $database->do('alter table uploads_new rename to uploads') or die "Couldn't rename new uploads table"; # now do the openid_users table # this creates the new one check_table('openid_users', $openid_columns); check_table('openid_users_new', $openid_columns); $select = $database->prepare(<errstr; SELECT b.sessionid,a.openid_url,b.userid FROM openid_users as a,session as b WHERE a.userid=b.userid END ; $insert = $database->prepare(<errstr; REPLACE INTO openid_users_new(userid,openid_url) VALUES (?,?) END ; $select->execute() or die $select->errstr; while (my ($sessionid,$url,$userid) = $select->fetchrow_array()) { $insert->execute($userid,$url) or die $insert->errstr; } $select->finish(); $insert->finish(); $database->do('drop table openid_users') or die "Couldn't drop old openid_users table: ",$database->errstr; $database->do('alter table openid_users_new rename to openid_users') or die "Couldn't rename new openid_users table: ",$database->errstr; $database->commit(); }; if ($@) { warn "upgrade failed due to $@. Rolling back"; eval {$database->rollback()}; die "Can't continue"; } else { print STDERR "Successfully upgraded schema from 0 to 1.\n"; } } sub upgrade_from_1_to_2 { # Create sharing table. check_table("sharing", $sharing_columns); local $database->{AutoCommit} = 0; local $database->{RaiseError} = 1; eval { # Upgrade sharing table from my $select = $database->prepare("SELECT trackid, users, public_users FROM uploads") or die $database->errstr; $select->execute(); my $run = 0; while (my ($trackid, $users, $public_users) = $select->fetchrow_array()) { my @users = split ", ", $users if $users; my @public_users = split ", ", $public_users if $public_users; $database->do("INSERT INTO sharing (trackid, userid, public) VALUES (?, ?, ?)", undef, $trackid, $_, 0) foreach @users; $database->do("INSERT INTO sharing (trackid, userid, public) VALUES (?, ?, ?)", undef, $trackid, $_, 1) foreach @public_users; $run = 1 if ($users || $public_users); } # Now delete the users & public_users columns from the database. check_table("uploads", $uploads_columns); $select->finish(); $database->commit() if $run; }; if ($@) { warn "upgrade failed due to $@. Rolling back"; eval {$database->rollback()}; die "Can't continue"; } else { print STDERR "Successfully upgraded schema from 1 to 2.\n"; } } sub upgrade_from_2_to_3 { # add the gecos field check_table('users',$users_columns); } sub upgrade_from_3_to_4 { # change the size of the password table in the users table local $database->{AutoCommit} = 0; local $database->{RaiseError} = 1; eval { check_table("users_new",$users_columns); my $select = $database->prepare(<errstr; SELECT userid,email,pass,gecos,remember,openid_only,confirmed,cnfrm_code,last_login,created FROM users END ; # query to insert data into new users table my $insert = $database->prepare(<errstr; REPLACE INTO users_new (userid,email,pass,gecos,remember,openid_only,confirmed,cnfrm_code,last_login,created) VALUES (?,?,?,?,?,?,?,?,?,?) END ; $select->execute(); while (my @cols = $select->fetchrow_array) { $insert->execute(@cols); } $select->finish; $insert->finish; $database->do('drop table users') or die "Couldn't drop old users table"; $database->do('alter table users_new rename to users') or die "Couldn't rename new users table"; $database->commit(); }; if ($@) { warn "upgrade failed due to $@. Rolling back"; eval {$database->rollback()}; die "Can't continue"; } else { print STDERR "Successfully upgraded schema from 3 to 4.\n"; } } __END__ GBrowse-2.56/bin/gbrowse_netinstall.pl000555001750001750 4136113036764442 20205 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME gbrowse_netinstall.pl =head1 SYNOPSIS gbrowse_netinstall.pl -b|--build_param_str BUILD_STRING [options] options: -h|--help Show this message -d|--dev Use the developement version of both GBrowse and bioperl from CVS --bioperl_dev Use the development version of BioPerl from git --gbrowse_dev Use the development version of GBrowse from SVN --build_param_str= Use this string to set Makefile.PL parameters such as CONF or PREFIX for GBrowse installation --install_param_str= Use this string to predefine 'make install' parameters such as CONF or PREFIX for GBrowse installation --wincvs WinCVS is present--allow cvs install on Windows NOTE: This will not work; GBrowse is in svn now, so this script will have to be updated --gbrowse_path Path to GBrowse tarball (will not download GBrowse); Assumes a resulting 'Generic-Genome-Browser' directory --bioperl_path Path to BioPerl tarball (will not download BioPerl); Assumes a resulting'bioperl-live' directory --skip_start Don't wait for 'Enter' at program start --skip_bioperl Don't fetch and install BioPerl; assumes a working bioperl is already installed =head1 DESCRIPTION Net-based installer of GBrowse Save this to disk as "gbrowse_netinstall.pl" and run: [sudo] perl gbrowse_netinstall.pl =cut # Universal Net-based installer # Save this to disk as "gbrowse_netinstall.pl" and run: # perl gbrowse_netinstall.pl use warnings; use strict; use CPAN '!get'; use Config; use Getopt::Long; use Pod::Usage; use File::Copy qw( cp move ); use File::Temp qw(tempdir); use LWP::Simple; use Cwd; use constant NMAKE => 'http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe'; my ( $show_help, $get_from_cvs, $build_param_string, $working_dir, $get_gbrowse_cvs, $get_bioperl_svn, $is_cygwin, $windows, $binaries, $make, $tmpdir, $wincvs, $gbrowse_path,$bioperl_path, $skip_start, $install_param_string, $skip_bioperl, $perl_path); BEGIN { GetOptions( 'h|help' => \$show_help, # Show help and exit 'd|dev' => \$get_from_cvs, # Use the dev svn 'build_param_str=s' => \$build_param_string, # Build parameters 'bioperl_dev' => \$get_bioperl_svn, 'gbrowse_dev' => \$get_gbrowse_cvs, 'wincvs' => \$wincvs, 'gbrowse_path=s' => \$gbrowse_path, 'bioperl_path=s' => \$bioperl_path, 'install_param_str=s' => \$install_param_string, 'skip_start' => \$skip_start, 'skip_bioperl' => \$skip_bioperl, ) or pod2usage(2); pod2usage(2) if $show_help; $perl_path = $Config{perlpath}; print STDERR "\nAbout to install GBrowse and all its prerequisites.\n"; print STDERR "\nYou will be asked various questions during this process. You can almost always"; print STDERR "\naccept the default answer (with a notable exception of libgd on MacOSX;\n"; print STDERR "see the documentation on the GMOD website for more information.)\n"; print STDERR "The whole process will take several minutes and will generate lots of messages.\n"; print STDERR "\nPress return when you are ready to start!\n"; my $h = <> unless $skip_start; print STDERR "*** Installing Perl files needed for a net-based install ***\n"; $windows = $Config{osname} =~ /mswin/i; if ($windows and $] == 5.010) { print STDERR "\n\nActiveState Perl 5.10 is not compatible with GBrowse due to problems\n"; print STDERR "with the AS implementation. Please remove it and install Perl 5.8 instead.\n\n\n"; exit(0); } if ($windows) { print STDERR "\n\nInstalling Win32 perl module\n\n"; system("ppm install Win32"); } eval "CPAN::Config->load"; eval "CPAN::Config->commit"; $working_dir = getcwd; $tmpdir = tempdir(CLEANUP=>1) or die "Could not create temporary directory: $!"; $binaries = $Config{'binexp'}; $make = $Config{'make'}; if ($windows) { system("ppm install YAML"); } else { CPAN::Shell->install('YAML'); } CPAN::Shell->install('Archive::Zip'); CPAN::Shell->install('HTML::Tagset'); CPAN::Shell->install('LWP::Simple'); eval "use Archive::Zip ':ERROR_CODES',':CONSTANTS'"; if ($windows && !-e "$binaries/${make}.exe") { print STDERR "Installing make utility...\n"; -w $binaries or die "$binaries directory is not writeable. Please re-login as Admin.\n"; chdir $tmpdir; my $rc = mirror(NMAKE,"nmake.zip"); die "Could not download nmake executable from Microsoft web site." unless $rc == RC_OK() or $rc == RC_NOT_MODIFIED(); my $zip = Archive::Zip->new('nmake.zip') or die "Couldn't open nmake zip file for decompression: $!"; $zip->extractTree == AZ_OK() or die "Couldn't unzip file: $!"; -e 'NMAKE.EXE' or die "Couldn't extract nmake.exe"; cp('NMAKE.EXE',"$binaries/${make}.EXE") or die "Couldn't install nmake.exe: $!"; cp('NMAKE.ERR',"$binaries/${make}.ERR"); # or die "Couldn't install nmake.err: $!"; # not fatal } CPAN::Shell->install('Archive::Tar'); #print STDERR $@; #print STDERR "at end of BEGIN{}\n"; 1; }; #print STDERR "here i am\n"; #print STDERR $@; use Archive::Tar; #use CPAN '!get'; $is_cygwin = 1 if ( $^O eq 'cygwin' ); if ($get_from_cvs) { $get_bioperl_svn = $get_gbrowse_cvs = 1; } if ($wincvs or ($windows and $get_from_cvs)) { die "\n\nGBrowse is now in svn and fetching from svn on Windows\nis not currently supported\n "; } if ($windows and !$wincvs and $get_gbrowse_cvs ) { die "\n\nThe development/cvs tags are not supported on Windows when\n" ."WinCVS is not installed; exiting...\n"; } $build_param_string ||=""; $install_param_string ||=""; use constant BIOPERL_VERSION => 'BioPerl-1.6.1'; use constant BIOPERL_REQUIRES => '1.006001'; # sorry for the redundancy use constant BIOPERL_LIVE_URL => 'http://github.com/bioperl/bioperl-live/tarball/master'; use constant GBROWSE_DEFAULT => 'Generic-Genome-Browser-1.70'; use constant SOURCEFORGE_MIRROR2 => 'http://superb-west.dl.sourceforge.net/sourceforge/gmod/'; use constant SOURCEFORGE_MIRROR1 => 'http://easynews.dl.sourceforge.net/sourceforge/gmod/'; use constant SOURCEFORGE_GBROWSE => 'http://sourceforge.net/project/showfiles.php?group_id=27707&package_id=34513'; use constant BIOPERL => 'http://bioperl.org/DIST/'.BIOPERL_VERSION.'.tar.gz'; my %REPOSITORIES = ( #'BioPerl-Release-Candidates' => 'http://bioperl.org/DIST/RC', 'BioPerl-Regular-Releases' => 'http://bioperl.org/DIST', 'Kobes' => 'http://theoryx5.uwinnipeg.ca/ppms', 'Bribes' => 'http://www.Bribes.org/perl/ppm', 'tcool' => 'http://ppm.tcool.org/archives/', ); # this is so that ppm can be called in a pipe $ENV{COLUMNS} = 80; # why do we have to do this? $ENV{LINES} = 24; setup_ppm() if $windows; unless ( eval "use GD 2.31; 1" ) { if ($windows) { print STDERR "Installing GD via ppm.\n"; print STDERR "(This may take a while...\n"; system("ppm install GD"); } else { print STDERR "Installing GD via CPAN...\n"; CPAN::Shell->install('GD') unless eval "use GD 2.31; 1"; } } print STDERR "\n*** Installing prerequisites for BioPerl ***\n"; if ($windows and !eval "use DB_File; 1") { print STDERR "Installing DB_File for BioPerl.\n"; # GBrowse doesn't like DB_File 1.820, so we explicitly get DB_File by url system("ppm install http://ppm.tcool.org/archives/DB_File.ppd"); } system("ppm install SVG") if $windows; CPAN::Shell->install('GD::SVG'); CPAN::Shell->install('IO::String'); CPAN::Shell->install('Text::Shellwords'); if ($windows) { #CGI::Session and Digest::MD5 both fail to install via cpan on windows system("ppm install CGI-Session"); system("ppm install Digest-MD5"); } else { CPAN::Shell->install('CGI::Session'); CPAN::Shell->install('Digest::MD5'); } CPAN::Shell->install('File::Temp'); CPAN::Shell->install('Class::Base'); CPAN::Shell->install('Statistics::Descriptive'); CPAN::Shell->install('Data::Stag'); unless ($skip_bioperl) { my $version = BIOPERL_REQUIRES; if (!(eval "use Bio::Perl $version; 1") or $get_bioperl_svn or $bioperl_path) { print STDERR "\n*** Installing BioPerl ***\n"; #would like to use ppm, but ppm won't install 1.6 #if ($windows and !$get_bioperl_svn and !$bioperl_path) { # my $bioperl_index = find_bioperl_ppm(); # system("ppm install --force $bioperl_index"); #} else { # recent versions of Module::Build fail to install without force! CPAN::Shell->force('Module::Build') unless eval "require Module::Build; 1"; do_install(BIOPERL, 'bioperl.tgz', BIOPERL_VERSION, 'Build', $get_bioperl_svn ? 'svn' : '', '', $bioperl_path, '', $perl_path); #} } else { print STDERR "BioPerl is up to date.\n"; } } print STDERR "\n *** Installing Bio::Graphics ***\n"; CPAN::Shell->install('Bio::Graphics'); print STDERR "\n *** Installing Generic-Genome-Browser ***\n"; my $latest_version = find_gbrowse_latest(); ##the find_gbrowse_latest function is broken at the moment; since ##the version of GBrowse 1 is unlike to change more than once in the ##near future, we'll just hard code the value $latest_version = 'Generic-Genome-Browser-1.70'; my $gbrowse = SOURCEFORGE_MIRROR1.$latest_version.'.tar.gz'; eval {do_install($gbrowse, 'gbrowse.tgz', $latest_version, 'make', $get_gbrowse_cvs ? 'svn' : '', $build_param_string, $gbrowse_path, $install_param_string, $perl_path)}; if ($@ =~ /Could not download/) { print STDERR "Could not download: server down? Trying a different server...\n"; $gbrowse = SOURCEFORGE_MIRROR2.$latest_version.'.tar.gz'; do_install($gbrowse, 'gbrowse.tgz', $latest_version, 'make', $get_gbrowse_cvs? 'svn' : '', $build_param_string, $gbrowse_path, $install_param_string, $perl_path,); } exit 0; END { open STDERR,">/dev/null"; # windows has an annoying message when cleaning up temp file } sub do_install { my ($download,$local_name,$distribution,$method, $from_cvs,$build_param_string,$file_path,$install_param_string, $perl_path) = @_; $install_param_string ||= ''; chdir $tmpdir; do_get_distro($download,$local_name,$distribution,$from_cvs,$file_path); my $build_str = $windows ? "Build" : "./Build"; if ($method eq 'make') { system("$perl_path Makefile.PL $build_param_string") == 0 or die "Couldn't run perl Makefile.PL command\n"; system("$make install UNINST=1 $install_param_string") == 0 ; } elsif ($method eq 'Build') { system("$perl_path $build_str.PL --yes=1") == 0 or die "Couldn't run perl Build.PL command\n"; system("$build_str install --uninst 1") == 0; } } sub do_get_distro { my ($download,$local_name,$distribution,$distribution_method,$file_path) = @_; if ($file_path) { chdir $working_dir; if (-e $file_path) { #must be an absolute path cp($file_path, "$tmpdir/$local_name"); } elsif (-e "$working_dir/$file_path") { #assume it's a rel path from the original directory cp("$working_dir/$file_path", "$tmpdir/$local_name"); } else { print "Couldn't find $file_path; nothing to do so quitting...\n"; exit(-1); } $distribution = ($local_name =~ /gbrowse/) ? "Generic-Genome-Browser" : "bioperl-live"; chdir $tmpdir; extract_tarball($local_name,$distribution); } elsif ($distribution_method) { my $distribution_dir; if ($local_name =~ /gbrowse/) { $distribution_dir = 'Generic-Genome-Browser'; unless ( #should do an svn checkout of the stable branch (system( "$distribution_method co https://gmod.svn.sourceforge.net/svnroot/gmod/Generic-Genome-Browser/branches/stable $distribution_dir") == 0 or $is_cygwin) ) { print STDERR "Failed to check out the GBrowse from svn: $!\n"; return undef; } } else { #bioperl print STDERR "Downloading bioperl-live...\n"; $distribution_dir = 'bioperl-live'; my $filename = 'bioperl-live.tar.gz'; # =determine_filename(); my $url = BIOPERL_LIVE_URL."/$filename"; my $rc = mirror($url, $filename); unless ($rc == RC_OK or $rc == RC_NOT_MODIFIED){ print STDERR "Failed to get nightly bioperl-live file: $rc\n"; return undef; } extract_tarball($filename,$distribution_dir); return 1; } chdir $distribution_dir or die "Couldn't enter $distribution_dir directory: $@"; } else { print STDERR "Downloading $download...\n"; my $rc = mirror($download,$local_name); die "Could not download $distribution distribution from $download." unless $rc == RC_OK or $rc == RC_NOT_MODIFIED; extract_tarball($local_name,$distribution); } return 1; } #this is probably not going to be needed again, as the nightly #bioperl build names have been simplified sub determine_filename { my $listing = "dirlisting.html"; my $rc = mirror(BIOPERL_LIVE_URL, $listing); die "Could not get directory listing of bioperl nightly build url: $rc\n" unless ($rc == RC_OK or $rc == RC_NOT_MODIFIED); my $filename; open LIST, $listing or die "unable to open $listing: $!\n"; while () { if (/href="(bioperl-live.*?\.tar\.gz)"/) { $filename = $1; last; } } close LIST; unlink $listing; return $filename; } sub extract_tarball { my ($local_name,$distribution) = @_; print STDERR "Unpacking $local_name...\n"; my $z = Archive::Tar->new($local_name,1) or die "Couldn't open $distribution archive: $@"; my @extracted = $z->extract() or die "Couldn't extract $distribution archive: $@"; if (%{$extracted[0]}->{'name'} =~ /^(bioperl.*?)\//) { my $bioperl_dir = $1; warn $bioperl_dir; move($bioperl_dir, $distribution) or die "couldn't move bioperl dir: $@"; } $distribution =~ s/--/-/; chdir $distribution or die "Couldn't enter $distribution directory: $@"; return; } # make sure ppm repositories are correct! sub setup_ppm { open S,"ppm repo list --csv|" or die "Couldn't open ppm for listing: $!"; my %repository; while () { chomp; my($index,$package_count,$name) = split /,/; $repository{$name} = $index; } close S; print STDERR "Adding needed PPM repositories. This may take a while....\n"; for my $name (keys %REPOSITORIES) { next if $repository{$name}; system("ppm rep add $name $REPOSITORIES{$name}"); } } sub find_bioperl_ppm { print STDERR "Finding most recent bioperl..."; open S,"ppm search bioperl |" or die "Couldn't open ppm for listing: $!"; local $/ = ''; # paragraph mode my ($blessed_one,$blessed_version); my $best = 0; while () { chomp; my ($number) = /^(\d+): bioperl/m; my ($version) = /^\s+Version: (.+)/m; my ($repository) = /^\s+Repo: (.+)/m; my $multiplier = 10000000; my $magnitude = 0; # this dumb thing converts 1.5.1 into a real number foreach (split /[._]/,$version) { $magnitude += $_ * ($multiplier/=10); } ($blessed_one,$best,$blessed_version) = ($number,$magnitude,$version) if $best < $magnitude; } close S; print STDERR $blessed_version ? "found $blessed_version\n" : "not found\n"; return $blessed_one; } sub find_gbrowse_latest { # print STDERR "Looking up most recent version..."; my $download_page = get(SOURCEFORGE_GBROWSE); my @files = $download_page =~ /(Generic-Genome-Browser--?\d+\.\d+)/g; my %versions = map {/(\d+\.\d+)/ => $_} @files; my @versions = sort {$b<=>$a} keys %versions; my $version = $versions[0] || GBROWSE_DEFAULT ; # print STDERR $version,"\n"; return $version; } GBrowse-2.56/bin/gbrowse_netinstall2.pl000555001750001750 3526113036764442 20271 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME gbrowse_netinstall.pl =head1 SYNOPSIS gbrowse_netinstall.pl -b|--build_param_str BUILD_STRING [options] options: -h|--help Show this message -d|--dev Use the developement version of both GBrowse and bioperl from CVS --bioperl_dev Use the development version of BioPerl from SVN --gbrowse_dev Use the development version of GBrowse from CVS --build_param_str= Use this string to set Makefile.PL parameters such as CONF or PREFIX for GBrowse installation --install_param_str= Use this string to predefine 'make install' parameters such as CONF or PREFIX for GBrowse installation --wincvs WinCVS is present--allow cvs install on Windows --gbrowse_path Path to GBrowse tarball (will not download GBrowse); Assumes a resulting 'Generic-Genome-Browser' directory --bioperl_path Path to BioPerl tarball (will not download BioPerl); Assumes a resulting'bioperl-live' directory --skip_start Don't wait for 'Enter' at program start =head1 DESCRIPTION Net-based installer of GBrowse Save this to disk as "gbrowse_netinstall.pl" and run: [sudo] perl gbrowse_netinstall.pl =cut # Universal Net-based installer # Save this to disk as "gbrowse_netinstall.pl" and run: # perl gbrowse_netinstall.pl use warnings; use strict; use CPAN; use Config; use Getopt::Long; use Pod::Usage; use File::Copy 'cp'; use File::Temp qw(tempdir); use LWP::Simple; use Cwd; use constant NMAKE => 'http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe'; my ( $show_help, $get_from_cvs, $build_param_string, $working_dir, $get_gbrowse_cvs, $get_bioperl_svn, $is_cygwin, $windows, $binaries, $make, $tmpdir, $wincvs, $gbrowse_path,$bioperl_path, $skip_start, $install_param_string, ); BEGIN { GetOptions( 'h|help' => \$show_help, # Show help and exit 'd|dev' => \$get_from_cvs, # Use the dev cvs 'build_param_str=s' => \$build_param_string, # Build parameters 'bioperl_dev' => \$get_bioperl_svn, 'gbrowse_dev' => \$get_gbrowse_cvs, 'wincvs' => \$wincvs, 'gbrowse_path=s' => \$gbrowse_path, 'bioperl_path=s' => \$bioperl_path, 'install_param_str=s' => \$install_param_string, 'skip_start' => \$skip_start, ) or pod2usage(2); pod2usage(2) if $show_help; print STDERR "\nAbout to install GBrowse and all its prerequisites.\n"; print STDERR "\nYou will be asked various questions during this process. You can almost always"; print STDERR "\naccept the default answer (with a notable exception of libgd on MacOSX;\n"; print STDERR "see the documentation on the GMOD website for more information.)\n"; print STDERR "The whole process will take several minutes and will generate lots of messages.\n"; print STDERR "\nNOTE: This installer will install bioperl-live, as the most recent GBrowse\n"; print STDERR "requires the many changes that have gone into BioPerl since its last release\n\n"; print STDERR "\nPress return when you are ready to start!\n"; my $h = <> unless $skip_start; print STDERR "*** Installing Perl files needed for a net-based install ***\n"; eval "CPAN::Config->load"; eval "CPAN::Config->commit"; $working_dir = getcwd; $tmpdir = tempdir(CLEANUP=>1) or die "Could not create temporary directory: $!"; $windows = $Config{osname} =~ /mswin/i; $binaries = $Config{'binexp'}; $make = $Config{'make'}; if ($windows) { system("ppm install YAML"); } else { CPAN::Shell->install('YAML'); } CPAN::Shell->install('Archive::Zip'); CPAN::Shell->install('HTML::Tagset'); CPAN::Shell->install('LWP::Simple'); eval "use Archive::Zip ':ERROR_CODES',':CONSTANTS'"; if ($windows && !-e "$binaries/${make}.exe") { print STDERR "Installing make utility...\n"; -w $binaries or die "$binaries directory is not writeable. Please re-login as Admin.\n"; chdir $tmpdir; my $rc = mirror(NMAKE,"nmake.zip"); die "Could not download nmake executable from Microsoft web site." unless $rc == RC_OK() or $rc == RC_NOT_MODIFIED(); my $zip = Archive::Zip->new('nmake.zip') or die "Couldn't open nmake zip file for decompression: $!"; $zip->extractTree == AZ_OK() or die "Couldn't unzip file: $!"; -e 'NMAKE.EXE' or die "Couldn't extract nmake.exe"; cp('NMAKE.EXE',"$binaries/${make}.EXE") or die "Couldn't install nmake.exe: $!"; cp('NMAKE.ERR',"$binaries/${make}.ERR"); # or die "Couldn't install nmake.err: $!"; # not fatal } CPAN::Shell->install('Archive::Tar'); #print STDERR $@; #print STDERR "at end of BEGIN{}\n"; 1; }; #print STDERR "here i am\n"; #print STDERR $@; use Archive::Tar; use CPAN '!get'; $is_cygwin = 1 if ( $^O eq 'cygwin' ); if ($get_from_cvs) { $get_bioperl_svn = $get_gbrowse_cvs = 1; } if ($windows and !$wincvs and $get_gbrowse_cvs ) { die "\n\nThe development/cvs tags are not supported on Windows when\n" ."WinCVS is not installed; exiting...\n"; } $build_param_string ||=""; $install_param_string ||=""; use constant BIOPERL_VERSION => 'bioperl-1.5.2_103'; use constant BIOPERL_REQUIRES => '1.005003'; # sorry for the redundancy use constant BIOPERL_LIVE_URL => 'http://bioperl.org/DIST/nightly_builds/'; use constant GBROWSE_DEFAULT => '2.00'; use constant SOURCEFORGE_MIRROR1 => 'http://superb-west.dl.sourceforge.net/sourceforge/gmod/'; use constant SOURCEFORGE_MIRROR2 => 'http://easynews.dl.sourceforge.net/sourceforge/gmod/'; use constant SOURCEFORGE_GBROWSE => 'http://sourceforge.net/project/showfiles.php?group_id=27707&package_id=34513'; use constant BIOPERL => 'http://bioperl.org/DIST/'.BIOPERL_VERSION.'.tar.gz'; my %REPOSITORIES = ('BioPerl-Release-Candidates' => 'http://bioperl.org/DIST/RC', 'BioPerl-Regular-Releases' => 'http://bioperl.org/DIST', 'Kobes' => 'http://theoryx5.uwinnipeg.ca/ppms', 'Bribes' => 'http://www.Bribes.org/perl/ppm'); # this is so that ppm can be called in a pipe $ENV{COLUMNS} = 80; # why do we have to do this? $ENV{LINES} = 24; setup_ppm() if $windows; unless ( eval "use GD 2.31; 1" ) { if ($windows) { print STDERR "Installing GD via ppm.\n"; print STDERR "(This may take a while...\n"; system("ppm install GD"); } else { print STDERR "Installing GD via CPAN...\n"; CPAN::Shell->install('GD') unless eval "use GD 2.31; 1"; } } print STDERR "\n*** Installing prerequisites for BioPerl ***\n"; if ($windows and !eval "use DB_File; 1") { print STDERR "Installing DB_File for BioPerl.\n"; system("ppm install DB_File"); } system("ppm install SVG") if $windows; CPAN::Shell->install('GD::SVG'); CPAN::Shell->install('IO::String'); CPAN::Shell->install('Text::Shellwords'); CPAN::Shell->install('CGI::Session'); CPAN::Shell->install('File::Temp'); CPAN::Shell->install('Class::Base'); CPAN::Shell->install('Digest::MD5'); CPAN::Shell->install('Statistics::Descriptive'); CPAN::Shell->install('JSON'); CPAN::Shell->install('JSON::Any'); # recent versions of Module::Build fail to install without force! CPAN::Shell->force(install=>'Module::Build') unless eval "require Module::Build; 1"; my $version = BIOPERL_REQUIRES; if (!(eval "use Bio::Perl $version; 1") or $get_bioperl_svn or $bioperl_path) { print STDERR "\n*** Installing BioPerl ***\n"; if ($windows and !$get_bioperl_svn and !$bioperl_path) { my $bioperl_index = find_bioperl_ppm(); system("ppm install --force $bioperl_index"); } else { do_install(BIOPERL, 'bioperl.tgz', BIOPERL_VERSION, 'Build', $get_bioperl_svn ? 'svn' : '', '', $bioperl_path); } } else { print STDERR "BioPerl is up to date.\n"; } print STDERR "\n *** Installing Generic-Genome-Browser ***\n"; my $latest_version = find_gbrowse_latest(); my $gbrowse = SOURCEFORGE_MIRROR1.$latest_version.'.tar.gz'; eval {do_install($gbrowse, 'gbrowse.tgz', $latest_version, 'Build', $get_gbrowse_cvs ? 'cvs' : '', $build_param_string, $gbrowse_path, $install_param_string)}; if ($@ =~ /Could not download/) { print STDERR "Could not download: server down? Trying a different server...\n"; $gbrowse = SOURCEFORGE_MIRROR2.$latest_version.'.tar.gz'; do_install($gbrowse,'gbrowse.tgz',$latest_version,'make',$get_gbrowse_cvs,$build_param_string,$install_param_string); } exit 0; END { open STDERR,">/dev/null"; # windows has an annoying message when cleaning up temp file } sub do_install { my ($download,$local_name,$distribution,$method, $from_cvs,$build_param_string,$file_path,$install_param_string) = @_; chdir $tmpdir; do_get_distro($download,$local_name,$distribution,$from_cvs,$file_path); my $build_str = $windows ? "Build" : "./Build"; if ($method eq 'make') { system("perl Makefile.PL $build_param_string") == 0 or die "Couldn't run perl Makefile.PL command\n"; system("$make install UNINST=1 $install_param_string") == 0 ; } elsif ($method eq 'Build') { system("perl $build_str.PL --yes=1") == 0 or die "Couldn't run perl Build.PL command\n"; system("$build_str install --uninst 1") == 0; } } sub do_get_distro { my ($download,$local_name,$distribution,$distribution_method,$file_path) = @_; if ($file_path) { chdir $working_dir; if (-e $file_path) { #must be an absolute path cp($file_path, "$tmpdir/$local_name"); } elsif (-e "$working_dir/$file_path") { #assume it's a rel path from the original directory cp("$working_dir/$file_path", "$tmpdir/$local_name"); } else { print "Couldn't find $file_path; nothing to do so quitting...\n"; exit(-1); } $distribution = ($local_name =~ /gbrowse/) ? "Generic-Genome-Browser" : "bioperl-live"; chdir $tmpdir; extract_tarball($local_name,$distribution); } elsif ($distribution_method) { my $distribution_dir; if ($local_name =~ /gbrowse/) { $distribution_dir = 'Generic-Genome-Browser'; print STDERR "\n\nPlease press return when prompted for a password.\n"; unless ( (system( "$distribution_method -d:pserver:anonymous\@gmod.cvs.sourceforge.net:/cvsroot/gmod login")==0 or $is_cygwin) && (system( "$distribution_method -z3 -d:pserver:anonymous\@gmod.cvs.sourceforge.net:/cvsroot/gmod co -kb -P Generic-Genome-Browser") == 0 or $is_cygwin) ) { print STDERR "Failed to check out the GBrowse from CVS: $!\n"; return undef; } } else { #bioperl print STDERR "Downloading bioperl-live...\n"; $distribution_dir = 'bioperl-live'; my $filename = 'bioperl-live.tar.gz'; # =determine_filename(); my $url = BIOPERL_LIVE_URL."/$filename"; my $rc = mirror($url, $filename); unless ($rc == RC_OK or $rc == RC_NOT_MODIFIED){ print STDERR "Failed to get nightly bioperl-live file: $rc\n"; return undef; } extract_tarball($filename,$distribution_dir); return 1; } chdir $distribution_dir or die "Couldn't enter $distribution_dir directory: $@"; } else { print STDERR "Downloading $download...\n"; my $rc = mirror($download,$local_name); die "Could not download $distribution distribution from $download." unless $rc == RC_OK or $rc == RC_NOT_MODIFIED; extract_tarball($local_name,$distribution); } return 1; } #this is probably not going to be needed again, as the nightly #bioperl build names have been simplified sub determine_filename { my $listing = "dirlisting.html"; my $rc = mirror(BIOPERL_LIVE_URL, $listing); die "Could not get directory listing of bioperl nightly build url: $rc\n" unless ($rc == RC_OK or $rc == RC_NOT_MODIFIED); my $filename; open LIST, $listing or die "unable to open $listing: $!\n"; while () { if (/href="(bioperl-live.*?\.tar\.gz)"/) { $filename = $1; last; } } close LIST; unlink $listing; return $filename; } sub extract_tarball { my ($local_name,$distribution) = @_; print STDERR "Unpacking $local_name...\n"; my $z = Archive::Tar->new($local_name,1) or die "Couldn't open $distribution archive: $@"; $z->extract() or die "Couldn't extract $distribution archive: $@"; $distribution =~ s/--/-/; chdir $distribution or die "Couldn't enter $distribution directory: $@"; return; } # make sure ppm repositories are correct! sub setup_ppm { open S,"ppm repo list --csv|" or die "Couldn't open ppm for listing: $!"; my %repository; while () { chomp; my($index,$package_count,$name) = split /,/; $repository{$name} = $index; } close S; print STDERR "Adding needed PPM repositories. This may take a while....\n"; for my $name (keys %REPOSITORIES) { next if $repository{$name}; system("ppm rep add $name $REPOSITORIES{$name}"); } } sub find_bioperl_ppm { print STDERR "Finding most recent bioperl..."; open S,"ppm search bioperl |" or die "Couldn't open ppm for listing: $!"; local $/ = ''; # paragraph mode my ($blessed_one,$blessed_version); my $best = 0; while () { chomp; my ($number) = /^(\d+): bioperl/m; my ($version) = /^\s+Version: (.+)/m; my ($repository) = /^\s+Repo: (.+)/m; my $multiplier = 10000000; my $magnitude = 0; # this dumb thing converts 1.5.1 into a real number foreach (split /[._]/,$version) { $magnitude += $_ * ($multiplier/=10); } ($blessed_one,$best,$blessed_version) = ($number,$magnitude,$version) if $best < $magnitude; } close S; print STDERR $blessed_version ? "found $blessed_version\n" : "not found\n"; return $blessed_one; } sub find_gbrowse_latest { # print STDERR "Looking up most recent version..."; my $download_page = get(SOURCEFORGE_GBROWSE); my @files = $download_page =~ /(Generic-Genome-Browser--?\d+\.\d+)/g; my %versions = map {/(\d+\.\d+)/ => $_} @files; my @versions = sort {$b<=>$a} keys %versions; my $version = $versions[0] || GBROWSE_DEFAULT ; # print STDERR $version,"\n"; return $versions{$version}; } GBrowse-2.56/bin/gbrowse_set_admin_passwd.pl000555001750001750 472213036764442 21334 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use FindBin '$Bin'; use lib "$Bin/../lib"; use GBrowse::ConfigData; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::UserDB; use Getopt::Long; my ($name,$pass); my @ORIGINAL_ARGV = @ARGV; GetOptions('name=s' => \$name, 'password=s' => \$pass) or die <config('wwwuser'); my $uid = (getpwnam($wwwuser))[2]; unless ($uid == $<) { print STDERR "Not running as $wwwuser. Trying to use sudo to remedy. You may be asked for your login password.\n"; my @args = ('sudo','-u',$wwwuser,$0, @ORIGINAL_ARGV); exec @args; exit 0; } my $globals = Bio::Graphics::Browser2->open_globals or die "Couldn't open GBrowse.conf"; my $userdb = Bio::Graphics::Browser2::UserDB->new($globals); $name ||= $globals->admin_account; unless ($pass) { print STDERR "New password for $name: "; system "stty -echo"; $pass = ; chomp($pass); print STDERR "\n"; my $newpass; print STDERR "New password for $name (confirm): "; $newpass = ; chomp($newpass); print STDERR "\n"; system "stty echo"; die "Passwords don't match!\n" unless $pass eq $newpass; } $userdb->delete_user_by_username($name); # this creates a new session for the admin user my $session = $globals->session; my $sessionid = $session->id; my $uploadsid = $session->uploadsid; $session->flush(); my ($status,undef,$message) = $userdb->do_add_user($name,'admin@nowhere.net','GBrowse Administrator',$pass,$sessionid,'allow admin'); warn $message,"\n"; $userdb->set_confirmed_from_username($name); warn "Admin account \"$name\" is now registered with sessionid=$sessionid, uploadsid=$uploadsid.\n" if $message =~ /success/i; exit 0; __END__ GBrowse-2.56/bin/gbrowse_slave000555001750001750 616013036764442 16506 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Getopt::Long; use FindBin '$Bin'; use lib "$Bin/../lib"; use Bio::Graphics::Browser2::Render::Slave; use constant DEFAULT_PORT => 8101; my ($port,$debug,$logfile,$pidfile,$user,$kill,$preload,$tmpdir,$prefork_copies); my $usage = < Network port number to listen to (default 8101). --prefork -f Number of preforked copies to run (default 1) --verbose -v Verbosity level (0-3) --user -u User to run under (same as current) --log -l Log file path (default, use STDERR) --pid PID file path (default, none) --kill -k Kill running server (use in conjunction with --pid). --preload Path to a config file containing override information and databases to preload --tmp|-T Override location of configuration file cache files. Bare-naked Gbrowse render server. Launch with the port number to listen on. No other configuration information is necessary. The needed configuration will be transmitted from the master server at run time. If you need to override some configuration information (for example, to specify a different tmp_base directory for session information), you may place it in a configuration file in the [GENERAL] section. All options in the [GENERAL] section will override the transmitted information. Any [name:database] sections containing database information located in the preload config file will be preloaded to reduce execution latency. USAGE ; Getopt::Long::Configure('bundling'); GetOptions('port|p=i' => \$port, 'prefork|f=i' => \$prefork_copies, 'verbose|v=i' => \$debug, 'logfile|l=s' => \$logfile, 'pidfile|pid=s' => \$pidfile, 'user|u=s' => \$user, 'kill|k' => \$kill, 'preload=s' => \$preload, 'tmp|T=s' => \$tmpdir, ) or die $usage; if ($kill) { kill_running_server(); exit 0; } $port ||= DEFAULT_PORT; $prefork_copies ||= 1; my $server = Bio::Graphics::Browser2::Render::Slave->new(LocalPort=>$port, User => $user, LogFile => $logfile, PidFile => $pidfile, PreForkCopies => $prefork_copies, CCacheDir=> $tmpdir, ) or die "Could not create server.\n"; $server->preload_databases($preload) if $preload && -r $preload; $server->debug($debug); $server->run(); exit 0; sub kill_running_server { my $pid; if ($pidfile) { open my $f,$pidfile or die "Can't open $pidfile: $!"; chomp($pid = <$f>); } elsif (-d '/proc') { # try to get pid from process list opendir my $d,"/proc"; while (my $dir = readdir($d)) { next unless $dir =~ /^\d+$/; open my $f,"/proc/$dir/status" or next; my $cmd = <$f>; $cmd =~ /Name:\s+gbrowse_server/ or next; $pid = $dir; last; } } die "Can't find pid of running slave server" unless $pid; kill TERM => $pid or die "Could not signal process $pid: $!"; warn "Server terminated.\n"; unlink $pidfile if $pidfile; } GBrowse-2.56/bin/gbrowse_slave_start_aws.sh000555001750001750 25313036764442 21163 0ustar00lsteinlstein000000000000#!/bin/sh # pass this as the user data file to the GBrowse AWS image # in order to start up the instance in slave mode. exec /opt/gbrowse/etc/init.d/gbrowse-slave start GBrowse-2.56/bin/gbrowse_syn_load_alignment_database.pl000555001750001750 1235013036764442 23516 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w # $Id: load_alignment_database.pl,v 1.1.2.4 2009-06-03 08:09:26 sheldon_mckay Exp $ use strict; # load_alignment_database.pl -- a script to load the database for gbrowse_syn. # The expected file format is tab-delimited (shown below): # species1 ref1 start1 end1 strand1 cigar_string1 species2 ref2 start2 end2 strand2 cigar_string2 coords1... | coords2... # the coordinate format: pos1_species1 pos1_species2 ... posn_species1 posn_species2 | pos1_species2 pos1_species1 ... posn_species2 posn_species1, # where pos is the matching sequence coordinate (ungapped) in each species. # use strict; use Bio::DB::GFF::Util::Binning 'bin'; use Getopt::Long; use constant MINBIN => 1000; use vars qw/$create $user $pass $dsn $verbose $create $aln_idx/; $| = 1; GetOptions( 'user=s' => \$user, 'pass=s' => \$pass, 'dsn=s' => \$dsn, 'verbose' => \$verbose, 'create' => \$create ); my $usage = "Usage: load_alignment_database.pl -u username -p password -d database [-v, -c] file1, file2 ... filen\n\n"; $dsn || die "Error: no database name\n$usage"; $user || die "Error: no user name\n$usage"; if ($create && $verbose) { print STDERR "\nNote: a new database $dsn will be initialized\n EXISTING DATA WILL BE DELETED\n\n"; } elsif ($verbose) { print STDERR "\nNote: data will be appended to the existing database $dsn\n\n"; } $dsn = "dbi:mysql:$dsn" unless $dsn =~ /^dbi/; eval "require DBI; 1" or die "DBI module not installed. Cannot continue"; my $dbh = DBI->connect($dsn, $user, $pass); unless ($dbh) { $dsn =~ s/\S+\:([^:]+)$/$1/; my $error = DBI->errstr; die <do('drop table if exists alignments') or die DBI->errstr; $dbh->do('drop table if exists map') or die DBI->errstr; $dbh->do(<errstr; create table alignments ( hit_id int not null auto_increment, hit_name varchar(100) not null, src1 varchar(100) not null, ref1 varchar(100) not null, start1 int not null, end1 int not null, strand1 enum('+','-') not null, seq1 mediumtext, bin double(20,6) not null, src2 varchar(100) not null, ref2 varchar(100) not null, start2 int not null, end2 int not null, strand2 enum('+','-') not null, seq2 mediumtext, primary key(hit_id), index(src1,ref1,bin,start1,end1) ) END ; $dbh->do(<errstr; create table map ( map_id int not null auto_increment, hit_name varchar(100) not null, src1 varchar(100), pos1 int not null, pos2 int not null, primary key(map_id), index(hit_name) ) END ; } $dbh->do('alter table alignments disable keys'); $dbh->do('alter table map'); my $sth=$dbh->prepare(<errstr; insert into alignments (hit_name,src1,ref1,start1,end1,strand1,seq1,bin,src2,ref2,start2,end2,strand2,seq2) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?) END ; my $sth2 = $dbh->prepare('insert into map (hit_name,src1,pos1,pos2) values(?,?,?,?)'); my $hit_idx; while (<>) { chomp; my ($src1,$ref1,$start1,$end1,$strand1,$seq1,$src2,$ref2,$start2,$end2,$strand2,$seq2,@maps) = split "\t"; # not using the cigar strings right now ($seq1,$seq2) = ('',''); # deal with coordinate maps my ($switch,@map1,@map2); for (@maps) { if ($_ eq '|') { $switch++; next; } $switch ? push @map2, $_ : push @map1, $_; } my %map1 = @map1; my %map2 = @map2; # standardize hit names my $hit1 = 'H'.pad(++$hit_idx); my $bin1 = scalar bin($start1,$end1,MINBIN); my $bin2 = scalar bin($start2,$end2,MINBIN); my $hit2 = "${hit1}r"; # force ref strand to always be positive and invert target strand as required invert(\$strand1,\$strand2) if $strand1 eq '-'; $sth->execute($hit1,$src1,$ref1,$start1,$end1,$strand1,$seq1,$bin1, $src2,$ref2,$start2,$end2,$strand2,$seq2) or warn $sth->errstr; for my $pos (sort {$a<=>$b} keys %map1) { next unless $pos && $map1{$pos}; $sth2->execute($hit1,$src1,$pos,$map1{$pos}) or die $sth->errstr; } # reciprocal hit is also saved to facilitate switching amongst reference sequences invert(\$strand1,\$strand2) if $strand2 eq '-'; $sth->execute($hit2,$src2,$ref2,$start2,$end2,$strand2,$seq2,$bin2, $src1,$ref1,$start1,$end1,$strand1,$seq1) or warn $sth->errstr; # saving pair-wise coordinate maps -- these are needed for gridlines for my $pos (sort {$a<=>$b} keys %map2) { next unless $pos && $map2{$pos}; $sth2->execute($hit1,$src2,$pos,$map2{$pos}) or die $sth->errstr; } print STDERR " processed $hit1!\r" if $verbose; } $dbh->do('alter table alignments enable keys'); print "\nDone\n"; sub pad { my $num = shift; until ((length $num) >=6) { $num = '0' . $num; } $num; } sub invert { my $strand1 = shift; my $strand2 = shift; $$strand1 = $$strand1 eq '+' ? '-' : '+'; $$strand2 = $$strand2 eq '+' ? '-' : '+'; } GBrowse-2.56/bin/gbrowse_syn_load_alignments_msa.pl000555001750001750 2332613036764442 22722 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w # This script will load the gbrowse_syn alignment database directly from a # multiple sequence alignment file. BEGIN { # Check for DBI before running the script # Doing this here will allow the "compile" tests to pass for GBrowse # even if DBI is not installed. eval { require DBI; DBI->import; }; if ($@) { die "The DBI perl module is required to run this script\n"; } } use strict; use Bio::AlignIO; use List::Util 'sum'; use Getopt::Long; use Bio::DB::GFF::Util::Binning 'bin'; use Data::Dumper; use constant MINBIN => 1000; use constant FORMAT => 'clustalw'; use constant VERBOSE => 0; use constant MAPRES => 100; use vars qw/$format $create $user $pass $dsn $aln_idx $verbose $nomap $mapres $hit_idx $pidx %map/; $| = 1; GetOptions( 'format=s' => \$format, 'user=s' => \$user, 'pass=s' => \$pass, 'dsn=s' => \$dsn, 'map=i' => \$mapres, 'verbose' => \$verbose, 'nomap' => \$nomap, 'create' => \$create ); my $usage = "Usage: load_alignments_msa.pl -u username -p password -d database [-f format, -m map_resolution, -v, -n, -c] file1, file2 ... filen\n\n"; $dsn || die $usage; $user || die $usage; $format ||= FORMAT; $verbose ||= VERBOSE; $mapres ||= MAPRES; my ($dbh,$sth_hit,$sth_map) = prepare_database($dsn,$user,$pass); while (my $infile = shift) { print "Processing alignment file $infile...\n" if $verbose; my $alignIO = Bio::AlignIO->new( -file => $infile, -format => $format); while (my $aln = $alignIO->next_aln) { my $len = $aln->length; $pidx = 0; print STDERR "Processing Multiple Sequence Alignment " . ++$aln_idx . " (length $len)\t\t\t\r" if $verbose; next if $aln->num_sequences < 2; my %seq; %map = (); my $map = {}; for my $seq ($aln->each_seq) { my $seqid = $seq->id; my ($species,$ref,$strand) = check_name_format($seqid,$seq); next if $seq->seq =~ /^-+$/; $strand ||= $seq->start < $seq->end ? '+' : '-'; # We have to tell the sequence object what its strand is $seq->strand($strand eq '-' ? -1 : 1) unless $seq->strand; $seq{$species} = [$ref, $seq->display_name, $seq->start, $seq->end, $strand, $seq->seq, $seq]; } # make all pairwise hits and grid coordinates my @species = keys %seq; for my $p (map_pairwise(@species)) { my ($s1,$s2) = @$p; my $array1 = $seq{$s1}; my $array2 = $seq{$s2}; my $seq1 = $$array1[6]; my $seq2 = $$array2[6]; unless ($nomap) { $array1->[7] = make_map($seq1,$seq2,$map); $array2->[7] = make_map($seq2,$seq1,$map); } make_hit($s1 => $array1, $s2 => $array2); } } } # Make coordinate maps at the specified resolution sub make_map { my ($s1,$s2,$map) = @_; $s1 && $s2 || return {}; unless (UNIVERSAL::can($s1,'isa')) { warn "WTF? $s1 $s2\n" and next; } column_to_residue_number($s1,$s2); my $coord = nearest($mapres,$s1->start); $coord += $mapres if $coord < $s1->start; my @map; my $reverse = $s1->strand ne $s2->strand; # have to get the column number from residue position, then # the matching residue num from the column number while ($coord < $s1->end) { my $col = column_from_residue_number($s1,$coord); my $coord2 = residue_from_column_number($s2,$col) if $col; push @map, ($coord,$coord2) if $coord2; $coord += $mapres; } return {@map}; } sub column_to_residue_number { for my $seq (@_) { my $str = $seq->seq; my $id = $seq->id; next if $map{$id}; my $rev = $seq->strand < 0; my $res = $rev ? $seq->end - 1 : $seq->start + 1; my @cols = split '', $str; my $pos; my $col; for my $chr (@cols) { unless ($chr eq '-') { $rev ? $res-- : $res++; } $col++; $map{$id}{col}{$col} = $res; $map{$id}{res}{$res} ||= $col; } } } sub column_from_residue_number { my ($seq, $res) = @_; my $id = $seq->id; return $map{$id}{res}{$res}; } sub residue_from_column_number { my ($seq, $col) = @_; my $id = $seq->id; print"WTF? $seq $id $col\n" unless $id &&$col; return $map{$id}{col}{$col}; } sub make_hit { my ($s1,$aln1,$s2,$aln2,$fh) = @_; my $rightnum = $nomap ? 7 : 8; die "wrong number of keys @$aln1" unless @$aln1 == $rightnum; die "wrong number of keys @$aln2" unless @$aln2 == $rightnum; my $map1 = $aln1->[7] || {}; my $map2 = $aln2->[7] || {}; # not using these yet my ($cigar1,$cigar2) = qw/. ./; load_alignment($s1,@{$aln1}[0,2..4],$cigar1,$s2,@{$aln2}[0,2..4],$cigar2,$map1,$map2); } sub map_pairwise { my @out; for my $i (0..$#_) { for my $j ($i+1..$#_) { push @out, [$_[$i], $_[$j]]; } } return @out; } # stolen from Math::Round sub nearest { my $targ = abs(shift); my $half = 0.50000000000008; my @res = map { if ($_ >= 0) { $targ * int(($_ + $half * $targ) / $targ); } else { $targ * POSIX::ceil(($_ - $half * $targ) / $targ); } } @_; return (wantarray) ? @res : $res[0]; } sub check_name_format { my $name = shift; my $seq = shift; my $nogood = <<" END"; Problem with sequence name $name The Sequence name needs to contain some meta-data to identify the species, reference sequence and coordinates. Supported Sequence Name formats: # Downloaded via Ensembl Compara API species/seqid/start-end where species = name of species, genome, strain, etc (string with no '-' characters) sequence = name of reference sequence (string with no '/' characters) start = start coordinate of the alignment relative to the reference sequence (integer) end = end coordinate of the alignment relative to the reference sequence (integer) in this format, the strand is + unless end < start # Legacy gbrowse_syn format species-seqid(strand)/start..end where (strand) = orientation of the alignment (relative to the reference sequence; + or -) Examples: homo_sapiens/1/100000-200000 c_elegans-I(+)/1..2300 END ; die $nogood unless $name =~ /^([^-]+)-([^\(]+)\(([+-])\)$/ # Why did I do this? || $name =~ m!^([^/]+)/([^/]+)!; # from Bio::LocatableSeq die $nogood unless $seq->start && $seq->end; return ($1,$2,$3); } sub prepare_database { my ($dns,$user,$pass) = @_; $dsn = "dbi:mysql:$dsn" unless $dsn =~ /^dbi/; my $dbh = DBI->connect($dsn, $user, $pass) or die DBI->errstr; if ($create) { $dbh->do('drop table if exists alignments') or die DBI->errstr; $dbh->do('drop table if exists map') or die DBI->errstr; $dbh->do(<<" END;") or die DBI->errstr; create table alignments ( hit_id int not null auto_increment, hit_name varchar(100) not null, src1 varchar(100) not null, ref1 varchar(100) not null, start1 int not null, end1 int not null, strand1 enum('+','-') not null, seq1 mediumtext, bin double(20,6) not null, src2 varchar(100) not null, ref2 varchar(100) not null, start2 int not null, end2 int not null, strand2 enum('+','-') not null, seq2 mediumtext, primary key(hit_id), index(src1,ref1,bin,start1,end1) ) END; $dbh->do(<<" END;") or die DBI->errstr; create table map ( map_id int not null auto_increment, hit_name varchar(100) not null, src1 varchar(100), pos1 int not null, pos2 int not null, primary key(map_id), index(hit_name) ) END; $dbh->do('alter table alignments disable keys'); $dbh->do('alter table map'); } my $hit_insert = $dbh->prepare(<errstr; insert into alignments (hit_name,src1,ref1,start1,end1,strand1,seq1,bin,src2,ref2,start2,end2,strand2,seq2) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?) END ; my $map_insert = $dbh->prepare('insert into map (hit_name,src1,pos1,pos2) values(?,?,?,?)'); return $dbh, $hit_insert, $map_insert; } sub load_alignment { my ($src1,$ref1,$start1,$end1,$strand1,$seq1,$src2,$ref2,$start2,$end2,$strand2,$seq2,$map1,$map2) = @_; # not using the cigar strings right now ($seq1,$seq2) = ('',''); $map1 ||= {}; $map2 ||= {}; my %map1 = %$map1; my %map2 = %$map2; # standardize hit names my $hit1 = 'H' . sprintf('%010s', ++$hit_idx); my $bin1 = scalar bin($start1,$end1,MINBIN); my $bin2 = scalar bin($start2,$end2,MINBIN); my $hit2 = "${hit1}r"; # force ref strand to always be positive and invert target strand as required invert(\$strand1,\$strand2) if $strand1 eq '-'; $sth_hit->execute($hit1,$src1,$ref1,$start1,$end1,$strand1,$seq1,$bin1, $src2,$ref2,$start2,$end2,$strand2,$seq2) or warn $sth_hit->errstr; unless ($nomap) { for my $pos (sort {$a<=>$b} keys %map1) { next unless $pos && $map1{$pos}; $sth_map->execute($hit1,$src1,$pos,$map1{$pos}) or die $sth_map->errstr; } } # reciprocal hit is also saved to facilitate switching amongst reference sequences invert(\$strand1,\$strand2) if $strand2 eq '-'; $sth_hit->execute($hit2,$src2,$ref2,$start2,$end2,$strand2,$seq2,$bin2, $src1,$ref1,$start1,$end1,$strand1,$seq1) or warn $sth_hit->errstr; # saving pair-wise coordinate maps -- these are needed for gridlines unless ($nomap) { for my $pos (sort {$a<=>$b} keys %map2) { next unless $pos && $map2{$pos}; $sth_map->execute($hit1,$src2,$pos,$map2{$pos}) or die $sth_map->errstr; } } print STDERR "Processed pair-wise alignment ".++$pidx."\r" if $verbose; } sub done { $dbh->do('alter table alignments enable keys'); print "\nDone!\n\n"; } sub invert { my $strand1 = shift; my $strand2 = shift; $$strand1 = $$strand1 eq '+' ? '-' : '+'; $$strand2 = $$strand2 eq '+' ? '-' : '+'; } GBrowse-2.56/bin/gbrowse_sync_aws_slave.pl000555001750001750 1371313036764442 21050 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME gbrowse_sync_aws_slave.pl Synchronize local file system to GBrowse slave volume. =head1 SYNOPSIS % sudo gbrowse_sync_aws_slave.pl --conf /etc/gbrowse2/aws_balancer.conf \ --mysql /var/lib/mysql \ --postgres /var/lib/postgresql syncing data....done data stored in snapshot(s) snap-12345 updated conf file, previous version in /etc/gbrowse2/aws_balancer.conf.bak =head1 DESCRIPTION This script is run in conjunction with Amazon Web Server-based GBrowse render slave load balancing, which is described in more detail in the manual page for gbrowse_aws_balancer.pl. The gbrowse_sync_aws_script.pl script should be run on the GBrowse master machine each time you add a new database to an existing data source, or if you add a whole new data source. What it does is to prepare a new Amazon EBS snapshot containing a copy of all the data needed for the GBrowse slave to run. This snapshot is then attached to new slave instances. After running, it updates the conf file with the current versions of the slave AMI and the data snapshot(s). % sudo gbrowse_sync_aws_script.pl --conf /etc/gbrowse2/aws_balancer.conf \ --mysql /var/lib/mysql \ --postgres /var/lib/postgresql The --conf argument is required. The script will create a snapshot of the appropriate size, mount it on a temporary staging instance, and rsync a copy of your gbrowse databases directory (e.g. /var/lib/gbrowse2/databases) to the snapshot. If you have created mysql or postgres databases, you must also give the paths to their database file directories, as shown in the example. Note that ALL your mysql and postgres data files located on the master machine will be copied; not just those used for track display. =head1 ENVIRONMENT VARIABLES The following environment variables are used if the corresponding command line options are not present: EC2_ACCESS_KEY AWS EC2 access key EC2_SECRET_KEY AWS EC2 secret key =head1 SEE ALSO L, L =head1 AUTHOR Lincoln Stein, lincoln.stein@gmail.com Copyright (c) 2013 Ontario Institute for Cancer Research This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use FindBin '$Bin'; use lib "$Bin/../lib"; use lib '/home/lstein/projects/LibVM-EC2-Perl/lib'; use Getopt::Long; use GBrowse::ConfigData; use File::Spec; use Bio::Graphics::Browser2::Render::Slave::AWS_Balancer; use constant GB => 1_073_741_824; use constant DEBUG => 0; my ($balancer,$slave); my $program = $0; # this obscures the AWS secrets from ps; it is not 100% effective ($0 = "$program @ARGV") =~ s/(\s--?[as]\S*?)(=|\s+)\S+/$1$2xxxxxxxxxx/g; $SIG{TERM} = sub {exit 0}; $SIG{INT} = sub {exit 0}; my($ConfFile,$AccessKey,$SecretKey,$MySqlPath,$PostGresPath,$Verbosity); GetOptions( 'access_key=s' => \$AccessKey, 'secret_key=s' => \$SecretKey, 'conf=s' => \$ConfFile, 'mysql=s' => \$MySqlPath, 'postgres=s' => \$PostGresPath, 'verbosity=i' => \$Verbosity, ) or exec 'perldoc',$program; $ConfFile ||= File::Spec->catfile(GBrowse::ConfigData->config('conf'),'aws_balancer.conf'); unless (DEBUG || $< == 0) { my @argv; push @argv,('--access_key'=>$AccessKey) if $AccessKey; push @argv,('--secret_key'=>$SecretKey) if $SecretKey; push @argv,('--conf' =>File::Spec->rel2abs($ConfFile)) if $ConfFile; push @argv,('--mysql' =>File::Spec->rel2abs($MySqlPath)) if $MySqlPath; push @argv,('--postgres' =>File::Spec->rel2abs($PostGresPath)) if $PostGresPath; push @argv,('--verbosity' =>$Verbosity) if defined $Verbosity; $program = File::Spec->rel2abs($program); print STDERR <new( -conf => $ConfFile, -access_key => $AccessKey||'', -secret_key => $SecretKey||'', ); $Verbosity = 3 unless defined $Verbosity; $balancer->verbosity($Verbosity); # run the remote staging server print STDERR "[info] Launching a slave server for staging...\n"; $slave = $balancer->launch_staging_server(); $slave->shell if DEBUG; $slave->stop_services(); # figure out total size needed on destination volume my $DataBasePath = GBrowse::ConfigData->config('databases'); my $gig_needed = tally_sizes($DataBasePath,$MySqlPath,$PostGresPath); # keep an extra 10 G free my $gig_have = $slave->volume_size; if ($gig_needed + 5 > $gig_have) { $gig_needed = $gig_have + 10; # grow by 10 G increments $slave->info("Increasing size of slave data volume...\n"); $slave->grow_volume($gig_needed); } $slave->info("Syncing files...\n"); $slave->put("$DataBasePath/",'/opt/gbrowse/databases'); $slave->put("$MySqlPath/", '/opt/gbrowse/lib/mysql') if $MySqlPath; $slave->put("$PostGresPath/",'/opt/gbrowse/lib/postgresql') if $PostGresPath; my @snapshots = $slave->snapshot_data_volumes; $balancer->update_data_snapshots(@snapshots); $slave->info("Updating $ConfFile.\n"); $slave->info("Synchronization done. New data is in snapshot(s) @snapshots.\n"); exit 0; sub tally_sizes { my @dirs = @_; my $out = `sudo du -scb @dirs`; my ($bytes) = $out=~/^(\d+)\s+total/m; return int($bytes/GB)+1; } END { if ($slave) { $slave->terminate } undef $slave; } __END__ GBrowse-2.56/bin/gtf2gff3.pl000555001750001750 13356713036764442 15742 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long; #----------------------------------------------------------------------------- #----------------------------------- MAIN ------------------------------------ #----------------------------------------------------------------------------- my $usage = " Synopsis: gtf2gff3 --cfg gtf2gff3_MY_CONFIG.cfg gtf_file > gff3_file gtf2gff3 --help # for a more detailed help message. Description: This script will convert GTF formatted files to valid GFF3 formatted files. It will map the column 3 (\"type\" column) to valid SO, but because any non standard term may appear in that column in GTF files, you may edit the config file to provide your own GTF feature to SO mapping. The script will also build gene models from exons, CDSs and other features given in the GTF file. It is currently tested on Ensemble and Twinscan GTF, and it should work on any other files that follow the same specification. It does not work on GTF from the UCSC table browser because those files use the same ID for gene and transcript, so it is impossible to group multiple transcripts to a gene. See the README that came with the script for more info. Options: --cfg Provide the filename for a config file. See the configuration file provided with this script for format details. Use this configuration file to modify the behavior of the script. If no config file is given it looks for ./gtf2gff3.cfg, ~/gtf2gff3.cfg or /etc/gtf2gff3.cfg in that order. --help Provide a more detailed help message. "; my ($help, $cfg_file); my $opt_success = GetOptions('help' => \$help, 'cfg=s' => \$cfg_file); die $usage if ! $opt_success; if ($help) { print `perldoc $0`; exit; } my $file = shift; die $usage unless $file; my $home = $ENV{HOME} || '.'; #Apache has no home, so avoid the error. my @cfg_files = ($cfg_file, './gtf2gff3.cfg', "$home/gtf2gff3.cfg", '/etc/gtf2gff3.cfg', ); @cfg_files = grep {-e $_ if $_} @cfg_files; $cfg_file = shift @cfg_files; $cfg_file ||= ''; ################################################################################ # LOAD CONFIGURATION OR USE DEFAULTS ################################################################################ my %config; eval { require Config::Std; read_config $cfg_file => my %config if -e $cfg_file; }; if ($@ =~ /Can't locate/) { print STDERR "Config::Std not installed. Will use built-in defaults.\n"; } our $INPUT_FEATURE_MAP = $config{INPUT_FEATURE_MAP}; $INPUT_FEATURE_MAP ||= {gene => 'gene', mRNA => 'mRNA', exon => 'exon', five_prime_UTR => 'five_prime_utr', start_codon => 'start_codon', CDS => 'CDS', stop_codon => 'stop_codon', three_prime_UTR => 'three_prime_utr'}; our $GTF_ATTRB_MAP = $config{GTF_ATTRB_MAP}; $GTF_ATTRB_MAP ||= {gene_id => 'gene_id', gene_name => 'gene_name', trnsc_id => 'transcript_id', trnsc_name => 'transcript_name'}; our $GFF3_ATTRB_MAP = $config{GFF3_ATTRB_MAP}; $GFF3_ATTRB_MAP ||= {gene_id => 'gene_id', gene_name => 'gene_name', trnsc_id => 'transcript_id', trnsc_name => 'transcript_name', id => 'ID', parent => 'Parent', name => 'Name'}; our $LIMIT_ATTRB = $config{MISC}{LIMIT_ATTRB} || 1; our $ATTRB_DELIMITER = $config{MISC}{ATTRB_DELIMITER} ? qr{$config{MISC}{ATTRB_DELIMITER}} : qr{\s*;\s*}; our $ATTRB_REGEX = $config{MISC}{ATTRB_REGEX} ? qr{$config{MISC}{ATTRB_REGEX}} : qr{^\s*(\S+)\s+(\"[^\"]*\")\s*$}; our $START_IN_CDS = $config{MISC}{START_IN_CDS} || 1; our $STOP_IN_CDS = $config{MISC}{STOP_IN_CDS} || 0; our $DEFAULT_STRAND = $config{MISC}{DEFAULT_STRAND}; ################################################################################ my ($genes, $features) = parse_gtf($file); $genes = build_genes($genes); print_gff3($genes, $features); #----------------------------------------------------------------------------- #-------------------------------- SUBROUTINES -------------------------------- #----------------------------------------------------------------------------- sub parse_gtf { my $file = shift; open (my $IN, '<', $file) or die "FATAL: Can't open GTF file: $file for reading.\n$!\n"; # %genes will have the following structure: # $genes->gene_id->trnsc_id->feature_type->feature # | # ->other->feature_type->feature # my (%genes, %features); while (<$IN>) { chomp; s/^\s+//; s/\s+$//; #Handle full line comments, meta-comments and blank lines; #Grab any comments my ($comment) = $_ =~ s/(\#.*$)//; ; my ($seqname, $source, $feature_type, $start, $end, $score, $strand, $frame, $attrb_text) = split "\t", $_; my $attributes = parse_attributes($attrb_text); $feature_type = $INPUT_FEATURE_MAP->{$feature_type}; #Note here that we're mapping between GTF/GFF and GFF3 #nomeclature for the hash keys my $feature = {seq_id => $seqname, source => $source, type => $feature_type, start => $start, end => $end, score => $score, strand => $strand, phase => $frame, attributes => $attributes, comment => $comment}; #Feature has a gene_id if (exists $attributes->{$GTF_ATTRB_MAP->{gene_id}}) { my $gene_id = $attributes->{$GTF_ATTRB_MAP->{gene_id}}[0]; #Feature has a gene ID and transcript ID if (exists $attributes->{$GTF_ATTRB_MAP->{trnsc_id}}) { my $trnsc_id = $attributes->{$GTF_ATTRB_MAP->{trnsc_id}}[0]; # fix broken UCSC GTF! if ($gene_id eq $trnsc_id) { ($gene_id = $trnsc_id) =~ s/\.\d+$//; $attributes->{gene_id}[0] = $gene_id; } push @{$genes{$seqname}{$gene_id}{$trnsc_id}{$feature_type}}, $feature; } else { push @{$genes{$seqname}{$gene_id}{other}{$feature}}, $feature; } } else { push @{$features{$feature_type}}, $feature; } } return (\%genes, \%features); } #----------------------------------------------------------------------------- sub parse_attributes { my $attrb_text = shift; #Skip it if it's undefined or empty return if ! defined $attrb_text || $attrb_text =~ /^\s+$/; #Split the attributes my @attrb_array = split $ATTRB_DELIMITER, $attrb_text; #Grab key, value pairs my %attributes; ATT: for my $attrb (@attrb_array) { my ($key, $value); if ($attrb =~ $ATTRB_REGEX) { ($key, $value) = ($1, $2); $value =~ s/\"//g if $value !~ /\s/; } else { print STDERR "ERROR: Missing or non-standard attributes: parse_attributes\n"; next ATT; } push @{$attributes{$key}}, $value; } return \%attributes; } #----------------------------------------------------------------------------- sub build_genes { my $genes = shift; my @genes; for my $seq_id (keys %{$genes}) { for my $gene_id (keys %{$genes->{$seq_id}}) { my $gene = build_gene($genes->{$seq_id}{$gene_id}); push @genes, $gene; } } return \@genes; } #----------------------------------------------------------------------------- sub build_gene { my $trnscs = shift; my @trnscs; TRN: for my $trnsc_id (keys %{$trnscs}) { if ($trnsc_id eq 'other') { #Handle non-transcript gene features print STDERR "ERROR: Non-transcript gene feature " . "not supported. Please contact the author for " . "support: build_gene\n"; next TRN; } my $features = $trnscs->{$trnsc_id}; my $trnsc = build_trnsc($features); push @trnscs, $trnsc; } my $gene = validate_and_build_gene(\@trnscs); return $gene; } #----------------------------------------------------------------------------- sub build_trnsc { my $features = shift; my $exons = $features->{exon} || []; my $CDSs = $features->{CDS} || []; my $start = $features->{start_codon} || []; my $stop = $features->{stop_codon} || []; my $five_UTRs = $features->{five_prime_utr} || []; my $three_UTRs = $features->{three_prime_utr} || []; #We require at least CDSs or exons unless (scalar @{$CDSs} || scalar @{$exons}) { print STDERR "ERROR: Must have at least exons or CDSs to" . "build a transcript: build_trnsc\n"; return; } #Make start codons if they don't exist $start = process_start($exons, $CDSs, $start, $five_UTRs) if ! scalar @{$start}; #Make stop codons if they don't exist $stop = process_stop($exons, $CDSs, $stop, $three_UTRs) if ! scalar @{$stop}; #Make UTRs, exons and/or CDSs if they don't exist ($five_UTRs, $exons, $CDSs, $three_UTRs) = process_exon_CDS_UTRs($exons, $CDSs, $start, $stop, $five_UTRs, $three_UTRs); $features = {exon => $exons, five_prime_UTR => $five_UTRs, start_codon => $start, CDS => $CDSs, stop_codon => $stop, three_prime_UTR => $three_UTRs}; #Build and validate the transcripts my $trnsc = validate_and_finish_trnsc($features); return $trnsc; } #----------------------------------------------------------------------------- sub process_start { my ($exons, $CDSs, $start, $five_UTRs) = @_; my ($start_codon_start, $start_codon_end); my $strand; #Get the strand for exons or CDSs if (scalar @{$exons}) { $strand = strand($exons->[0]->{strand}); } elsif (scalar @{$CDSs}) { $strand = strand($CDSs->[0]->{strand}); } else { die "FATAL: Need exons or CDSs to build transcripts: " . "process_start.\n"; } #Already have start if (scalar @{$start}) { return $start; } ################################################################################ # Don't infer start codons from CDS unless backed by UTR or exon infered UTR ################################################################################ #Build start from CDS elsif (scalar @{$CDSs} && scalar @{$exons}) { $CDSs = sort_features($CDSs, $strand); my $first_CDS = $CDSs->[0]; $exons = sort_features($exons, $strand); my $first_exon = $exons->[0]; if ($strand == 1) { if ($first_exon->{start} < $first_CDS->{start}) { $start_codon_start = $first_CDS->{start}; #Move start codon out of CDS if config says to if ($START_IN_CDS == 0) { $start_codon_start -= 3; } } } elsif ($strand == -1) { if ($first_exon->{end} > $first_CDS->{end}) { $start_codon_start = $first_CDS->{end} - 2; #Move start codon out of CDS if config says to if ($START_IN_CDS == 0) { $start_codon_start += 3; } } } $start_codon_end = $start_codon_start + 2 if defined $start_codon_start; } #Here we assume that if you have 5' UTR and CDS that the start codon #must be at the begining of the first CDS. To be more rigorous we should #check the coordinates and be sure that the 5' UTR and CDS are contiguous. elsif (scalar @{$CDSs} && scalar @{$five_UTRs}) { $CDSs = sort_features($CDSs, $strand); my $first_CDS = $CDSs->[0]; if ($strand == 1) { $start_codon_start = $first_CDS->{start}; #Move start codon out of CDS if config says to if ($START_IN_CDS == 0) { $start_codon_start -= 3; } } elsif ($strand == -1) { $start_codon_start = $first_CDS->{end} - 2; #Move start codon out of CDS if config says to if ($START_IN_CDS == 0) { $start_codon_start += 3; } } $start_codon_end = $start_codon_start + 2; } #Build start from UTRs - I haven't seen an example of this yet. Maybe I should #only create a start codon if it falls within an exon or CDS. elsif (scalar @{$five_UTRs}) { die "FATAL: Untested code in process_start. Contact the aurthor for support\n"; $five_UTRs = sort_features($five_UTRs, $strand); my $last_five_UTR = $five_UTRs->[-1]; $start_codon_start = $strand == 1 ? $last_five_UTR->{start} + 1 : $last_five_UTR->{end} - 3; $start_codon_end = $start_codon_start + 2; } #No CDSs or UTRs - let's pretend it's non-coding elsif (scalar @{$exons}) { return []; } else { return []; # We don't really need to die here some annotations have stop_codon, but not start_codon # die "FATAL: Invalid feature set: process_start\n"; } return [] if (! defined $start_codon_start || ! defined $start_codon_end); $start = [{start => $start_codon_start, end => $start_codon_end, type => 'start_codon', score => '.', phase => '0'}]; return $start; } #----------------------------------------------------------------------------- sub process_stop { my ($exons, $CDSs, $stop, $three_UTRs) = @_; my ($stop_codon_start, $stop_codon_end); #Get the strand my $strand; if (scalar @{$exons}) { $strand = strand($exons->[0]->{strand}); } elsif (scalar @{$CDSs}) { $strand = strand($CDSs->[0]->{strand}); } else { die "FATAL: Need exons or CDSs to build transcripts: " . "process_stop\n"; } #If we already have a stop then return it. if (scalar @{$stop}) { return $stop; } ################################################################################ # Don't infer stop codons from CDS unless backed by UTR or exon infered UTR ################################################################################ #Build stop from CDSs elsif (scalar @{$CDSs}) { $CDSs = sort_features($CDSs, $strand); my $last_CDS = $CDSs->[-1]; $exons = sort_features($exons, $strand); my $last_exon = $exons->[0]; if ($strand == 1) { if ($last_exon->{end} > $last_CDS->{end}) { $stop_codon_start = $last_CDS->{end} - 2; #Move stop codon out of CDS is config says to if ($STOP_IN_CDS == 0) { $stop_codon_start += 3; } } } elsif ($strand == -1) { if ($last_exon->{start} < $last_CDS->{start}) { $stop_codon_start = $last_CDS->{start}; #Move stop codon out of CDS is config says to if ($STOP_IN_CDS == 0) { $stop_codon_start -= 3; } } } $stop_codon_end = $stop_codon_start + 2 if defined $stop_codon_end; } elsif (scalar @{$CDSs} && scalar @{$three_UTRs}) { $CDSs = sort_features($CDSs, $strand); my $last_CDS = $CDSs->[-1]; if ($strand == 1) { $stop_codon_start = $last_CDS->{end} - 2; #Move stop codon out of CDS is config says to if ($STOP_IN_CDS == 0) { $stop_codon_start += 3; } } elsif ($strand == -1) { $stop_codon_start = $last_CDS->{start}; #Move stop codon out of CDS is config says to if ($STOP_IN_CDS == 0) { $stop_codon_start -= 3; } } $stop_codon_end = $stop_codon_start + 2; } #Build stop from UTRs elsif (scalar @{$three_UTRs}) { die("FATAL: Untested code: process_stop.\n"); my $strand = strand($three_UTRs->[0]); $three_UTRs = sort_features($three_UTRs, $strand); my $first_three_UTR = $three_UTRs->[0]; $stop_codon_start = $strand == 1 ? $first_three_UTR->{start} - 3 : $first_three_UTR->{end} + 1; $stop_codon_end = $stop_codon_start + 2; } elsif (scalar @{$exons}) { #Treating this as a non-coding transcript return []; } else { # We don't really need to die here. Some features may have # start_codon, but not stop_codon return []; #die "FATAL: Invalid feature set: process_stop\n"; } return [] if (! defined $stop_codon_start || ! defined $stop_codon_end); $stop = [{start => $stop_codon_start, end => $stop_codon_end, type => 'stop_codon', score => '.', phase => '0'}]; return $stop; } #----------------------------------------------------------------------------- sub process_exon_CDS_UTRs { my ($exons, $CDSs, $start, $stop, $five_UTRs, $three_UTRs) = @_; #Check what features we already have so we don't rebuild them my $have_five_UTRs++ if scalar @{$five_UTRs}; my $have_exons++ if scalar @{$exons}; my $have_start++ if scalar @{$start}; my $have_CDSs++ if scalar @{$CDSs}; my $have_stop++ if scalar @{$stop}; my $have_three_UTRs++ if scalar @{$three_UTRs}; #If CDSs already exist make sure that they include start and stop codons if (scalar @{$CDSs}) { include_terminal_codons($CDSs, $start, $stop); } #If we already have everything, then return if ($have_exons && $have_CDSs && ($have_five_UTRs || $have_three_UTRs)) { return ($five_UTRs, $exons, $CDSs, $three_UTRs); } #Build CDSs && UTRs elsif ($have_exons && ($have_start || $have_stop || $have_CDSs || $have_three_UTRs || $have_five_UTRs)) { # Make sure that evaluate exons can handle only a start OR a stop!!! for my $exon (@{$exons}) { my ($five_UTR, $CDS, $three_UTR) = evaluate_exon($exon, $start->[0], $stop->[0]); push @{$five_UTRs}, $five_UTR if scalar keys %{$five_UTR} && ! $have_five_UTRs; push @{$CDSs}, $CDS if scalar keys %{$CDS} && ! $have_CDSs; push @{$three_UTRs}, $three_UTR if scalar keys %{$three_UTR} && ! $have_three_UTRs; } } #Build exons elsif (!$have_exons && $have_CDSs){ $exons = build_exons($five_UTRs, $start, $CDSs, $stop, $three_UTRs); } #Treat as non-coding even if we have a start or stop but not both elsif ($have_exons && ! $have_CDSs && ! $have_five_UTRs && ! $have_three_UTRs && ! $have_start && ! $have_stop) { #Treating this as a non_coding transcript return ($five_UTRs, $exons, $CDSs, $three_UTRs); } else { die "FATAL: Invalid feature set: process_exon_CDS_UTR\n"; } return ($five_UTRs, $exons, $CDSs, $three_UTRs); } #----------------------------------------------------------------------------- sub include_terminal_codons { my ($CDSs, $start, $stop) = @_; my $strand = strand($CDSs->[0]{strand}); $CDSs = sort_features($CDSs, $strand); my $first_CDS = $CDSs->[0]; my $last_CDS = $CDSs->[-1]; if ($strand == 1) { if (scalar @{$start}) { $first_CDS->{start} = $start->[0]{start} if $start->[0]{end} + 1 == $first_CDS->{start}; } #START_IN_CDS was considered when start was built, so it could introduce errors #to consider it again here # elsif (defined $START_IN_CDS) { # $first_CDS->{start} -= 3 if ! $START_IN_CDS; # } if (scalar @{$stop}) { $last_CDS->{end} = $stop->[0]{end} if $stop->[0]{start} - 1 == $last_CDS->{end}; } #STOP_IN_CDS was considered when stop was built, so it could introduce errors #to consider it again here # elsif (defined $STOP_IN_CDS) { # $last_CDS->{end} += 3 if ! $STOP_IN_CDS; # } } elsif ($strand == -1) { if (scalar @{$start}) { $first_CDS->{end} = $start->[0]{end} if $start->[0]{start} - 1 == $first_CDS->{end}; } #START_IN_CDS was considered when start was built, so it could introduce errors #to consider it again here # elsif (defined $START_IN_CDS) { # $first_CDS->{end} += 3 if ! $START_IN_CDS; # } if (scalar @{$stop}) { $last_CDS->{start} = $stop->[0]{start} if $stop->[0]{end} + 1 == $last_CDS->{start}; } #STOP_IN_CDS was considered when stop was built, so it could introduce errors #to consider it again here # elsif (defined $STOP_IN_CDS) { # $last_CDS->{start} -= 3 if ! $STOP_IN_CDS; # } } } #----------------------------------------------------------------------------- sub evaluate_exon { my ($exon, $start, $stop) = @_; my $strand = strand($exon); my %five_UTR; my %CDS; my %three_UTR; ####################################### # Allow success if missing either start or stop ####################################### if ($strand == 1) { #Exon is fully 5' UTR if (defined $start->{start} && $exon->{end} <= $start->{start}) { $five_UTR{start} = $exon->{start}; $five_UTR{end} = $exon->{end}; } #Exon stradles start codon elsif (defined $start->{start} && $exon->{start} < $start->{start} && $exon->{end} > $start->{start} ) { $five_UTR{start} = $exon->{start}; $five_UTR{end} = $start->{start} - 1; if (defined $stop->{start}) { $CDS{start} = $start->{start}; $CDS{end} = $exon->{end}; $CDS{phase} = 0; } } #Exon is fully CDS elsif (defined $start->{start} && defined $stop->{end} && $exon->{start} >= $start->{start} && $exon->{end} <= $stop->{end} ) { $CDS{start} = $exon->{start}; $CDS{end} = $exon->{end}; #Set phase if this is first CDS if ($exon->{start} == $start->{end} + 1 || $exon->{start} == $start->{start} ) { $CDS{phase} = 0; } } #Exon stradles stop codon elsif (defined $stop->{end} && $exon->{start} < $stop->{end} && $exon->{end} > $stop->{end} ) { $three_UTR{start} = $stop->{end} + 1; $three_UTR{end} = $exon->{end}; if (defined $start->{start}) { $CDS{start} = $exon->{start}; $CDS{end} = $stop->{end}; } } #Exon is fully 3' UTR elsif (defined $stop->{end} && $exon->{start} >= $stop->{end}) { $three_UTR{start} = $exon->{start}; $three_UTR{end} = $exon->{end}; } else { # die "Fatal error in evaluate_exon\n"; } } else { #Exon is fully 5' UTR if (defined $start->{end} && $exon->{start} >= $start->{end}) { $five_UTR{start} = $exon->{start}; $five_UTR{end} = $exon->{end}; } #Exon stradles start codon elsif (defined $start->{end} && $exon->{start} < $start->{end} && $exon->{end} > $start->{end} ) { $five_UTR{start} = $start->{end} + 1; $five_UTR{end} = $exon->{end}; if (defined $stop->{start}) { $CDS{start} = $exon->{start}; $CDS{end} = $start->{end}; } $CDS{phase} = 0; } #Exon is fully CDS elsif (defined $start->{end} && defined $stop->{start} && $exon->{end} <= $start->{end} && $exon->{start} >= $stop->{start} ) { $CDS{start} = $exon->{start}; $CDS{end} = $exon->{end}; #Set phase 0 if this is first CDS if ($exon->{end} == $start->{start} - 1 || $exon->{end} == $start->{end} ) { $CDS{phase} = 0; } } #Exon stradles stop codon elsif (defined $stop->{start} && $exon->{end} > $stop->{start} && $exon->{start} < $stop->{start} ) { $three_UTR{start} = $exon->{start}; $three_UTR{end} = $stop->{start} - 1; if (defined $start->{end}) { $CDS{start} = $stop->{start}; $CDS{end} = $exon->{end}; } } #Exon is fully 3' UTR elsif (defined $stop->{start} && $exon->{end} <= $stop->{start}) { $three_UTR{start} = $exon->{start}; $three_UTR{end} = $exon->{end}; } else { # die "Fatal error in evaluate_exon\n"; } } return (\%five_UTR, \%CDS, \%three_UTR); } #----------------------------------------------------------------------------- sub build_exons { my ($five_UTRs, $start, $CDSs, $stop, $three_UTRs) = @_; my $strand = $CDSs->[0]{strand}; my @exons; #Make an exon for every 5' UTR for my $five_UTR (@{$five_UTRs}) { push @exons, {start => $five_UTR->{start}, end => $five_UTR->{end}, type => 'exon', score => '.', strand => $strand, phase => '.'}; } #Make and exon for every CDS $CDSs = sort_features($CDSs); for my $CDS (@{$CDSs}) { my $exon = {start => $CDS->{start}, end => $CDS->{end}, type => 'exon', score => '.', strand => $strand, phase => '.'}; #START_IN_CDS and STOP_IN_CDS were already considered when start and stop were #constructed and CDSs were adjusted in include_terminal_codons =head1 if ($i == 0 && $START_IN_CDS == 0) { if ($strand == 1) { $exon->start = $start->[0]{start}; } else { $exon->end = $start->[0]{end}; } } if ($i == (scalar @{$CDSs} - 1) && $STOP_IN_CDS == 0) { if ($strand == 1) { $exon->{end} = $stop->[0]{end}; } else { $exon->{start} = $stop->[0]{start} } } =cut push @exons, $exon; } #Make an exon for every 3' UTR for my $three_UTR (@{$three_UTRs}) { push @exons, {start => $three_UTR->{start}, end => $three_UTR->{end}, type => 'exon', score => '.', strand => $strand, phase => '.'}; } #Merge any contiguous exons (i.e. from UTR & CDS neighbors) my $exons = sort_features(\@exons, 1); my @merged_exons = shift @{$exons}; while (my $exon = shift @{$exons}) { if ($exon->{start} <= $merged_exons[-1]{end} + 1) { $merged_exons[-1]{end} = $exon->{end}; } else { push @merged_exons, $exon; } } return \@merged_exons; } #----------------------------------------------------------------------------- sub validate_and_finish_trnsc { my $features = shift; my ($seq_id, $source, $strand, $gene_id, $gene_name, $trnsc_id, $trnsc_name); #Find default parameters from either exons or CDSs TYPE: for my $type ( qw|exon CDS| ) { for my $feature (@{$features->{$type}}) { $seq_id ||= $feature->{seq_id}; $source ||= $feature->{source}; $strand ||= $feature->{strand}; $gene_id ||= $feature->{attributes}{$GTF_ATTRB_MAP->{gene_id}}; $gene_name ||= $feature->{attributes}{$GTF_ATTRB_MAP->{gene_name}}; $trnsc_id ||= $feature->{attributes}{$GTF_ATTRB_MAP->{trnsc_id}}; $trnsc_name ||= $feature->{attributes}{$GTF_ATTRB_MAP->{trnsc_name}}; last TYPE if ! grep {! defined $_} ($seq_id, $source, $strand, $gene_name, $trnsc_id, $trnsc_name); } } #Flag if we have any coding features (CDS, start_codon, stop_codon) my $coding_flag; #Min and max for transcript boundaries my ($min, $max); for my $feature_type (keys %{$features}) { my $count; #For keeping track of the phase for the next CDS. my $next_phase = '.'; #Sort the features $features->{$feature_type} = sort_features($features->{$feature_type}, strand($strand)); for my $feature (@{$features->{$feature_type}}) { #min and max to calculate transcript boundaries $min = ! defined $min ? $feature->{start} : $min > $feature->{start} ? $feature->{start} : $min; $max = ! defined $max ? $feature->{end} : $max < $feature->{end} ? $feature->{end} : $max; #Set the flag if we see indications of coding features if (grep {$feature_type eq $_} qw(CDS start_codon stop_codon)) { $coding_flag++ if $feature->{start}; } #Calculate CDS phases. if ($feature_type eq 'CDS') { ($feature, $next_phase) = CDS_phase($feature, $next_phase); } #Set parameters to defaults for all features that #don't already have them set if (! defined $feature->{seq_id}) { $feature->{seq_id} = $seq_id; } elsif ($feature->{seq_id} ne $seq_id) { print STDERR "ERROR: seq_id conflict: " . "validate_and_finish_trnsc\n"; } if (! defined $feature->{source}) { $feature->{source} = $source; } elsif ($feature->{source} ne $source) { print STDERR "ERROR: source conflict: " . "validate_and_finish_trnsc\n"; } if (! defined $feature->{type}) { $feature->{type} = $feature_type; } elsif ($feature->{type} ne $feature_type) { print STDERR "ERROR: type conflict: " . "validate_and_finish_trnsc\n"; } if (! defined $feature->{strand}) { $feature->{strand} = $strand; } elsif ($feature->{strand} ne $strand) { print STDERR "ERROR: strand conflict: " . "validate_and_finish_trnsc\n"; } if (! defined $feature->{score}) { $feature->{score} = '.'; } if (! defined $feature->{phase}) { $feature->{phase} = '.'; } #Set attributes $feature->{attributes} = {parent => $trnsc_id, id => ["$feature_type:" . $trnsc_id->[0] . ":" . ++$count]}; } } my $trnsc_type = $coding_flag ? 'mRNA' : 'transcript'; my $attributes = {parent => $gene_id, parent_name => $gene_name, id => $trnsc_id, name => $trnsc_name}; my $trnsc = {seq_id => $seq_id, source => $source, type => $trnsc_type, start => $min, end => $max, score => '.', strand => $strand, phase => '.', attributes => $attributes, features => $features}; return $trnsc; } #----------------------------------------------------------------------------- sub CDS_phase { my ($feature, $next_phase) = @_; #If phase isn't already valid assign it if (! defined $feature->{phase} || $feature->{phase} !~ /^0|1|2$/) { $feature->{phase} = $next_phase; } #If phase is valid, calculate the next phase if ($feature->{phase} =~ /^0|1|2$/) { my $length = ($feature->{end} - $feature->{start}) + 1; # my $hang_3 = $length % 3; # 3' overhang # my $hang_5 = 3 - $hang_3; # 5' overhang # # #The next phase is equal to this phase # #plus the modulus 3 of the length wrapped # #at 2. # $next_phase = $feature->{phase} + $hang_5; # $next_phase -= 3 if $next_phase > 2; # This was update 5/24/10 in response to an # e-mail from Leighton Prichard regarding # errors in the GFF3 spec. The code above # calculates the phase correctly, but the # formula suggested by Leighton is cleaner. $next_phase = ($feature->{phase} - $length) % 3; } return ($feature, $next_phase); } #----------------------------------------------------------------------------- sub validate_and_build_gene { my $trnscs = shift; #Get parameter defaults my $seq_id = $trnscs->[0]{seq_id}; my $source = $trnscs->[0]{source}; my $strand = $trnscs->[0]{strand}; my $gene_id = $trnscs->[0]{attributes}{parent}; my $gene_name = $trnscs->[0]{attributes}{parent_name}; #Get gene boundaries and check all transcripts for agreement with #parameter defaults my ($min, $max); for my $trnsc (@{$trnscs}) { $min = ! defined $min ? $trnsc->{start} : $min > $trnsc->{start} ? $trnsc->{start} : $min; $max = ! defined $max ? $trnsc->{end} : $max < $trnsc->{end} ? $trnsc->{end} : $max; print STDERR "ERROR: seq_id conflict: " . "validate_and_build_gene\n" if $seq_id ne $trnsc->{seq_id}; print STDERR "ERROR: sourc`e conflict: " . "validate_and_build_gene\n" if $source ne $trnsc->{source}; print STDERR "ERROR: strand conflict: " . "validate_and_build_gene\n" if $strand ne $trnsc->{strand}; print STDERR "ERROR: gene_id conflict: " . "validate_and_build_gene\n" if $gene_id->[0] ne $trnsc->{attributes}{parent}[0]; } my $attributes = {id => $gene_id, name => $gene_name}; my $gene = {seq_id => $seq_id, source => $source, type => 'gene', start => $min, end => $max, score => '.', strand => $strand, phase => '.', attributes => $attributes, trnscs => $trnscs}; return $gene; } #----------------------------------------------------------------------------- sub print_gff3 { my $genes = shift; #GFF3 Header here print "##gff-version 3\n"; for my $gene (@{$genes}) { print_gene($gene); } print_features($features) if scalar keys %{$features}; } #----------------------------------------------------------------------------- sub print_gene { my $gene = shift; my $attrb_text = make_attribute_text($gene->{attributes}); $attrb_text .= ";Name=$gene->{attributes}{id}[0]"; print join "\t", ($gene->{seq_id}, $gene->{source}, $gene->{type}, $gene->{start}, $gene->{end}, $gene->{score}, $gene->{strand}, $gene->{phase}, $attrb_text, ); print " " . $gene->{comment} if $gene->{comment}; print "\n"; for my $trnsc (@{$gene->{trnscs}}) { print_trnsc($trnsc); } } #----------------------------------------------------------------------------- sub print_trnsc { my $trnsc = shift; my $attrb_text = make_attribute_text($trnsc->{attributes}); print join "\t", ($trnsc->{seq_id}, $trnsc->{source}, $trnsc->{type}, $trnsc->{start}, $trnsc->{end}, $trnsc->{score}, $trnsc->{strand}, $trnsc->{phase}, $attrb_text, ); print " " . $trnsc->{comment} if $trnsc->{comment}; print "\n"; print_features($trnsc->{features}); } #----------------------------------------------------------------------------- sub print_features { my $features = shift; my @sorted_feature_types = sort_feature_types($features); for my $feature_type (@sorted_feature_types) { $features->{$feature_type} = sort_features($features->{$feature_type}); for my $feature (@{$features->{$feature_type}}) { my $attrb_text = make_attribute_text($feature->{attributes}); print join "\t", ($feature->{seq_id}, $feature->{source}, $feature->{type}, $feature->{start}, $feature->{end}, $feature->{score}, $feature->{strand}, $feature->{phase}, $attrb_text, ); print " " . $feature->{comment} if $feature->{comment}; print "\n"; } } } #----------------------------------------------------------------------------- sub make_attribute_text { my $attributes = shift; #Only print the attributes listed in $LIMIT_ATTRB my @tags = $LIMIT_ATTRB ? grep {exists $GFF3_ATTRB_MAP->{$_}} keys %{$attributes} : keys %{$attributes}; my %order = (id => 1, name => 2, parent => 3, ); my @pairs; for my $tag (sort {$order{$a} || 999 <=> $order{$b} || 999} @tags) { next unless $attributes->{$tag}; my $tag_text = $GFF3_ATTRB_MAP->{$tag} || $tag; my $value_text = join ',', @{$attributes->{$tag}}; my $pair_text = join '=', ($tag_text, $value_text); push @pairs, $pair_text; } my $attrb_text = join ';', @pairs; return $attrb_text; } #----------------------------------------------------------------------------- sub sort_features { my ($features, $strand) = @_; $strand = strand($strand) || strand($features->[0]); #Make sure we get the array ref that we wanted if (ref $features eq 'ARRAY') { #If we get an array ref with more than one element - sort it if (scalar @{$features} > 1) { #Sort + strand features if ($strand == 1) { my @sorted_features = sort {$a->{start} <=> $b->{start}} @{$features}; $features = \@sorted_features; return $features; } #Sort - strand features elsif ($strand == -1) { my @sorted_features = sort {$b->{end} <=> $a->{end}} @{$features}; $features = \@sorted_features; return $features; } } #Empty or 1 length array just return it else { return $features; } } #Don't allow someone to misuse sort_features - require array ref else { die "FATAL: Array reference required: sort_features.\n"; } } #----------------------------------------------------------------------------- sub sort_feature_types { my ($feature_types) = @_; #Make sure we get the hash ref that we wanted if (ref $feature_types eq 'HASH') { my @types = keys %{$feature_types}; @types = grep{scalar @{$feature_types->{$_}} > 0} @types; my $strand; for my $type (@types) { if (defined $feature_types->{$type}[0]{strand}) { $strand = $feature_types->{$type}[0]{strand}; last; } } $strand = strand($strand); die "FATAL: Can't determine strand in: sort_feature_types.\n" if ! defined $strand; #If we get an hash ref with more than one element - sort it if (scalar keys %{$feature_types} > 1) { #Sort + strand features if ($strand == 1) { my @sorted_types = sort { min_feature($feature_types->{$a}, 'start') <=> min_feature($feature_types->{$b}, 'start') || min_feature($feature_types->{$a}, 'end') <=> min_feature($feature_types->{$b}, 'end') } @types; return @sorted_types; } #Sort - strand features elsif ($strand == -1) { my @sorted_types = sort { max_feature($feature_types->{$b}, 'start') <=> max_feature($feature_types->{$a}, 'start') || max_feature($feature_types->{$b}, 'end') <=> max_feature($feature_types->{$a}, 'end') } @types; return @sorted_types; } } #Empty or 1 length hash just return it else { return keys %{$feature_types}; } } #Don't allow someone to misuse sort_features - require array ref else { die "FATAL: Hash reference required: sort_feature_types.\n"; } } #----------------------------------------------------------------------------- sub strand { my $feature = shift; my $strand = ref $feature ? $feature->{strand} : $feature; #If strand is undefined or invalid... if (! defined $strand || $strand !~ /\+|-|1|-1/) { # ...and if we have a default value then use it... if ($DEFAULT_STRAND) { $strand = $DEFAULT_STRAND; } else { # ...otherwise allow undefined to pass through.. return $strand if ! defined $strand; } } if ($strand eq '+') { return 1; } elsif ($strand eq '-') { return -1; } elsif ($strand == 1 || $strand == -1) { return $strand; } # ...finally if all else fails die die "FATAL: Invalid value passed to strand: $strand."; } #----------------------------------------------------------------------------- sub min_feature { my ($features, $terminus) = @_; my $min; for my $feature (@{$features}) { $min ||= $feature->{$terminus}; $min = $feature->{$terminus} if $min > $feature->{$terminus}; } return $min; } #----------------------------------------------------------------------------- sub max_feature { my ($features, $terminus) = @_; my $max; for my $feature (@{$features}) { $max ||= $feature->{$terminus}; $max = $feature->{$terminus} if $max < $feature->{$terminus}; } return $max; } #----------------------------------------------------------------------------- =head1 NAME gtf2gff3 =head1 VERSION This document describes version 0.1 =head1 SYNOPSIS gtf2gff3 --cfg gtf2gff3_MY_CONFIG.cfg gtf_file > gff3_file =head1 DESCRIPTION This script will convert GTF formatted files to valid GFF3 formatted files. It will map the value in column 3 (\"type\" column) to valid SO, but because many non standard term may appear in that column in GTF files, you may edit the config file to provide your own GTF feature to SO mapping. The script will also build gene models from exons, CDSs and other features given in the GTF file. It is currently tested on Ensemble and Twinscan GTF, and it should work on any other files that follow the same specification. It does not work on GTF from the UCSC table browser because those files use the same ID for gene and transcript, so it is impossible to group multiple transcripts to a gene. See the README that came with the script for more info. =head1 OPTIONS: =over =item --cfg Provide the filename for a config file. See the configuration file provided with this script for format details. Use this configuration file to modify the behavior of the script. If no config file is given it looks for ./gtf2gff3.cfg, ~/gtf2gff3.cfg or /etc/gtf2gff3.cfg in that order. =item --help Provide a detailed man page style help message and then exit. =back =head1 DIAGNOSTICS =over =item C<< ERROR: Missing or non-standard attributes: parse_attributes >> A line in the GTF file did not have any attributes, or it's attributes column was unparsable. =item C<< ERROR: Non-transcript gene feature not supported. Please contact the author for support: build_gene >> This warning indicates that a line was skipped because it contained a non-transcript gene feature, and the code is not currently equipped to handle this type of feature. This probably isn't too hard to add, so contact me if you get this error and would like to have these features supported. =item C<< ERROR: Must have at least exons or CDSs to build a transcript: build_trnsc >> Some feature had a transcript_id and yet there were no exons or CDSs associated with that transcript_id so the script failed to build a transcript. =item C<< ERROR: seq_id conflict: validate_and_finish_trnsc >> Found two features within the same transcript that didn't share the same seq_id. =item C<< ERROR: source conflict: validate_and_finish_trnsc >> Found two features within the same transcript that didn't share the same source. =item C<< ERROR: type conflict: validate_and_finish_trnsc >> Found two features within the same transcript that were expected to share the same type and yet they didn't. =item C<< ERROR: strand conflict: validate_and_finish_trnsc >> Found two features within the same transcript that didn't share the same strand. =item C<< ERROR: seq_id conflict: validate_and_build_gene >> Found two features within the same gene that didn't share the same seq_id. =item C<< ERROR: source conflict: validate_and_build_gene >> Found two features within the same gene that didn't share the same source. =item C<< ERROR: strand conflict: validate_and_build_gene >> Found two features within the same gene that didn't share the same strand. =item C<< ERROR: gene_id conflict: validate_and_build_gene >> Found two features within the same gene that didn't share the same gene_id. =item C<< FATAL: Can't open GTF file: file_name for reading. >> Unable to open the GTF file for reading. =item C<< FATAL: Need exons or CDSs to build transcripts: process_start >> A start_codon feature was annotated and yet there were no exons or CDSs associated with that transcript_id so the script failed. =item C<< FATAL: Untested code in process_start. Contact the aurthor for support. >> The script is written to infer a start codon based on the presence of a 5' UTR, but we had no example GTF of this type when we wrote the code, so we killed process rather than run untested code. Contact the author for support. =item C<< FATAL: Invalid feature set: process_start >> We tried to consider all possible ways of infering a start codon or infering a a non-coding gene, and yet we've failed. Your combination of gene features doesn't make sense to us. You should never get this error, and if you do, we'd really like to see the GTF file that generated it. Please contact the author for support. =item C<< FATAL: Need exons or CDSs to build transcripts: process_stop >> A stop_codon feature was annotated and yet there were no exons or CDSs associated with that transcript_id so the script failed. =item C<< FATAL: Untested code in process_stop. Contact the aurthor for support. >> The script is written to infer a stop codon based on the presence of a 3' UTR, but we had no example GTF of this type when we wrote the code, so we killed process rather than run untested code. Contact the author for support. =item C<< FATAL: Invalid feature set: process_stop >> We tried to consider all possible ways of infering a stop codon or infering a a non-coding gene, and yet we've failed. Your combination of gene features doesn't make sense to us. You should never get this error, and if you do, we'd really like to see the GTF file that generated it. Please contact the author for support. =item C<< FATAL: Invalid feature set: process_exon_CDS_UTR >> We tried to consider all possible ways of infering exons, CDSs and UTRs and yet we've failed. Your combination of gene features doesn't make sense to us. You really should ever get this error, and if you do, we'd really like to see the GTF file that generated it. Please contact the author for support. =item C<< FATAL: Array reference required: sort_features. >> A user shouldn't be able to trigger this error. It almost certainly indicates a software bug. Please contact the author. =item C<< FATAL: Can't determine strand in: sort_feature_types. >> This may indicate that your GTF file does not indicate the strand for features that require it. It may also indicate a software bug. Please contact the author. =item C<< FATAL: Hash reference required: sort_feature_types. >> A user shouldn't be able to trigger this error. It almost certainly indicates a software bug. Please contact the author. =item C<< FATAL: Invalid value passed to strand: strand. >> This may indicate that your GTF file does not indicate the strand for features that require it. Consider using the DEFAULT_STRAND paramater in the config file. It may also indicate a software bug. Please contact the author. =back =head1 CONFIGURATION AND ENVIRONMENT A configuration file is provided with this script. The script will look for that configuration file in ./gtf2gff3.cfg, ~/gtf2gff3.cfg or /etc/gtf2gff3.cfg in that order. If the configuration file is not found in one of those locations and one is not provided via the --cfg flag it will try to choose some sane defaults, but you really should provide the configuration file. See the supplied configuration file itself as well as the README that came with this package for format and details about the configuration file. =head1 DEPENDENCIES This script requires the following perl packages that are available from CPAN (www.cpan.org). Getopt::Long; use Config::Std; =head1 INCOMPATIBILITIES None reported. =head1 BUGS AND LIMITATIONS No bugs have been reported. Please report any bugs or feature requests to: =head1 AUTHOR Barry Moore =head1 LICENCE AND COPYRIGHT Copyright (c) 2007, University of Utah This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. =cut GBrowse-2.56/bin/load_genbank.pl000555001750001750 1367613036764442 16714 0ustar00lsteinlstein000000000000#!/usr/bin/perl # $Id: load_genbank.pl,v 1.1 2008-10-16 17:01:27 lstein Exp $ use strict; use Bio::DB::GFF; use Getopt::Long; =head1 NAME load_genbank.pl - Load a Bio::DB::GFF database from GENBANK files. =head1 SYNOPSIS % load_genbank.pl -d genbank -f localfile.gb % load_genbank.pl -d genbank -a AP003256 NOTE: The script bp_genbank2gff.pl in the BioPerl distribution is the same as this script. =head1 DESCRIPTION This script loads a Bio::DB::GFF database with the features contained in a either a local genbank file or an accession that is fetched from genbank. Various command-line options allow you to control which database to load and whether to allow an existing database to be overwritten. This script currently only uses MySQL, though it is a proof-of- principle and could easily be extended to work with other RDMS that are supported by GFF through adaptors. =head1 COMMAND-LINE OPTIONS Command-line options can be abbreviated to single-letter options. e.g. -d instead of --database. --create Force creation and initialization of database --dsn Data source (default dbi:mysql:test) --user Username for mysql authentication --pass Password for mysql authentication --proxy Proxy server to use for remote access --file Arguments that follow are Genbank/EMBL file names (default) --accession Arguments that follow are genbank accession numbers --stdout Write converted GFF file to stdout rather than loading =head1 SEE ALSO L, L, L =head1 AUTHOR Scott Cain, cain@cshl.org Lincoln Stein, lstein@cshl.org Copyright (c) 2003 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut package Bio::DB::GFF::Adaptor::biofetch_to_stdout; use CGI 'escape'; use Bio::DB::GFF::Util::Rearrange; use Bio::DB::GFF::Adaptor::biofetch; use vars '@ISA'; @ISA = 'Bio::DB::GFF::Adaptor::biofetch'; sub new { my $class = shift; my $self = bless {},$class; my ($proxy) = rearrange(['PROXY'],@_); if ($proxy) { my @args = ref($proxy) ? @$proxy : eval $proxy; $self->{_proxy} = \@args if @args; } $self; } sub load_gff_line { my ($self,$options) = @_; # synthesize GFF3-compatible line my @attributes; if (my $parent = $options->{gname}) { push @attributes,"Parent=".escape($parent) unless $options->{method} =~ /^gene$/; push @attributes,"ID=".escape($parent); } if (my $tstart = $options->{tstart}) { my $tstop = $options->{tstop}; my $target = escape($options->{gname}); push @attributes,"Target=$target+$tstart+$tstop"; } my %a; if (my $attributes = $options->{attributes}) { for my $a (@$attributes) { my ($tag,$value) = @$a; push @{$a{escape($tag)}},escape($value); } for my $a (keys %a) { push @attributes,"$a=".join(',',@{$a{$a}}); } } my $last_column = join ';',@attributes; if ($options->{method} eq 'origin') { print "##sequence-region $options->{gname} $options->{start} $options->{stop}\n"; } $$options{score} ||='.'; $$options{source} ||='genbank'; print join("\t",@{$options}{qw(ref source method start stop score strand phase)},$last_column),"\n"; } sub load_sequence_string { my $self = shift; my ($acc,$seq) = @_; $seq =~ s/(.{1,60})/$1\n/g; print ">$acc\n\L$seq\U\n"; } sub setup_load { my $self = shift; print "##gff-version 3\n"; } sub finish_load { } 1; package main; my ($DSN,$ADAPTOR,$CREATE,$USER,$PASSWORD,$FASTA,$ACC,$FILE,$PROXY,$STDOUT); GetOptions ('dsn:s' => \$DSN, 'user:s' => \$USER, 'password:s' => \$PASSWORD, 'accession' => \$ACC, 'file' => \$FILE, 'proxy:s' => \$PROXY, stdout => \$STDOUT, create => \$CREATE) or die < ... Load a Bio::DB::GFF database from GFF files. Options: --create Force creation and initialization of database --dsn Data source (default dbi:mysql:test) --user Username for mysql authentication --pass Password for mysql authentication --proxy Proxy server to use for remote access --file Arguments that follow are Genbank/EMBL file names (default) --accession Arguments that follow are genbank accession numbers This script loads a Bio::DB::GFF database with the features contained in a either a local genbank file or an accession that is fetched from genbank. Various command-line options allow you to control which database to load and whether to allow an existing database to be overwritten. This script currently only uses MySQL, though it is a proof-of- principle and could easily be extended to work with other RDMS that are supported by GFF through adaptors. USAGE ; # some local defaults $DSN ||= 'dbi:mysql:test'; $ADAPTOR = $STDOUT ? 'biofetch_to_stdout' : 'biofetch'; my @auth; push @auth,(-user=>$USER) if defined $USER; push @auth,(-pass=>$PASSWORD) if defined $PASSWORD; push @auth,(-proxy=>$PROXY) if defined $PROXY; my $db = Bio::DB::GFF->new(-adaptor=>$ADAPTOR,-dsn => $DSN,@auth) or die "Can't open database: ",Bio::DB::GFF->error,"\n"; if ($CREATE) { $db->initialize(1); } die "you must specify either an accession to retrieve from\nembl or a local file containing data in embl format\n" unless @ARGV; if ($ACC && !$FILE) { while ($_ = shift) { print STDERR "Loading $_..."; my $result = $db->load_from_embl(/^NC_/?'refseq':'embl' => $_); print STDERR $result ? "ok\n" : "failed\n"; } } else { while ($_ = shift) { print STDERR "Loading $_...\n"; my $result = $db->load_from_file($_); print STDERR $result ? "ok\n" : "failed\n"; } } GBrowse-2.56/bin/make_das_conf.pl000555001750001750 1441113036764442 17045 0ustar00lsteinlstein000000000000#!/usr/bin/perl # $Id: make_das_conf.pl,v 1.1 2008-10-16 17:01:27 lstein Exp $ use strict; use Bio::Das 1.03; use Getopt::Long; my @COLORS = qw(cyan blue red yellow green wheat turquoise orange); # default colors my $color = 0; # position in color cycle my %known_aggregators = map {$_=>1} qw(clone match processed_transcript wormbase_gene orf reftranscript waba_alignment coding cds alignment transcript ucsc_assembly ucsc_ensgene ucsc_refgene ucsc_sanger22 ucsc_sanger22pseudo ucsc_softberry ucsc_twinscan ucsc_unigene); my $proxy; GetOptions('proxy=s' => \$proxy) or usage_statement(); my $url = shift; $url or usage_statement(); $url =~ m!^http:.+das(/\w+)?$! or usage_statement("This doesn't look like a DAS URL to me."); $ENV{HTTP_PROXY} ||= $proxy; list_sources($url) && exit 0 if $url =~ m!das/?$!; generate_config_file($url); exit 0; sub usage_statement { my $error = shift; $error .= "\n" if $error; die < Options: -proxy This utility attempts to contact a DAS source and to create a starter configuration file for gbrowse. If you don\'t know the list of data sources it will retrieve them and ask you to select one. If you need an HTTP proxy, set the HTTP_PROXY environment variable to the host and port number, in the form "http://proxy.host:port/", or pass the proxy URL to the -proxy option. END ; } sub list_sources { my $url = shift; my $das = Bio::Das->new($url); warn "proxy = $ENV{HTTP_PROXY}"; $das->proxy($ENV{HTTP_PROXY}) if $ENV{HTTP_PROXY}; my @sources = $das->sources or bad_request_exit($das); print "The following DAS URLs are available at this server. Please call the script again\n"; print "using one of the following URLs:\n\n"; for my $s (@sources) { print $s->url,"\n"; print "\t",$s->description,"\n\n"; } 1; } sub generate_config_file { my $url = shift; my ($server,$dsn) = $url=~ m[^(.+/das)/(\w+)]; my $das = Bio::Das->new($server=>$dsn); $das->proxy($ENV{HTTP_PROXY}) if $ENV{HTTP_PROXY}; my @sources = $das->sources or bad_request_exit($das); my ($source) = grep {$_->id eq $das->default_dsn} @sources; my @types = $das->types or bad_request_exit($das); $source or bad_request_exit($das); my %seenit; my @aggregators = grep {!$seenit{$_}++} map { my ($method,$source) = split ':'; $known_aggregators{$method} ? $method : "$method\{$method\}" } @types; my $aggregators = join "\n ",@aggregators; my $description = $source->description; my $mapmaster = $source->master; my @entry_points = sort {"$a" cmp "$b"} $das->entry_points; foreach (@entry_points) { # remove coordinates s/:\d+,\d+$//; } my $proxy = $ENV{HTTP_PROXY} ? "-proxy $ENV{HTTP_PROXY}" : ''; # top part of the config file print <method || $type; my $source = $type->source; my $label = uc ($type eq $method ? $type : "${type}_${method}"); $label =~ s/:/_/g; my $desc = $source ? "These are ${method} features from $source." : "These are ${method} features."; my $key = $type; my $category = $type->category; my $idx = $color++ % @COLORS; print <error; die < /usr/local/apache/conf/gbrowse.conf/ucsc.conf =head1 DESCRIPTION This script generates a rough draft configuration file suitable for browsing a remote DAS server. To use this script, give it the URL of a DAS server. If you point it at the DAS base URL (without the data source name), as in "http://genome.cse.ucsc.edu/cgi-bin/das", it will print a list of valid data sources to standard output. If you give it a complete DAS URL, as in "http://genome.cse.ucsc.edu/cgi-bin/das/hg16", it will print a gbrowse configuration file to standard output. You will probably want to tweak the configuration file after you generate it. In particular, you will want to customize the glyph types associated with each track and adjust the list of examples given in the instructions (by default this script uses the complete list of entry points, which may be rather long). Also be aware that this script creates a set of aggregators that may or may not be correct. Consider the case of a DAS server which uses the canonical structure for a spliced mRNA: main method: mRNA subparts: 5'-UTR, CDS, 3'-UTR This conversion script will generate the following set of aggregators: mRNA{mRNA} 5'-UTR{5'-UTR} CDS{CDS} 3'-UTR{3'-UTR} It will also generate a total of four tracks, one each for the mRNA and each of its parts. This is, of course, incorrect. You will want to consolidate these into a single aggregator: mRNA{5'-UTR,3'-UTR,CDS/mRNA} =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2002 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut GBrowse-2.56/bin/process_bamfiles.pl000555001750001750 2464513036764442 17626 0ustar00lsteinlstein000000000000#!/usr/bin/perl #$Id: process_bamfiles.pl,v 1.6 2009-08-27 19:13:18 idavies Exp $ # The purpose of this module is to process a hierarchy of directories containing sam/bam # files and generate automatic GBrowse for them. Ultimately this will be integrated into # an upload interface for sam/bam. # directory structure # DATA_ROOT => /srv/gbrowse/gbrowse/data/bam_db # /human -- dsn name # /category 1 # /category 2 # /track_name.sorted.bam.bai # /elegans -- dsn name # /etc # # REF_ROOT => /srv/gbrowse/gbrowse/data/reference_db # /human.fa # /human.fa.fai # /elegan.fa # /elegans.fa.fai # # CONF_ROOT => /srv/gbrowse/gbrowse/data/conf # /human -- dsn name # track_name1.conf # track_name2.conf # /elegans -- dsn name # # we are going to hard-code these relationships as follows # ROOT # DATA_ROOT = ROOT/bam_db # REF_ROOT = ROOT/reference_db # CONF_ROOT = ROOT/conf # # the logic is as follows # 1. ROOT is defined as the startup argument # 2. traverse DATA_ROOT looking for sam & bam files # 3. for each sam/bam file, satisfy this dependency tree # basename.sam => basename.bam # basename.bam => basename.sorted.bam # basename.sorted.bam => basename.sorted.bam.bai # 4. compare modification date of CONF_ROOT/dsn/basename.conf to basename.sorted.bam.bai # and rebuild config file if necessary use strict; use warnings; use Getopt::Long; my $www_root; my $result = GetOptions('www_root:s' => \$www_root); my $usage =< Specify root path as seen by web server. -w If the web server will see the database files on a different path, as might happen on an NFS-mounted filesystem, you may specify the path that the web server sees using -w. USAGE ; my $root = shift; $root && $result or die $usage; $www_root ||= $root; my $bamfile_processor = BamFileTree->new($root,$www_root); $bamfile_processor->process(); exit 0; package BamFileTree; use File::Find 'find'; use File::Basename 'basename','dirname'; use IO::Dir; use File::Spec; use Cwd; use Carp; sub new { my $class = shift; my $root = shift; my $www_root = shift; return bless { root => $root, www_root => $www_root, },ref $class || $class; } sub root { shift->{root} } sub www_root { shift->{www_root} } sub data_root { return File::Spec->catfile(shift->root,'bam_db'); } sub ref_root { return File::Spec->catfile(shift->root,'reference_db'); } sub conf_root { return File::Spec->catfile(shift->root,'conf'); } sub process { my $self = shift; my @dsn = $self->get_data_dirs; for my $dsn (@dsn) { my @tracks = $self->get_data_tracks($dsn); foreach (@tracks) { eval { $self->process_bamfile($_); $self->build_conf($_); }; if ($@) { $self->status($_,"ERROR: $@"); } else { $self->status($_); } } my %track_names = map {$_->name=>1} @tracks; my @conf = $self->config_files($dsn); $self->remove_dangling_conf($_,\%track_names) foreach @conf; } } sub get_faidx { my $self = shift; my $dsn = shift; my $fasta = $self->get_fa($dsn); croak "No reference fasta file for $dsn found. Please install $fasta" unless -e $fasta; my $ref_root = $self->ref_root; unless (-e "$fasta.fai" && -M "$fasta.fai" < -M $fasta) { $self->invoke_sam('faidx',$fasta) or croak "samtools failed to index $fasta"; } return File::Spec->catfile($ref_root,"$dsn.fa.fai"); } sub get_fa { my $self = shift; my $dsn = shift; my $ref_root = $self->ref_root; my $fasta = File::Spec->catfile($ref_root,"$dsn.fa"); return $fasta; } sub get_data_dirs { my $self = shift; my $root = $self->data_root; my $dir = IO::Dir->new($root) or croak "$root is not a directory"; my @result; while (my $d = $dir->read) { next if $d =~ /^\./; next unless -d File::Spec->catfile($root,$d); push @result,$d; } $dir->close; return @result; } sub get_data_tracks { my $self = shift; my $dsn = shift; my $root = File::Spec->catfile($self->data_root,$dsn); croak "$root is not a directory" unless -e $root && -d _; # do a depth first traversal to get categories and tracks my @result; my $wanted = sub { if (/\.(bam|sam|sam.gz)$/i) { return if /\.sorted\.bam$/; (my $path = $File::Find::dir) =~ s!^$root/?!!; my @categories = File::Spec->splitdir($path); push @result,Track->new(-categories=>\@categories, -path => $File::Find::dir, -name => basename($_,'.sam.gz','.sam','.bam'), -dsn => $dsn, ); } }; find($wanted,$root); my %seen; return grep {!$seen{$_->name}++} @result; } sub process_bamfile { my $self = shift; my $track = shift; my $path = $track->path; my $base = $track->name; my $dsn = $track->dsn; my $cwd = getcwd; chdir $path; my $faidx = $self->get_faidx($dsn); $self->status($track,'importing'); $self->satisfy_sam_dependencies("$base.sam","$base.bam", 'import',$faidx,"$base.sam","$base.bam"); $self->status($track,'importing'); $self->satisfy_sam_dependencies("$base.sam.gz","$base.bam", 'import',$faidx,"$base.sam.gz","$base.bam"); $self->status($track,'sorting'); $self->satisfy_sam_dependencies("$base.bam","$base.sorted.bam", 'sort',"$base.bam","$base.sorted"); $self->status($track,'indexing'); $self->satisfy_sam_dependencies("$base.sorted.bam","$base.sorted.bam.bai", 'index',"$base.sorted.bam"); chdir $cwd; } sub config_files { my $self = shift; my $dsn = shift; my $croot= $self->conf_root; my $dir = IO::Dir->new(File::Spec->catfile($croot,$dsn)); my @results; while (my $entry = $dir->read) { next unless $entry =~ /\.conf$/; push @results,$entry; } $dir->close; return map {File::Spec->catfile($croot,$dsn,$_)} @results; } sub remove_dangling_conf { my $self = shift; my ($conf_path,$track_names) = @_; my $basename = basename($conf_path,'.conf'); return if $track_names->{$basename}; unlink $conf_path; } sub build_conf { my $self = shift; my $track = shift; my $dsn = $track->dsn; my $name = $track->name; my $category = $track->category; my $bam_path = File::Spec->catfile($track->path,"$name.sorted.bam"); my $fa_path = $self->get_fa($dsn); my $conf_file = File::Spec->catfile($self->conf_root,$dsn,"$name.conf"); my $read_category = $category ? "$category:Reads" : 'Reads'; my $pairs_category = $category ? "$category:Read Pairs" : 'Read Pairs'; return if -e $conf_file && -M $conf_file <= -M $bam_path; # already there warn "building configuration file for $bam_path\n"; $self->status($track,'building config'); my $www_root = $self->www_root; my $root = $self->root; unless ($www_root eq $root) { $www_root .= '/' unless $www_root =~ m!/$!; foreach ($fa_path,$bam_path) { s/$root/$www_root/ }; } open my $cf,'>',$conf_file or die "Couldn't open $conf_file: $!"; print $cf <display_name} label density = 50 bump = fast maxdepth = 2 connector = sub { my \$glyph = pop; \$glyph->level == 0 ? 'dashed' : 'solid'; } category = $pairs_category feature_limit = 250 key = $name Read Pairs [${name}_pairs:10001] feature = coverage:1000 glyph = wiggle_xyplot height = 80 min_score = 0 autoscale = local [$name] database = $name feature = match glyph = segments draw_target = 1 show_mismatch = 1 mismatch_color= red bgcolor = blue fgcolor = blue height = 5 label = sub {shift->display_name} label density = 10 bump = fast category = $read_category feature_limit = 250 key = $name Alignments [$name:10001] feature = coverage:1000 glyph = wiggle_xyplot height = 80 min_score = 0 autoscale = local END close $cf; } sub satisfy_sam_dependencies { my $self = shift; my ($source,$target,@args) = @_; return unless -e $source; my $source_mod = -M $source; # number of days BEFORE script started up my $target_mod = -M $target; if (!$target_mod or $source_mod < $target_mod) { # source more recent than target $self->invoke_sam(@args) or croak "Samtools failed: $!"; } } sub invoke_sam { my $self = shift; my @args = @_; warn "samtools @args...\n"; my $status = system 'samtools',@args; return $status == 0; } sub status { my $self = shift; my $track = shift; my $message = shift; my $name = $track->name; $track or croak "Usage: \$self->status(\$track,\$message)"; my $file = File::Spec->catfile($track->path,"$name.STATUS"); unless (defined $message) { unlink $file; return; } open my $fh,'>',$file or die "Couldn't open status file: $!"; print $fh $message; close $fh; } package Track; sub new { my $self = shift; my %args = @_; return bless {categories => $args{-categories}, path => $args{-path}, name => $args{-name}, dsn => $args{-dsn}, },ref $self || $self; } sub category { my $self = shift; my $c = $self->{categories} or return; return $c unless ref $c && ref $c eq 'ARRAY'; return join ':',@$c; } sub dsn { shift->{dsn} } sub path { shift->{path} } sub name { shift->{name} } __END__ GBrowse-2.56/bin/process_gadfly.pl000555001750001750 1564113036764442 17306 0ustar00lsteinlstein000000000000#!/usr/bin/perl if ($ARGV[0]=~/^-?-h/ || @ARGV < 1) { die <<'USAGE'; This script massages the RELEASE 3 Flybase/Gadfly GFF files located at http://www.fruitfly.org/sequence/release3download.shtml into the "correct" version of the GFF format. To use this script, download the whole genome FASTA file and save it to disk. (The downloaded file will be called something like "na_whole-genome_genomic_dmel_RELEASE3.FASTA", but the link on the HTML page doesn't give the filename.) Do the same for the whole genome GFF annotation file (the saved file will be called something like "whole-genome_annotation-feature-region_dmel_RELEASE3.GFF".) If you wish you can download the ZIP compressed versions of these files. Next run this script on the two files, indicating the name of the downloaded FASTA file first, followed by the gff file: % process_gadfly.pl na_whole-genome_genomic_dmel_RELEASE3.FASTA whole-genome_annotation-feature-region_dmel_RELEASE3.GFF > fly.gff The gadfly.gff file and the fasta file can now be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d fly -fasta na_whole-genome_genomic_dmel_RELEASE3.FASTA fly.gff (Where "fly" is the name of the database. Change it as appropriate. The database must already exist and be writable by you!) The resulting database will have the following feature types (represented as "method:source"): Component:arm A chromosome arm Component:scaffold A chromosome scaffold (accession #) Component:gap A gap in the assembly clone:clonelocator A BAC clone gene:gadfly A gene accession number transcript:gadfly A transcript accession number translation:gadfly A translation codon:gadfly Significance unknown exon:gadfly An exon symbol:gadfly A classical gene symbol similarity:blastn A BLASTN hit similarity:blastx A BLASTX hit similarity:sim4 EST->genome using SIM4 similarity:groupest EST->genome using GROUPEST similarity:repeatmasker A repeat IMPORTANT NOTE: This script will *only* work with the RELEASE3 gadfly files and will not work with earlier releases. USAGE ; } use strict; foreach (@ARGV) { $_ = "gunzip -c $_ |" if /\.gz$/; } if ($ARGV[0] =~ /fasta/i) { process_fasta(); } else { die "call as process_gadfly.pl \"release3_dna.FASTA\" \"release3_features.GFF\""; } while (<>) { next if /^\#/; chomp; my ($ref,$csource,$cmethod,$start,$stop,$cscore,$strand,$cphase,$cgroup) = split "\t"; next if $start > $stop; # something wrong. Don't bother fixing it. my $fixed_group = fix_group($csource,$cmethod,$cgroup); print join("\t",$ref,$csource,$cmethod,$start,$stop,$cscore,$strand,$cphase,$fixed_group),"\n"; dump_symbol($ref,$csource,$cmethod,$start,$stop,$cscore,$strand,$cphase,$cgroup) if $cgroup =~ /symbol/i; } sub fix_group { my ($source,$method,$group) = @_; my (@group,$gene); push @group,"Transcript $1" if $group =~ /transgrp=([^; ]+)/; push @group,"Gene $1" if $method eq 'gene' && $group =~ /genegrp=([^; ]+)/; $gene ||= qq(Note "FlyBase $1") if $group =~ /dbxref=FlyBase:(\w+)/; $gene ||= qq(Note "GadFly $1") if $group =~ /genegrp=([^; ]+)/; push @group,qq(Note "Symbol $1") if $group =~ /symbol=([^; ]+)/ && "Gene $1" ne $group[0]; push @group,$gene; return join ' ; ',@group; } # called when we encounter a gene symbol sub dump_symbol { my ($ref,$csource,$cmethod,$start,$stop,$cscore,$strand,$cphase,$cgroup) = @_; my ($symbol) = $cgroup=~/symbol=([^;]+)/; my ($gene) = $cgroup=~/genegrp=([^;]+)/; return if $symbol eq $gene; $cmethod = 'symbol'; print join("\t",$ref,$csource,$cmethod,$start,$stop,$cscore,$strand,$cphase,qq(Symbol "$symbol")),"\n"; } sub process_fasta { my $file = shift @ARGV; open F,$file or die "Can't open $file: $!"; print STDERR "Reading big FASTA file, please be patient...\n"; my ($current_id,%lengths); while () { if (/^>(\S+)/) { $current_id = $1; next; } die "this doesn't look like a fasta file to me" unless $current_id; chomp; $lengths{$current_id} += length; } foreach (sort keys %lengths) { print join("\t",$_,'arm','Component',1,$lengths{$_},'.','+','.',qq(Sequence "$_")),"\n"; } } __END__ =head1 NAME process_gadfly.pl - Massage Gadfly/FlyBase GFF files into a version suitable for the Generic Genome Browser =head1 SYNOPSIS % process_gadfly.pl ./RELEASE2 > gadfly.gff =head1 DESCRIPTION This script massages the RELEASE 3 Flybase/Gadfly GFF files located at http://www.fruitfly.org/sequence/release3download.shtml into the "correct" version of the GFF format. To use this script, download the whole genome FASTA file and save it to disk. (The downloaded file will be called something like "na_whole-genome_genomic_dmel_RELEASE3.FASTA", but the link on the HTML page doesn't give the filename.) Do the same for the whole genome GFF annotation file (the saved file will be called something like "whole-genome_annotation-feature-region_dmel_RELEASE3.GFF".) If you wish you can download the ZIP compressed versions of these files. Next run this script on the two files, indicating the name of the downloaded FASTA file first, followed by the gff file: % process_gadfly.pl na_whole-genome_genomic_dmel_RELEASE3.FASTA whole-genome_annotation-feature-region_dmel_RELEASE3.GFF > fly.gff The gadfly.gff file and the fasta file can now be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d fly -fasta na_whole-genome_genomic_dmel_RELEASE3.FASTA fly.gff (Where "fly" is the name of the database. Change it as appropriate. The database must already exist and be writable by you!) The resulting database will have the following feature types (represented as "method:source"): Component:arm A chromosome arm Component:scaffold A chromosome scaffold (accession #) Component:gap A gap in the assembly clone:clonelocator A BAC clone gene:gadfly A gene accession number transcript:gadfly A transcript accession number translation:gadfly A translation codon:gadfly Significance unknown exon:gadfly An exon symbol:gadfly A classical gene symbol similarity:blastn A BLASTN hit similarity:blastx A BLASTX hit similarity:sim4 EST->genome using SIM4 similarity:groupest EST->genome using GROUPEST similarity:repeatmasker A repeat IMPORTANT NOTE: This script will *only* work with the RELEASE3 gadfly files and will not work with earlier releases. =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2002 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut GBrowse-2.56/bin/process_ncbi_human.pl000555001750001750 3610713036764442 20143 0ustar00lsteinlstein000000000000#!/usr/bin/perl #!/usr/bin/perl -w =head1 NAME ncbi_2_gff.pl - Massage NCBI chromosome annotation into GFF-format suitable for Bio::DB::GFF =head1 VERSION (CVS-info) $RCSfile: process_ncbi_human.pl,v $ $Revision: 1.1 $ $Author: lstein $ $Date: 2008-10-16 17:01:27 $ =head2 SYNOPSIS perl process_ncbi_human.pl [options] /path/to/gzipped/datafile(s) =head2 DESCRIPTION This script massages the chromosome annotation files located at ftp://ftp.ncbi.nih.gov/genomes/H_sapiens/maps/mapview/chromosome_order/ into the GFF-format recognized by Bio::DB::GFF. If the resulting GFF-files are loaded into a Bio::DB:GFF database using the utilities described below, the annotation can be viewed in the Generic Genome Browser (http://www.gmod.org/ggb/) and interfaced with using the Bio::DB:GFF libraries. (NB these NCBI-datafiles are dumps from their own mapviewer database backend, according to their READMEs) To produce the GFF-files, download all the chr*sequence.gz files from the FTP-directory above. While in that same directory, run the following example command (see also help clause by running script with no arguments): process_ncbi_human.pl --locuslink [path to LL.out_hs.gz] chr*sequence.gz This will unzip all the files on the fly and open an output file with the name chrom[$chrom]_ncbiannotation.gff for each, read the LocusLink records into an in-memory hash and then read through the NCBI feature lines, lookup 'locus' features in the LocusLink hash for details on 'locus' features and print to the proper GFF files. LL.out_hs.gz is accessible here at the time of writing: ftp://ftp.ncbi.nih.gov/refseq/LocusLink/LL.out_hs.gz Note that several of the NCBI features are skipped from the reformatting, either because their nature is not fully known at this time (TAG,GS_TRAN) or their sheer volume stands in the way of them being accessibly in Bio::DB::GFF at this time (EST similarities). You can easily change this by modifying the $SKIP variable to your liking to add or remove features, but if you add then you will have to add handling for those new features. To bulk-import the GFF-files into a Bio::DB::GFF database, use the bulk_load_gff.pl utility provided with Bio::DB::GFF =head2 AUTHOR Gudmundur Arni Thorisson Emummi@cshl.orgE Copyright (c) 2002 Cold Spring Harbor Laboratory This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut use strict; use Getopt::Long; use IO::File; use Bio::DB::GFF::Util::Binning 'bin'; use File::Basename; my $self = basename($0); my ($doTSCSNP,$doLocuslink,$debug); my $opt = &GetOptions ('locuslink=s' => \$doLocuslink, 'tscsnp=s' => \$doTSCSNP, 'debug=s' => \$debug, ); die < Massage NCBI chromosome annotation datafiles into GFF-format suitable for importing into Bio::DB::GFF database. Note that the program handles both unzipped datafiles and gzipped, bzipped or compressed ones, so do not bother with unzipping big downloads before running. See 'perldoc $self' for more info Options: --locuslink Path to zipped LocusLink file, currently located at ftp://ftp.ncbi.nih.gov/refseq/LocusLink/LL.out_hs.gz used to lookup gene description and official symbols --tscsnp DSN string to TSC MySQL database to use for auxiliary SNP feature attributes (CSHL internal use) --debug Enable debugging output for the DBI database driver. (CSHL internal use) Options can be abbreviated. For example, you can use -l for --locuslink. Author: Gudmundur Arni Thorisson Copyright (c) 2002 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. USAGE ; #Prepare decompression streams for input files, if necessary my %FH; print "\nPreparing input and output streams:\n"; foreach (@ARGV) { my $chrom=basename($_); # NG 02-10-24 ($chrom) = $chrom=~/0?([0-9,XYxy]{1,2})/; # NG 02-10-24 unless($chrom) { print "can't get chrom name from filename '$_', SKIPPING"; next; } $FH{'Chr'.$chrom} = IO::File->new("chrom$chrom\_ncbiannotation.gff",">") or die $_,": $!"; $_ = "gunzip -c $_ |" if /\.gz$/; $_ = "uncompress -c $_ |" if /\.Z$/; $_ = "bunzip2 -c $_ |" if /\.bz2$/; } #If TSC SNP processing is to be performed, connect to db and prepare query my $dbh; my $tsc_sth; if($doTSCSNP) { #Is this an argstring or file with the string in it? my $dbistring = -f $doTSCSNP ? `cat $doTSCSNP` : $doTSCSNP; $dbh = &dbConnect($dbistring); $dbh->trace($debug) if $debug; print "\nConnecting to TSC database using '$dbistring'\n"; my $query = qq/ SELECT ta.snp_id, ta.variation, tr.locus_id, tr.gene_symbol, tr.fxn_class, tf.institute_code as lab, tf.pop_type, tf.outcome, tf.pooled_data, tf.num_people_typed, tf.allele_a_freq as A, tf.allele_c_freq as C, tf.allele_g_freq as G, tf.allele_t_freq as T FROM tbl_dbsnp_2_tsc dbsnp LEFT JOIN tbl_refsnp_gene_fxn tr on tr.refsnp_id=dbsnp.rs_id LEFT JOIN tbl_allele_freq tf on tf.dbsnp_id=dbsnp.ss_id LEFT JOIN TBL_SNP_ALL ta on ta.snp_id = dbsnp.tsc_id WHERE dbsnp.rs_id = ? limit 1/; $tsc_sth = $dbh->prepare($query); } #If Locuslink-processing is to be performed, Read #previously cached data structure from disk my $llData; if($doLocuslink) { $doLocuslink = "gunzip -c $doLocuslink |" if $doLocuslink =~ /\.gz$/; $doLocuslink = "uncompress -c $doLocuslink |" if $doLocuslink =~ /\.Z$/; $doLocuslink = "bunzip -c $doLocuslink |" if $doLocuslink =~ /\.bz$/; open LL,$doLocuslink || die $!; my $l = 0; while() { $l++; print "\r--$l LocusLink records loaded" if $l % 100 ==0; my ($id,$osym,$isym,$mim,$chrom,$loc,$desc,$taxid,$db) = split /\t/; my $name = $osym || $isym; #print " Loading in Locuslink id='$id',osym='$osym',isym='$isym',name='$name',desc='$desc'\n"; $llData->{$id}->{name} = $name; $llData->{$id}->{isym} = $isym; $llData->{$id}->{mim} = $mim; $llData->{$id}->{chrom}= $chrom; $llData->{$id}->{loc} = $loc; $llData->{$id}->{desc} = $desc; $llData->{$id}->{taxid}= $taxid; $llData->{$id}->{db} = $db; } close LL; } my %sources = (snp => 'dbSNP', sts => 'UniSTS', locus => 'LocusLink', transcript => 'RefSeq', transcript_mouse => 'RefSeq', transcript_human => 'RefSeq', component => 'Genbank', contig => 'RefSeq', tag => 'SAGE', gs_tran => 'GenomeScan', ); my %classes = (component => 'Sequence', sts => 'STS', snp => 'SNP', locus => 'Locus', transcript => 'Transcript', transcript_human => 'Transcript', transcript_mouse => 'Transcript', contig => 'Contig', clone => 'Clone', tag => 'SAGE_tag', gs_tran => 'Transcript', ); my %subcomponents = (transcript => 'exon', transcript_human => 'exon', transcript_mouse => 'exon', gs_tran => 'exon', locus => 'exon', component => 'subcomponent', ); #And now process all incoming data streams my $i = 0; my %maxCoords; my $SKIP = q/^EST|component|clone/; my %groups = (); #aggregate parent features my %density = (); my $binSize = 100000; my $max = 0; print "\nStarting main loop:\n"; while(<>) { chomp; next if /^\#/; my ($type,$objId,$name,$chrom,$start,$stop,$strand) = split "\t"; my ($class,$source); my $score = '.'; $strand = '.' unless $strand =~ m/^(\+|\-)$/; $type = lc $type; if($type eq 'gs_tran') { $type = 'transcript'; $source = 'GenomeScan'; } elsif($type eq 'est_human' && $name =~ /^NM_/) { $type = 'transcript'; $source = 'RefSeq-human'; } elsif($type eq 'est_mouse' && $name =~ /^NM_/) { $type = 'transcript'; $source ='RefSeq-mouse'; } next if $type =~ /$SKIP/i; $i++; #my ($chrom,$ctg) = split /\|/,$chromctg; next if $chrom =~ /NT/; #ambigously placed NT-contig at start of chrom $chrom = "Chr$chrom"; $max = $stop if $stop > $max; $class ||= $classes{$type}; unless($class) { print "need class for type '$type': '$_' (OR add type to \$SKIP pattern\n"; next; } my $method = $type; $source ||= $sources{$type} || die "ERROR: need source for type '$type'"; $objId = $name if $type =~ /transcript|snp|contig|gs_tran|tag/; my $attributes = qq/$class $objId/; $attributes .= qq/; Name $name/ unless $objId eq $name; my $bin = &bin($start,$stop,$binSize); $bin =~ s/^[10]+\.[0]+//; $bin ||= 0; #print "\$bin='$bin' ($start=>$stop)\n"; $density{$chrom}->{$method.'_dens:'.$source}->{$bin}++; #Deduce start/stop for certain parent features to be printed #to output file AFTER we've processed everything. This is #necessary because NCBI only gives start/stop values for the child #features, like exons in a gene, but not the whole parent feature if($type =~ /transcript|locus/) { $groups{$type}->{$objId}->{$chrom}->{name} = $name; $groups{$type}->{$objId}->{$chrom}->{start} ||= 9999999999999; $groups{$type}->{$objId}->{$chrom}->{stop} ||= 0; $groups{$type}->{$objId}->{$chrom}->{start} = $start if $start < $groups{$type}->{$objId}->{$chrom}->{start}; $groups{$type}->{$objId}->{$chrom}->{stop} = $stop if $stop > $groups{$type}->{$objId}->{$chrom}->{stop}; $groups{$type}->{$objId}->{$chrom}->{source} = $source; $groups{$type}->{$objId}->{$chrom}->{strand} = $strand; $groups{$type}->{$objId}->{$chrom}->{method} = $method; $groups{$type}->{$objId}->{$chrom}->{class} = $class; $method = $subcomponents{$type}; next if $type eq 'locus'; } #This is for internal CSHL usage elsif($type =~ /snp/ && $doTSCSNP) { #print " -got refSNP ID: $name, let's do TSC lookup\n"; if(my $tscAttributes = &queryTSCdb($dbh,$name)) { #$FH{$chrom}->print(qq/$chrom\tTSC\tsnp\t$start\t$stop\t.\t$strand\t.\t$tscAttributes\n/); $attributes .= $tscAttributes; #print "\$attributes='$attributes'\n"; } } #Trying to work around the contig pile-up at the start of a chromosome if($method eq 'contig' && $stop == 0) { print STDERR "SKIPPING, contig '$name' as stop = $stop and start = $start.\n"; } #And finally print to the proper output stream $FH{$chrom}->print(qq/$chrom\t$source\t$method\t$start\t$stop\t.\t$strand\t$score\t$attributes\n/); #Collect max coordinates, to deduce chromosome sizes $maxCoords{$chrom} ||= 0; $maxCoords{$chrom} = $stop if $stop > $maxCoords{$chrom}; #Progress indicator if ( $i % 1000 == 0) { my ($chrom) = $ARGV=~ /0?([0-9,XYxy]{1,2})/; print STDERR "$i total features parsed. Now doing chromosome $chrom"; print STDERR -t STDOUT && !$ENV{EMACS} ? "\r" : "\n"; } }#MAIN LOOP ENDS #Print out group features like transcripts and genes that #were collected before and print to the proper output streams print "\nPrinting out collected aggregate features\n"; foreach my $type(keys %groups) { foreach my $objId (keys %{$groups{$type}}) { #print "\$name='$name'\n"; foreach my $chrom(keys %{$groups{$type}->{$objId}}) { my $name = $groups{$type}->{$objId}->{$chrom}->{name}; my $start = $groups{$type}->{$objId}->{$chrom}->{start}; my $stop = $groups{$type}->{$objId}->{$chrom}->{stop}; my $strand = $groups{$type}->{$objId}->{$chrom}->{strand}; my $method = $groups{$type}->{$objId}->{$chrom}->{method}; my $class = $groups{$type}->{$objId}->{$chrom}->{class}; my $source = $groups{$type}->{$objId}->{$chrom}->{source}; if($type eq 'locus' && $doLocuslink) { my $llInfo = ''; my $ll = $llData->{$objId}; my $id = $ll->{id}; my $note = $ll->{desc} ? qq/Note "$name:$ll->{desc}"/ : ' '; $note =~ s/;/\\;/g; $FH{$chrom}->print( qq/$chrom\t$source\t$method\t$start\t$stop\t.\t$strand\t.\tLocus $objId/); $FH{$chrom}->print(qq/; Name $name/) unless $objId eq $name; $FH{$chrom}->print(qq/; $note\n/); } else { $FH{$chrom}->print(qq/$chrom\t$source\t$method\t$start\t$stop\t.\t$strand\t.\t$class $name; Name $name\n/); } } } } # $density{$method.'_dens:'.$source}->{$bin}++; #Print out the collected binned density stats print "Printing out density stats\n"; foreach my $chrom(sort keys %density) { foreach my $meth(sort keys %{$density{$chrom}}) { my $bc = 0; foreach my $bin(sort {$a<=>$b}keys %{$density{$chrom}->{$meth}}) { $bc++; my $count = $density{$chrom}->{$meth}->{$bin}; my $binstart = $bin*$binSize; my $binstop = $binstart+$binSize; print " \$bin=$bin,\$binstart=$binstart,\$count=$count\n"; $FH{$chrom}->print(qq/$chrom\tNCBI\t$meth\t$binstart\t$binstop\t$count\t.\t.\t\n/); } print " $bc bins for method $meth\n"; } } #Print a line for the reference sequences themselves while(my ($chrom,$max) = each %maxCoords) { $FH{$chrom}->print(qq/$chrom\tassembly\tchromosome\t1\t$max\t.\t+\t.\tSequence \"$chrom\"\n/); } print "\nDONE. $i features parsed\n\n"; #------------------------------------------------ # Subroutines #------------------------------------------------ #For internal CSHL use. Queries our inhouse MySQL database with #SNP Consortium data for various auxiliary data on some SNPs sub queryTSCdb { my $dbh = shift; my $rs_id = shift; my $attributes; $rs_id =~ s/rs//; #Baeat vid herna, na i classification string fra dbSNP my ($note,$tsc_id,$var,$lab,$dbsnp_id,$class,$gene_symbol,$locus_id,$freq); $tsc_sth->execute($rs_id) || die $@; my $tscInfo = $tsc_sth->fetchrow_hashref() || return undef; do{ #while(my($k,$v) = each %$tscInfo){print " '$k'=>'$v'\n";} #dbSNP stuff, may apply to more than just TSC snps $locus_id = $tscInfo->{locus_id}; $class = $tscInfo->{fxn_class}; $gene_symbol = $tscInfo->{gene_symbol}; $attributes .= qq/; SNPClass $class/ if $class; #TSC specific stuff $tsc_id = $tscInfo->{snp_id} || return $attributes; $tsc_id = sprintf("TSC%7.7d", $tsc_id); $var = lc $tscInfo->{variation}; $lab = $tscInfo->{institute_code}; $dbsnp_id = $tscInfo->{dbsnp_id}; $freq = 1 if $tscInfo->{pop_type} && $tscInfo->{outcome} eq 'S'; $attributes .= qq/; Alias $tsc_id/; #$attributes .= qq/; Variation $var/ if $var; $attributes .= qq/; AllFreq 1/ if $freq; }while($tscInfo = $tsc_sth->fetchrow_hashref()); $note = qq/; Note "$tsc_id($var)"/; $rs_id = $dbh=$tsc_id=$var=$lab=$dbsnp_id=$class=$gene_symbol=$locus_id= $tscInfo=$freq= undef; return $attributes.$note; } sub dbConnect { my $dsn = shift; my $dbh; eval "require DBI; 1" or die "DBI module not installed. Cannot continue"; eval{$dbh = DBI->connect($dsn, { RaiseError => 1, FetchHashKeyName => 'NAME_lc', } ) }; if($@ || !$dbh) { print STDERR "ERROR, cannot connect to DB! $@\n"; die $DBI::errstr; } return $dbh; } GBrowse-2.56/bin/process_sgd.pl000555001750001750 721713036764442 16575 0ustar00lsteinlstein000000000000#!/usr/bin/perl # $Id: process_sgd.pl,v 1.4 2008-10-16 17:01:27 lstein Exp $ # This script will convert from SGD format to GFF format # See http://genome-www4.stanford.edu/Saccharomyces/SGD/doc/db_specifications.html use strict; # hard-coded length data that I couldn't get directly my %CHROMOSOMES = (I => 230_203, II => 813_139, III => 316_613, IV => 1_531_929, V => 576_869, VI => 270_148, VII => 1_090_937, VIII => 562_639, IX => 439_885, X => 745_444, XI => 666_445, XII => 1_078_173, XIII => 924_430, XIV => 784_328, XV => 1_091_284, XVI => 948_061, Mit => 85_779); my @ROMAN = qw(I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI Mit); if ($ARGV[0] =~ /^--?h/) { die < This script massages the SGD sequence annotation flat files located at ftp://genome-ftp.stanford.edu/pub/yeast/data_dump/feature/chromosomal_features.tab into a version of the GFF format suitable for display by the generic genome browser. To use this script, get the SGD chromosomal_features.tab file from the FTP site listed above, and run the following command: % process_sgd.pl chromosomal_features.tab > yeast.gff The yeast.gff file can then be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d yeast.gff USAGE ; } # first print out chromosomes # We hard coded the lengths because they are not available in the features table. for my $chrom (sort keys %CHROMOSOMES) { print join("\t",$chrom,'chromosome','Component',1,$CHROMOSOMES{$chrom},'.','.','.',qq(Sequence "$chrom")),"\n"; } # this is hard because the SGD idea of a feature doesn't really map onto the GFF idea. while (<>) { chomp; my($id,$gene,$aliases,$type,$chromosome,$start,$stop,$strand,$sgdid,$sgdid2,$description,$date) = split "\t"; my $ref = $ROMAN[$chromosome-1]; $description =~ s/"/\\"/g; $description =~ s/;/\\;/g; $strand = $strand eq 'W' ? '+' : '-'; ($start,$stop) = ($stop,$start) if $strand eq '-'; die "Strand logic is messed up" if $stop < $start; if ($gene) { my @aliases = split(/\|/,$aliases); my $aliases = join " ; ",map {qq(Alias "$_")} @aliases; my $group = qq(Gene "$gene" ; Note "$description"); $group .= " ; $aliases" if $aliases; print join("\t",$ref,'sgd','gene',$start,$stop,'.',$strand,'.',$group),"\n"; $description .= "\\; AKA @aliases" if @aliases; } print join("\t",$ref,'sgd',$type,$start,$stop,'.',$strand,'.',qq($type "$id" ; Note "$description")),"\n"; } __END__ =head1 NAME process_sgd.pl - Massage SGD annotation flat files into a version suitable for the Generic Genome Browser =head1 SYNOPSIS % process_sgd.pl chromosomal_features.tab > yeast.gff =head1 DESCRIPTION This script massages the SGD sequence annotation flat files located at ftp://genome-ftp.stanford.edu/pub/yeast/data_dump/feature/chromosomal_features.tab into a version of the GFF format suitable for display by the generic genome browser. To use this script, get the SGD chromosomal_features.tab file from the FTP site listed above, and run the following command: % process_sgd.pl chromosomal_features.tab > yeast.gff The yeast.gff file can then be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d yeast.gff =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2002 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut GBrowse-2.56/bin/report_missing_language_tags.pl000555001750001750 75213036764442 22164 0ustar00lsteinlstein000000000000#!/usr/bin/perl # this is just a development tool that I use to find missing language-specific # tags when I update POSIX.pm chdir '..' unless -d 'conf'; chdir "conf/languages" or die "Can't cd to languages directory: $!"; my $posix = require "./POSIX.pm"; print "Missing tags:\n"; for my $file (<*.pm>) { next if $file =~ /^POSIX/; my $contents = require "./$file"; my @missing = sort grep {!$contents->{$_}} keys %$posix; next unless @missing; print "$file: @missing\n\n"; } GBrowse-2.56/bin/scan_gbrowse.pl000555001750001750 474513036764442 16741 0ustar00lsteinlstein000000000000#!/usr/bin/perl #$Id: scan_gbrowse.pl,v 1.1 2009-03-05 23:02:59 lstein Exp $ # This script scans the gbrowse at the indicated URL and returns track # configuration stanzas for all tracks that are marked "discoverable." # If the --cache argument is present, then results will be # cached for seconds. use strict; use warnings; use Getopt::Long; use File::Spec; use File::Basename 'basename'; use LWP::Simple; use constant SECS_PER_DAY => 60*60*24; my $cache_time = 0; my $USAGE = < Scan the gbrowse2 instance at for discoverable tracks and create appropriate remote track configuration stanzas suitable for incorporation into the local gbrowse2 config file. Options: --cache Cache the results in a temporary file for cachetime seconds. USAGE ; GetOptions('cache=i' => \$cache_time) or die $USAGE; my $url = shift or die $USAGE; my $tmpdir = File::Spec->catfile(File::Spec->tmpdir,'gbrowse_scanner'.'_'.(getpwuid($<))[0]); unless (-e $tmpdir && -d _) { mkdir $tmpdir or die "Couldn't create $tmpdir: $!"; } (my $fname = $url) =~ s!/!_!g; my $cache_file = File::Spec->catfile($tmpdir,"$fname.cache"); my $dest_file = File::Spec->catfile($tmpdir,"$fname.dest"); build_cache($url,$dest_file,$cache_file) unless -e $cache_file && ((-M $cache_file) * SECS_PER_DAY)<$cache_time; open my $fh,'<',$cache_file or die "Couldn't open cache file $cache_file: $!"; print while <$fh>; close $fh; exit 0; sub build_cache { my ($url,$dest,$cache) = @_; $url =~ s/\?.+//; # get rid of any CGI args there already my $source = basename($url); $url .= '/' unless $url =~ /\/$/; my $response = mirror("$url?gbgff=scan",$dest); if (is_error($response)) { die "Could not scan $url. Status code was $response"; } open my $fh,'<',$dest or die "Could not open $dest: $!"; open my $out,'>',$cache or die "Could not open $cache for writing: $!"; my ($hostname) = $url =~ /^\w+:\/\/([^\/]+)/; (my $colon_escape = $url) =~ s/:/\\:/g; # paragraph mode to read stanzas local $/ = ''; while (<$fh>) { my ($label,$rest) = /\[([^\]]+)\]\s+(.+)/s; my $remote = "$url?gbgff=1;s=1;t=$label;segment=\$segment"; chomp($rest); print $out < \$wig, "p=s" => \$path, ); if (!$wig || !$path) {die "Usage: split_wig.pl -w FILE.wig -p DATABASE_PATH\n";} mkdir "$path/wib_files"; mkdir "$path/gff3_files"; my $count=0; my $chr_old=''; my $dir=tempdir(CLEANUP => 1); my $out=File::Temp->new(DIR => $dir, UNLINK => 0, SUFFIX => '.dat'); my $header=`head -n 1 $wig`; open IN, $wig or die "Cannot open $wig: $!\n"; while () { my $line=$_; chomp $line; if ($line=~/chrom/) { if ($count>=900) { $out=File::Temp->new(DIR => $dir, UNLINK => 0, SUFFIX => '.dat'); print $out $header; $count=0; } my @fields=split /\s/,$line; my $chr=$fields[1]; $chr=~s/chrom=//; if ($chr ne $chr_old) { $count++; } $chr_old=$chr; } print $out "$line\n"; } close IN; my @files=<$dir/*.dat>; my @filepath=split /\//,$wig; my @filename=split /\./,$filepath[-1]; my $suf=1; foreach (@files) { my $tmpout=File::Temp->new(); my $outfile="$path/gff3_files/$filename[0]_$suf.gff3"; system("wiggle2gff3.pl --path=$path/wib_files $_ > $tmpout"); system ("sed 's/microarray_oligo/$filename[0]/' $tmpout > $outfile"); $suf++; } exit; GBrowse-2.56/bin/ucsc_genes2gff.pl000555001750001750 1762113036764442 17165 0ustar00lsteinlstein000000000000#!/usr/bin/perl # convert UCSC gene files into GFF3 data use strict; use File::Basename 'basename'; use Getopt::Long; my $executable = basename($0); my ($SRC,$ORIGIN); GetOptions('src:s' => \$SRC, 'origin:i' => \$ORIGIN, ) or die < Choose a source for the gene, default "UCSC" -origin Choose a relative position to number from, default is "1" The resulting file is in GFF3 format and should be loaded into a Bio::DB::GFF database using the following command: bp_bulk_load_gff.pl -c -d db1 --maxfeature 1000000000 --gff3_munge file.gff USAGE $SRC ||= 'UCSC'; $ORIGIN ||= 1; print "##gff-version 3\n"; # automatically uncompress varous compression formats foreach (@ARGV) { $_ = "gunzip -c $_ |" if /\.gz$/; $_ = "uncompress -c $_ |" if /\.Z$/; $_ = "bunzip2 -c $_ |" if /\.bz2$/; } while (<>) { chomp; next if /^\#/;; next if /random/; ## added line my (undef,$id,$chrom,$strand,$txStart,$txEnd,$cdsStart,$cdsEnd,$exons,$exonStarts,$exonEnds) = split /\t/; my ($utr5_start,$utr5_end,$utr3_start,$utr3_end); # adjust for Jim's 0-based coordinates $txStart++; $cdsStart++; $txStart -= $ORIGIN; $txEnd -= $ORIGIN; $cdsStart -= $ORIGIN; $cdsEnd -= $ORIGIN; # print the transcript print join ("\t",$chrom,$SRC,'mRNA',$txStart,$txEnd,'.',$strand,'.',"ID=$id"),"\n"; # now handle the CDS entries -- the tricky part is the need to keep # track of phase my $phase = 0; my @exon_starts = map {$_-$ORIGIN} split ',',$exonStarts; my @exon_ends = map {$_-$ORIGIN} split ',',$exonEnds; if ($strand eq '+') { for (my $i=0;$i<@exon_starts;$i++) { # for each exon start my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_start < $cdsStart) { # in a 5' UTR push (@utr_start, $exon_start); } elsif ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } elsif ($exon_end > $cdsEnd) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 5' end $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 3' end $utr_start[0]= $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if (defined $utr_start[0] == defined $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] < $cdsStart) { print join ("\t",$chrom,$SRC,"five_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } # end of if } # end of foreach if (defined $cds_start && $cds_start <= $cds_end) { print join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$id"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { print join ("\t",$chrom,$SRC,"three_prime_UTR",,$utr_start[$i], $utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } } # end of for each exon } # matches if strand = + if ($strand eq '-') { my @lines; for (my $i=@exon_starts-1; $i>=0; $i--) { # count backwards my $exon_start = $exon_starts[$i] + 1; my $exon_end = $exon_ends[$i]; my (@utr_start,@utr_end,$cds_start,$cds_end); if ($exon_end > $cdsEnd) { # in a 5' UTR push (@utr_end, $exon_end); } elsif ($exon_end < $cdsStart) { push (@utr_end, $exon_end); } else { $cds_end = $exon_end; } if ($exon_start > $cdsEnd) { push (@utr_start, $exon_start); } elsif ($exon_start < $cdsStart) { push (@utr_start, $exon_start); } else { $cds_start = $exon_start; } if ($utr_start[0] && !$utr_end[0]) { # half in half out on 3' end $utr_end[0] = $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $exon_end; } if ($utr_end[0] && !$utr_start[0]) { # half in half out on 5' end $utr_start[0] = $cdsEnd + 1; $cds_end = $cdsEnd; $cds_start = $exon_start; } # If the CDS is within the exon if (defined $utr_start[0] == defined $utr_end[0] && $utr_start[0] < $cdsStart && $utr_end[0] > $cdsEnd) { $utr_end[0]= $cdsStart - 1; $cds_start = $cdsStart; $cds_end = $cdsEnd; push (@utr_start, $cdsEnd + 1); push (@utr_end, $exon_end); } die "programmer error, not an even number of utr_starts and utr_ends" unless $#utr_start == $#utr_end; die "programmer error, cds_start and no cds_end" unless defined $cds_start == defined $cds_end; for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_start[$i] > $cdsEnd) { unshift @lines,join ("\t",$chrom,$SRC,"five_prime_UTR",,$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } # end of for if (defined $cds_start && $cds_start <= $cds_end) { unshift @lines,join ("\t",$chrom,$SRC,'CDS',$cds_start,$cds_end,'.',$strand,$phase,"Parent=$id"),"\n"; $phase = (($cds_end-$cds_start+1-$phase)) % 3; } for (my $i=0;$i<@utr_start;$i++) { # for each utr start if (defined $utr_start[$i] && $utr_start[$i] <= $utr_end[$i] && $utr_end[$i] < $cdsStart) { unshift @lines,join ("\t",$chrom,$SRC,"three_prime_UTR",$utr_start[$i],$utr_end[$i],'.',$strand,'.',"Parent=$id"),"\n" } } # end for } print @lines; } } # end while <> __END__ =head1 NAME ucsc_genes2gff.pl - Convert UCSC Genome Browser-format gene files into GFF files suitable for loading into gbrowse =head1 SYNOPSIS % uscsc_genes2gff.pl [options] ucsc_file1 ucsc_file2... Options: -src Choose a source for the gene, default "UCSC" -origin Choose a relative position to number from, default is "1" =head1 DESCRIPTION This script massages the gene files available from the "tables" link of the UCSC genome browser (genome.ucsc.edu) into a form suitable for loading of gbrowse. Warning: it only works with the gene tables. Other tables, such as EST alignments, contours and repeats, have their own formats which will require other scripts to parse. To use this script, get one or more UCSC tables, either from the "Tables" link on the browser, or from the UCSC Genome Browser FTP site. Give the table file as the argument to this script. You may want to provide an alternative "source" field. Otherwise this script defaults to "UCSC". % pucsc_genes2gff.pl -src RefSeq refseq_data.ucsc > refseq.gff The resulting GFF file can then be loaded into a Bio::DB::GFF database using the following command: % bulk_load_gff.pl -d refseq.gff =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2003 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty. =cut GBrowse-2.56/bin/wiggle2gff3.pl000555001750001750 2123613036764442 16405 0ustar00lsteinlstein000000000000#!/usr/bin/perl =head1 NAME wiggle2gff3.pl =head1 SYNOPSIS wiggle2gff3.pl [options] WIG_FILE > load_data.gff3 Converts UCSC WIG format files into gff3 files suitable for loading into GBrowse databases. This is used for high-density quantitative data such as CNV, SNP and expression arrays. =head1 DESCRIPTION Use this converter when you have dense quantitative data to display using the xyplot, density, or heatmap glyphs, and too many data items (thousands) to load into GBrowse. It creates one or more space- efficient binary files containing the quantitative data, as well as a small GFF3 file that can be loaded into Chado or other GBrowse databases. Typical usage is as follows: % wiggle2gff3.pl --method=microarray_oligo my_data.wig > my_data.gff3 =head2 Options The following options are accepted: --method= Set the method for the GFF3 lines representing each quantitative data point in the track. The default is "microarray_oligo." --source= Set the source field for the GFF3 file. The default is none. --gff3 Create a GFF3-format file (the default) --featurefile Create a "featurefile" format file -- this is the simplified format used for GBrowse uploads. This option is incompatible with the --gff3 option. --sample If true, then very large files (>5 MB) will be sampled to obtain minimum, maximum and standard deviation; otherwise the entire file will be scanned to obtain these statistics. This will process the files faster but may miss outlier values. --path= Specify the directory in which to place the binary wiggle files. The default is the current temporary directory (/tmp or whatever is appropriate for your operating system). --base= Same as "--path". --trackname specify the trackname base for the wigfile creation --help This documentation. This script will accept a variety of option styles, including abbreviated options ("--meth=foo"), single character options ("-m foo"), and other common variants. =head2 Binary wiggle files The binary "wiggle" files created by this utility are readable using the L module. The quantitative data is scaled to the range of 1-255 (losing lots of precision, but still more than enough for data visualization), and stored in a packed format in which each file corresponds to the length of a single chromosome or contig. Once created, the binary files should not be moved or renamed, unless you are careful to make corresponding changes to the pathnames given by the "wigfile" attribute in the GFF3 file feature lines. You should also be careful about using the cp command to copy the binary files; they are formatted with "holes" in such a way that missing data does not take up any space on disk. If you cp them, the holes will fill up with zeroes and the space savings will be lost. Better to use the "tar" command with its --sparse option to move the files from one place to another. =head2 Example WIG File This example is from L: # filename: example.wig # # 300 base wide bar graph, autoScale is on by default == graphing # limits will dynamically change to always show full range of data # in viewing window, priority = 20 positions this as the second graph # Note, zero-relative, half-open coordinate system in use for bed format track type=wiggle_0 name="Bed Format" description="BED format" \ visibility=full color=200,100,0 altColor=0,100,200 priority=20 chr19 59302000 59302300 -1.0 chr19 59302300 59302600 -0.75 chr19 59302600 59302900 -0.50 chr19 59302900 59303200 -0.25 chr19 59303200 59303500 0.0 chr19 59303500 59303800 0.25 chr19 59303800 59304100 0.50 chr19 59304100 59304400 0.75 chr19 59304400 59304700 1.00 # 150 base wide bar graph at arbitrarily spaced positions, # threshold line drawn at y=11.76 # autoScale off viewing range set to [0:25] # priority = 10 positions this as the first graph # Note, one-relative coordinate system in use for this format track type=wiggle_0 name="variableStep" description="variableStep format" \ visibility=full autoScale=off viewLimits=0.0:25.0 color=255,200,0 \ yLineMark=11.76 yLineOnOff=on priority=10 variableStep chrom=chr19 span=150 59304701 10.0 59304901 12.5 59305401 15.0 59305601 17.5 59305901 20.0 59306081 17.5 59306301 15.0 59306691 12.5 59307871 10.0 # 200 base wide points graph at every 300 bases, 50 pixel high graph # autoScale off and viewing range set to [0:1000] # priority = 30 positions this as the third graph # Note, one-relative coordinate system in use for this format track type=wiggle_0 name="fixedStep" description="fixed step" visibility=full \ autoScale=off viewLimits=0:1000 color=0,200,100 maxHeightPixels=100:50:20 \ graphType=points priority=30 fixedStep chrom=chr19 start=59307401 step=300 span=200 1000 900 800 700 600 500 400 300 200 100 You can convert this into a loadable GFF3 file with the following command: wiggle2gff3.pl --meth=example --so=example --path=/var/gbrowse/db example.wig \ > example.gff3 The output will look like this: ##gff-version 3 chr19 example example 59302001 59304700 . . . Name=Bed Format;wigfile=/var/gbrowse/db/track001.chr19.1199828298.wig chr19 example example 59304701 59308020 . . . Name=variableStep;wigfile=/var/gbrowse/db/track002.chr19.1199828298.wig chr19 example example 59307401 59310400 . . . Name=fixedStep;wigfile=/var/gbrowse/db/track003.chr19.1199828298.wig =head1 PROBLEMS This script has trouble with wig files from very fragmented genomes (>100K scaffolds). In this case, you may wish to run split_wig.pl, which splits the original wig file into a series of smaller files with a maximum of 900 scaffolds each. It then runs wiggle2gff3.pl for each subfile and stores the results in separate folders. =head1 SEE ALSO L, L, L, L, L =head1 AUTHOR Lincoln Stein . Copyright (c) 2008 Cold Spring Harbor Laboratory This package is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. See DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use Bio::Graphics::Wiggle::Loader; use Getopt::Long; use Pod::Usage; use File::Spec; use File::Temp 'tempfile',':seekable'; my ($show_help, $method, $source, $use_gff3, $use_featurefile, $base_directory, $trackname,$sample); GetOptions( 'h|help' => \$show_help, # Show help and exit 'method=s' => \$method, 'source=s' => \$source, 'gff3' => \$use_gff3, 'sample' => \$sample, 'featurefile' => \$use_featurefile, 'base|path=s' => \$base_directory, 't|trackname:s' => \$trackname, ) or pod2usage(-verbose=>2); pod2usage(-verbose=>2) if $show_help; die "Only one of -gff3 or -featurefile options is allowed. Use -h for help" if $use_gff3 && $use_featurefile; unless (defined $base_directory) { $base_directory = File::Spec->tmpdir(); warn "Using $base_directory as base directory for binary files"; } -d $base_directory && -w _ or die "$base_directory is not a writeable directory. Use -h for more help"; my $loader = Bio::Graphics::Wiggle::Loader->new($base_directory) or die "could not create loader"; $loader->allow_sampling(1) if $sample && $loader->can('allow_sampling'); # newish feature # specify the trackname base if provided $loader->{trackname} = $trackname if defined $trackname; my $type = $use_featurefile ? 'featurefile' : 'gff3'; while (my $file = shift) { my $fh; if ($file =~ /\.(gz|bz2)$/) { warn "creating tempfile"; $fh = tempfile(); my $unzipper = $file =~ /\.gz$/ ? 'gunzip -c' : 'bunzip2 -c'; my $unzip = IO::File->new("$unzipper $file|"); my $data; while ($unzip->read($data,1024)) { $fh->print($data); } $unzip->close; seek($fh,0,SEEK_SET); } else { $fh = IO::File->new($file) or die "could not open $file: $!"; } print STDERR "Processing $file..."; $loader->load($fh); print STDERR "done.\n"; print $loader->featurefile($type,$method,$source); } 1; GBrowse-2.56/cgi-bin000755001750001750 013036764442 14316 5ustar00lsteinlstein000000000000GBrowse-2.56/cgi-bin/das000444001750001750 11175213036764442 15214 0ustar00lsteinlstein000000000000#!/usr/bin/perl eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell use strict; use warnings; # $Id$ use Bio::Graphics::Browser2; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] DAS FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; my %sys_env = %ENV; while (!$FCGI_DONE) { my $status = $fcgi->Accept; next unless $status >= 0; %ENV = ( %sys_env, %ENV ); my $globals = Bio::Graphics::Browser2->open_globals; CGI->initialize_globals(); GBrowse2::Das->new($globals)->run(); $fcgi->Finish(); } } else { my $globals = Bio::Graphics::Browser2->open_globals; GBrowse2::Das->new($globals)->run(); } exit 0; package GBrowse2::Das; use Carp; use strict; use Bio::Graphics::Browser2::Region; use Bio::Graphics::Browser2::RegionSearch; use Bio::Graphics::Browser2::DataSource; use Bio::Graphics::Browser2::RenderPanels; # just for make_link method use Bio::Graphics::Browser2::Util 'shellwords'; use Bio::DB::GFF; use File::Spec; use Date::Parse; use Date::Format; use CGI qw/header path_info param url request_method escapeHTML/ ; use constant DAS_VERSION => 'DAS/1.50'; use constant SO => 'http://song.cvs.sourceforge.net/viewvc/*checkout*/song/ontology/so.obo'; use constant CAPABILITIES => join '; ',qw(error-segment/1.0 unknown-segment/1.0 unknown-feature/1.0 feature-by-id/1.0 group-by-id/1.0 sources/1.0 dna/1.0 features/1.0 stylesheet/1.1 types/1.0 entry_points/1.0 dsn/1.0 sequence/1.0 ); use constant INVALID_SOURCE =>'invalid data source; use the sources or dsn command to get list'; use constant INVALID_OP =>'invalid request; please append a command such as /types to this URL'; use constant ERRCODES => { 200 => 'OK', 400 => 'Bad command', 401 => 'Bad data source', 402 => 'Bad command arguments', 403 => 'Bad reference object', 404 => 'Bad stylesheet', 405 => 'Coordinate error', 500 => 'Internal server error (oops)', 501 => 'Unimplemented feature', }; use constant CACHE_STYLESHEET=> 0; my (%CACHED_TYPES,%SO_HASH); sub new { my $class = shift; my $globals = shift; return bless {globals => $globals},ref $class || $class; } sub globals { shift->{globals} } sub render { shift->{render} } sub datasource { shift->{dsn} } sub track { shift->{track} } sub set_track { shift->{track} = shift } sub set_datasource { my $self = shift; my $dsn = shift; my $track; if ($dsn =~ /(.+)\|(.+)/) { # composite $dsn = $1; $track = $2; } my $source = $self->globals->create_data_source($dsn); if (!$source) { $self->error_header(INVALID_SOURCE,401); return; } if (!$track) { $self->error_header(INVALID_SOURCE,401); return; } if ($track && !$source->setting($track => 'das category')) { $self->error_header(INVALID_SOURCE,401); return; } $self->{track} = $track; $self->{dsn} = $source; } sub run { my $self = shift; my (undef,$dsn,$operation) = split '/',path_info(); $self->dispatch($operation || $dsn,$dsn); } sub dispatch { my $self = shift; my ($op,$dsn) = @_; do { $self->error_header(INVALID_OP,400); return } unless $op; do { $self->list_dsns(); return } if $op eq 'dsn'; do { $self->list_sources(); return } if $op eq 'sources'; # all other arguments expect a valid data source $self->set_datasource($dsn); do { $self->list_sources(); return } if $op eq $dsn; do { $self->stylesheet(); return } if $op eq 'stylesheet'; do { $self->entry_points(); return } if $op eq 'entry_points'; do { $self->types(); return } if $op eq 'types'; do { $self->features(); return } if $op eq 'features'; do { $self->dna(); return } if $op eq 'dna'; # if we get here we got an operation we don't understand $self->error_header(INVALID_OP,400); return; } sub error_header { my $self = shift; my ($message,$code) = @_; $code ||= 500; print header(-type =>'text/plain', -Access_Control_Allow_Origin => '*', -Access_Control_Expose_Headers => 'X-DAS-Version, X-DAS-Status, X-DAS-Capabilities, X-DAS-Server', -X_DAS_Version => DAS_VERSION, -X_DAS_Status => "$code ".ERRCODES->{$code}, -X_DAS_Capabilities => CAPABILITIES, ) unless $self->{header}++; return if request_method() eq 'HEAD'; print $message,"\n"; } sub ok_header { my $self = shift; print header(-type =>'text/xml', -Access_Control_Allow_Origin => '*', -Access_Control_Expose_Headers => 'X-DAS-Version, X-DAS-Status, X-DAS-Capabilities, X-DAS-Server', -X_DAS_Version => DAS_VERSION, -X_DAS_Status => '200 '.ERRCODES->{200}, -X_DAS_Server => "GBrowse/$Bio::Graphics::Browser2::VERSION", -X_DAS_Capabilities => CAPABILITIES, ) unless $self->{header}++; } sub list_dsns { my $self = shift; my $globals = $self->globals; my $j = ' 'x3; $self->ok_header(); print qq(\n\n); my $self_url = url(-full=>1); $self_url =~ s/dsn.*$//; print "\n"; for my $dsn (sort $globals->data_sources) { my $source = $globals->create_data_source($dsn); if (my $mapmaster = $source->setting('das mapmaster')) { $mapmaster = "$self_url/$dsn" if $mapmaster eq 'SELF'; for my $track ($source->labels) { next if $track =~ /:/; next unless $source->setting($track=>'das category'); my $citation = $source->setting($track=>'citation'); my $key = $source->setting($track=>'key'); my $description = $source->description($dsn)."; $track track"; $description .= "; $key" if $key; $description .= "; $citation" if $citation; $description = _xml_escapeASCII( $description ); $description = _xml_escapeLiteral( $description ); print "$j\n"; print qq($j$j$dsn|$track\n); print qq($j$j),$mapmaster,qq(\n); print qq($j$j),$description,qq(\n); print "$j\n"; } } } print "\n"; } # escape functions cribbed from XML::Writer (which is public domain) sub _xml_escapeLiteral { my $data = $_[0]; if ($data =~ /[\&\<\>\"]/) { $data =~ s/\&/\&\;/g; $data =~ s/\/\>\;/g; $data =~ s/\"/\"\;/g; } return $data; } sub _xml_escapeASCII($) { my $data = shift; $data =~ s/([^\x00-\x7F])/sprintf('&#x%X;', ord($1))/ge; return $data; } sub list_sources { my $self = shift; my $globals = $self->globals; my $j = ' 'x3; $self->ok_header(); print < END ; my $self_url = url(-full=>1); $self_url =~ s/sources.*$//; my @sources = $self->datasource ? $self->datasource : sort $globals->data_sources; print "\n"; SOURCE: for my $dsn (sort $globals->data_sources) { my $source = $globals->create_data_source($dsn); my $sourceinfo = ($source->setting('das source') || $source->setting('metadata')) or next; my %a = $sourceinfo =~ m/-(\w+)\s+([^-].+?(?= -[a-z]|$))/g; for (keys %a) { $a{$_} =~ s/\s+$// }; # trim for (qw(maintainer created coordinates authority source testrange)) { next if exists $a{$_}; warn "'das source' option requires mandatory '$_' field; skipping\n"; next SOURCE; } my $created; { local $^W = 0; # to quench uninit warnings from Date::Parser my @time = strptime($a{created}); @time = localtime unless @time; $created = strftime("%Y-%m-%dT%T%z",@time) || ''; } my $version = $a{version} || $a{coordinates_version} || ''; my @tracks = $self->track ? $self->track : sort $source->labels; for my $track (@tracks) { next unless $source->setting($track=>'das category'); my $citation = CGI::escapeHTML($source->setting($track=>'citation')); my $key = CGI::escapeHTML($source->setting($track=>'key')); my $title = CGI::escapeHTML($source->description($dsn)); my $description = $source->description($dsn)."; $track track"; $description .= "; $key" if $key; $description .= "; $citation" if $citation; $description = CGI::escapeHTML(CGI::unescapeHTML($description)); my $authority = CGI::escapeHTML($a{authority}); $authority .= "_$version" if $version; my $base = url(); $base =~ s/\?$//; my $maintainer = CGI::escapeHTML($a{maintainer}); my $uri = CGI::escape($dsn).'|'.CGI::escape($track); print < $authority,$a{source},$a{species} END ; for ('types','features','entry_points','stylesheet') { print < END } print < END } } print "\n"; } sub stylesheet { my $self = shift; my $globals = $self->globals; my $source = $self->datasource; my $cache_file = File::Spec->catfile(File::Spec->tmpdir, 'gbrowse_'.$source->name.'.stylesheet'); if (CACHE_STYLESHEET && -e $cache_file) { my $cache_mtime = (stat(_))[9]; if ($cache_mtime >= $source->mtime) { open my $f,$cache_file or die "$cache_file: $!"; ok_header(); print while <$f>; close $f; return; } } my $stylesheet = $self->_stylesheet(); if (open my $f,'>',$cache_file) { print $f $stylesheet; close $f; } $self->ok_header(); print $stylesheet; } sub _stylesheet { my $self = shift; my $source = $self->datasource; my $track = $self->track; my ($category2type,$type2category) = $self->categories; my %default_style = $source->default_style; $default_style{-link} ||= $source->setting(general=>'link'); my $stylesheet = < END ; local $^W=0; my %valid_attributes = map {$_=>1} qw(height fgcolor bgcolor label bump parallel linewidth style font fontsize linewidth direction); my %boolean_attributes = map {$_=>1} qw(label bump parallel); for my $cat ('default',keys %{$category2type}) { $stylesheet .= qq( \n); my (%seenit,%doneit); my @types = grep {!$seenit{$_}++} exists $category2type->{$cat} ? @{$category2type->{$cat}} : 'default|default'; for my $toplevel (@types) { my $db = $source->open_database($track); my $subtypemap = $self->expand_types($db,$toplevel); for my $type ('default',keys %$subtypemap) { my $forced_type = $source->setting($track=>'das type'); my $typeid = $type eq 'default' ? 'default' : ($forced_type || $self->guess_type($type)); next if $doneit{$typeid}++; my ($glyph,%style); my %type_style = $source->style($track); %style = (%default_style,map {ref $type_style{$_} ? () : ($_=>$type_style{$_}) } keys %type_style); delete $style{-feature}; delete $style{-feature_low}; delete $style{-link} if $style{-link} eq 'AUTO'; my $parts = $subtypemap->{$type}; my %style_hint; if (defined $parts && $parts > 0) { # a group! next unless $cat eq 'group'; ($glyph,%style_hint) = $self->guess_glyph($style{-glyph},1); if ($style{-glyph} eq 'gene' && $type eq $toplevel) { $glyph = 'HIDDEN' ; %style = %style_hint = (); } %style = (%style,%style_hint); } else { next if $cat eq 'group'; ($glyph,%style_hint) = $style{'-das glyph'} ? ($style{'-das glyph'}) : $self->guess_glyph($style{-glyph}); $glyph ||= 'box'; } $stylesheet .= qq( \n); $stylesheet .= qq( \n); $stylesheet .= qq( <\U$glyph\E>\n); for my $attribute (keys %style) { (my $name = $attribute) =~ s/^-//; $name =~ s/\s/_/g; next if $name =~ /glyph|category|das/; next unless $valid_attributes{lc $name}; my $value = $boolean_attributes{lc $name} ? ($style{$attribute} ? 'yes' : 'no') : escapeHTML($style{$attribute}); $stylesheet .= qq( <\U$name\E>$value<\U/$name\E>\n); } $stylesheet .= qq( \n); $stylesheet .= qq( \n); $stylesheet .= qq( \n); } } $stylesheet .= qq( \n); } $stylesheet .= < END ; return $stylesheet; } sub guess_glyph { my $self = shift; my ($suggested_glyph,$group) = @_; my $class = "Bio::Graphics::Glyph::$suggested_glyph"; my %style; eval "require $class" unless $class->can('new'); if ($group) { return $class->isa('Bio::Graphics::Glyph::transcript') ? ('LINE',-style=>'hat') : $class->isa('Bio::Graphics::Glyph::cds') ? ('LINE',-style=>'hat') : 'LINE'; } else { return $class->isa('Bio::Graphics::Glyph::arrow') ? 'ARROW' :$class->isa('Bio::Graphics::Glyph::anchored_arrow') ? 'ANCHORED_ARROW' :$class->isa('Bio::Graphics::Glyph::crossbox') ? 'CROSS' :$class->isa('Bio::Graphics::Glyph::ex') ? 'EX' :$class->isa('Bio::Graphics::Glyph::line') ? 'LINE' :$class->isa('Bio::Graphics::Glyph::transcript') ? 'BOX' :$class->isa('Bio::Graphics::Glyph::segments') ? 'LINE' :$class->isa('Bio::Graphics::Glyph::span') ? 'SPAN' :$class->isa('Bio::Graphics::Glyph::text_in_box') ? 'TEXT' :$class->isa('Bio::Graphics::Glyph::toomany') ? 'TOOMANY' :$class->isa('Bio::Graphics::Glyph::triangle') ? 'TRIANGLE' :$class->isa('Bio::Graphics::Glyph::primers') ? 'PRIMERS' :'BOX'; } } sub categories { my $self = shift; my $source = $self->datasource; my $dsn = $source->name; return @{$CACHED_TYPES{$dsn}} if exists $CACHED_TYPES{$dsn}; my (%category2type,%type2category,@types); my @labels = $source->labels; my $track = $self->track; my $category = $source->setting($track=>'das category'); my $has_subparts = $source->setting($track=>'das subparts'); my $has_superparts = $source->setting($track=>'das superparts'); my $structural = $source->setting($track=>'das landmark') || $has_subparts || $has_superparts; $category ||= 'structural' if $structural; next unless $category; # skip sections without a category marked my @composite_types = $source->label2type($track); push @types,@composite_types; my $t = Bio::DB::GFF->parse_types(@composite_types); my $db = $source->open_database($track); if ($db && $db->can('aggregators')) { $_->disaggregate($t,$db) foreach $db->aggregators; } my @t = map {defined($_->[1]) ? join(':',@$_) : $_->[0]} @$t; my %seenit; my @all_types = grep {!$seenit{$_}++} @t,@composite_types; push @{$category2type{$category}}, (@composite_types,@all_types); push @{$category2type{'group'}}, (@composite_types,@all_types); $type2category{$_} = $category foreach @composite_types; my $so_hash = $self->so_hash; for my $type (@all_types) { my $typeobj = Bio::DB::GFF::Typename->new($type); $type2category{__fuzzy__}{$typeobj} = $typeobj; my $so = $so_hash->{lc $type} if $so_hash; for my $t ($type,$so) { next unless $t; $type2category{$t} = $category; $type2category{__label__}{$t} = $track; $type2category{__subparts__}{$t}++ if $has_subparts; $type2category{__superparts__}{$t}++ if $has_superparts; } } $CACHED_TYPES{$dsn} = [(\%category2type,\%type2category,\@types)]; return @{$CACHED_TYPES{$dsn}}; } # Given a feature type, return all the subtypes that it contains # in the form [type,has_children] sub expand_types { my $self = shift; my ($db,$type) = @_; unless (exists $self->{type2subtypes}{$type}) { $self->{type2subtypes}{$type} = {}; TRY: { my $iterator = $db->features(-types=>$type,-iterator=>1) or last TRY; my $example = $iterator->next_seq or last TRY; $self->_add_types($self->{type2subtypes}{$type},$example); } } return $self->{type2subtypes}{$type}; } sub _add_types { my $self = shift; my ($hash,$feature) = @_; my @subparts = $feature->get_SeqFeatures; $hash->{$feature->method} = @subparts; $self->_add_types($hash,$_) foreach @subparts; } sub guess_type { my $self = shift; my $feature = shift; my $track = $self->track; my $type = ref $feature ? $feature->method : $feature; my $source = $self->datasource; return $type unless $source->fallback_setting($track=>'das use so'); my $glyph = $source->fallback_setting($track=>'glyph'); my $hash = $self->so_hash() or return $type; return $hash->{lc $type} || $type; } sub so_hash { my $self = shift; return \%SO_HASH if tied %SO_HASH; my $so_file = File::Spec->catfile(File::Spec->tmpdir,'SO.obo'); my $so_hash = File::Spec->catfile(File::Spec->tmpdir,'SO.db'); $self->fetch_sofile($so_file) or return unless -e $so_file; eval 'use DB_File' unless DB_File->can('new'); eval 'use Fcntl' unless Fcntl->can('O_CREAT'); $self->hash_sofile($so_file,$so_hash) or return unless -e $so_hash && (stat($so_hash))[9] >= (stat($so_file))[9]; tie %SO_HASH,'DB_File',$so_hash,Fcntl->O_RDONLY,0666,$DB_File::DB_HASH or return; return \%SO_HASH; } sub fetch_sofile { my $self = shift; return if $self->{so_fetch}++; # only try once per session my $so_file = shift; my $so_url = SO; eval "use LWP::Simple; 1" unless LWP::Simple->can('mirror'); my $result = eval { local $SIG{ALRM} = sub {die "timeout"}; alarm(5); my $result = LWP::Simple::mirror($so_url => $so_file); alarm 0; LWP::Simple::is_success($result); }; return $result; } sub hash_sofile { my $self = shift; my ($so_file,$so_hash) = @_; my %hash; tie %hash,'DB_File',$so_hash,Fcntl->O_CREAT|Fcntl->O_RDWR,0666,$DB_File::DB_HASH or return; open my $f,$so_file or return; local $/ = ''; # paragraph mode while (<$f>) { next unless /\[Term\]/; my ($id) = /^id: +(SO:\d+)/m; my ($name) = /^name: (.+)/m; my @synonyms = /^synonym: "(.+)"/mg; $hash{lc $_} = $id foreach ($name,@synonyms); } } sub types { my $self = shift; return $self->all_types() unless param('ref') or param('segment'); my $source = $self->datasource; my ($category2type,$type2category,$types) = $self->categories; my $summary = param('summary'); my $url = $self->get_url(); my @filter = param('type'); unless (@filter) { @filter = @$types; } my @segments = $self->get_segments() or return; $self->ok_header(); print < END ; foreach (@segments) { my ($reference,$class,$start,$stop) = @$_; next unless $reference; my $seq = $self->get_segment_obj($reference,$start,$stop) or next; unless ($seq) { #empty section my $version = $self->seq2version($reference); print qq(\n); print qq(\n); next; } my $s = $seq->start; my $e = $seq->stop; # use absolute coordinates -- people expect it my $name = $seq->seq_id; my $version = $self->seq2version($name); print qq(\n); my @args = (-enumerate=>1); push @args,(-types=>\@filter) if @filter; my %histogram = $seq->types(@args); foreach (keys %histogram) { my ($method,$source) = split ':'; my $count = $histogram{$_}; my $category = $self->transmute($_,$type2category); $category ||= ''; #get rid of uninit variable warnings $method ||= ''; $source ||= ''; $count ||= 0; (my $type = $_) =~ s/:[^:]+$//; my $id = $self->type2so($type); print qq(\t$count\n); } print qq(\n); } print < END } # ----------------------------------------------------------------- sub dna { my $self = shift; my @segments = $self->get_segments() or return; $self->ok_header(); print qq(\n); print qq(\n); print qq(\n); for my $segment (@segments) { my ($reference,$refclass,$start,$stop) = @$segment; my ($seg,$dna); for my $dbid ('general',$self->track) { $seg = $self->get_segment_obj($reference,$start,$stop,undef,$dbid); unless ($seg) { $self->error_segment($reference,$start,$stop); last; } $dna = $seg->dna; last if $dna && $dna =~ /[gatc]/i; }; next unless $dna; my $length = length $dna; $dna =~ s/(.{60})/$1\n/g; my $ref = $seg->ref; my $s = $seg->start; my $e = $seg->end; print < $dna END } print qq(\n); } # ----------------------------------------------------------------- sub type2so { my $self = shift; my $type = shift; my $track = $self->track; my $source = $self->datasource; return $type unless $source->fallback_setting($track=>'das use so'); my $hash = $self->so_hash() or return $type; return $hash->{lc $type} || $type; } # list of all the types sub all_types { my $self = shift; my ($category2type,$type2category,$types) = $self->categories; my $url = $self->get_url(); my $track = $self->track(); $self->ok_header(); print < END ; for my $t (@$types) { my $category = $self->transmute($t,$type2category); my $typeobj = Bio::DB::GFF::Typename->new($t); my $method = $typeobj->method; my $source = $typeobj->source; my $id = $t; $id = $self->type2so($id); print qq(\t\n); } print < END } sub error_segment { my $self = shift; my ($reference,$start,$stop) = @_; my $source = $self->datasource; my $mapmaster = $source->setting('das mapmaster'); my $authoritative = $mapmaster && ($mapmaster eq 'SELF' || $mapmaster eq (url(-full=>1) . "/". $source->name)); my $tag = $authoritative ? 'ERRORSEGMENT' : 'UNKNOWNSEGMENT'; my $attributes = ''; $attributes .= qq( start="$start") if defined $start; $attributes .= qq( stop="$stop") if defined $stop; print qq(<$tag id="$reference"$attributes />\n); } sub error_id { my $self = shift; my $id = shift; print qq( \n); } # =============== humungous features processing steps ================= # ----------------------------------------------------------------- # get the features for the segment indicated sub features { my $self = shift; my $source = $self->datasource; my $track = $self->track; my @segments = $self->get_segments(); my $summary = param('summary'); my $url = $self->get_url(); my @filter = param('type'); my @category = param('category'); my ($category2type,$type2category,$top_types) = $self->categories; my %valid_types = map {$_=>1} @$top_types; unless (@filter || @category) { @filter = @$top_types; } push @filter,map {exists $category2type->{$_} ? @{$category2type->{$_}} : $_ } @category; @filter = map {shellwords($source->setting($track => 'feature'))} @filter = grep {$valid_types{$_}} @filter; $self->ok_header(); print < END ; foreach (@segments) { my ($reference,$refclass,$start,$stop) = @$_; my @features = $self->get_segment_obj($reference,$start,$stop,1); $self->error_segment($reference,$start,$stop) unless @features; for my $seq (@features) { $self->dump_segment($seq,\@filter,undef,$type2category); } } # dump feature requests, if any for my $id (param('feature_id'),param('group_id')) { my @segments = $self->get_feature_obj($id); $self->error_id($id) unless @segments; foreach (@segments) { eval{$_->absolute(1)}; } my @exact_matches = grep {$id eq $_->display_name} @segments; my @to_dump = @exact_matches ? @exact_matches : @segments; dump_segment($_,\@filter,'toplevel') foreach @to_dump; } print < END } sub dump_segment { my $self = shift; my $seq = shift; my $filter = shift; my $toplevel = shift; my $type2category = shift; my $source = $self->datasource; my $r = $seq->seq_id; my $s = $seq->start; my $e = $seq->stop; ($s,$e) = ($e,$s) if $s > $e; my $version = seq2version($r); if ($toplevel) { print qq(\n); return; } print qq(\n); my %agg_map; my $db = $source->open_database($self->track); if ($db->can('aggregators')) { %agg_map = map {($_->get_method||'') => ($_->main_name||'')} $db->aggregators; } if (@$filter) { my $iterator = $db->features(-seq_id=>$r,-start=>$s,-end=>$e,-types=>$filter,-merge=>1,-iterator=>1); while (my $f = $iterator->next_seq) { $self->print_feature($f,undef,$self->transmute($f->type,$type2category),\%agg_map); } } print qq(\n); } sub print_feature { my $self = shift; my $f = shift; my $parent = shift; my $category = shift; my $agg_map = shift; my $count = shift || 0; my $group = shift || $parent || $f; my $level = shift || 0; my $sequence = shift || 0; my @subparts = $self->children($f); my $no_parent = @subparts && $self->no_parent_wanted($f); $self->_print_feature($f, $parent, $category, $agg_map, $count, $group, $level, $sequence, ) unless $no_parent; $self->print_feature($_, ($no_parent ? undef : $f), $category, $agg_map, ++$count, $group, $level+1, $sequence++, ) foreach @subparts; } sub _print_feature { local $^W = 0; # kill some uninit variable warnings my $self = shift; my $f = shift; my $parent = shift; my $category = shift; my $agg_map = shift || {}; my $count = shift; my $group = shift; my $level = shift || 0; my $sequence = shift || 0; my $datasource = $self->datasource; my $track = $self->track; my $flabel = $f->display_name||''; my $source = $f->source; my $method = $f->method; my $start = $f->start; my $end = $f->stop; my $score = $f->score; my $orientation = $f->strand || 0; my $phase = $f->phase; my $type = $self->guess_type($f); my $typelabel = $f->type; my $pid = $self->feature2id($parent) if $parent; my $id = $self->feature2id($f) || $pid; $id .= ".$sequence" if $pid && $id eq $pid; my $counter = 0; my @children = $self->children($f); my @child_ids = map {$self->feature2id($_)||"$id.".$counter++} @children; my @notes = $f->notes if $f->can('notes'); my %attributes = $f->attributes if $f->can('attributes'); my $das_version = $datasource->setting('das version') || 1.5; my $panel = Bio::Graphics::Browser2::RenderPanels->new(-source=>$datasource); my $gclass; if ($f->can('group')) { # Bio::DB::GFF feature $gclass = (ref($group) && $group->can('class')) ? $group->class : 'anonymous'; } else { $gclass = ''; } my $group_type = $self->forced_group($parent||$f) || eval{$parent->type} || $type; $group_type =~ s/\:\w+$//; # This is way nasty. The aggregator may have changed the method of the # main feature, so we need to change it back to what it was originally # for the purpose of serializing on the net. What amazing shortsightedness # on the part of someone who should know better. $method = $agg_map->{$method} if defined $agg_map->{$method}; $phase ||= 0; $orientation ||= 0; $score = '-' unless defined $score; $orientation = $orientation >= 0 ? '+' : '-'; ($start,$end) = ($end,$start) if defined($start) && defined($end) && $start > $end; # group stuff my $groupid = $group->primary_id; my $grouplabel = $group->display_name; my ($group_info,$link,$gtype,$url); $url = $panel->make_link($f,undef,$self->track); $url ||= 'none'; if ($url ne 'none') { $self->hack_link(\$url); $link = qq($flabel); } if (@child_ids) { my $glyph = $datasource->fallback_setting($track=>'glyph'); $gtype = " type='$type'"; } else { $gtype = " type='$group_type'"; } if (%attributes) { for my $tag (keys %attributes) { next if $tag =~ /parent_id/ || $tag =~ /load_id/; my @values = ref($attributes{$tag}) ? @{$attributes{$tag}} : $attributes{$tag}; $group_info .= join("\n",map {qq(\t$_)} @values)."\n"; } } elsif (@notes) { $group_info = join("\n",map {qq(\t$_)} @notes); } if ($group_info) { # post-fix formatting $group_info =~ s/^\t//; $group_info =~s/\n$//; } my ($target,$target_info); if (($target = $f->target) && $target->can('start')) { my $start = $target->start; my $stop = $target->stop; my $seqid = $target->ref; $target_info = qq(); } my ($map,$type2category); $map = qq() ; $start ||= ''; $end ||= ''; # suppress printing parent features for earlier versions of DAS return if $das_version < 1.6 and @child_ids; $flabel ||= $grouplabel; print < $typelabel $method $start $end $score $orientation $phase END ; if ($das_version >= 1.6) { print qq( \n) if defined $pid; print qq( \n) foreach @child_ids; } print qq( $link\n) if $link; print qq( $target_info\n) if $target_info; if (defined $groupid) { $gtype ||= ''; if ($group_info) { print qq( \n); print qq( $group_info\n) if $group_info; print qq( \n); } else { print qq( \n); } } print < END ; } sub children { my $self = shift; my $feat = shift; my @children = $feat->get_SeqFeatures; my @expanded_children; for my $c (@children) { if ($self->split_location($c)) { my @grand_children = $c->get_SeqFeatures; push @expanded_children,@grand_children; } else { push @expanded_children,$c; } } return @expanded_children; } sub split_location { my $self = shift; my $f = shift; my @subparts = $f->get_SeqFeatures; my %subtypes = map {$_->type=>1} @subparts; return keys %subtypes == 1 && $subtypes{$f->type}; } # unfortunately, the gbrowse library returns a relative address # for AUTO links sub hack_link { my $self = shift; my $url_ref = shift; return if $$url_ref =~ m!^\w+:!; unless ($self->{prefix}) { my $self_url = url(-full=>1,-path=>1); ($self->{prefix}) = $self_url =~ m!^(\w+://[^/]+)!; ($self->{suffix}) = $self_url =~ m!.+(/das/.+)!; } $$url_ref =~ s!$self->{suffix}!!; $$url_ref = "$self->{prefix}$$url_ref"; } sub no_parent_wanted { my $self = shift; my $feature = shift or return; return unless $feature; my $source = $self->datasource; my $track = $self->track; my $type = $feature->type; return $self->{no_parent}{$type} if exists $self->{no_parent}{$type}; my $no_parent = $source->fallback_setting($track => 'das flatten'); return $self->{no_parent}{$type} = $no_parent; } # ----------------------------------------------------------------- sub forced_group { my $self = shift; my $feature = shift or return; my $type = $feature->type; return $self->{forced_group}{$type} if exists $self->{forced_group}{$type}; return $self->{forced_group}{$type} = $self->datasource->setting($self->track=>'das type'); } sub feature2id { my $self = shift; my $f = shift; my $id = $f->primary_id; # HACK my $db = $self->datasource->open_database($self->track); $id = unpack('L',$id) if $db->isa('Bio::DB::GFF::Adaptor::berkeleydb'); return $id; } # -----------------querying regions------------------------------------- sub get_segments { my $self = shift; my $source = $self->datasource; # extended segment argument my @segments; foreach (param('segment')) { my ($ref,$start,$stop) = /^(\S+?)(?::(\d+)(?:\.\.|,)(\d+))?$/; push @segments,[$ref,$start,$stop]; } push @segments,[scalar param('ref'), scalar param('start'), scalar param('stop')] if param('ref'); return unless @segments; foreach (@segments){ my ($reference,$start,$stop) = @$_; my $class = $source->setting('reference class') || 'Sequence'; my $name = $reference; if ($reference =~ /^(\w+):(\S+)$/) { $class = $1; $name = $2; } my @values = ($name,$class,$start,$stop); $_ = \@values; } return wantarray ? @segments : \@segments; } sub get_segment_obj { my $self = shift; my ($reference,$start,$stop,$as_feature,$dbid) = @_; my $source = $self->datasource; my $db = $source->open_database($self->track); my $search = $self->get_search_object; my $term = defined $start ? "$reference:$start..$stop" : $reference; my @features = $search->features(-search_term=>$term); return unless @features; # the "feature" flag is used when we are looking for supercomponents # and we want to fetch the segment as a feature object so as to find its parent return @features if $as_feature; return wantarray ? $search->features2segments(\@features,$dbid||$self->track) : $search->feature2segment($features[0],$dbid||$self->track); } sub get_search_object { my $self = shift; my $db = shift; return $self->{searchobj} if defined $self->{searchobj}; my $search = Bio::Graphics::Browser2::RegionSearch->new( { source => $self->datasource, state => {}, }); $search->init_databases(); return $self->{searchobj} = $search; } #------------------- little utils -------------- sub get_url { my $self = shift; my $url = url(-path=>1, -query=>1); $url =~ tr/&/\;/; return $url; } sub seq2version { my $self = shift; my $seqname = shift or return '1.0'; return $seqname =~ /\.(\d+)$/ ? $1 : '1.0'; } # calculate type and category from type and method sub transmute { my $self = shift; my $type = shift; my $map = shift; # try fast exact match first return $map->{$type} if exists $map->{$type}; # otherwise do a fuzzy match for my $typeobj (values %{$map->{__fuzzy__}}) { if ($typeobj->match($type)) { my $category = $map->{$typeobj}; # fetch category for this object $map->{$type} = $category; # remember exact match for later return $category; } } return 'miscellaneous'; # no success } GBrowse-2.56/cgi-bin/gbgff000444001750001750 373313036764442 15457 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell # $Id: gbgff,v 1.2 2009-08-27 19:13:18 idavies Exp $ # just redirect to gbrowse in same directory use strict; use warnings; use File::Basename 'dirname'; use CGI 'url','path_info','redirect','header','param'; use Bio::Graphics::Browser2::Render; umask 022; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] GBrowse FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; while (!$FCGI_DONE && ($fcgi->Accept >= 0)) { CGI->initialize_globals(); process_transaction(); } } else { process_transaction(); } exit 0;; sub process_transaction { my $base = url(); my $path_info = path_info(); $path_info =~ s!^/!!; my $source = param('source'); my $segment = param('q') || param('segment'); my $ref = param('ref') || param('seqid'); my $start = param('start'); my $end = param('end') || param('stop'); my $dump = param('d'); my $type = param('t') || param('type'); my $id = param('id'); my $stylesheet= param('s'); my $url = dirname($base); $url .= '/gbrowse'; $url .= "/".($source || $path_info); $url .= "/?"; $url .= "gbgff=1"; $url .= ";q=".($segment || "$ref:$start..$end"); $url .= ";d=$dump" if defined $dump; $url .= ";t=$type" if defined $type; $url .= ";id=$id" if defined $id; $url .= ";s=$stylesheet" if defined $stylesheet; print redirect($url); } 1; GBrowse-2.56/cgi-bin/gbrowse000444001750001750 274113036764442 16052 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use CGI; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::Render::HTML; umask 022; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; my $init; if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] GBrowse FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; my %sys_env = %ENV; warn "[$$] FastCGI initializing and loading default data sources...\n"; my $globals = Bio::Graphics::Browser2->open_globals; if($globals->preload_datasources) { foreach ($globals->data_sources) { warn "[$$] Loading $_\n"; my $source = $globals->create_data_source($_); $source->open_database(); # cache default database in memory } } else { warn "[$$] Preload disabled"; } while (!$FCGI_DONE) { my $status = $fcgi->Accept; next unless $status >= 0; %ENV = (%sys_env, %ENV); CGI->initialize_globals(); my $render = Bio::Graphics::Browser2::Render::HTML->new($globals); eval { local $SIG{PIPE} = sub {die "pipe"}; $render->run(); }; warn $@ if $@; $render->destroy; } my $pgrp = getpgrp(); kill TERM => -$pgrp; } else { $SIG{TERM} = sub { warn "[$$] gbrowse going down..."; CORE::exit 0 }; my $globals = Bio::Graphics::Browser2->open_globals; Bio::Graphics::Browser2::Render::HTML->new($globals)->run(); } exit 0; GBrowse-2.56/cgi-bin/gbrowse_details000444001750001750 5165513036764442 17607 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell use strict; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::RegionSearch; use Bio::Graphics::Browser2::Markup; use Bio::Graphics::Browser2::UserTracks; use Bio::Graphics::Glyph::generic; our $VERSION = '$Id: gbrowse_details,v 1.7 2009-08-27 19:13:18 idavies Exp $'; our ($INDEX,%COLORS,%URLS,%formatterCache); use constant DEFAULT_CONF => '/etc/apache2/gbrowse'; use constant DEFAULT_MASTER => 'GBrowse.conf'; umask 022; my $conf_dir = Bio::Graphics::Browser2->config_base; my $conf_file = $ENV{GBROWSE_MASTER} || DEFAULT_MASTER; my $conf = Bio::Graphics::Browser2->new(File::Spec->catfile($conf_dir,$conf_file)) or die "Couldn't read globals"; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; my $modperl = $ENV{MOD_PERL}; my $init; if ($modperl && !$init++) { $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] GBrowse FastCGI process caught sig$sig. Exiting... (pid $$)\n"; CORE::exit 0 }; } if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] GBrowse FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; my %sys_env = %ENV; while (!$FCGI_DONE) { my $status = $fcgi->Accept; next unless $status >= 0; %ENV = ( %sys_env, %ENV ); CGI->initialize_globals(); DetailRenderer->new($conf)->run(); $fcgi->Finish(); } } else { DetailRenderer->new($conf)->run(); } exit 0; package DetailRenderer; use strict; use constant DEBUG => 0; use constant MAX_DNA => 500_000; use CGI qw(:standard *table *TR escape); use Bio::Graphics::Browser2::Realign 'align'; use Data::Dumper 'Dumper'; sub new { my $package = shift; my $conf = shift; return bless { index => 0, colors => {}, urls => {}, formatterCache => {}, globals => $conf, },ref $package || $package; } sub globals { my $self = shift; my $d = $self->{globals}; $self->{globals} = shift if @_; $d; } sub state { my $self = shift; my $d = $self->{state}; $self->{state} = shift if @_; $d; } sub source { my $self = shift; my $d = $self->{source}; $self->{source} = shift if @_; $d; } sub run { my $self = shift; my $conf = $self->globals; my $session = $conf->session; $conf->update_data_source($session); $self->source($conf->create_data_source($session->source)); $self->state($session->page_settings); $self->add_user_tracks($session); my $name = param('name'); my $class = param('class'); my $ref = param('ref'); my $start = param('start'); my $end = param('end'); my $f_id = param('feature_id'); my $db_id = param('db_id'); my $rmt = param('remote'); $self->state->{dbid} = $db_id if $db_id; # to search correct database # This populates the $self->{urls} variable with link rules from the config file. $self->get_link_urls(); my $search = Bio::Graphics::Browser2::RegionSearch->new( { source => $self->source, state => $self->state, }); $search->init_databases(); # this is the weird part; we create a search name based on the arguments # provided to us my ($search_term,$search_class); if ($f_id) { $search_term = "id:$f_id"; } elsif ($class && $name) { $search_term = $name; $search_class = $class; } elsif (defined $ref && defined $start && defined $end) { $search_term = "$ref:$start..$end"; } else { $search_term = $name; } unless (defined $search_term) { print header, start_html('gbrowse_details error'), p({-class=>'error'}, 'This script must be called with one or more of the parameters name, feature_id or db_id.'); end_html; exit 0; } warn "search term = $search_term" if DEBUG; my $features = eval {$search->search_features({-name=>$search_term,-class=>$search_class})} || []; warn "search_features(-search_term=>$search_term): $@" if $@; warn "features = @$features" if DEBUG; warn "segments = ",join ' ',$features->[0]->segments if (DEBUG && @$features); # provide customized content for popup balloons if (defined $rmt) { print header,start_html; print $self->remote_content($rmt,$features->[0]); print end_html; } else { print header(); my $css = $self->source->global_setting('stylesheet'); my $stylesheet = $self->globals->resolve_path($css,'url'); { local $^W = 0; # shut up a warning from CGI.pm print start_html(-title => "GBrowse Details: $search_term", -style => $stylesheet); print h1("$name Details"); } if (@$features) { print $self->print_features($features); } else { print p({-class=>'error'},'Requested feature not found in database.'); } print end_html(); } } sub add_user_tracks { my $self = shift; my $session = shift; my $source = $self->source; my $userdata = Bio::Graphics::Browser2::UserTracks->new($source,$session); my @user_tracks = $userdata->tracks; for my $track (@user_tracks) { my $config_path = $userdata->track_conf($track); eval {$source->parse_user_file($config_path)}; } } ###################### sub print_features { my $self = shift; my $features = shift; my $subf = shift || 0; my $string; my @colors = qw(none lightgrey yellow pink orange brown tan teal cyan lime green blue gray); for my $f (@$features) { my $method = $f->primary_tag . $subf; warn "index = $self->{index}, method = $method" if DEBUG; $self->{colors}{$method} ||= $colors[$self->{index}++ % @colors]; my $options = {-bgcolor => $self->{colors}{$method}} unless $self->{colors}{$method} eq 'none'; $string .= start_table({-cellspacing=>0}); $string .= $self->print_multiple($f, $options, 'Name', $f->name) if $f->name; $string .= $self->print_multiple($f, $options, 'Class', $f->class) unless $f->class eq 'Sequence' || $subf; $string .= $self->print_multiple($f, $options, 'Type', $f->primary_tag); my $description = Bio::Graphics::Glyph::generic->get_description($f); $string .= $self->print_multiple($f, $options, 'Description', $description) if $description; $string .= $self->print_multiple($f, $options, 'Source', $f->source_tag) if $f->source_tag; $string .= $self->print_multiple($f, $options, "Position", $f); $string .= $self->print_multiple($f, $options, "Length", $f->length); eval { local $^W = 0; if ($f->can('hit') && (my $hit = $f->hit)) { # try to correct for common GFF2 error of indicating a -/- alignment # using a (-) src strand and a hit_start > hit_end my $bug = $f->strand < 0 && $f->hit->strand < 0; $string .= $self->print_multiple($f, $options, 'Query', $hit->seq_id); $string .= $self->print_multiple( $f->hit, $options, 'Matches', $hit->seq_id.':'.$hit->start.'..'.$hit->end. ($hit->strand >= 0 ? ' (+)':' (-)') ); $string .= $self->print_multiple($f, $options, '', $self->print_matches($f,$hit,$bug));# if $subf; } $string .= $self->print_multiple($f, $options, "Score", $f->score) if $f->can('score') && defined $f->score; my %attributes = $f->attributes if $f->can('attributes'); for my $a (sort grep {!/Hit/} keys %attributes) { $string .= $self->print_multiple($f, $options, $a, $f->attributes($a)); } $string .= $self->print_multiple($f, $options, 'primary_id', $f->primary_id) if $f->can('primary_id'); $string .= $self->print_multiple($f, $options, 'gbrowse_dbid', $f->gbrowse_dbid) if $f->can('gbrowse_dbid') && $f->gbrowse_dbid; $string .= TR({-valign=>'top',-class=>'databody'}, th({-height=>3},''), td({-height=>3},'') ); # try to sort features with hits so that hit is in order. # But, subfeatures don't always have the hit, so check for # that too my @subfeatures = $f->get_SeqFeatures; if ($f->can('hit') && $f->hit && $subfeatures[0] && $subfeatures[0]->hit) { @subfeatures = sort {$a->hit->start <=> $b->hit->start} @subfeatures; } else { @subfeatures = sort {$a->start <=> $b->start} @subfeatures; } my $subtable = $self->print_multiple($f, $options, 'Parts', $self->print_features(\@subfeatures,$subf+1) ) if @subfeatures; $string .= $subtable || ''; # prevent uninit variable warning $string .= CGI::end_table(); if ($subtable or $subf==0) { if ($f->length > MAX_DNA) { $string .= "Sequence display limited to ".MAX_DNA." bases"; } else { my $dna = $self->get_seq($f); $dna = $dna->seq if ref $dna; # compensate for API changes $string .= $self->print_dna($f, $dna, $f->start, $f->strand, \@subfeatures, $subf+1) if $dna; } } } } return $string; } sub get_seq { my $self = shift; my $f = shift; my $ref = $f->seq_id; my $start = $f->start; my $end = $f->end; my $strand = $f->strand; # the sequence must live in the database flagged in the [GENERAL] section my $db = $self->source->open_database() or return; my ($seg) = $db->segment($ref,$start,$end) or return; return $seg->seq if eval {$f->target && $f->strand < 0 && $f->target->strand < 0}; return $strand >= 0 ? $seg->seq : $seg->seq->revcom; } sub print_dna { my $self = shift; my ($feature,$dna,$start,$strand,$features,$subf) = @_; my %seenit; warn "dna=$dna" if DEBUG; my $markup = Bio::Graphics::Browser2::Markup->new; for my $f (@$features) { warn "f = $f" if DEBUG; my $method = $f->primary_tag . $subf; warn "$method => $self->{colors}{$method}" if DEBUG; next if $self->{colors}{$method} eq 'none'; $markup->add_style($method => "BGCOLOR $self->{colors}{$method}"); } # add a newline every 80 positions $markup->add_style('newline',"\n"); # add a space every 10 positions $markup->add_style('space'," "); my @markup; for my $f (@$features) { my ($s,$e); if ($strand >=0) { $s = $f->low - $start; $e = $f->high - $start; } else { if ($start - $f->high < 0) { #how much of a hack is this! #it fixes chado feature differences $s = $start + length($dna) - $f->low -1; $e = $start + length($dna) - $f->high -1; } else { $s = $start - $f->low; $e = $start - $f->high; } } ($s,$e) = ($e,$s) if $s > $e; my $method = $f->primary_tag . $subf; next if $self->{colors}{$method} eq 'none'; push @markup,[$method,$s,$e+1]; # Duelling off-by-one errors.... } push @markup,map {['newline',80*$_]} (1..length($dna)/80); push @markup,map {['space',10*$_]} grep {$_ % 8} (1..length($dna)/10); $markup->markup(\$dna,\@markup); my $position = $self->position($feature); my $name = $feature->name; my $class = $feature->class; $name ||= ''; return pre(">$name class=$class position=$position\n".$dna); } sub print_matches { my $self = shift; my ($src,$tgt,$bug) = @_; my $sdna = $src->dna or return ''; my $tdna = $tgt->dna or return ''; my $top_label = $src->seq_id; my $bot_label = $tgt->seq_id; my $src_x = $src->start; my $src_y = $src->end; my $tgt_x = $tgt->start; my $tgt_y = $tgt->end; my $tdir = $tgt->strand || +1; my $sdir = $src->strand || +1; ($tgt_x,$tgt_y) = ($tgt_y,$tgt_x) if $tgt->strand < 0; if ($bug) { # correct for buggy data files that show -/- alignments; really -/+ $tdir = -1; $sdir = 1; $tgt_x = $tgt_y; $tdna = reversec($tdna); } warn ("sdir = $sdir, $src_x -> $src_y / $tgt_x -> $tgt_y") if DEBUG; my ($top,$middle,$bottom) = do_align($src,$sdna,$tdna); ($top,$middle,$bottom) = clip($top,$middle,$bottom); my $m = max(length($top_label),length($bot_label)); my $p = max(length($src_x),length($src_y),length($tgt_x),length($tgt_y)); my $l = ' ' x ($m+$p+2); # adjusting for HTML my $string; my @top = $top =~ /(.{1,60})/g; my @middle = $middle =~ /(.{1,60})/g; my @bottom = $bottom =~ /(.{1,60})/g; $src_x = $src_y if $sdir < 0; for (my $i=0; $i<@top; $i++) { my $src_delta = $sdir * (length($top[$i]) - $top[$i]=~tr/-/-/); my $tgt_delta = $tdir * (length($bottom[$i]) - $bottom[$i]=~tr/-/-/); $string .= sprintf("%${m}s %${p}d %s %d\n$l%s\n%${m}s %${p}d %s %d\n\n", $top_label,$src_x,$top[$i],$src_x + $src_delta - $sdir, $middle[$i], $bot_label,$tgt_x,$bottom[$i],$tgt_x + $tgt_delta - $tdir); $src_x += $src_delta; $tgt_x += $tgt_delta; } return pre($string); } sub clip { my ($src,$align,$tgt) = @_; my @src = split '',$src; my @align = split '',$align; my @tgt = split '',$tgt; while ($src[0] eq '-') { shift @src; shift @align; shift @tgt; } while ($src[-1] eq '-') { pop @src; pop @align; pop @tgt; } return (join('',@src),join('',@align),join('',@tgt)); } sub do_align { my ($src,$sdna,$tdna) = @_; if (my $cigar = eval {$src->cigar_array}) { my ($pad_source,$pad_target,$pad_match); for my $event (@$cigar) { my ($op,$count) = @$event; if ($op eq 'I' || $op eq 'S') { $pad_source .= '-' x $count; $pad_target .= substr($tdna,0,$count,''); $pad_match .= ' ' x $count; } elsif ($op eq 'D' || $op eq 'N') { $pad_source .= substr($sdna,0,$count,''); $pad_target .= '-' x $count; $pad_match .= ' ' x $count; } elsif ($op eq 'H' || $op eq 'P') { # nothing needs to be done for hard clipping or pads } else { $pad_match .= join '',( map {substr($sdna,$_,1) eq substr($tdna,$_,1) ? '|' : ' ' } (0..$count-1)); $pad_source .= substr($sdna,0,$count,''); $pad_target .= substr($tdna,0,$count,''); } } return ($pad_source,$pad_match,$pad_target); } else { return align($sdna,$tdna); } } sub max { if (@_ == 2) { return $_[0] > $_[1] ? $_[0] : $_[1]; } else { return (sort {$b<=>$a} @_)[0]; } } sub print_multiple { my $self = shift; local $^W = 0; # get rid of uninit variable warnings my $feature = shift; my $options = shift; my $label = shift; $options ||= {}; my @a = $self->format_values($feature,$label,@_); return '' unless @a; my $LINK = ""; my $isFirst=1; my $string = ' ' ; for my $obj (@a) { if ($self->{urls}{$label}){ $LINK = $self->{urls}{$label}; if ( ref ($LINK) eq 'CODE' ){ #Testing subs $LINK= eval { $LINK->($label,$obj)}; $LINK = $LINK ? "$obj" : $obj; } else { #end testing subs $LINK =~ s/\$tag/$label/; $LINK=~ s/\$value/$obj/; $LINK = "$obj"; } # testing subs } # for EST alignment features, create a link to get the orignal EST sequence if (($label eq 'Query') && ($self->{urls}{'alignment'}) && ($obj =~ /alignment/i)){ my $name = shift @a; $LINK = $self->{urls}{'alignment'}; $LINK=~ s/\$value/$name/; $LINK = "$obj : (Aligned Sequence)"; } # Wrap way long lines, but not those involving HTML tags or # inside
    ]*>)/,$obj unless $obj =~ /
    'top',-class=>'databody'},
    				  th({-align=>'LEFT',
    				      -valign=>'top',
    				      -class=>'datatitle',
    				      -width=>100},length $label>0 ? "$label: " : ''),
    				  td($options, $LINK ? $LINK : $obj)
    		);
    	} else {
    	    
    	    $string .= join '', TR({-class=>'databody'},
    				   th({-align=>'RIGHT',-class=>'datatitle',-width=>100},' '),
    				   td($options,$LINK?$LINK:$obj)
    		);
    	}
    	$LINK='';
        }
        $string;
    }
    
    sub position {
        my $self = shift;
    
        my $f      = shift;
        my $simple = shift;
        my $bug    = shift; # for (-) (-) alignments
    
        my $ref   = $f->seq_id;
        my $start = $f->start;
        my $end   = $f->end;
        if ($simple) {
    	($start,$end) = ($end,$start) if $f->strand < 0;
    	return "$ref $start..$end";
        }
        my $s = $f->strand;
        if ($bug) {  # data bug
    	($start,$end) = ($end,$start);
    	$s *= -1;
        }
        my $strand = $s > 0 ? '+' : $s < 0 ? '-' : '';
    
        my $src = escape($self->source->name);
        my $url = "../gbrowse/$src?name=$ref:$start..$end";
        return a({-href=>$url},$strand ? "$ref:$start..$end ($strand strand)" 
    	                           : "$ref:$start..$end");
    }
    
    sub get_link_urls {
        my $self = shift;
    
        my $source = $self->source;
        my $urls   = $self->{urls};
    
        my @LINK_CONFIGS = map {$_=~/\:DETAILS$/?$_:undef} 
            $source->Bio::Graphics::FeatureFile::setting();
    
        foreach (@LINK_CONFIGS){
    	next unless $_;
    	next unless $_=~/(.*?)\:DETAILS/;
    	next unless $1;
    	my $URL = $source->setting("$_", 'url');
    	next unless $URL;
    	$urls->{$1}=$URL;
        }
    }
    
    sub format_values {
        my $self = shift;
    
        my ($feature,$tag,@values) = @_;
        my $formatter    = $self->get_formatter($feature,$tag);
    
        $Data::Dumper::Indent = 3;
        $Data::Dumper::Terse  = 1;
        return map {ref($_) ? "
    ".Dumper($_)."
    " : $_} @values unless $formatter; if (ref $formatter eq 'CODE') { return map {$formatter->($_,$tag,$feature)} @values; } my $name = $feature->display_name; my $start = $feature->start || ''; my $end = $feature->end || ''; my $strand = $feature->strand || ''; my $method = $feature->primary_tag || ''; my $source = $feature->source_tag || ''; my $type = eval {$feature->type} || $method || ''; my $class = eval {$feature->class} || ''; my $description = eval { join ' ',$feature->notes } || ''; $formatter =~ s/\$tag/$tag/g; $formatter =~ s/\$name/$name/g; $formatter =~ s/\$start/$start/g; $formatter =~ s/\$end/$end/g; $formatter =~ s/\$stop/$end/g; $formatter =~ s/\$strand/$strand/g; $formatter =~ s/\$method/$method/g; $formatter =~ s/\$source/$source/g; $formatter =~ s/\$type/$type/g; $formatter =~ s/\$class/$class/g; $formatter =~ s/\$description/$description/g; return map {my $tmp_formatter = $formatter; $tmp_formatter =~ s/\$value/$_/g; $tmp_formatter} @values; } sub get_formatter { my $self = shift; my ($feature,$tag) = @_; my $method = $feature->primary_tag; my $source = $feature->source_tag; my $key = join ':',$method,$source,$tag; return $self->{formatterCache}{$key} if exists $self->{formatterCache}{$key}; my $config = $self->source; my $s; # implement simple search path for formatters SEARCH: for my $base ("$method:$source",$method,'default') { for my $option ($tag,'default') { $s ||= $config->setting("$base:details" => lc $option); $s ||= $config->setting("$base:DETAILS" => lc $option); last SEARCH if defined $s; } } unless (defined $s) { $s = sub {$self->format_position(@_)} if $tag eq 'Position'; # $s = sub {$self->format_position(@_)} if $tag eq 'Matches'; $s = sub {$self->format_name(@_) } if $tag eq 'Name'; } return $self->{formatterCache}{$key} = $s; } sub format_position { my $self = shift; my (undef,undef,$feature) = @_; $self->position($feature); } sub format_matches { my $self = shift; my (undef,undef,$feature) = @_; # try to correct for common GFF2 error of indicating a -/- alignment # using a (-) src strand and a hit_start > hit_end my $bug = $feature->strand < 0 && $feature->hit->strand < 0; $self->position($feature->hit,undef,$bug) } sub format_name { my $self = shift; my $name = shift; b($name) } # do something for popup balloons sub remote_content { my $self = shift; # the key for the text or code-ref in the gbrowse config file my ($key,$feat) = @_; my $contents = $self->source->setting('TOOLTIPS',$key) or die "$key is empty"; my $coderef = (ref $contents||'') eq 'CODE'; return $contents unless $coderef; # paranoia? die "Error: $key is not a CODE-REF" if ref $contents && !$coderef; # pass feature, other args are user-defined my %args = (feature => $feat) if $feat; for my $arg (param()) { my @vals = param($arg); my $val = @vals > 1 ? \@vals : $vals[0]; $args{$arg} = $val; } return $contents->(\%args); } sub reversec { my $dna = shift; $dna =~ tr/gatcGATC/ctagCTAG/; $dna = reverse $dna; return $dna; } __END__ GBrowse-2.56/cgi-bin/gbrowse_gmap000444001750001750 5247413036764442 17106 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell =pod =head1 GBrowse/GMap Mashup The purpose of this code is to create a mash up of GBrowse data and Google Maps that displays diversity data of a feature in the locations that they were sampled. =head1 Code This code was started as a modification of the gbrowse_details script. Template Toolkit is used to generate the html for the page. The template is encased after the __DATA__ token. =head1 Installation =head2 PhyloGeoViz PhyloGeoViz is a Google Maps/Population data mashup. It does the heavy lifting of displaying the diversity data on Google Maps. This means that PhyloGeoViz (or something functionally equivalent) is required for the gbrowse_gmap script to work. Fortunately, PhyloGeoViz is freely available and easy to install. =head3 PhyloGeoViz Web Sites More detailed and up to date information on PhyloGeoViz is available at its web site, http://phylogeoviz.org/. The code is available at http://code.google.com/p/phylogeoviz/ . =head3 PhyloGeoViz Installation =over 4 =item * PHP PhyloGeoViz is a PHP application. Make sure PHP is installed and working on your server. =item * Get PhyloGeoViz Code PhyloGeoViz is available through Google. Simply download using Subversion (svn). From the Linux command line it looks like this: svn checkout http://phylogeoviz.googlecode.com/svn/trunk/ phylogeoviz-read-only =item * Make a directory in your web server's document tree Examples: mkdir /var/www/html/phylogeoviz or mkdir /usr/local/apache2/htdocs/phylogeoviz =item * Copy PhyloGeoViz Copy the contents of the phylogeoviz-read-only directory into the newly created directory: cp phylogeoviz-read-only/* /var/www/html/phylogeoviz/ =back =head3 PhyloGeoViz Configuration In the top directory of your new PhyloGeoViz installation is a file called config.php. This is a php file where information is set to customize PhyloGeoViz. Open it with your favorite editor. Example: vim /var/www/html/phylogeoviz/config.php =over 4 =item * $gmap_api_key To use Google Maps, a GMap API key must be supplied. As of writing, keys are freely available from Google at http://code.google.com/apis/maps/. Set the $gmap_api_key to your new api key. As follows: gmap_api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; Note: You must keep the quotes and the semicolon intact for it to work. =item * $popup_url Each PhyloGeoViz pie has a marker in the middle. Clicking on that pops up a window with information. If set $popup_url will be used as a base url to get html to fill the pop-up window. We want that to point to this (the gbrowse_gmap) script. $popup_url = "/cgi-bin/gb2/gbrowse_gmap/pop_demo?pop_name="; Note: You still must keep the quotes and the semicolon intact for it to work. =back =head3 Test PhyloGeoViz To check that the installation worked, go to your web site: http://localhost/phylo/ This will give you a page that says "Input Your Data". Click the "Autofill some example data" link to get some example data and click "Draw Map!". If a Google Map appears with several pie charts, then you have successfully installed Phylogeoviz. =head2 Configuration To place the mashup in a balloon, simply add a modified version of the following to the track configuration. balloon click = http://localhost/cgi-bin/gbrowse_gmap/yeast_chr1?ref=$ref;start=$start;end=$end;name=$name;class=$class;balloon=1 Similarly, to set the mashup as a feature link add a modified version of the following to the track configuration. link = http://localhost/cgi-bin/gbrowse_gmap/yeast_chr1?ref=$ref;start=$start;end=$end;name=$name;class=$class; Note that the only difference between the two URLs was the balloon option. The balloon option needs to be set to 1 if it will be popped up in a balloon. The "yeast_chr1" portion should be replaced with the coorect data source. Also, "localhost" should be changed to your url. A relative url may not work because Google ties the api key to a URL. =head2 Current Data Requirements =over 4 =item * Different Populations will have different track types. =item * Latitude and Longitude A track is identified as being a population if it has latitude and longitude values assigned in the configuration file. =item * Haplotypes Each haplotype of a population is stored as a feature with the "score" value deterimining its weight. The feature "name" is the haplotype name. For features to be considered as part of the same population group, they must all share the same start and end. =item * Start and end of all used features the same. Only features that have the same start and end as the chosen feature will be displayed. If a feature has a different start or end, it will be excluded. =item * SeqFeature::Store is being used. I'm pretty sure that this won't work for anything other than SeqFeature::Store. I haven't tested that assumption though. There should be a way to generalize this. The feature searching is where I'm conserned about it. =back =head3 Example Data contig1 Contig scaffold 1 793 . . . Name=contig1 contig1 POPA SNP 50 50 8 . . ID=snp.POPA.contig1.50.AA;Name=AA contig1 POPA SNP 50 50 4 . . ID=snp.POPA.contig1.50.AG;Name=AG contig1 POPB SNP 50 50 1 . . ID=snp.POPB.contig1.50.AA;Name=AA contig1 POPB SNP 50 50 4 . . ID=snp.POPB.contig1.50.AG;Name=AG contig1 POPB SNP 50 50 5 . . ID=snp.POPB.contig1.50.NN;Name=NN contig1 POPC SNP 50 50 3 . . ID=snp.POPC.contig1.50.AA;Name=AA contig1 POPC SNP 50 50 2 . . ID=snp.POPC.contig1.50.AG;Name=AG =head2 GMap API Key (Depricated) Since this script is now using PhyloGeoViz for the GMap interactions, we no longer need the api key. I'm keeping this section of comments in case we ever need it again. =head1 Interesting Methods =cut use strict; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::RegionSearch; use Template; use JSON; our $VERSION = '$Id: gbrowse_gmap,v 1.2 2009-08-27 19:13:18 idavies Exp $'; use constant DEFAULT_CONF => '/etc/apache2/gbrowse'; use constant DEFAULT_MASTER => 'GBrowse.conf'; # Colors were chosen based on a chart found at # http://www.mrexcel.com/forum/showthread.php?t=374530 # These colors should be discerned by everyone my @color_list = ( '#F0E442', # Yellow '#0072B2', # Blue '#D55E00', # Vermillion '#CC79A7', # Reddish Purple '#000000', # Black '#E69F00', # Orange '#56B4E9', # Sky Blue '#2B9F78', # Bluish Green ); my $conf_dir = $ENV{GBROWSE_CONF} || DEFAULT_CONF; my $conf_file = $ENV{GBROWSE_MASTER} || DEFAULT_MASTER; my $conf = Bio::Graphics::Browser2->new( File::Spec->catfile( $conf_dir, $conf_file ) ) or die "Couldn't read globals"; my $gmap_renderer = GMapRenderer->new($conf); $gmap_renderer->run(); exit 0; package GMapRenderer; use strict; use Math::Trig; use Data::Dumper; use constant DEBUG => 0; use CGI qw(:standard *table *TR escape); sub new { print STDERR "NEW GMAP RENDERER\n"; my $package = shift; my $conf = shift; return bless { index => 0, globals => $conf, }, ref $package || $package; } sub globals { my $self = shift; my $d = $self->{globals}; $self->{globals} = shift if @_; $d; } sub state { my $self = shift; my $d = $self->{state}; $self->{state} = shift if @_; $d; } sub source { my $self = shift; my $d = $self->{source}; $self->{source} = shift if @_; $d; } sub distance_in_km { # Algorhythm described by By Chris Veness # Found at http://www.movable-type.co.uk/scripts/latlong.html my $self = shift; my %args = @_; my $lat1 = $args{'lat1'} || 0; my $lng1 = $args{'lng1'} || 0; my $lat2 = $args{'lat2'} || 0; my $lng2 = $args{'lng2'} || 0; my $debug = $args{'debug'} || 0; my $earth_radius = 6371; my $lat_dist = deg2rad( $lat2 - $lat1 ); my $lng_dist = deg2rad( $lng2 - $lng1 ); # I don't know what a or c stand for so I'm leaving them as $a and $c my $a = sin( $lat_dist / 2 ) * sin( $lat_dist / 2 ) + cos( deg2rad($lat1) ) * cos( deg2rad($lat2) ) * sin( $lng_dist / 2 ) * sin( $lng_dist / 2 ); my $c = 2 * atan2( sqrt($a), sqrt( 1 - $a ) ); return $earth_radius * $c; } sub get_pie_sizes { my $self = shift; my $lats = shift; my $lngs = shift; # Get max distance my $max_distance = 0; my $min_distance = -1; for ( my $i = 0; $i <= $#{ $lats || [] }; $i++ ) { my $lat1 = $lats->[$i]; my $lng1 = $lngs->[$i]; for ( my $j = $i + 1; $j <= $#{ $lats || [] }; $j++ ) { my $lat2 = $lats->[$j]; my $lng2 = $lngs->[$j]; my $dist = $self->distance_in_km( lat1 => $lat1, lng1 => $lng1, lat2 => $lat2, lng2 => $lng2, ); $max_distance = $dist if ( $dist > $max_distance ); $min_distance = $dist if ( $min_distance < 0 || $dist < $min_distance ); } } my $max_size = int( $min_distance / 3 ); return ( $max_size, $max_size, $max_size ); } sub run { my $self = shift; print STDERR "++ Running ++\n"; my $conf = $self->globals; my $session = $conf->session; $conf->update_data_source($session); $self->source( $conf->create_data_source( $session->source ) ); $self->state( $session->page_settings ); my $name = param('name'); my $class = param('class'); my $ref = param('ref'); my $start = param('start'); my $end = param('end'); my $f_id = param('feature_id'); my $db_id = param('db_id'); my $balloon = param('balloon'); #print STDERR Dumper(param())." \n"; # print STDERR "name : $name\n" if ( defined $name ); # print STDERR "class : $class\n" if ( defined $class ); # print STDERR "ref : $ref\n" if ( defined $ref ); # print STDERR "start : $start\n" if ( defined $start ); # print STDERR "end : $end\n" if ( defined $end ); # print STDERR "f_id : $f_id\n" if ( defined $f_id ); # print STDERR "db_id : $db_id\n" if ( defined $db_id ); $self->state->{dbid} = $db_id if $db_id; # to search correct database my $search = Bio::Graphics::Browser2::RegionSearch->new( { source => $self->source, state => $self->state, } ); $search->init_databases(); # this is the weird part; we create a search name based on the arguments # provided to us my $search_term; if ($f_id) { $search_term = "id:$f_id"; } elsif ( $class && $name ) { $search_term = "$class:$name"; } elsif ( defined $ref && defined $start && defined $end ) { $search_term = "$ref:$start..$end"; } else { $search_term = $name; } my $features = $search->search_features( { -search_term => $search_term } ); if ( not @{ $features || [] } ) { print header, start_html; print "No Features Found\n"; print end_html; return; } # Now that we know that we have a feature, let's begin # Get all the tracks that have latitude and longitude values. We are going # to take all of the features in this region that have geolocation and # display them. my %type_geolocation; foreach my $type ( keys %{ $self->source->{'config'} || {} } ) { if ( defined $self->source->{'config'}{$type}{'latitude'} and defined $self->source->{'config'}{$type}{'longitude'} ) { my $feature_key = $self->source->{'config'}{$type}{'feature'}; $type_geolocation{$feature_key} = $self->source->{'config'}{$type}; } } # If there is only one feature, we need to see what other features are # at this location. my $feature = $features->[0]; my $fstart = $feature->start; my $fend = $feature->end; my $fref = $feature->ref; $search_term = "$fref:$fstart..$fend"; # This is a bit sketchy but when using SeqFeature::Store, and serching only # on a span of sequence, search_features() returns a SeqFeature::Segment # object. I don't know if this is the same behavior in the other adaptors. my $segments = $search->search_features( { -search_term => $search_term } ); my $segment = $segments->[0]; # Get the features in this segment that are of the same geolocation my @seg_features = $segment->features( map { $_->{'feature'} } values %type_geolocation ); #print STDERR Dumper(map {$_->{'type'}}@seg_features)." \n"; #print STDERR Dumper(@seg_features) . " \n"; my %population_data; my %hap_names; # Extract the population data from the features. Only keep the features # that have the same start and stop. Populate the population data hash. # Example: # $population_data{'polymorphic_sequence_variant:CS'}->{'GT'}=$score; foreach my $seg_feature (@seg_features) { next unless ( $seg_feature->{'start'} == $fstart and $seg_feature->{'stop'} == $fend ); my $feature_key = $seg_feature->{'type'} . ( defined $seg_feature->{'source'} ? ":" . $seg_feature->{'source'} : '' ); my $score = $seg_feature->{'score'}; my $name = $seg_feature->{'name'}; $population_data{$feature_key}->{$name} += $score; $hap_names{$name} = 1; } # If we only want the population details menu, then print that and return if ( param('pop_details') ) { my $pop_name = param('pop_name'); print STDERR "PD:\n"; print STDERR Dumper( \%population_data ) . " \n"; unless ( $self->print_pop_details( pop_name => $pop_name, type_geolocation => \%type_geolocation, population_data => \%population_data, ) ) { print header, start_html; print "Failed to print population details.\n"; print end_html; } return; } # Create the values that will be passed to PhyloGeoViz my @sorted_pop_keys = sort keys %population_data; my @sorted_pop_names = map { $type_geolocation{$_}->{'key'} } @sorted_pop_keys; my @sorted_hap_names = sort keys %hap_names; my $numpops = scalar(@sorted_pop_names); my $numhaps = scalar(@sorted_hap_names); my @pop_lat = map { $type_geolocation{$_}->{'latitude'} } @sorted_pop_keys; my @pop_lng = map { $type_geolocation{$_}->{'longitude'} } @sorted_pop_keys; my @pop_include = map {1} @sorted_pop_keys; my @hap_include = map {1} @sorted_hap_names; my @hapgroups = map {'Haplotypes'} @sorted_hap_names; my @pop_haps; foreach my $pop_key (@sorted_pop_keys) { my @haps; foreach my $hap_name (@sorted_hap_names) { push @haps, ( $population_data{$pop_key}->{$hap_name} || 0 ); } push @pop_haps, \@haps; } my @pie_sizes = $self->get_pie_sizes( \@pop_lat, \@pop_lng ); my @set_hap_colors; for ( my $i = 0; $i <= $#sorted_hap_names; $i++ ) { push @set_hap_colors, [ $sorted_hap_names[$i], $color_list[$i] ]; } # options to be passed into the link back my %link_options = ( pop_details => 1, ); $link_options{'ref'} = $ref if ( defined $ref ); $link_options{'start'} = $start if ( defined $start ); $link_options{'end'} = $end if ( defined $end ); $link_options{'db_id'} = $db_id if ( defined $db_id ); #print STDERR Dumper( \%population_data ) . " \n"; #print STDERR Dumper( \@sorted_pop_names ) . " \n"; #print STDERR Dumper( \@sorted_hap_names ) . " \n"; #print STDERR Dumper( \@pop_haps ) . " \n"; #my $numpops = 2; #my $numhaps = 2; #my @pop_names = ( 'Iowa', 'Else' ); #my @hap_names = ( 'Gold', 'Purple' ); #my @pop_lat = ( 37.0625, 25 ); #my @pop_lng = ( -95.677068, -95 ); #my @pop_haps = ( [ 9, 1 ], [ 5, 5 ] ); #my @hapgroups = ( 'Up', 'Down' ); #my @pop_include = ( 1, 1 ); #my @hap_include = ( 1, 1 ); my $html; my $template = Template->new( FILTERS => { dump => sub { Dumper( shift() ) }, nbsp => sub { my $s = shift; $s =~ s{\s+}{\ }g; $s }, }, ) or $self->error( "Couldn't create Template object: " . Template->error() ); print header(); my $css = $self->source->global_setting('stylesheet'); my $style_sheet = $self->globals->resolve_path( $css, 'url' ); my $phylo_url = 'http://phylogeoviz.org/latest/newviewer.php'; if ( defined $self->source->{'config'}{'general'}{'phylogeoviz_url'} ) { $phylo_url = $self->source->{'config'}{'general'}{'phylogeoviz_url'}; } #$phylo_url = 'http://localhost:8081/phylo/printparams.php'; #my $phylo_url = 'http://localhost:8081/phylo/newviewer.php'; my $iframe_height = '90%'; my $iframe_width = '100%'; my @phylo_link_params = ( [ 'numpops', $numpops ], [ 'numhaps', $numhaps ], [ 'anchor_pies', 1 ], [ 'pop_names', JSON::to_json( \@sorted_pop_names ) ], [ 'hap_names', JSON::to_json( \@sorted_hap_names ) ], [ 'pop_lat', JSON::to_json( \@pop_lat ) ], [ 'pop_lng', JSON::to_json( \@pop_lng ) ], [ 'pop_haps', JSON::to_json( \@pop_haps ) ], [ 'hapgroups', JSON::to_json( \@hapgroups ) ], [ 'set_hap_colors', JSON::to_json( \@set_hap_colors ) ], [ 'pop_include', JSON::to_json( \@pop_include ) ], [ 'hap_include', JSON::to_json( \@hap_include ) ], [ 'radii_in_km', JSON::to_json( \@pie_sizes ) ], [ 'link_options', JSON::to_json( \%link_options ) ], ); if ($balloon) { $iframe_height = '400'; $iframe_width = '400'; my $map_padding = 40; push @phylo_link_params, ( [ 'map_width', $iframe_width - $map_padding ], [ 'map_height', $iframe_height - $map_padding ], [ 'map_only', 1 ], ); } # must escape the JSON objects my $request_str = join( '&', map { $_->[0] . "=" . CGI::escape( $_->[1] ) } @phylo_link_params ); # For some reason, the balloon interprets the escaping. # So we must escape again if it is a balloon. if ($balloon) { $request_str = CGI::escape($request_str); } my %options = ( style_sheet => $style_sheet, numpops => $numpops, numhaps => $numhaps, request_str => $request_str, phylo_url => $phylo_url, iframe_width => $iframe_width, iframe_height => $iframe_height, balloon => $balloon, ); $template->process( \*DATA, \%options, \$html ) or die $template->error(); print $html; return; } =pod =head2 print_pop_details This method prints out the population details for the given feature. This is to be presented in a smallish popup balloon. It presents population information and creates links to GBrowse. The reason that this is not it's own script is that it is just a small portion of the gbrowse_gmap project. I'm trying to minimize the file footprint of this project. =cut sub print_pop_details { my $self = shift; my %args = @_; my $pop_name = $args{pop_name} or return 0; my $type_geolocation = $args{type_geolocation} or return 0; my $population_data = $args{population_data} or return 0; my $pop_key = undef; foreach my $local_pop_key ( keys %$type_geolocation ) { print STDERR "POP_KEY $local_pop_key\n"; if ( $type_geolocation->{$local_pop_key}{'key'} eq $pop_name ) { print STDERR "FOUND\n"; $pop_key = $local_pop_key; last; } } return 0 unless ( defined $pop_key ); my $longitude = $type_geolocation->{$pop_key}{'longitude'}; my $latitude = $type_geolocation->{$pop_key}{'latitude'}; my $category = $type_geolocation->{$pop_key}{'category'}; print header, start_html; print qq[
    $pop_name
    Location: $latitude, $longitude
    ]; for my $hap_name ( sort keys %{ $population_data->{$pop_key} } ) { print "\n"; } print "
    $hap_name: " . $population_data->{$pop_key}{$hap_name} . "
    "; print "
    "; print end_html; return 1; } __DATA__ [% IF not balloon %] [% ELSE %]
    Local PhyloGeoViz
    Official PhyloGeoViz [% END %] Official PhyloGeoViz GBrowse-2.56/cgi-bin/gbrowse_img000444001750001750 7225113036764442 16731 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell # $Id: gbrowse_img,v 1.7 2009-08-31 19:46:38 lstein Exp $ use strict; use Bio::Graphics::Browser2; use Bio::Graphics::Browser2::Render::HTML; use Bio::Graphics::Browser2::Util; use Bio::Graphics::Karyotype; use Digest::MD5 'md5_hex'; # call with following arguments: # source database source # type list of feature mnemonics # options track options, in format mnemonic+option+mnemonic+option... # name landmark or range to display, in format Name:start..stop # dbid database name # width desired width of image, in pixels (height cannot be set) # add a feature to superimpose on top of the image # in format: reference+type+name+start..stop,start..stop,start..stop # multiple "add" arguments are allowed # style stylesheet for added features # h_region region(s) to hilight # h_feat feature(s) to hilight umask 022; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; my $modperl = $ENV{MOD_PERL}; my $init; if ($modperl && !$init++) { $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] GBrowse FastCGI process caught sig$sig. Exiting... (pid $$)\n"; CORE::exit 0 }; } if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] gbrowse_img FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; my %sys_env = %ENV; warn "[$$] FastCGI initializing and loading default data sources...\n"; my $globals = Bio::Graphics::Browser2->open_globals; if($globals->preload_datasources) { foreach ($globals->data_sources) { warn "[$$] Loading $_\n"; my $source = $globals->create_data_source($_); $source->open_database(); # cache default database in memory } } else { warn "[$$] Preload disabled"; } while (!$FCGI_DONE) { my $status = $fcgi->Accept; next unless $status >= 0; %ENV = ( %sys_env, %ENV ); CGI->initialize_globals(); my $gbi = GBrowse_img->new($globals); $gbi->run(); $gbi->destroy; } } else { my $globals = Bio::Graphics::Browser2->open_globals; GBrowse_img->new($globals)->run(); } exit 0; package GBrowse_img; use CGI qw(param start_html end_html p h1 path_info escape img); use File::Spec; use File::Temp 'tmpnam','tempfile','tempdir'; use Bio::Graphics::Browser2::Shellwords; use constant DEBUG => 0; use constant MAX_SEGMENT => 1_000_000; use constant TOO_MANY_SEGMENTS => 500; use constant PANEL_GAP => 3; sub new { my $class = shift; my $globals = shift; my $render = Bio::Graphics::Browser2::Render::HTML->new($globals); return bless {render => $render},ref $class || $class; } sub run { my $self = shift; my $render = $self->render; $render->set_details_multiplier(1); unless (param()) { print $self->header(); print $self->usage(); return; } $render->set_source() && exit; # may cause a redirect and exit $render->init(); if ($render->data_source->must_authenticate && !$self->session->private) { my $base = $render->globals->gbrowse_url; print $self->header(); print CGI->h1('Authentication required. Please log into',CGI->a({-href=>$base},'GBrowse'),'from this computer.'); return; } $render->add_user_tracks($render->data_source); $render->update_state(); # notice that there is no explicit flush() of the session/state, and therefore the # changes to the session are not stored. warn join ' ',$render->potential_tracks if DEBUG; # self-documentation feature: dump out tab-delimited list of mnemonics and keys if (param('list')) { $self->dump_sources($render) if param('list') eq 'sources'; $self->dump_types($render) if param('list') eq 'types'; return; } if (param('debug')) { $self->dump_state($render); return; } $self->render_image(); return; } sub render { shift->{render} } sub session { shift->render->session } sub cookie { shift->render->create_cookie } sub source { shift->render->data_source } sub destroy { my $self = shift; $self->{render}->destroy; undef $self->{render}; } sub header { my $self = shift; if (@_ == 1) { unshift @_,'-type'; } my $cookie = $self->cookie(); return CGI::header(-cookie => $cookie, @_); } sub dump_sources { my $self = shift; my $source = $self->source; print $self->header('text/plain'); print "## Sources\n"; print join "\n",$source->globals->data_sources,"\n"; } sub dump_types { my $self = shift; my $render = $self->render; my $source = $self->source; print $self->header('text/plain'); print "## Feature types for source ",$source->name,"\n"; my @labels = grep {!/:/ and !/^_/} $source->labels; my %default = map {$_=>1} $source->default_labels; for my $l (@labels) { my $d = $default{$l} ? 'default' : ''; my $key = $render->setting($l=>'key')||''; print join("\t",$l,$key,$d),"\n"; } } sub dump_state { my $self = shift; my $render = $self->render; print $self->header('text/plain'); print "## Current state for debugging\n"; print "Source: ",$self->source->name,"\n"; print "Segment: ",$render->segment,"\n"; print "Labels: ",join(' ',$render->detail_tracks),"\n"; } sub render_image { my $self = shift; my $render = $self->render; my $renderer = $render->get_panel_renderer; my $format = param('format') || 'GD'; my $flip = param('flip') || 0; my $embed = param('embed'); if (my @regions = param('h_region')) { $render->state->{h_region} = \@regions; } my $convert_to_pdf; if ($format eq 'PDF' && ($convert_to_pdf = `which svg2pdf` || `which inkscape`)) { $format = 'GD::SVG'; } $format = 'GD::SVG' if $format eq 'SVG'; $format = 'GD' if $embed; my ($img_data,$map) = $render->region->feature_count > 1 ? $self->render_multiple($renderer,$format,$flip,$embed) : $self->render_tracks ($renderer,$format,$flip,$embed); my $seg = $render->segment; my $fname = $seg ? $seg->seq_id.':'.$seg->start.'..'.$seg->end : "NA"; if ($embed) { my $url = $renderer->source->generate_image($img_data); my $js = $render->data_source->globals->js_url; my @scripts = map { {src=>"$js/$_"} } qw(balloon.js balloon.config.js prototype.js GBox.js); print $self->header(-type=>'text/html'); print start_html(-script=>\@scripts), $render->render_balloon_settings, img( { -src => $url, -usemap => "#gbrowse2_img_map"} ), $map, end_html(); } elsif ($format eq 'GD') { print $self->header(-type=>'image/png', -content_disposition => "filename=$fname.png"); print $img_data->png; } elsif ($format eq 'GD::SVG' && $convert_to_pdf) { print $self->header(-type=>'application/pdf', -content_disposition => "filename=$fname.pdf"); my ($infh,$in) = tempfile(UNLINK=>0,SUFFIX=>'.svg'); my ($outfh,$out) = tempfile(UNLINK=>0,SUFFIX=>'.pdf'); print $infh $img_data or die "$in: $!"; close $infh; if ($convert_to_pdf =~ /svg2pdf$/) { system "svg2pdf $in $out 3<&1 1>&2 2>&3"; } else { system "inkscape -z --without-gui --export-pdf=$out $in 3<&1 1>&2 2>&3 | grep -v GDK_IS_DISPLAY"; } open (my $fh,'<',$out) or die "$out: $!"; while (<$fh>) {print $_} close $fh; unlink $in,$out; } elsif ($format eq 'GD::SVG') { print $self->header(-type => 'application/svg+xml', -content_disposition => "filename=$fname.svg"); print $img_data; } else { print $self->header('text/plain'); print "unknown format $format\n"; } } sub render_multiple { my $self = shift; my ($renderer,$format,$flip,$embed) = @_; my $features = $self->render->region->features; my $karyotype = Bio::Graphics::Karyotype->new(source => $self->render->data_source, language => $self->render->language); $karyotype->add_hits($features); my $panels = $karyotype->generate_panels($format); my (@gds,@seqids); for my $seqid (keys %$panels) { push @gds,$panels->{$seqid}{panel}->gd; push @seqids,$seqid; } my $img_data = $self->consolidate_images(\@gds,undef,undef,'horizontal',\@seqids); return ($img_data,undef); } sub render_tracks { my $self = shift; my ($renderer,$format,$flip,$embed) = @_; my $render = $self->render; my $external = $render->external_data; warn 'visible = ',join ' ',$render->visible_tracks if DEBUG; my @labels = $render->expand_track_names($render->detail_tracks); warn "labels = ",join ',',@labels if DEBUG; my @track_types = map {shellwords($_)} (param('t'),param('type'),param('track')); my $h_callback = make_hilite_callback(param('h_feat')); # If no tracks specified, we want to see all tracks with this feature if (!@track_types) { @track_types = @labels; } unshift @track_types,'_scale'; my $result = $renderer->render_track_images( { labels => \@track_types, external_features => $external, section => 'detail', cache_extra => [$format,param('h_feat'),param('h_region')], image_class => $format, flip => $flip, hilite_callback => $h_callback || undef, -key_style => 'between', -suppress_key => 0, } ); warn "returned labels = ",join ',',%$result if DEBUG; # Previously - @labels (caused drawing more tracks than asked for) my @image_data = @{$result}{grep {$result->{$_}} @track_types}; my @gds = map {$_->{gd} } @image_data; my @map_data = map {$_->{map}} @image_data; my $img_data = $self->consolidate_images(\@gds); my $map = $self->consolidate_maps (\@map_data, \@gds) if $embed; return ($img_data,$map); } sub calculate_composite_bounds { my $self = shift; my ($gds,$orientation) = @_; warn "consolidating ",scalar @$gds," GD objects" if DEBUG; my $height = 0; my $width = 0; if ($orientation eq 'vertical') { for my $g (@$gds) { warn "g=$g" if DEBUG; next unless $g; $height += ($g->getBounds)[1]; # because GD::SVG is missing the width() and height() methods $width ||= ($g->getBounds)[0]; } } elsif ($orientation eq 'horizontal') { for my $g (@$gds) { warn "g=$g" if DEBUG; next unless $g; $height = ($g->getBounds)[1] if $height < ($g->getBounds)[1]; $width += ($g->getBounds)[0]; } } return ($width,$height); } sub consolidate_images { my $self = shift; my ($gds,$width,$height,$orientation,$labels) = @_; $orientation ||= 'vertical'; ($width,$height) = $self->calculate_composite_bounds($gds,$orientation) unless defined $width && defined $height; warn "consolidating ",scalar @$gds," GD objects" if DEBUG; return $gds->[0]->isa('GD::SVG::Image') ? $self->_consolidate_svg($width,$height,$gds,$orientation,$labels) : $self->_consolidate_gd ($width,$height,$gds,$orientation,$labels); } sub make_hilite_callback { my @feature_names = @_; return unless @feature_names; my %colors; foreach (@feature_names) { my ($name,$color) = split '@'; $color ||= 'yellow'; $colors{$name} = $color; } return sub { my $feature = shift; my $color; # if we get here, we select the search term for highlighting my %names = map {lc $_=> 1} $feature->display_name, eval{$feature->get_tag_values('Alias')}; return unless %names; $color ||= $colors{$_} foreach keys %names; return $color; } } sub _consolidate_gd { my $self = shift; my ($width,$height,$gds,$orientation,$labels) = @_; my $class = ref($gds->[0]); (my $fontclass = $class)=~s/::Image//; my $lineheight = $fontclass->gdMediumBoldFont->height; my $charwidth = $fontclass->gdMediumBoldFont->width; $height += $lineheight if $orientation eq 'horizontal'; my $gd = $class->new($width,$height,1); my $white = $gd->colorAllocate(255,255,255); my $black = $gd->colorAllocate(0,0,0); eval { my $bg = $gds->[0]->getPixel(0,0); my @bg = $gds->[0]->rgb($bg); my $i = $gd->colorAllocate(@bg); $gd->filledRectangle(0,0,$width,$height,$i); }; my $offset = 0; if ($orientation eq 'vertical') { for my $g (@$gds) { next unless $g; $gd->copy($g,0,$offset,0,0,$g->getBounds); $offset += ($g->getBounds)[1]; } } else { for my $g (@$gds) { next unless $g; $gd->copy($g,$offset,$height-($g->getBounds)[1]-$lineheight,0,0,$g->getBounds); if ($labels) { my $l = shift @$labels; $gd->string($fontclass->gdMediumBoldFont, $offset+(($g->getBounds)[0]-$charwidth*length $l)/2, $height-$lineheight,$l,$black); } $offset += ($g->getBounds)[0]; } } return $gd; } # because the GD::SVG copy() method is broken sub _consolidate_svg { my $self = shift; my ($width,$height,$gds,$orientation,$labels) = @_; my $image_height = $height; if ($labels) { my $font = GD::SVG->gdMediumBoldFont; my $charwidth = $font->width; my $lineheight=$font->height; $image_height += $lineheight; for my $gd (@$gds) { my $l = shift @$labels; my $black = $gd->colorAllocate(0,0,0); $gd->string($font, (($gd->getBounds)[0]-$charwidth*length $l)/2, ($gd->getBounds)[1], $l,$black); } } my $svg = qq(\n\n); $svg .= qq(\n); if ($orientation eq 'vertical') { my $offset = 0; for my $g (@$gds) { my $s = $g->svg; my $current_height = 0; foreach (split "\n",$s) { if (m!!) { last; } elsif (/\n); } elsif ($current_height) { $svg .= "$_\n"; } } $svg .= "\n" if $current_height; $offset += $current_height; } $svg .= qq(\n); } else { my $offset = 0; for my $g (@$gds) { my $s = $g->svg; my $current_width = 0; foreach (split "\n",$s) { if (m!!) { last; } elsif (/getBounds)[1]; $svg .= qq(\n); } elsif ($current_width) { $svg .= "$_\n"; } } $svg .= "\n" if $current_width; $offset += $current_width; } $svg .= qq(\n); } # munge fonts slightly for systems that don't have Helvetica installed $svg =~ s/font="Helvetica"/font="san-serif"/gi; $svg =~ s/font-size="11"/font-size="9"/gi; $svg =~ s/font-size="13"/font-size="12"/gi; return $svg; } sub consolidate_maps { my $self = shift; my ($maps,$gds) = @_; my $offset = 0; my @integrated_list = 'gbrowse2_img'; for (my $i=0;$i<@$maps;$i++) { my $data = $maps->[$i]; shift @$data; for (@$data) { my ($name,$x1,$y1,$x2,$y2,@rest) = split "\t"; $y1 += $offset; $y2 += $offset; push @integrated_list,join "\t",($name,$x1,$y1,$x2,$y2,@rest); } $offset += ($gds->[$i]->getBounds)[1]; } return Bio::Graphics::Browser2::RenderPanels->map_html(\@integrated_list); } sub usage { return <<'END';

    gbrowse_img - CGI script to generate genome images via the Generic Genome Browser

    SYNOPSIS

    
      <img src="http://www.wormbase.org/tools/genome/gbrowse_img/c_elegans?name=mec-3;width=400">
    
    Will generate this picture:
    <a href="http://www.wormbase.org/tools/genome/gbrowse_img?list=sources">list</a>
    Will return this document: ## Sources b_malayi c_brenneri c_briggsae_cb25 c_briggsae c_elegans c_elegans_gmap c_elegans_pmap ws77 c_japonica c_remanei c_remanei_nGASP nGASP_submissions nGASP Gbrowse_karyotype p_pacificus yeast
    <a href="http://www.wormbase.org/tools/genome/gbrowse_img/c_elegans?list=types">types</a>
    Will return this document: ## Feature types for source c_elegans LOCI:overview Landmarks default RNAZ RNAz non-coding RNA genes CG Gene Models default CDS Coding Segments RNA Predicted non-coding RNAs HISTORICAL Obsolete gene models GENEFINDER GeneFinder Predictions TWINSCAN Twinscan Predictions GENEMARKHMM GeneMarkHMM Predictions mSPLICER_TRANSCRIPT mSplicer ...

    DESCRIPTION

    This CGI script is an interface to the Generic Genome Browser for the purpose of retrieving dynamic images of a region of the genome. It can be used as the destination of an <img> tag like this:

    <img src="http://www.wormbase.org/tools/genome/gbrowse_img/c_elegans?name=III:1..1000">
    

    The script can also be used to superimpose one or more external features onto the display, for example for the purpose of displaying BLAST hits, an STS or a knockout in the context of the genome.

    CGI arguments

    The script recognizes the following CGI arguments, which can be passed either as GET or POST argument=value pairs. Argument pairs must be separated by semicolons (preferred) or by ampersands. Many of the options have one-letter aliases that can be used to reduce URL lengths.

    ArgumentAliasDescription
    name q genomic landmark or range
    dbid   database name for disambiguating landmarks
    type t tracks to include in image
    width w desired width of image
    options o list of track options (compact, labeled, etc)
    abs b display position in absolute coordinates
    add a added feature(s) to superimpose on the image
    style s stylesheet for additional features
    keystylek where to place the image key
    overview  force an overview-style display
    flip f flip image left to right
    grid   turn grid on (1) or off (0)
    embed   generate full HTML for image and imagemap for use in an embedded frame
    format   format for the image (use "SVG" for scaleable vector graphics)
    list   get certain types of configuration information
    source   database name

    The arguments are explained in more detail here

    name (Alias: q)
    This argument specifies the region of the genome to be displayed. Several forms are recognized:
    • name=Landmark Display the landmark named "Landmark". Valid landmark names include chromosomes, contigs, clones, STSs, predicted genes, and any other landmark that the administrator has designated. Be careful when fetching large landmarks such as whole chromosomes!
    • name=Landmark:start..end Display the region between start and end relative to "Landmark".
    • name=Class:Landmark Display "Landmark", restricting to a particular class, such as "PCR_Product". The list of classes is under the control of the database administrator and is not yet available through this interface.
    • name=Class:Landmark:start..end As above, but restricted to the designated range.
    If you use multiple name options, then this script will generate an overview image showing the position of each landmark. The alias "q" can be used to shorten the length of the URL.

    dbid
    If the data source contains multiple defined databases, this argument is required to uniquely identify landmarks that may appear in multiple databases under different names. If not present, then the standard search algorithm is used. Use the symbolic database name indicated in the source configuration file. For example if the database stanza is "[scaffolds:database]" then pass "dbid=scaffolds".
    type (Aliases: t, track)
    This argument lists the feature types to display. The value of this argument is a list of track names separated by spaces ("+" characters when URL-escaped). For example:

          <img src="http://www.wormbase.org/tools/genome/gbrowse_img/c_elegans?name=mec-3;
                       type=tRNA+NG+WABA+CG+ESTB">
          
    Multiple type= arguments will be combined to form a single space-delimited list. The alias "t" can be used to shorten the length of the URL.

    If the track name has a space in it, put quotes around the name:

                type="microbe tRNA"+NG+WABA+CG+ESTB
          

    width (Alias: w)
    Width of the desired image, in pixels.

    options (Alias: o)
    A space-delimited list ("+" characters when URL-escaped) of mnemonic/option pairs describing how features should be formatted. Options are integers from 0 to 3, where 0=auto, 1=compact, 2=expanded, 3=expanded and labeled. For example, to specify that the tRNA and NG tracks should always be expanded and labeled, but that the WABA track should be compact, use:

          options=tRNA+3+NG+3+WABA+1
          

    The alias "o" can be used to shorten the length of the URL.

    add (Alias: a)
    Superimpose one or more additional features on top of the view. Features are specified as space ("+") delimited lists in the following format:

          add=Landmark+Type+Name+start..end,start..end,start..end
          
    "Landmark" is the landmark name, "Type" is a descriptive type that will be printed in the image caption, "Name" is a name for the feature to be printed above it, and start..end is a comma-delimited list of ranges for discontinuous feature. Names that contain white space must be quoted, for example "BLAST hit". Note that this all has to be URL-escaped, so an additional feature named "Your Sequence", type "Blast Hit", that is located on chromosome III in a gapped range between 20000 and 22000, will be formatted as:

          add=III+%22Blast%20Hit%22+%22Your%20Sequence%22+20000..21000,21550..22000
          

    One or both of the type and name can be omitted. If omitted, type will default to "Your Features" and the name will default to "Feature XX" where XX is an integer. This allows for a very simple feature line:

          add=III+20000..21000,21550..22000
          

    Multiple add= arguments are allowed. The alias "a" can be used to shorten the length of the URL.

    style
    The style argument can be used to control the rendering of additional features added with "add". It is a flattened version of the style configuration sections described in this document For example, if you have added a "Blast Hit" annotation, then you can tell the renderer to use a red arrow for this glyph in this way: style=%22Blast%20Hit%22+glyph=arrow+fgcolor=red

    keystyle (Alias: k)
    Controls the positioning of the track key. One of "right", "left", "between" (default) or "bottom"

    overview
    Ordinarily the image will show the detail panel if the query region corresponds to a single region, and the overview panel if multiple regions match (or if a region that is too large to show matches). Setting overview=1 will force the overview to be shown in all cases.

    flip (Alias: f)
    Flip the image left to right. Arguments are 0=don't flip (default), and 1=flip.

    embed
    Generate image and a corresponding HTML imagemap in a form suitable for embedding into a frame.

    format
    Specify the format for the image file. Either "GD" (the default) or "GD::SVG" for scaleable vector graphics.

    list
    If this argument is present, it will cause the script to dump out various types of information in plain text form. Currently the two values for this argument are sources, to dump out the list of data sources, and types, to dump out the list of configured types. For list=sources, the script will return a simple text list of the data source names. For list=types, the script will return a three-column tab-delimited list giving the track names and feature types corresponding to the currently-selected data source. The format is as follows:

          Mnemonic <tab> Full description of feature <tab> [default]
          

    The third column contains the word "default" if the track will be shown by default when no type argument is provided.

    source
    This argument specifies the database for the images. The list of sources can be found using list=sources.

    h_feat
    The name of a feature to highlight in the format feature_name@color_name". Example:
    h_feat=SKT5@blue
    You may omit "@color", in which case the highlight will default to yellow. You can specify multiple h_feat arguments in order to highlight several features with distinct colors.
    h_region
    The name of a region to highlight in a solid background color, in the format sequence_name:start..end@color_name". Example:
    h_region=Chr3:200000..250000@wheat
    You may omit "@color", in which case the highlighted region will default to lightgrey. You can specify multiple h_region arguments in order to highlight several regions with distinct colors.

    Putting it all together, here's a working (very long) URL:

    http://www.wormbase.org/tools/genome/gbrowse_img/c_elegans?name=B0001;add=B0001+pcr+pcr1+20000..333000;add=B0001+%22cool%20knockout%22+kn2+30000..20000,10000..5000;type=add+CG+WTP;style=pcr+glyph=primers;style=%22cool%20knockout%22+glyph=transcript2+bgcolor=orange;abs=1
    

    If you wish to associate the image with an imagemap so that clicking on a feature takes the user to the destination configured in the gbrowse config file, you may do so by placing the URL in an <iframe> section and using the embed=1 flag:

    <iframe src="http://localhost/cgi-bin/gbrowse_img/c_elegans?name=B0001;embed=1" width="100%" height="250">
       <img src="http://localhost/cgi-bin/gbrowse_img/c_elegans?name=B0001"/>
    </iframe>
    

    Placing an <img> tag inside the <iframe> tag arranges for older browsers that don't know about iframes to display the static image instead. You may need to adjust the width and height attributes in order to avoid browsers placing scrollbars around the frame.

    KNOWN BUGS

    The cookie that stores the configuration options for plugins does not transfer from gbrowse to gbrowse_img, so tracks generated by annotation plugins, such as the Restriction site annotator, will not display correctly when the image URL is generated on one machine and then viewed on another. Uploaded files will transfer correctly, however.

    AUTHOR

    Lincoln Stein lstein@cshl.org

    Copyright (c) 2002-2004 Cold Spring Harbor Laboratory

    This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

    For additional help, see The GMOD Project pages. END ; } __END__ GBrowse-2.56/cgi-bin/gbrowse_key_img000444001750001750 3636513036764442 17607 0ustar00lsteinlstein000000000000#!/usr/bin/perl eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell use strict; use GD; use Bio::Graphics; use CGI qw(:standard param); =head1 NAME gbrowse_key_img =head1 SYNOPSIS A small cgi script designed for generating key images for features using heat_map glyph Shows the color space used to display feature scores. Hardcoded to be 120x23 image and may be embedded in hover balloons using stanza code, i.e. balloon hover = sub { my $f = shift; my $score = $f->score; my $img_url = "...gbrowse_key_img?min=0;max=0.001;start_c=blue;end_c=green"; return $score ? join (" ","",$f->name,"(Score:".$score.")") : $f->name; The above code will display color key with score information =head2 Options Option Description Default ------ ----------- ------- -start_c Beginning of the color white gradient, expressed as a named color or RGB hex string -end_c End of the color gradient red -min Minimum score of the data 0 -max Maximum score of the data 255 -width Width of the image 120 -height Height of the image 20 =cut my $min = param('min') || 0; my $max = param('max') || 255; my $start_color = param('start_c') || 'white'; my $end_color = param('end_c') || 'red'; my $width = param('width') || 120; my $height = param ('height') || 20; my %COLORS; my $range = 255; # We have a 255-space all the time ? my $scale = 1; my $offset = 0; my $segments; for my $start (0..49) { $start *= 2; push @$segments, [ $start*$scale + $offset, ($start + 2)*$scale + $offset ]; } my $keyfeature = Bio::Graphics::Feature->new(-start =>1, -end =>$range, -segments =>$segments ); for (0..49) { my $score += ($range/50) * $_; ($keyfeature->segments)[$_]->score($score); } my $heater = HeatKey->new(-width => $width, -height => $height, -max => $max, -min => $min, -range => $range, -start_color=> $start_color, -end_color => $end_color ); $heater->calculate_gradient($keyfeature->{segments}); $heater->draw_image($keyfeature->{segments}); my $data = $heater->gd->png; print header(-type => 'image/png', -expires => '-1s'); binmode(STDOUT); print $data; exit 0; package HeatKey; use base 'Bio::Graphics::Glyph::heat_map'; # set up getter/setter methods BEGIN { no strict 'refs'; my @subs = qw/ h_start s_start v_start h_range s_range v_range width height start_color end_color min_score max_score low_rgb low_hsv high_rgb score_range gd translation key_font min max/; for my $sub ( @subs ) { *{$sub} = sub { my ($self, $v) = @_; my $k = "$sub"; if (defined $v) { $self->{$k} = $v; } return $self->{$k}; } } } sub new { my $class = shift @_; my %options = @_; my $width = $options{-width}; my $height = $options{-height}; my $max = $options{-max}; my $min = $options{-min}; my $range = $options{-range}; my $start_color = $options{-start_color}; my $end_color = $options{-end_color}; my $self = bless {translation => {}, gd => new GD::Image($width,$height), width => $width, height => $height, min_score => 0, max_score => $range, min => $min, max => $max, start_color => $start_color, end_color => $end_color, key_font => GD::Font->Small }, ref $class || $class; my %translation_table; $self->read_colors; for my $name (keys %COLORS) { my $idx = $self->gd->colorAllocate(@{$COLORS{$name}}); $translation_table{$name} = $idx; } $self->translation(\%translation_table); $self; } sub draw_image { my $self = shift; my $segments = shift; # Set up my $lines = $self->width; my $heat_height = int($self->height-$self->{key_font}->height); my $low_rgb = $self->low_rgb; $self->gd->filledRectangle(0,0,$self->width,$self->height,$self->color_index(255,255,255)); #Paint gradient for my $line (1..$self->width-2) { my $index = int($line*(scalar(@{$segments}-1)/$self->width)); my $score = ($keyfeature->segments)[$index]->score || 0; my $partcolor; # use start color if no score or no score gradient unless (defined $score && $self->score_range ) { $partcolor = $self->color_index(@$low_rgb); } else { my @rgb = $self->calculate_color($score); $partcolor = $self->color_index(@rgb); } $self->gd->line($line,$heat_height,$line,0,$partcolor); } #Write limits if (defined $self->min && $self->max) { my $padding = int($self->width/$self->{key_font}->width)-length("".$self->max)-2; my $label = sprintf("%-".$padding."s %-3s",$self->min,$self->max); $self->gd->string($self->{key_font},3,$heat_height,$label,$self->translate_color('black')); } } #Overriding to get rid of panel sub color2hsv { my ($self,$color) = @_; my $color_idx = $self->translate_color($color); my @rgb = $self->gd->rgb($color_idx); return [$self->RGBtoHSV(@rgb)]; } sub color_index { my ($self, @rgb) = @_; return $self->gd->colorResolve(@rgb); } sub option { my $self = shift; my $option_name = shift; return $self->{$option_name} ? $self->{$option_name} : undef; } # Trimmed functions from Bio::Graphics::Panel (no alpha, just basic rgb) sub translate_color { my $self = shift; my @colors = @_; my $index; my $gd = $self->gd or return 1; my $table = $self->translation or return 1; if (@colors == 3) { $index = $self->colorClosest($gd,@colors); } elsif ($colors[0] =~ /^\#([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})/i) { my ($r,$g,$b) = (hex($1),hex($2),hex($3)); $index = $self->colorClosest($gd,$r,$g,$b); } elsif ($colors[0] =~ /^(\d+),(\d+),(\d+)/i || $colors[0] =~ /^rgb\((\d+),(\d+),(\d+)\)/i ) { my (@rgb) = map {/(\d+)%/ ? int(255 * $1 / 100) : $_} ($1,$2,$3); $index = $self->colorClosest($gd,@rgb); } else { $index = defined $table->{$colors[0]} ? $table->{$colors[0]} : 1; } return $index; } sub read_colors { my $class = shift; local ($/) = "\n"; local $_; while () { chomp; last if /^__END__/; my ($name,$r,$g,$b) = split /\s+/; @{$COLORS{$name}} = (hex $r,hex $g, hex $b); } } 1; __DATA__ white FF FF FF black 00 00 00 aliceblue F0 F8 FF antiquewhite FA EB D7 aqua 00 FF FF aquamarine 7F FF D4 azure F0 FF FF beige F5 F5 DC bisque FF E4 C4 blanchedalmond FF EB CD blue 00 00 FF blueviolet 8A 2B E2 brown A5 2A 2A burlywood DE B8 87 cadetblue 5F 9E A0 chartreuse 7F FF 00 chocolate D2 69 1E coral FF 7F 50 cornflowerblue 64 95 ED cornsilk FF F8 DC crimson DC 14 3C cyan 00 FF FF darkblue 00 00 8B darkcyan 00 8B 8B darkgoldenrod B8 86 0B darkgray A9 A9 A9 darkgreen 00 64 00 darkkhaki BD B7 6B darkmagenta 8B 00 8B darkolivegreen 55 6B 2F darkorange FF 8C 00 darkorchid 99 32 CC darkred 8B 00 00 darksalmon E9 96 7A darkseagreen 8F BC 8F darkslateblue 48 3D 8B darkslategray 2F 4F 4F darkturquoise 00 CE D1 darkviolet 94 00 D3 deeppink FF 14 100 deepskyblue 00 BF FF dimgray 69 69 69 dodgerblue 1E 90 FF firebrick B2 22 22 floralwhite FF FA F0 forestgreen 22 8B 22 fuchsia FF 00 FF gainsboro DC DC DC ghostwhite F8 F8 FF gold FF D7 00 goldenrod DA A5 20 gray 80 80 80 grey 80 80 80 green 00 80 00 greenyellow AD FF 2F honeydew F0 FF F0 hotpink FF 69 B4 indianred CD 5C 5C indigo 4B 00 82 ivory FF FF F0 khaki F0 E6 8C lavender E6 E6 FA lavenderblush FF F0 F5 lawngreen 7C FC 00 lemonchiffon FF FA CD lightblue AD D8 E6 lightcoral F0 80 80 lightcyan E0 FF FF lightgoldenrodyellow FA FA D2 lightgreen 90 EE 90 lightgrey D3 D3 D3 lightpink FF B6 C1 lightsalmon FF A0 7A lightseagreen 20 B2 AA lightskyblue 87 CE FA lightslategray 77 88 99 lightsteelblue B0 C4 DE lightyellow FF FF E0 lime 00 FF 00 limegreen 32 CD 32 linen FA F0 E6 magenta FF 00 FF maroon 80 00 00 mediumaquamarine 66 CD AA mediumblue 00 00 CD mediumorchid BA 55 D3 mediumpurple 100 70 DB mediumseagreen 3C B3 71 mediumslateblue 7B 68 EE mediumspringgreen 00 FA 9A mediumturquoise 48 D1 CC mediumvioletred C7 15 85 midnightblue 19 19 70 mintcream F5 FF FA mistyrose FF E4 E1 moccasin FF E4 B5 navajowhite FF DE AD navy 00 00 80 oldlace FD F5 E6 olive 80 80 00 olivedrab 6B 8E 23 orange FF A5 00 orangered FF 45 00 orchid DA 70 D6 palegoldenrod EE E8 AA palegreen 98 FB 98 paleturquoise AF EE EE palevioletred DB 70 100 papayawhip FF EF D5 peachpuff FF DA B9 peru CD 85 3F pink FF C0 CB plum DD A0 DD powderblue B0 E0 E6 purple 80 00 80 red FF 00 00 rosybrown BC 8F 8F royalblue 41 69 E1 saddlebrown 8B 45 13 salmon FA 80 72 sandybrown F4 A4 60 seagreen 2E 8B 57 seashell FF F5 EE sienna A0 52 2D silver C0 C0 C0 skyblue 87 CE EB slateblue 6A 5A CD slategray 70 80 90 snow FF FA FA springgreen 00 FF 7F steelblue 46 82 B4 tan D2 B4 8C teal 00 80 80 thistle D8 BF D8 tomato FF 63 47 turquoise 40 E0 D0 violet EE 82 EE wheat F5 DE B3 whitesmoke F5 F5 F5 yellow FF FF 00 yellowgreen 9A CD 32 gradient1 00 ff 00 gradient2 0a ff 00 gradient3 14 ff 00 gradient4 1e ff 00 gradient5 28 ff 00 gradient6 32 ff 00 gradient7 3d ff 00 gradient8 47 ff 00 gradient9 51 ff 00 gradient10 5b ff 00 gradient11 65 ff 00 gradient12 70 ff 00 gradient13 7a ff 00 gradient14 84 ff 00 gradient15 8e ff 00 gradient16 99 ff 00 gradient17 a3 ff 00 gradient18 ad ff 00 gradient19 b7 ff 00 gradient20 c1 ff 00 gradient21 cc ff 00 gradient22 d6 ff 00 gradient23 e0 ff 00 gradient24 ea ff 00 gradient25 f4 ff 00 gradient26 ff ff 00 gradient27 ff f4 00 gradient28 ff ea 00 gradient29 ff e0 00 gradient30 ff d6 00 gradient31 ff cc 00 gradient32 ff c1 00 gradient33 ff b7 00 gradient34 ff ad 00 gradient35 ff a3 00 gradient36 ff 99 00 gradient37 ff 8e 00 gradient38 ff 84 00 gradient39 ff 7a 00 gradient40 ff 70 00 gradient41 ff 65 00 gradient42 ff 5b 00 gradient43 ff 51 00 gradient44 ff 47 00 gradient45 ff 3d 00 gradient46 ff 32 00 gradient47 ff 28 00 gradient48 ff 1e 00 gradient49 ff 14 00 gradient50 ff 0a 00 __END__ GBrowse-2.56/cgi-bin/gbrowse_login000444001750001750 675313036764442 17251 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell use strict; use Bio::Graphics::Browser2::UserDB; use Bio::Graphics::Browser2::Render; our $VERSION = '$Id: gbrowse_login,v 1.1 2009-08-27 20:33:23 idavies Exp $'; umask 022; my $fcgi = Bio::Graphics::Browser2::Render->fcgi_request; if ($fcgi) { my $FCGI_DONE = 0; $SIG{USR1} = $SIG{PIPE} = $SIG{TERM} = sub { my $sig = shift; my $time = localtime; print STDERR "[$time] [notice] gbrowse_login FastCGI process caught sig$sig. Exiting... (pid $$)\n"; $FCGI_DONE = 1; }; my %sys_env = %ENV; while (!$FCGI_DONE) { my $status = $fcgi->Accept; next unless $status >= 0; %ENV = ( %sys_env, %ENV ); CGI->initialize_globals(); GBrowseLogin->run(); $fcgi->Finish(); } } else { GBrowseLogin->run(); } package GBrowseLogin; use CGI qw(:standard); sub run { my %actions = map {$_=>1} param('action'); my %callback; warn 'gbrowse_login(',join ',',param('action'),')'; my $user = param('user'); my $pass = param('pass'); my $email = param('email'); my $fullname = param('fullname'); my $sessionid = param('session'); my $remember = param('remember'); my $old = param('old_val'); my $new = param('new_val'); my $column = param('column'); my $confirm = param('confirm'); my $openid = param('openid'); my $option = param('option'); my $source = param('source'); my $userdb = Bio::Graphics::Browser2::UserDB->new(Bio::Graphics::Browser2->open_globals); if($actions{list_openid}) { print header('application/json'); $userdb->do_list_openid($user) if $actions{list_openid}; return; } if($actions{confirm_openid}) { my $arg; my $print = -1; foreach(param('callback')) { $arg = $_ if($print == -1); $callback{$arg} = $_ if($print == 1); $print = $print * -1; } print header('application/json'); $userdb->do_confirm_openid(\%callback, $sessionid, $option,$email,$fullname); return; } print header(); $userdb->do_validate ($user, $pass, $remember) if $actions{validate}; $userdb->do_add_user_check ($user, $email, $fullname, $pass, $sessionid) if $actions{add_user_check}; $userdb->do_add_user ($user, $email, $fullname, $pass, $sessionid) if $actions{add_user}; $userdb->do_edit_confirmation ($email, $option) if $actions{edit_confirmation}; $userdb->do_confirm_account ($user, $confirm) if $actions{confirm_account}; $userdb->do_edit_details ($user, $column, $old, $new) if $actions{edit_details}; $userdb->do_email_info ($email) if $actions{email_info}; $userdb->do_delete_user ($user, $pass) if $actions{delete_user}; $userdb->do_add_openid_user ($user, $email,$fullname,$openid, $sessionid, $remember) if $actions{add_openid_user}; $userdb->do_check_openid ($openid, $sessionid, $source, $option) if $actions{check_openid}; $userdb->do_change_openid ($user, $pass, $openid, $option) if $actions{change_openid}; $userdb->do_get_gecos ($user) if $actions{get_gecos}; } __END__ GBrowse-2.56/cgi-bin/gbrowse_syn000444001750001750 15351513036764442 17011 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell use constant DEFAULT_CONF => '/etc/gbrowse2/synteny'; our $CONF_DIR = $ENV{GBROWSE_CONF} ? "$ENV{GBROWSE_CONF}/synteny" : DEFAULT_CONF; our $VERSION = 2.55; our $BIOGRAPHICS_VERSION = 1.8; use strict; use CGI qw/:standard Map Area delete_all/; use CGI::Carp 'fatalsToBrowser'; use CGI::Toggle; use List::Util qw/min max sum/; use Digest::MD5 'md5_hex'; use Bio::Graphics::Browser2; use Bio::Graphics; # Legacy libraries from 1.7 branch # will slowly replace these use Legacy::Graphics::Browser; use Legacy::Graphics::Browser::Util; use Legacy::Graphics::Browser::Synteny; use Legacy::Graphics::Browser::PageSettings; use Legacy::DB::SyntenyIO; use Legacy::DB::SyntenyBlock; use constant OVERVIEW_RATIO => 1.0; use constant OVERVIEW_BGCOLOR => 'gainsboro'; use constant IMAGE_WIDTH => 800; use constant INTERIMAGE_PAD => 5; use constant VERTICAL_PAD => 40; use constant ALIGN_HEIGHT => 6; use constant MAX_SPAN => 0.3; # largest gap allowed for merging inset panels use constant TOO_SMALL => 0.02; # minimum span for displayed alignments use constant MAX_GAP => 50_001; # maximum gap for chaining use constant MAX_SEGMENT => 2_000_001; use constant EXTENSION => 'syn'; # extension for species conf files use constant DEBUG => 0; use constant HELP => 'http://gmod.org/wiki/GBrowse_syn_Help'; # Display options -- using a hash here so that # $page_settings can be updated without using hard-coded # keys (not counting this constant!). use constant SETTINGS => ( aggregate => 0 , # chain alignments pgrid => 1, # gridlines shading => 1, # shaded polygons tiny => 0, # ignore small alignments pflip => 1, # flip (-) strand panels edge => 1, # outline polygons imagewidth => 800, # width of the image display => 'expanded', # ref + 2 or all in one ref => undef, start => undef, stop => undef, end => undef, name => undef, search_src => undef, species => undef ); use vars qw($INVALID_SRC $CONF_DIR $SCONF $CONF $VERSION $MAP $BIOGRAPHICS_VERSION $SYNTENY_IO @hits); # initialization $CONF_DIR = conf_dir($CONF_DIR); # error if no data sources configured my $go; while (<$CONF_DIR/*.synconf>) { $go++; } unless ($go) { print header, start_html('No data source'); print warning("No data source configured for GBrowse_syn\n"); print p('Please consult '.a({-href=>'http://gmod.org/wiki/GBrowse_syn'},'the documentation')); print < END ; print end_html; exit 0; } # search soure (general) configuration $CONF = Legacy::Graphics::Browser::Synteny->new(); $CONF->read_configuration($CONF_DIR,'synconf'); # species-specific configuration my $extension = $CONF->setting('config_extension') || EXTENSION; $SCONF = open_config($CONF_DIR,$extension); my ($page_settings,$session) = page_settings(); my $source = $page_settings->{source}; $CONF->page_settings($page_settings); $CONF->search_src($page_settings->{search_src}); $CONF->source($page_settings->{source}); $MAP = db_map(); $SYNTENY_IO = Legacy::DB::SyntenyIO->new($CONF->setting('join')); my $segment = landmark2segment($page_settings); if ($segment) { my $name = format_segment($segment); if (ref $segment ne 'Bio::DB::GFF::RelSegment') { redirect(url()."?name=$name"); } $CONF->current_segment($segment); param(name => $name); $page_settings->{name} = $name; } my @reset = (0,0); if (param('reset')) { @reset = (1, 'All settings have been reset to their default values'); } $CONF->print_page_top($CONF->setting('description'),@reset,$session); # warning if trying to search with no species if (!$segment && param('name') && !$CONF->page_settings("search_src")) { print warning("Error: select a species to search"); } # Which aligned species have been asked for my @requested_species = _unique(@{$page_settings->{species}}); if (!@requested_species) { my $search_src = $page_settings->{search_src} || ''; unless ($search_src && $search_src ne 'nosrc' && $MAP->{$search_src}->{db}) { $INVALID_SRC = $search_src; } @requested_species = grep {$_ ne $search_src} grep {$MAP->{$_}->{db}} keys %$MAP; } if ($segment) { @hits = map {$SYNTENY_IO->get_synteny_by_range(-src => $page_settings->{search_src}, -ref => $segment->abs_ref, -start => $segment->abs_start, -end => $segment->abs_end, -tgt => $_) } @requested_species; } my $header = $CONF->setting('header'); $header = &$header if ref $header; print $header || h1($CONF->setting('description')); if ($INVALID_SRC) { print warning("Species '$INVALID_SRC' is not configured for this database"); } search_form($segment); print overview_panel($CONF->whole_segment($segment),$segment) if $segment; if ($segment) { # make sure no hits go off-screen remap_coordinates($_) for @hits; segment_info($page_settings,$segment); my %species = map {$_->src2 => 1} @hits; my @species = sort keys %species; # either display ref species + 2 repeating or 'all in one' if ($page_settings->{display} eq 'expanded') { while (my @pair = splice @species, 0, 2) { draw_image($page_settings,\@hits,@pair); } } else { draw_image($page_settings,\@hits,@species); } } options_table(); print end_form(); print $CONF->footer || end_html(); # remember former source for the checkbox $page_settings->{old_src} = $CONF->search_src; exit 0; sub species_chooser { # pointless if < 3 species return '' if keys %$MAP < 3; my $src = $CONF->search_src(); my @species = grep {$_ ne $src} grep {$MAP->{$_}->{db}} keys %$MAP; my $default = $CONF->page_settings->{species} || \@species; push @$default, $CONF->page_settings('old_src'); if (!param('species')) { $default = [keys %$MAP]; } b(wiki_help('Aligned_Species',,$CONF->tr('Aligned Species'))) . ':' . br . checkbox_group( -id => 'speciesChooser', -name => 'species', -values => \@species, -labels => { map {$_ => $MAP->{$_}->{desc} } @species }, -default => $default, -multiple => 1, -size => 8, -override => 1, ); } sub expand_notice { # pointless if < 4 species return '' if keys %$MAP < 4; my $state = param('display') || $CONF->page_settings->{display}; my $ref = $CONF->search_src; my $title = b(wiki_help("Display_Mode",$CONF->tr("Display Mode")), ':'); my $url = url . "/" . $CONF->source; if ($state eq 'expanded') { return br, $title, br, "Three species/panel ", a( {-href => $url.'?display=compact'}, 'Click to show all species in one panel'); } else { return br, $title, br, 'All species in one panel ', a( {-href => $url.'?display=expanded'}, 'Click to show reference plus two species/panel'); } } sub landmark_search { my $segment = shift; my $default = format_segment($segment) if $segment; return $CONF->setting('no search') ? '' : b(wiki_help('Landmark',$CONF->tr('Landmark'))).':'.br. textfield(-name=>'name', -size=>25, -value=>$default); } sub species_search { my $default = $CONF->page_settings("search_src"); my %labels = map {$_=>$MAP->{$_}{desc}} keys %$MAP; my $values = [sort {$MAP->{$a}{desc} cmp $MAP->{$b}{desc}} grep {$MAP->{$_}{desc}} keys %labels]; unshift @$values, ''; my $onchange = "document.searchform.submit()"; return b(wiki_help('Reference_Species',$CONF->tr('Genome to Search'))) . ':' . br . popup_menu( -onchange => $onchange, -name =>'search_src', -values => $values, -labels => \%labels, -default => $default, -override => 1 ); } sub search_form { my $segment = shift; print start_form(-name=>'searchform',-method => 'post'); navigation_table($segment); } sub db_map { my %map; my @map = shellwords($CONF->setting('source_map')); while (my($symbol,$db,$desc) = splice(@map,0,3)) { $map{$symbol}{db} = $db; $map{$symbol}{desc} = $desc; } \%map; } sub _type_from_box { my $box = shift; my @type = split ':', $box->[0]; my ($feature,$fname) = @type[0,-1]; return ($feature,$fname); } sub draw_image { my ($page_settings,$hits,@species) = @_; my ($toggle_section,@hits); for my $species (@species) { push @hits, grep {$_->src2 eq $species} @$hits; } my $src = $CONF->page_settings("search_src"); my $segment = $CONF->current_segment or return; my $max_segment = $CONF->setting('max_segment') || MAX_SEGMENT; if ( $segment->length > $max_segment) { my $units = $CONF->unit_label($max_segment); print h2("Sorry: the size of region $segment exceeds the maximum ($units)"); exit; } my $max_gap = $segment->length * ($CONF->setting('max_span') || MAX_SPAN); # dynamically create synteny blocks @hits = aggregate(\@hits) if $CONF->page_settings("aggregate"); # save the hits by name so we can access them from the name alone for (@hits) { $CONF->name2hit( $_->name => $_ ); } # relate hits into "span" sorted by target contig/chromosomes # %span = ( target_database,target_contig => { target, contig, start, end } } ) my (%span,$hit2span,%instance); for my $h (sort {$a->tstart <=> $b->tstart} @hits) { my $src = $h->src2; my $contig = $h->target; $instance{$src,$contig} ||= 0; my $key = join $;,$src,$contig,$instance{$src,$contig}; # start a new span if the gap is too large if ($span{$key} && ($h->tstart >= $span{$key}{end}+$max_gap)) { $key = join $;,$src,$contig,++$instance{$src,$contig}; } # Tally the plus and minus strand total. We will flip the panel # if more aligned sequence is on the minus strand than the plus strand. # only count actual alignmnts (not aggregates). my $panel_flip = $CONF->panel_flip($key); if ($h->parts) { for my $p (@{$h->parts}) { $panel_flip->{$key}{yes} += ($p->tend - $p->tstart) if $p->tstrand eq '-'; $panel_flip->{$key}{no} += ($p->tend - $p->tstart) if $p->tstrand eq '+'; } } else { $panel_flip->{$key}{yes} += ($h->tend - $h->tstart) if $h->tstrand eq '-'; $panel_flip->{$key}{no} += ($h->tend - $h->tstart) if $h->tstrand eq '+'; } $span{$key}{start} = $h->tstart if !defined $span{$key}{start} or $span{$key}{start} > $h->tstart; $span{$key}{end} = $h->tend if !defined $span{$key}{end} or $span{$key}{end} < $h->tend; $contig =~ s/Superc/C/; $span{$key}{src} ||= $src; $span{$key}{contig} ||= $contig; $span{$key}{tstart} ||= $h->start; $span{$key}{tend} ||= $h->end; ($span{$key}{tstart}) = sort {$a<=>$b} ($h->start,$span{$key}{tstart}); ($span{$key}{tend}) = sort {$b<=>$a} ($h->end,$span{$key}{tend}); $hit2span->{$h} = $key; $hit2span->{$h->name} = $key; } # get rid of tiny spans my $src_fraction = ($CONF->setting('min_alignment_size') || TOO_SMALL || 0) * $segment->length; my @unused_hits; unless ($CONF->page_settings("tiny")) { for my $key (keys %span) { my $too_short = ($span{$key}{end} - $span{$key}{start}) < $src_fraction && ($span{$key}{tend} - $span{$key}{tstart}) < $src_fraction; if ($too_short) { delete $span{$key}; push @unused_hits, grep { $hit2span->{$_} eq $key } @hits; @hits = grep { $hit2span->{$_} ne $key } @hits; } } } # sort hits into upper and lower hits, based on this pattern: # # 1 3 5 7 upper spans # # - - - - - - - - - upper hits # # - - - - - - - - - lower hits # # 0 2 4 6 lower spans # my (%hit_positions); my $pidx = 0; my %species = map {$_->src2 => 1} @hits; my %position = map {$_ => ++$pidx} sort keys %species; for my $h (sort {($b->end-$b->start)<=>($a->end-$a->start)} @hits) { my $src = $h->src2; my $span_key = $hit2span->{$h}; $span{$span_key}{position} = $position{$src}; $hit_positions{$h} ||= $span{$span_key}{position}; } # Create the middle (reference) panel my ($upper_ff,$lower_ff,%is_upper); # restrict segment to aligned sequence my $only_aligned = 0; if ($only_aligned && @hits) { my @coords = map {$_->start, $_->end} @hits; my $new_name = $segment->ref .':'.(min @coords).'..'.(max @coords); $segment = landmark2segment($page_settings,$new_name,$CONF->page_settings('search_src')); } for my $h (@hits) { my $src = $h->src2; # keep track of the hits for mapping purposes $is_upper{$src} ||= $hit_positions{$h} % 2; my $ff = $is_upper{$src} ? \$upper_ff : \$lower_ff; $$ff ||= Bio::Graphics::FeatureFile->new; add_hit_to_ff($segment,$$ff,$h,$hit2span); } my $orphan_hit = 0; for my $h (@unused_hits) { warn "I am an orphan! ".$h->start."..".$h->end."\n" if DEBUG; my $is_upper = ++$orphan_hit % 2; my $ff = $is_upper ? \$upper_ff : \$lower_ff; $$ff ||= Bio::Graphics::FeatureFile->new; add_hit_to_ff($segment,$$ff,$h,$hit2span); } # base image width my $width = $CONF->page_settings('imagewidth') || $CONF->setting("imagewidth") || IMAGE_WIDTH; # but also allow for padding my $ip = $SCONF->setting('image_padding') || 0; my $pl = $SCONF->setting('pad_left') || 0; my $pr = $SCONF->setting('pad_right') || 0; my $padding = ($pl || $ip) + ($pr || $ip); my ($ref_img,$ref_boxes) = segment2image($segment, $src, { width => $width - $padding, features_top => $upper_ff, features_bottom => $lower_ff, background => 'white', } ) or die("no image"); $width = $ref_img->width; my $ref_title = $MAP->{$src}{desc} . ' ' . format_segment($segment); # pad all of the span coordinates for a bit of regional context for my $key (keys %span) { my $width = $span{$key}{end} - $span{$key}{start}; $span{$key}{start} -= int $width/20; $span{$key}{end } += int $width/20; } # we now create panels and corresponding hit feature files for each of the small # panels my $refwidth = $width; my $panel_count = keys %span; my $panels_above = my @panels_above = grep { $span{$_}{position} % 2 } keys %span; my $panels_below = my @panels_below = grep {!($span{$_}{position} % 2) } keys %span; my $bases_above = sum( map {$span{$_}{end} - $span{$_}{start}} @panels_above ); my $bases_below = sum( map {$span{$_}{end} - $span{$_}{start}} @panels_below ); my ($pad_top,$pad_bottom) = (0,0); my ($img,$boxes); my $im_pad = $CONF->setting('interimage_pad') || INTERIMAGE_PAD; for my $key (keys %span) { my $panel_position = $span{$key}{position}; my $is_above = $panel_position % 2; my $total_bases = $is_above ? $bases_above : $bases_below; my $panels = $is_above ? $panels_above : $panels_below; my $total_width = $refwidth - $panels*3*$im_pad + $im_pad; my $src = $span{$key}{src}; my $contig = $span{$key}{contig}; my $end = $span{$key}{end}; my $start = $span{$key}{start}; my $bases = $end - $start; my $name = "$contig:$start..$end"; my $segment = landmark2segment($page_settings,$name,$src); my @relevant_hits = grep {$hit2span->{$_} eq $key} @hits; my $rsegment = landmark2segment($page_settings,"$contig:$start..$end",$src); # width of inset panels scaled by size of target sequence $bases or next; my $scale = $bases/$total_bases; my $width = $total_width*$scale; my $ff = Bio::Graphics::FeatureFile->new; add_hit_to_ff($rsegment,$ff,$_,$hit2span,'invert') foreach @relevant_hits; my $segment_args = {width => $width}; if ($is_above) { $segment_args->{features_bottom} = $ff; $segment_args->{noscale} = 1; } else { $segment_args->{features_top} = $ff; } $segment_args->{flip}++ if panel_is_flipped($key,1); ($img,$boxes) = segment2image($segment, $src, $segment_args); $img or next; $span{$key}{image} = $img; $span{$key}{boxes} = $boxes; $span{$key}{title} = $MAP->{$src}{desc}; $span{$key}{title} .= ' (reverse)' if panel_is_flipped($key); $pad_top = $img->height if $is_above && $pad_top < $img->height; $pad_bottom = $img->height if !$is_above && $pad_bottom < $img->height; } # total height is height of reference + pad_top + pad_bottom + VERTICAL_PAD pixels of spacing my $total_height = $ref_img->height + $pad_top + $pad_bottom; my $vertical_pad = $CONF->setting('vertical_pad') || VERTICAL_PAD; $total_height += $vertical_pad if $panels_above; $total_height += $vertical_pad if $panels_below; $total_height += $im_pad; # create a master image for all panels my $gd = GD::Image->new($ref_img->width+2*$im_pad,$total_height+1,1) or return; $gd->saveAlpha(0); $gd->alphaBlending(1); my $white = $gd->colorAllocate(255,255,255); my $black = $gd->colorAllocate(0,0,0); my $cyan = $gd->colorAllocate(0,255,255); $gd->filledRectangle(0,0,$gd->width,$gd->height,$white); my $translucent = $gd->colorAllocateAlpha(0,0,255,90); for my $key (keys %span) { my $color = $CONF->setting($MAP->{$span{$key}{src}}{db}=>'color'); # report missing config for the species if no color is found $color || die <{$span{$key}{src}}{db}. Check the \[$MAP->{$span{$key}{src}}{db}\] stanza in your main configuration file; END ; my @colrgb = Bio::Graphics::Panel->color_name_to_rgb($color); $span{$key}{tcolor} = $gd->colorAllocateAlpha(@colrgb,110); $span{$key}{bgcolor} = $gd->colorAllocateAlpha(@colrgb,115); $span{$key}{border} = $gd->colorResolve(@colrgb); } my $ref_top = $panels_above ? $pad_top + $vertical_pad : $im_pad; my $ref_bottom = $ref_top + $ref_img->height; # paste the individual panels into the picture my @map_items; my %x = ( above => $im_pad, below => $im_pad); # order the panels by hit order my (@sorted_spans,%seen_span); for my $h (sort {$a->start <=> $b->start} @hits) { my $span = $hit2span->{$h}; push @sorted_spans, $span if ++$seen_span{$span} == 1; } my $max_height_above = max( map {eval{$span{$_}{image}->height}} grep {$span{$_}{position} % 2} @sorted_spans); my $max_height_below = max( map {eval{$span{$_}{image}->height}} grep {! ($span{$_}{position} % 2)} @sorted_spans); for my $key (@sorted_spans) { my $is_above = $span{$key}{position} % 2; my $img = $span{$key}{image} or next; my $xi = $is_above ? 'above' : 'below'; my $max_height = $is_above ? $max_height_above : $max_height_below; my $img_y = $is_above ? $ref_top-$vertical_pad-$img->height : $ref_bottom+$vertical_pad ; my $msk_y = $is_above ? $ref_top-$vertical_pad-$max_height : $img_y; $span{$key}{offsets} = [$x{$xi},$img_y]; my @rect = ($x{$xi},$msk_y,$x{$xi}+$img->width,$msk_y+$max_height); $gd->copy($img,$x{$xi},$img_y,0,0,$img->width,$img->height); $gd->filledRectangle(@rect,$span{$key}{bgcolor}); $gd->rectangle(@rect,$span{$key}{border}); $gd->string(GD::gdSmallFont,$x{$xi}+5,$msk_y,$span{$key}{title},$black) if $img->width > 75; $x{$xi} += $img->width + $im_pad; my $name = "$span{$key}{contig}:$span{$key}{start}..$span{$key}{end}"; push @map_items,Area({shape=>'rect', coords=>join(',',@rect), href=>"?search_src=$span{$key}{src};name=$name", title=>$span{$key}{title}}); } # middle row (reference) my @rect = ($im_pad,$ref_top,$im_pad+$ref_img->width,$ref_top+$ref_img->height); $gd->copy($ref_img,$im_pad,$ref_top,0,0,$ref_img->width,$ref_img->height); my $color = $CONF->setting($MAP->{$src}{db}=>'color'); $color ||= 'blue'; my $bgcolor = $gd->colorAllocateAlpha(Bio::Graphics::Panel->color_name_to_rgb($color),110); my $border = $gd->colorResolve(Bio::Graphics::Panel->color_name_to_rgb($color)); $gd->filledRectangle(@rect,$bgcolor); $gd->rectangle(@rect,$border); my $title = $MAP->{$src}{desc} . ' (reference)'; $gd->string(GD::gdSmallFont,$rect[0]+5,$rect[1],$title,$black); push @map_items,Area({shape=>'rect', coords=>join(',',@rect), title=>$ref_title}); # sort out the coordinates of all the hits so that we can join them # first the hits in the reference panel my (%ref_boxes,%panel_boxes); for my $box (@$ref_boxes) { ref $box or next; my ($feature,$fname) = _type_from_box($box); my @rect = ($im_pad+$box->[1],$ref_top+$box->[2],$im_pad+$box->[3],$ref_top+$box->[4]); if ($feature =~ /^match(_part)?$/) { $ref_boxes{$fname} = \@rect; } else { my %atts = %{$box->[5]}; my $url = url(); $url =~ s/gbrowse_syn.*$//; $atts{href} =~ s/\.\.\/\.\.\//$url/ if $atts{href}; push @map_items,Area({shape=>'rect',coords=>join(',',@rect),%atts}); } $gd->rectangle(@rect,$black) if DEBUG; } # now for the hits in each individual panel my %tcolors; for my $key (keys %span) { defined $span{$key}{offsets} or next; my ($left,$top) = @{$span{$key}{offsets}}; my $boxes = $span{$key}{boxes}; for my $box (@$boxes) { ref $box or next; my ($feature,$fname) = _type_from_box($box); #next unless $feature =~ /^match(_part)?$/; my @rect = ($left+$box->[1],$top+$box->[2],$left+$box->[3],$top+$box->[4]); if ($feature =~ /^match(_part)?$/) { $panel_boxes{$fname} = \@rect; } else { push @map_items, Area( { shape => 'rect', coords => join(',',@rect), %{$box->[5]}}); } $tcolors{$fname} = $span{$key}{tcolor}; $gd->rectangle(@rect,$black) if DEBUG; } } my %grid_line; my %gc; $gc{1} = $CONF->page_settings("pgrid") ? $gd->colorResolveAlpha(10,10,10,100) : $gd->colorResolveAlpha(10,10,10,70); $gc{3} = $gd->colorResolveAlpha(10,10,255,100); my $thickness = 3; my $grid_upper; for my $feature (keys %ref_boxes) { next unless defined $ref_boxes{$feature} && defined $panel_boxes{$feature}; my $hit = $CONF->name2hit($feature); next unless defined $hit; my $span = $hit2span->{$feature}; my $flip = !panel_is_flipped($span) && $CONF->flip($feature) || panel_is_flipped($span) && !$CONF->flip($feature); my ($rx1,$ry1,$rx2,$ry2) = @{$ref_boxes{$feature}}; my ($px1,$py1,$px2,$py2) = @{$panel_boxes{$feature}}; my $upper = $py2 < $ry1; if ($CONF->page_settings("shading")) { my $poly = GD::Polygon->new(); $upper = $py2 < $ry1; ($rx1,$rx2) = ($rx2,$rx1) if $flip; if ($upper) { $grid_upper ||= $ry2; $poly->addPt($px1,$py2); $poly->addPt($px2,$py2); $poly->addPt($rx2,$ry1); $poly->addPt($rx1,$ry1); } else { $poly->addPt($px1,$py1); $poly->addPt($px2,$py1); $poly->addPt($rx2,$ry2); $poly->addPt($rx1,$ry2); } $gd->filledPolygon($poly,$tcolors{$feature}); } } my %within_a_pixel; # reloop to avoid mysterious alpha-channel interaction # between shading and grid-lines for my $feature (keys %ref_boxes) { next unless defined $ref_boxes{$feature} && defined $panel_boxes{$feature}; next if $feature =~ /aggregate/; my $exact = $CONF->setting('grid coordinates'); $exact = $exact && $exact eq 'exact'; next unless my $hit = $CONF->name2hit($feature); my $span = $hit2span->{$feature}; my $flip = !panel_is_flipped($span) && $CONF->flip($feature) || panel_is_flipped($span) && !$CONF->flip($feature); my ($rx1,$ry1,$rx2,$ry2) = @{$ref_boxes{$feature}}; my ($px1,$py1,$px2,$py2) = @{$panel_boxes{$feature}}; my $upper = $py2 < $ry1; my @grid_coords = $CONF->page_settings("pgrid") ? grid_coords( $hit, $ref_boxes{$feature}, $panel_boxes{$feature}, panel_is_flipped($span), $segment) : (); # add edges if ($CONF->page_settings("edge")) { unshift @grid_coords, $flip ? [$rx1,$px2] : [$rx1,$px1]; push @grid_coords, $flip ? [$rx2,$px1] : [$rx2,$px2]; } my $tidx = 0; for my $pair (@grid_coords) { my ($x1,$x2) = @$pair; $grid_line{$x1}{thickness} = 1 if $exact; unless ($grid_line{$x1}{thickness}) { $thickness = ++$tidx == 5 ? 3 : 1; $tidx = 0 if $tidx == 5; } else { $thickness = $grid_line{$x1}{thickness}; } $gd->setThickness($thickness); if ($upper) { $gd->line($x1,$ry1,$x2,$py2,$gc{$thickness}); $gd->line($x2,$py2,$x2,0,$gc{$thickness}); $grid_line{$x1}{top} ||= $ry2; } else { my $pad = $im_pad; $gd->line($x1,$ry2,$x2,$py1,$gc{$thickness}); $gd->line($x2,$py1,$x2,$gd->height-$pad-1,$gc{$thickness}); $grid_line{$x1}{bottom} ||= $ry1; } $grid_line{$x1}{thickness} ||= $thickness; } } for my $g (keys %grid_line) { # skip the line if there is one already drawn # a pixel to the left or right; next if $within_a_pixel{$g-1} || $within_a_pixel{$g+1} || $within_a_pixel{$g}; $within_a_pixel{$g} = 1; my $thickness = $grid_line{$g}{thickness}; $gd->setThickness($thickness); $grid_line{$g}{top} ||= $grid_upper;#$ref_top; $grid_line{$g}{bottom} ||= $ref_bottom; $gd->line($g,$grid_line{$g}{top},$g,$grid_line{$g}{bottom},$gc{$thickness}); } my $url = $SCONF->generate_image($gd); my $label = $CONF->page_settings->{display} eq 'compact' ? # all 'Details' : # or a sub-set join(', ',@species); my $map_name = md5_hex($label); print toggle( $label, table( {-width=>'100%'}, Tr( td( {-align=>'center', -class => 'databody'}, img({-src=>$url,-border=>0,-usemap=>'#'.$map_name} ))) ), ); my $map = Map({-name=>$map_name},reverse @map_items); $map =~ s/\{width}; my $hits_top = $options->{features_top}; my $hits_bottom = $options->{features_bottom}; my $background = $options->{background} || 'white'; my $flip = $options->{flip}; my $dsn = $MAP->{$src}{db} or return; $SCONF->source($dsn); # make sure balloon tooltips are turned on $SCONF->setting('GENERAL','balloon tips',1); my @tracks = shellwords($CONF->setting($dsn => 'tracks')); my $ff_scale = Bio::Graphics::FeatureFile->new; $ff_scale->add_type( SCALE => { fgcolor => 'black', glyph => 'arrow', tick => 2, double => 0, description => 0} ); $ff_scale->add_feature(segment2feature($segment,$ff_scale)); my @labels; if ($hits_top && $hits_bottom) { @labels = ('ff_top','ff_scale',@tracks,'ff_bottom'); } elsif ($hits_top) { @labels = ('ff_top','zz_scale',@tracks); } elsif ($hits_bottom) { @labels = (@tracks,'ff_scale','ff_bottom'); } else { @labels = ('ff_scale',@tracks); } my %ff_hash; $ff_hash{ff_top} = $hits_top if $hits_top; $ff_hash{ff_bottom} = $hits_bottom if $hits_bottom; # coerce correct track order in bottom panel my $scale_label = $hits_bottom && !$hits_bottom ? 'zz_scale' : 'ff_scale'; $ff_hash{$scale_label} = $ff_scale; $SCONF->width($width); my $im_pad = $CONF->setting('interimage_pad') || INTERIMAGE_PAD; # padding must be temporarily overridden for inset panels my ($pl,$pr); unless ($src eq $CONF->search_src()) { $pl = $SCONF->setting('pad_left'); $pr = $SCONF->setting('pad_right'); $SCONF->setting('general','pad_left' => $im_pad); $SCONF->setting('general','pad_right' => $im_pad); } $SCONF->setting('general','detail bgcolor'=> $background); my $title = $MAP->{$src}{desc}; # cache no panels if some params change my $no_cache = [md5_hex(url(-query_string=>1))]; landmark2segment() if _isref($segment); my ($img,$boxes) = $SCONF->render_panels( { drag_n_drop => 0, image_and_map => 1, keystyle => 'none', segment => $segment, labels => \@labels, title => $title, -grid => 0, do_map => 1, noscale => 1, feature_files=>\%ff_hash, -flip => $flip, cache_extra => $no_cache, } ); # restore original padding unless ($src eq $CONF->search_src()) { $SCONF->setting('general','pad_left' => $pl); $SCONF->setting('general','pad_right' => $pr); } return ($img,$boxes,$segment); } sub _isref { my $segment = shift; return $segment->ref eq $CONF->page_settings('ref') && $segment->start == $CONF->page_settings('start') && $segment->stop == $CONF->page_settings('stop'); } sub format_segment { my $seg = shift; return $seg->ref.':'.$seg->start.'..'.$seg->end; } sub landmark2segment { my $settings = shift || $CONF->page_settings; my ($name,$source) = @_; if ($name && $source) { } elsif ($CONF->page_settings("name")) { $name = $CONF->page_settings("name"); } elsif ($CONF->page_settings("ref")) { $name = $CONF->page_settings("ref") . ':'; $name .= $CONF->page_settings("start") . ':'; $name .= $CONF->page_settings("stop"); } $source ||= $CONF->page_settings("search_src"); my $segment = _do_search($name,$source) if $name && $source; # Did not find our segment? Try the other species if (!$segment) { for my $src (grep {defined $_} @{$settings->{species}}) { next if $src eq $source; $segment = _do_search($name,$src) if $name; if ($segment) { $settings->{search_src} = $src; $CONF->search_src($src); last; } } } # remember our search! if ($segment && $source && $source eq $settings->{search_src}) { $settings->{"ref"} = $segment->ref; $settings->{"start"} = $segment->start; $settings->{"stop"} = $segment->end; $settings->{"name"} = format_segment($segment); } return $segment; } sub _do_search { my ($landmark,$src) = @_; my $dsn = $MAP->{$src}{db} or return undef; $SCONF->source($dsn); my $db = open_database(); my ($segment) = grep {$_} $SCONF->name2segments($landmark,$db); return $segment; } sub warning { h2({-style=>'color:red'},@_); } sub add_hit_to_ff { my ($segment,$ff,$hit,$hit2span,$invert) = @_; my $flip_hit = $hit->tstrand eq '-'; $CONF->flip($hit->name => 1) if $flip_hit; my @attributes = $flip_hit ? (-attributes => {flip=>1}) : (); my $src = $hit->src2; my $setcolor = $CONF->setting($MAP->{$src}->{db} => 'color'); $ff->add_type( "match:$src" => { bgcolor => $setcolor, fgcolor => $setcolor, height => $CONF->setting('align_height') || ALIGN_HEIGHT, glyph => 'segments', label => 0, box_subparts => 1, connector => 'dashed', }, ); my $seqid = $invert ? $hit->target : $hit->seqid; my $strand = $invert ? $hit->tstrand : $hit->strand; my $start = $invert ? $hit->tstart : $hit->start; my $end = $invert ? $hit->tend : $hit->end; my $feature = Bio::Graphics::Feature->new( -source => $src, -type => 'match', -name => $hit->name, -seq_id => $seqid, -strand => $strand eq '-' ? -1 : 1, -configurator => $ff ); my $parts = $CONF->{parts}->{$hit->name}; if ($parts) { for my $part (@$parts) { $CONF->flip($part->name => 1) if $flip_hit; $hit2span->{$part->name} = $hit2span->{$hit}; $CONF->name2hit($part->name => $part); my $start = $invert ? $part->tstart : $part->start; my $end = $invert ? $part->tend : $part->end; my $subfeat = Bio::Graphics::Feature->new( -type => 'match_part', -name => $part->name, -start => $start, -end => $end, -strand => $strand ); $feature->add_segment($subfeat,'EXPAND'); } } else { $feature->start($start); $feature->end($end); } $ff->add_feature($feature); } sub adjust_container { my $h = shift; if ($h->parts) { my @coords = map {$_->tstart,$_->tend} @{$h->parts}; my ($max,$min) = (max(@coords),min(@coords)); $h->tstart($min) if $h->tstart != $min; $h->tend($max) if $h->tend != $max; @coords = map {$_->start,$_->end} @{$h->parts}; ($max,$min) = (max(@coords),min(@coords)); $h->start($min) if $h->start != $min; $h->end($max) if $h->end != $max; } return $h; } sub navigation_table { my $segment = shift; my @species = @_; my ($table,$whole_segment); my $slidertable = ''; if ($segment) { my $whole_segment = $CONF->whole_segment(); my ($label) = $CONF->tr('Scroll'); $slidertable = $CONF->slidertable; } elsif (my $name = $CONF->page_settings('name')) { $slidertable = "$name not found in ".($CONF->search_src||'NO SPECIES SELECTED'); my $style = "font-size:90%;color:red"; $slidertable = p(b(span({-style=>$style},$slidertable))); } $CONF->section_setting(Instructions => 'open'); $CONF->section_setting(Search => 'open'); $table .= toggle( $CONF->tr('Instructions'), div({-class=>'searchtitle'}, br.'Select a Region to Browse and a Reference species:', p($CONF->show_examples()))); my $html_frag = $INVALID_SRC ? '' : html_frag($segment,$CONF->page_settings); $table .= toggle( $CONF->tr('Search'), table({-border=>0, -width => '100%', -cellspacing=>0}, TR({-class=>'searchtitle'}, td({-align=>'left', -colspan=>3}, $html_frag ) ), TR({-class=>'searchtitle'}, td({-align=>'left', -width=>'30%'}, [ landmark_search($segment) . ' ' . submit(-name=>$CONF->tr('Search')) . reset(-name=>$CONF->tr('Reset'), -onclick=>"window.location='?reset=1'"), species_search(), $slidertable ] ) ), TR({-class=>'searchtitle'}, td({-colspan=>3}, species_chooser()) ), TR({-class=>'searchtitle'}, td({-valign=>'bottom'}, source_menu() ) . td( {-colspan=>2, -valign=>'bottom'}, expand_notice() ) ), ) # end table ); # end toggle section print $table,br; } sub expand_display { return '' if keys %$MAP < 4; my $options = [qw/expanded compact/]; my $labels = { expanded => 'ref. species plus 2', compact => 'all species in one panel' }; my $default = ['expanded']; my $name = 'display'; b(' ', wiki_help("Display Mode",$CONF->tr('Display Mode')), ': ') . popup_menu({-name => $name, -labels => $labels, -values => $options, -default => $default}); } sub options_table { my @onclick = (); my $radio_style = {-style=>"background:lightyellow;border:5px solid lightyellow", @onclick}; my $space = '  '; my @grid = (span($radio_style, option_check('Grid lines', 'pgrid'))) unless $SYNTENY_IO->nomap; print toggle( $CONF->tr('Display_settings'), table({-cellpadding => 5, -width => '100%', -border => 0, -class => 'searchtitle'}, TR( td( b(wiki_help('Image Widths',$CONF->tr('Image widths')), ': '), span( $radio_style, radio_group( -name => 'imagewidth', -values => [640,768,800,1024,1280], -default=>$CONF->page_settings('imagewidth'), @onclick )) ), td( expand_display() ), td( submit(-name => 'Update Image') ) ), TR( td( {-colspan => 3}, b(wiki_help('Image Options',$CONF->tr('Image options')), ': '), div( span($radio_style, option_check('Chain alignments', 'aggregate')),$space, span($radio_style, option_check('Flip minus strand panels', 'pflip')),$space, @grid, span($radio_style, option_check('Edges', 'edge')), $space, span($radio_style, option_check('Shading', 'shading')), ) ) ) ) ); } sub option_check { my $label = shift; my $name = shift; $label = wiki_help($label,$CONF->tr($label)); my $checked = $CONF->page_settings("$name") ? 'on' : 'off'; return $label.' '.radio_group(-name => $name, -values => [qw/on off/], -default =>$checked); } sub source_menu { my $settings = shift; my @sources = $CONF->sources; my $show_sources = $CONF->setting('show sources'); $show_sources = 1 unless defined $show_sources; # default to true my $sources = $show_sources && @sources > 1; my $source = $CONF->get_source; return $sources ? b(wiki_help('Data Source',$CONF->tr('Data Source')), ': ') . br. popup_menu(-onchange => 'document.searchform.submit()', -name => 'source', -values => \@sources, -labels => { map {$_ => $CONF->description($_)} $CONF->sources}, -default => $source, ) : $CONF->description($sources[0]); } sub aggregate { my $hits = shift; $CONF->{parts} = {}; my @sorted_hits = sort { $a->target cmp $b->target || $a->tstart <=> $b->tstart} @$hits; my (%group,$last_hit); for my $hit (@sorted_hits) { if ($last_hit && belong_together($last_hit,$hit)) { push @{$group{$last_hit}}, $hit; $group{$hit} = $group{$last_hit}; } else { push @{$group{$hit}}, $hit; } $last_hit = $hit; } $hits = []; my %seen; for my $grp (grep {++$seen{$_} == 1} values %group) { if (@$grp > 1) { my @coords = sort {$a<=>$b} map {$_->start,$_->end} @$grp; my @tcoords = sort {$a<=>$b} map {$_->tstart,$_->tend} @$grp; my $hit = Legacy::DB::SyntenyBlock->new($grp->[0]->name."_aggregate"); $hit->add_part($grp->[0]->src,$grp->[0]->tgt); $hit->start(shift @coords); $hit->end(pop @coords); $hit->tstart(shift @tcoords); $hit->tend(pop @tcoords); $CONF->{parts}->{$hit->name} = $grp; push @$hits, $hit; } else { push @$hits, $grp->[0]; } } return @$hits; } sub belong_together { my ($feat1,$feat2) = @_; my $max_gap = $CONF->setting('max_gap') || MAX_GAP; return unless $feat1->target eq $feat2->target; # same chromosome return unless $feat1->seqid eq $feat2->seqid; # same reference sequence return unless $feat1->tstrand eq $feat2->tstrand; # same strand if ($feat1->tstrand eq '+') { return unless $feat1->end < $feat2->end; # '+' strand monotonically increasing } else { return unless $feat1->end > $feat2->end; # '-' strand monotonically decreasing } my $dist1 = abs($feat2->end - $feat1->start); my $dist2 = abs($feat2->tend - $feat1->tstart); return unless $dist2 < $max_gap && $dist1 < $max_gap; return $dist2; } sub overview_panel { my ($whole_segment,$segment) = @_; return '' if $SCONF->section_setting('overview') eq 'hide'; my $image = overview($whole_segment,$segment); my $ref = $MAP->{$CONF->page_settings("search_src")}->{desc}; my $width = $CONF->page_settings('imagewidth') || $CONF->setting("imagewidth") || IMAGE_WIDTH; my $ip = $SCONF->setting('image_padding') || $CONF->image_padding || param('image_padding') || 0; my $pl = $SCONF->setting('pad_left') || 0; my $pr = $SCONF->setting('pad_right') || 0; $width += ($pl || $ip) + ($pr || $ip); return toggle('Overview', table({-border=>0,-width=>'100%'}, TR(th("

    Reference genome: $ref
    ")), TR({-class=>'databody'}, td({-align=>'center'}, div({ id => 'overview_panels', style => "position:relative;width:${width}px"}, $image) ) ) ) ); } sub overview { my ($region_segment,$segment) = @_; return unless $segment; my $width = $CONF->page_settings('imagewidth') || IMAGE_WIDTH; $width *= $CONF->setting('overview_ratio') || OVERVIEW_RATIO; $CONF->width($width); # the postgrid will be invoked to hilite the currently selected region my $postgrid = hilite_regions_closure([$segment->start,$segment->end,'yellow']); # reference genome my $ref = $MAP->{$CONF->page_settings("search_src")}->{desc}; my ($overview) = $CONF->render_panels( { length => $segment->length, section => 'overview', segment => $region_segment, postgrid => $postgrid, label_scale => 2, lang => $SCONF->language, keystyle => 'left', settings => $CONF->page_settings(), scale_map_type => 'centering_map', cache_extra => [$segment->start,$segment->end], do_map => 1, drag_n_drop => 0, image_button => 0, -grid => 0, -pad_top => 5, -bgcolor => $CONF->setting('overview bgcolor') || OVERVIEW_BGCOLOR, } ); # make sure overview is busy with redirects #my $server =$ENV{SERVER_NAME}; #if ($server) { # $overview =~ s/src="/src="http:\/\/$server\//; #} return div({-id=>'overview',-class=>'track'},$overview); } sub toggle { my $title = shift; my @body = @_; my $id = "\L${title}_panel\E"; my ($label) = $CONF->tr($title) or return ''; my $state = $CONF->section_setting($title) || 'open'; return '' if $state eq 'off'; my $settings = $CONF->page_settings; my $visible = exists $settings->{section_visible}{$id} ? $settings->{section_visible}{$id} : $state eq 'open'; $settings->{section_visible}{$id} = $state eq 'open'; return toggle_section({on=>$visible}, $id, b($label), @body); } sub get_options { my $tracks_to_show = shift; my $settings = $CONF->page_settings; my %options = map {$_=>$settings->{features}{$_}{options}} @$tracks_to_show; my %limits = map {$_=>$settings->{features}{$_}{limit}} @$tracks_to_show; return (\%options,\%limits); } sub hilite_regions_closure { my @h_regions = @_; return sub { my $gd = shift; my $panel = shift; my $left = $panel->pad_left; my $top = $panel->top; my $bottom = $panel->bottom; for my $r (@h_regions) { my ($h_start,$h_end,$h_color) = @$r; my ($start,$end) = $panel->location2pixel($h_start,$h_end); if ($end-$start <= 1) { $end++; $start-- } # so that we always see something # assuming top is 0 so as to ignore top padding $gd->filledRectangle($left+$start,0,$left+$end,$bottom, $panel->translate_color($h_color)); } }; } sub feature2segment { my $feature = shift; return $feature if ref $feature eq 'Bio::DB::GFF::RelSegment'; my $refclass = $CONF->setting('reference class') || 'Sequence'; my $db = open_database(); my $version = eval {$_->isa('Bio::SeqFeatureI') ? undef : $_->version}; return $db->segment(-class => $refclass, -name => $feature->ref, -start => ($feature->start - int($feature->length/20)), -stop => ($feature->end + int($feature->length/20)), -absolute => 1, defined $version ? (-version => $version) : ()); } sub segment2feature { my $segment = shift; my $ff = shift; my $start = $segment->start; my $end = $segment->end; my $type = 'SCALE'; return Bio::Graphics::Feature->new( -start => $start, -end => $end, -type => $type, -name => $segment->ref, -seq_id => $segment->ref, -configurator => $ff ); } sub expand { my $seq = shift; $seq =~ s/(\S)(\d+)/($1 x $2)/eg; return $seq; } sub remap_coordinates { my $hit = shift; my $segment = shift || $CONF->current_segment; my $flip = $hit->tstrand eq '-'; return unless $hit->start < $segment->start || $hit->end > $segment->end; if ($hit->start < $segment->start) { my ($new_start,$new_tstart) = $SYNTENY_IO->get_nearest_position_match($hit,$hit->src1,$segment->start,1000); unless ($new_start) { ($new_start,$new_tstart) = guess_nearest_position_match($hit,$segment->start,$flip); } if ($new_start) { my $hsp = $hit->parts->[0]; $hsp->start($new_start); $flip ? $hsp->tend($new_tstart) : $hsp->tstart($new_tstart); } } if ($hit->end > $segment->end) { my ($new_end,$new_tend) = $SYNTENY_IO->get_nearest_position_match($hit,$hit->src1,$segment->end,1000); unless ($new_end) { ($new_end,$new_tend) = guess_nearest_position_match($hit,$segment->end,$flip); } if ($new_end) { my $hsp = $hit->parts->[-1]; $hsp->end($new_end); $flip ? $hsp->tstart($new_tend) : $hsp->tend($new_tend); } } $hit = adjust_container($hit); } # If we can't get a mapped coordinate, interpolate based # on relative hit lengths sub guess_nearest_position_match { my $hit = shift; my $coord = shift; my $flip = shift; my $hlen = $hit->end - $hit->start; my $tlen = $hit->tend - $hit->tstart; my $lratio = $tlen/$hlen; my $hoffset = $coord - $hit->start; my $toffset = $lratio * $hoffset; my $WAG = int($flip ? $hit->tend - $toffset : $hit->tstart + $toffset); return ($coord,$WAG); } # take a vote to flip the panel: the majority strand wins sub panel_is_flipped { my $key = shift; return 0 unless $CONF->page_settings('pflip'); my $panel_flip = $CONF->panel_flip($key); my $yes = $panel_flip->{$key}{yes} || 0; my $no = $panel_flip->{$key}{no} || 0; return $yes > $no; } # map the reference and target coordinates to pixel locations # to draw gridlines sub locations2pixels { my ($loc,$hit,$refbox,$hitbox,$flip,$loc2) = @_; #my $reversed = $hit->strand ne $hit->tstrand; my ($ref_location,$hit_location) = $loc && $loc2 ? ($loc,$loc2) : $SYNTENY_IO->get_nearest_position_match($hit,$hit->src1,$loc); unless ($ref_location && $hit_location) { ($ref_location,$hit_location) = guess_nearest_position_match($hit,$loc,$flip); } $ref_location && $hit_location || return 0; $ref_location -= $hit->start if $ref_location; $hit_location -= $hit->tstart if $hit_location; my $ref_length = $hit->end - $hit->start; my $hit_length = $hit->tend - $hit->tstart; my $ref_pixels = $refbox->[2] - $refbox->[0]; my $hit_pixels = $hitbox->[2] - $hitbox->[0]; my $ref_conversion = $ref_length/$ref_pixels; my $hit_conversion = $hit_length/$hit_pixels || return 0; my $ref_pixel = $refbox->[0] + int($ref_location/$ref_conversion + 0.5); my $hit_pixel; if ($flip) {# && $reversed) { $hit_pixel = $hitbox->[2] - int($hit_location/$hit_conversion + 0.5); } else { $hit_pixel = $hitbox->[0] + int($hit_location/$hit_conversion + 0.5); } $ref_pixel = 0 if $ref_pixel < 0; $hit_pixel = 0 if $hit_pixel < 0; $hit_pixel = $hitbox->[0] if $hit_pixel < $hitbox->[0]; $hit_pixel = $hitbox->[2] if $hit_pixel > $hitbox->[2]; return [$ref_pixel,$hit_pixel]; } sub grid_coords { my ($hit,$refbox,$hitbox,$flip,$segment) = @_; # don't bother if there are no coords in the database return () if $SYNTENY_IO->nomap; # exact coordinates if configured my $gcoords = $CONF->setting('grid coordinates') || 'AUTO'; if ($gcoords eq 'exact') { return exact_grid_coords(@_); } my $step = grid_step($segment) or return; my $start = nearest(100,$hit->start); $start += $CONF->page_settings("edge") ? $step : 100; my @pairs; my $offset = $start; until ($offset > $hit->end) { my $pair = locations2pixels($offset,$hit,$refbox,$hitbox,$flip); push @pairs, $pair if $pair; $offset += $step; } return @pairs; } # Do not round off or scale, use the grid as provided sub exact_grid_coords { my ($hit,$refbox,$hitbox,$flip,$segment) = @_; my $seq_pairs = [$SYNTENY_IO->grid_coords_by_range($hit,$CONF->page_settings->{search_src})]; $seq_pairs = reorder_pairs($flip,$seq_pairs,1); my @pairs; for my $s (@$seq_pairs) { my $pair = locations2pixels($s->[0],$hit,$refbox,$hitbox,$flip,$s->[1]); push @pairs, $pair if $pair; } return @pairs; } # unflip grid-lines for flipped opposite strand panels sub reorder_pairs { my $flip = shift; my $pairs = shift; my $force_even = shift; return $pairs if @$pairs > 1 && @$pairs % 2 && !$force_even; return [] if @$pairs == 1; return $pairs if !$flip; if (@$pairs % 2) { shift @$pairs; } my $new_pairs = []; while (my $p1 = shift @$pairs) { my $p2 = shift @$pairs; push @$new_pairs, [$p1->[0],$p2->[1]]; push @$new_pairs, [$p2->[0],$p1->[1]]; } return $new_pairs; } # will become more sophisticated ? sub grid_step { my $segment = shift; return nearest(100,int($segment->length/75)) || 100; } sub my_path_info { my (undef,$path) = Legacy::Graphics::Browser::Util::_broken_apache_hack(); my ($src) = $path =~ /([^\/]+)/; return $src; } sub page_settings { my $session = Legacy::Graphics::Browser::PageSettings->new( $CONF, param('id') ); my $source = param('src') || param('source') || my_path_info() || $session->source; if (!$source) { ($source) = $CONF->sources; } redirect_legacy_url($source); my $old_source = $session->source($source); $CONF->source($source); my $settings = get_settings($session); return ($settings,$session); } sub get_settings { my $session = shift; my $hash = $session->page_settings; default_settings($hash) if param('reset') or !%$hash; adjust_settings($hash); $hash->{id} = $session->id; return $hash; } sub default_settings { my $settings = shift; $settings ||= {}; $settings->{width} = $CONF->setting('default width') || $CONF->width; $settings->{source} = $CONF->source; $settings->{v} = $VERSION; $settings->{grid} = 1; my %default = SETTINGS; foreach (keys %default) { $settings->{$_} ||= $default{$_}; } set_default_tracks($settings); } sub set_default_tracks { my $settings = shift; my @labels = $CONF->labels; $settings->{tracks} = \@labels; foreach (@labels) { $settings->{features}{$_} = { visible => 0, options => 0, limit => 0 }; } foreach ( $CONF->default_labels ) { $settings->{features}{$_}{visible} = 1; } } sub _is_checkbox { my $option = shift; return grep {/$option/} qw/aggregate pgrid shading tiny pflip edge/; } sub adjust_settings { my $settings = shift; if ( param('reset') ) { %$settings = (); return default_settings($settings); } $settings->{width} = param('width') if param('width'); my $divider = $CONF->setting('unit_divider') || 1; # Update settings with URL params local $^W = 0; # kill uninitialized variable warning my %settings = SETTINGS; for my $option (keys %settings) { next if $option eq 'species'; my $value = param($option); if ($value) { $value = undef if $value eq 'off'; if ($option =~ /start|stop|end/) { next unless $value =~ /^[\d-]+/; } # sigh $option = 'stop' if $option eq 'end'; $settings->{$option} = $value; } } $settings->{name} ||= "$settings->{ref}:$settings->{start}..$settings->{stop}" if defined $settings->{ref} && $settings->{start} && $settings->{stop}; # expect >1 species my @species = param('species'); if (!@species) { $settings->{species} = [keys %$MAP]; } else { $settings->{species} = \@species; } param( name => $settings->{name} ); if ( (request_method() eq 'GET' && param('ref')) || (param('span') && $divider*$settings->{stop}-$divider*$settings->{start}+1 != param('span')) || grep {/left|right|zoom|nav|regionview\.[xy]|overview\.[xy]/} param() ) { $CONF->zoomnav($settings); $settings->{name} = "$settings->{ref}:$settings->{start}..$settings->{stop}"; param(name => $settings->{name}); } $settings->{name} =~ s/^\s+//; # strip leading $settings->{name} =~ s/\s+$//; # and trailing whitespace return 1; } sub _unique { my %seen; my $src = $CONF->search_src || ''; my @list = grep {!$seen{$_}++} grep {$_} @_; return grep {$_ ne $src} @list; } # nearest function appropriated from Math::Round sub nearest { my $targ = abs(shift); my $half = 0.50000000000008; my @res = map { if ($_ >= 0) { $targ * int(($_ + $half * $targ) / $targ); } else { $targ * POSIX::ceil(($_ - $half * $targ) / $targ); } } @_; return (wantarray) ? @res : $res[0]; } # cetralized help via the the GMOD wiki or a defined URL sub wiki_help { my $label = shift; my @body = shift || $label; my $url = HELP; (my $blabel = $label) =~ s/_/ /g; $label =~ s/\s+/_/g; return a({ -href => "${url}#${label}", -target => '_wiki_help', -onmouseover => "balloon.showTooltip(event,'Click for more information about $blabel')"}, @body); } sub segment_info { my ($settings,$segment) = @_; my $whole_segment = $CONF->whole_segment($segment); my $padl = $CONF->setting('pad_left') || $CONF->image_padding; my $padr = $CONF->setting('pad_right') || $CONF->image_padding; my $max = $CONF->setting('max segment') || MAX_SEGMENT; my $width = ($settings->{width} * OVERVIEW_RATIO); hide(image_padding => $padl); hide(max_segment => $max); hide(overview_start => $whole_segment->start); hide(overview_stop => $whole_segment->end); hide(overview_pixel_ratio => $whole_segment->length/$width); hide(overview_width => $width + $padl + $padr); hide(detail_start => $segment->start); hide(detail_stop => $segment->end); hide(overview_width => $width + $padl + $padr); } sub hide { my ($name,$value) = @_; print hidden( -name => $name, -value => $value, -override => 1 ), "\n"; } GBrowse-2.56/conf000755001750001750 013036764442 13733 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/GBrowse.conf000444001750001750 2154413036764442 16335 0ustar00lsteinlstein000000000000# This is the global configuration for gbrowse # It contains setting common to all data sources as well # as the various constants formerly scattered amongst scripts and libraries [GENERAL] config_base = $CONF # overridden by environment variable GBROWSE_CONF htdocs_base = $HTDOCS url_base = /gbrowse2 tmp_base = $TMP persistent_base = $PERSISTENT userdata_base = $PERSISTENT/userdata db_base = $DATABASES # These paths are relative to the url base buttons = images/buttons balloons = images/balloons openid = images/openid gbrowse_help = . js = js # These paths are relative to the config base plugin_path = plugins language_path = languages templates_path = templates moby_path = MobyServices # session settings session lock type = default # If no session driver is set, then GBrowse will pick one for you. # It will use db_file for the driver and storable for the serializer # if available; otherwise falling back to the file driver and default serializer. # Override driver guessing by setting these options # The safest, but slowest session driver... #session driver = driver:file;serializer:default #session args = Directory $PERSISTENT/sessions # to use the berkeley DB driver comment out the previous # line and uncomment these two #session driver = driver:db_file;serializer:default #session args = FileName $PERSISTENT/sessions.db # DBI backend to use for uploaded userdata. # The SQLite option is the easiest to use and the best tested. # if this option is commented out, then GBrowse will # try 'DBI::SQLite', 'berkeleydb', 'DBI::mysql' and finally the 'memory' # backend. # NOTICE the double semicolon! This is a DBI Perl module, NOT a DBI connection string. # For the DBI::mysql adaptor to work, you must give the web user # permission to create databases named userdata_% using the following # mysql command: # mysql> grant all privileges on `userdata\_%`.* to 'www-data'@localhost identified by 'foobar'; # Note the backquotes around the database name, and do be sure to replace "foobar" with # a more secure password! # for SQLite #upload_db_adaptor = DBI::SQLite # for Berkeleydb #upload_db_adaptor = berkeleydb # for mysql #upload_db_adaptor = DBI::mysql #upload_db_host = localhost #upload_db_user = www-data #upload_db_pass = foobar # Debug settings debug = 0 debug_external = 0 debug_plugins = 0 # Performance settings slave_timeout = 45 global_timeout = 60 search_timeout = 15 max_render_processes = 4 # try double number of CPU/cores preload data sources = 0 # when true & f[ast]cgi loads all datasources at startup, # can be bad if many or ds have many tracks # Renderfarm settings #include renderfarm.conf # Clean up settings (used by the gbrowse_clean script) expire session = 1M # expire unused sessions after a month expire cache = 2h # expire cached data if unmodified for >2 hours expire uploads = 6w # expire uploaded data if unused for >6 weeks # Appearance settings truecolor = 1 # better appearance at the expense of larger image files # truetype = 1 # turn on vector fonts in tracks. Requires Bio::Graphics 2.33 or higher, and truetype support on the server. # The #include line following this one defines a transparent theme. # Replace "transparent_colors" with "solid_gray_colors" # or "warm_colors" for different themes. #include "themes/warm_colors" # #include "themes/transparent_colors" # #include "themes/solid_gray_colors" balloon tips = 1 titles are balloons = 1 plugins = FastaDumper RestrictionAnnotator SequenceDumper TrackDumper overview grid = 0 region grid = 0 detail grid = 1 image widths = 450 640 800 1024 default width = 800 pad_left = 60 pad_right = 30 too many landmarks = 100 track listing style = categories # either "categories" or "facets" # Loads more details image data than can fit on the screen. This lets the user drag and drop the details # tracks, without loading more data from the server. A value of 1 is default (no drag and drop). A value # of 3 loads one full width on each side. details multiplier = 3 # where to link to when user clicks in detailed view link = AUTO # HTML to insert inside the section head = # At the top of the HTML... header = # At the footer footer =

    The Generic Genome Browser. For questions about the data at this site, please contact its webmaster. For support of the browser software only, send email to gmod-gbrowse@lists.sourceforge.net or visit the GMOD Project web pages.

    # Various places where you can insert your own HTML -- see configuration docs html1 = html2 = html3 = html4 = html5 = html6 = # Limits on genomic regions (can be overridden in datasource config files) region segment = 200000 max segment = 5000000 default segment = 5000 zoom levels = 100 200 1000 2000 5000 10000 20000 50000 100000 200000 500000 1000000 region sizes = 1000 5000 10000 20000 default region = 5000 fine zoom = 10% # keyword search maxima max keyword results = 1000 ###### Authorization ###### # uncomment this to use the PAM authentication plugin # authentication plugin = PamAuthenticate ####### User Account Registration Database ###### # If no authentication plugin is defined, and # "user_accounts" is true, then GBrowse # will attempt to use its internal user accounts database # to authenticate and/or register users. user_accounts = 1 user_accounts_registration = 1 user_accounts_openid = 1 # Path to the database -- you will need to create this database and grant all # privileges on it to the indicated user. user_account_db = DBI:SQLite:$DATABASES/users.sqlite # For SQLite # user_account_db = DBI:SQLite:$DATABASES/users.sqlite # For MySQL # user_account_db = DBI:mysql:gbrowse_login;user=gbrowse;password=gbrowse # The number of public files to display public_files = 10 # What email gateway to use for outgoing registration confirmation messages. # The full format is # :::: # Only the first field, the server name, is required. # The port is assumed to be 25 unless ssl encryption is specified, in # which case it defaults to 465. # protocol is either "plain" or "ssl", "plain" assumed. # username and password may be required by the gateway for authentication # # here are some common options # smtp_gateway = localhost # localhost has properly configured outgoing gateway # smtp_gateway = smtp.oicr.on.ca # indicated machine will forward email for you # smtp_gateway = smtp.gmail.com:465:ssl:joe.user:secret # use gmail with account "joe.user" and password "secret" # smtp_gateway = none # disable outgoing email smtp_gateway = none # disable outgoing email # These values are used in the login confirmation message sent during # user registration. You may customize application_name = GBrowse application_name_long = The Generic Genome Browser email_address = noreply@gmod.org # name of the "superuser" who can add public tracks admin_account = admin admin_dbs = $DATABASES/admin_uploads ######## DEFAULT DATASOURCE ######### default source = yeast ############################################################################################### # Global settings for plugins (used for the PamAuthenticate plugin only at this point) ############################################################################################### [PamAuthenticate:plugin] login hint = your UNIX account login help = Please see your system administrator for help
    if you have lost your password.
    pam service name = gbrowse ############################################################################################### # # DATASOURCE DEFINITIONS # One stanza for each configured data source # ############################################################################################### [yeast] description = Yeast chromosomes 1+2 (basic) path = yeast_simple.conf [yeast_advanced] description = Yeast chromosomes 1+2 (advanced) path = yeast_chr1+2.conf [yeast_renderfarm] description = Renderfarm demo (gbrowse_slave must be running!) path = yeast_renderfarm.conf [pop_demo] description = Population Display Demo path = pop_demo.conf [volvox] description = Tutorial database path = volvox.conf GBrowse-2.56/conf/aws_balancer.conf000444001750001750 204413036764442 17360 0ustar00lsteinlstein000000000000[LOAD TABLE] #req/s min max 0.1 0 1 0.5 0 2 1.0 1 3 2.0 2 4 5.0 3 6 6.0 4 6 7.0 5 7 10.0 6 8 15.0 8 8 [MASTER] external_ip = # optional; will figure it out if needed poll_interval = 0.5 # minutes between polling steps server_status_url = http://localhost/server-status # URL on master that invokes Apache server-status [SLAVE] instance_type = m1.medium # pretty nice performance, might also try medium spot_bid = 0.10 # the pricing will cost no more than $0.10/hr ports = 8101 # can be several space-delimited port numbers region = us-west-2 # needed only when run from a non-AWS computer image_id = GBrowse-2.54 # AMI of the slave data_snapshots = # EBS snapshot(s) to attach to the slave availability_zone = # optional subnet = # optional security_group = # optional; will manage own security group if needed GBrowse-2.56/conf/detail_select_menu.conf000444001750001750 314413036764442 20566 0ustar00lsteinlstein000000000000[DETAIL SELECT MENU] width = 250 html =
    SELECTION [X]
    Zoom in
    Recenter on this region
    Dump selection as FASTA
    Submit selection to UCSC BLAT
    Submit selection to NCBI BLAST
    GBrowse-2.56/conf/enzymes.txt000444001750001750 522713036764442 16331 0ustar00lsteinlstein000000000000AatII GACGTC 5 Acc65I GGTACC 1 AccI GT[AC][GT]AC 2 AclI AACGTT 2 AfeI AGCGCT 3 AflII CTTAAG 1 AflIII AC[AG][CT]GT 1 AgeI ACCGGT 1 AhdI GAC.....GTC 6 AluI AGCT 2 AlwNI CAG...CTG 6 ApaI GGGCCC 5 ApaLI GTGCAC 1 ApoI [AG]AATT[CT] 1 AscI GGCGCGCC 2 AseI ATTAAT 2 AsiSI GCGATCGC 5 AvaI C[CT]CG[AG]G 1 AvaII GG[AT]CC 1 AvrII CCTAGG 1 BamHI GGATCC 1 BanI GG[CT][AG]CC 1 BanII G[AG]GC[CT]C 5 BclI TGATCA 1 BfaI CTAG 1 BfrBI ATGCAT 3 BglI GCC.....GGC 7 BglII AGATCT 1 BlpI GCT.AGC 2 Bme1580I G[GT]GC[AC]C 5 BsaAI [CT]ACGT[AG] 3 BsaBI GAT....ATC 5 BsaHI G[AG]CG[CT]C 2 BsaJI CC..GG 1 BsaWI [AT]CCGG[AT] 1 BsiEI CG[AG][CT]CG 4 BsiHKAI G[AT]GC[AT]C 5 BsiWI CGTACG 1 BslI CC.......GG 7 BsoBI C[CT]CG[AG]G 1 Bsp1286I G[AGT]GC[ACT]C 5 BspDI ATCGAT 2 BspEI TCCGGA 1 BspHI TCATGA 1 BsrFI [AG]CCGG[CT] 1 BsrGI TGTACA 1 BssHII GCGCGC 1 BssKI CC.GG 0 BstAPI GCA.....TGC 7 BstBI TTCGAA 2 BstEII GGT.ACC 1 BstNI CC[AT]GG 2 BstUI CGCG 2 BstXI CCA......TGG 8 BstYI [AG]GATC[CT] 1 BstZ17I GTATAC 3 Bsu36I CCT.AGG 2 BtgI CC[AG][CT]GG 1 Cac8I GC..GC 3 ClaI ATCGAT 2 DdeI CT.AG 1 DpnI GATC 2 DpnII GATC 0 DraI TTTAAA 3 DraIII CAC...GTG 6 DrdI GAC......GTC 7 EaeI [CT]GGCC[AG] 1 EagI CGGCCG 1 EcoNI CCT.....AGG 5 EcoO109I [AG]GG.CC[CT] 2 EcoRI GAATTC 1 Fnu4HI GC.GC 2 FseI GGCCGGCC 6 FspI TGCGCA 3 HaeII [AG]GCGC[CT] 5 HaeIII GGCC 2 HhaI GCGC 3 HincII GT[CT][AG]AC 3 HindIII AAGCTT 1 HinfI GA.TC 1 HinP1I GCGC 1 HpaI GTTAAC 3 HpaII CCGG 1 Hpy188I TC.GA 3 Hpy188III TC..GA 2 Hpy99I CG[AT]CG 5 HpyCH4III AC.GT 3 HpyCH4IV ACGT 1 HpyCH4V TGCA 2 KasI GGCGCC 1 KpnI GGTACC 5 MboI GATC 0 MfeI CAATTG 1 MluI ACGCGT 1 MscI TGGCCA 3 MseI TTAA 1 MslI CA[CT]....[AG]TG 5 MspA1I C[AC]GC[GT]G 3 MspI CCGG 1 MwoI GC.......GC 7 NaeI GCCGGC 3 NarI GGCGCC 2 NciI CC[CG]GG 2 NcoI CCATGG 1 NdeI CATATG 2 NgoMIV GCCGGC 1 NheI GCTAGC 1 NlaIII CATG 4 NlaIV GG..CC 3 NotI GCGGCCGC 2 NruI TCGCGA 3 NsiI ATGCAT 5 NspI [AG]CATG[CT] 5 PacI TTAATTAA 5 PaeR7I CTCGAG 1 PciI ACATGT 1 PflFI GAC...GTC 4 PflMI CCA.....TGG 7 PmeI GTTTAAAC 4 PmlI CACGTG 3 PpuMI [AG]GG[AT]CC[CT] 2 PshAI GAC....GTC 5 PsiI TTATAA 3 PspGI CC[AT]GG 0 PspOMI GGGCCC 1 PstI CTGCAG 5 PvuI CGATCG 4 PvuII CAGCTG 3 RsaI GTAC 2 RsrII CGG[AT]CCG 2 SacI GAGCTC 5 SacII CCGCGG 4 SalI GTCGAC 1 Sau3AI GATC 0 Sau96I GG.CC 1 SbfI CCTGCAGG 6 ScaI AGTACT 3 ScrFI CC.GG 2 SexAI ACC[AT]GGT 1 SfcI CT[AG][CT]AG 1 SfiI GGCC.....GGCC 8 SfoI GGCGCC 3 SgrAI C[AG]CCGG[CT]G 2 SmaI CCCGGG 3 SmlI CT[CT][AG]AG 1 SnaBI TACGTA 3 SpeI ACTAGT 1 SphI GCATGC 5 SspI AATATT 3 StuI AGGCCT 3 StyI CC[AT][AT]GG 1 SwaI ATTTAAAT 4 TfiI GA[AT]TC 1 TliI CTCGAG 1 TseI GC[AT]GC 1 Tsp45I GT[CG]AC 0 Tsp509I AATT 0 TspRI CA[CG]TG.. 7 Tth111I GAC...GTC 4 XbaI TCTAGA 1 XcmI CCA.........TGG 8 XhoI CTCGAG 1 XmaI CCCGGG 1 XmnI GAA....TTC 5 GBrowse-2.56/conf/log4perl.conf000444001750001750 256613036764442 16500 0ustar00lsteinlstein000000000000log4perl.logger.Bio.DB.Das.Chado = DEBUG, Chado log4perl.appender.Chado = Log::Log4perl::Appender::File log4perl.appender.Chado.filename = /etc/httpd/logs/gbrowse.log log4perl.appender.Chado.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.Chado.layout.ConversionPattern =%c - [%d{HH:mm}] %M() in file .../%F{2} (line %L) says: %m%n log4perl.logger.Bio.DB.Das.Chado.Segment = DEBUG, Chado_Segment log4perl.appender.Chado_Segment = Log::Log4perl::Appender::File log4perl.appender.Chado_Segment.filename = /etc/httpd/logs/gbrowse.log log4perl.appender.Chado_Segment.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.Chado_Segment.layout.ConversionPattern =%c - [%d{HH:mm}] %M() in file .../%F{2} (line %L) says: %m%n log4perl.logger.das = DEBUG, das log4perl.appender.das = Log::Log4perl::Appender::File log4perl.appender.das.filename = /etc/httpd/logs/gbrowse.log log4perl.appender.das.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.das.layout.ConversionPattern =%c - [%d{HH:mm}] %M() in file .../%F{2} (line %L) says: %m%n GBrowse-2.56/conf/pop_demo.conf000444001750001750 632013036764442 16542 0ustar00lsteinlstein000000000000[GENERAL] description = Population Demo db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $PERSISTENT/databases/pop_demo html1=

    This is a demo of GBrowse and PhyloGeoViz working together to display population data on a Google Map.

    This demo uses the public PhyloGeoViz. To fully take advantage of all the features, PhyloGeoViz will also need to be installed locally. Please see the gbrowse_gmap documentation for further details by running "perldoc /path/to/gbrowse_gmap".

    Populations:
    • POPA: Clicking opens PhyloGeoViz in a new window
    • POPB: Clicking opens PhyloGeoViz in a balloon
    • POPC: Default behavior of GBrowse
    # list of tracks to turn on by default default features = POPA POPB POPC # examples to show in the introduction examples = contig1 # what image widths to offer image widths = 450 640 800 1024 # default width of detailed view (pixels) default width = 640 # feature to show on startup initial landmark = contig1 # max and default segment sizes for detailed view max segment = 200000 default segment = 50000 # zoom levels zoom levels = 100 200 1000 2000 5000 10000 20000 40000 50000 100000 200000 show sources = 0 cache time = 0 # Make space for gene names on the left. pad_left = 100 label density = 25 bump density = 100 # "automatic" classes to try when an unqualified identifier is given automatic classes = search attributes = Name Alias # other customization options... # Point to the url of PhyloGeoViz #phylogeoviz_url = /phylo/newviewer.php phylogeoviz_url = http://phylogeoviz.org/latest/newviewer.php ######################## # Default glyph settings ######################## [TRACK DEFAULTS] glyph = generic height = 10 bgcolor = lightgrey fgcolor = black font2color = blue label density = 25 bump density = 100 # where to link to when user clicks in detailed view link = AUTO ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### # General Category # ====================================================== # Variation Category # ---------------------------------- # Genotype Frequencies [POPA] feature = SNP:POPA glyph = generic label_position = left fgcolor = brown width = 5 linewidth = 2 category = Variation key = POPA latitude = 43.612 longitude = -79.365 link =/cgi-bin/gb2/gbrowse_gmap/pop_demo?ref=$ref;start=$start;end=$end;name=$name;class=$class [POPB] feature = SNP:POPB glyph = generic label_position = left fgcolor = red width = 5 linewidth = 2 category = Variation key = POPB latitude = 41.689 longitude = -91.560 balloon click = /cgi-bin/gb2/gbrowse_gmap/pop_demo?ref=$ref;start=$start;end=$end;name=$name;class=$class;balloon=1 [POPC] feature = SNP:POPC glyph = generic label_position = left fgcolor = blue width = 5 linewidth = 2 category = Variation key = POPC latitude = 44 longitude = -100 GBrowse-2.56/conf/renderfarm.conf000444001750001750 5613036764442 17025 0ustar00lsteinlstein000000000000[GENERAL] renderfarm = 0 remote renderer = GBrowse-2.56/conf/slave_preload.conf000444001750001750 60613036764442 17541 0ustar00lsteinlstein000000000000# use this to preload one or more databases into slave memory # see the examples below #[yeast12] #db_adaptor = Bio::DB::SeqFeature::Store #db_args = -adaptor memory # -dir $PERSISTENT/databases/yeast_chr1+2 #[scaffolds] #db_adaptor = Bio::DB::SeqFeature::Store #db_args = -adaptor memory # -dir $PERSISTENT/databases/yeast_scaffolds GBrowse-2.56/conf/submitter_plugin.conf000444001750001750 343613036764442 20341 0ustar00lsteinlstein000000000000# Configuration for submitter plugin (used in above menu) [Submitter:plugin] submitter = [UCSC_BLAT] url = http://genome.ucsc.edu/cgi-bin/hgBlat seq_label = userSeq output = hyperlink type = DNA extra_html = Genome: [NCBI_BLAST] confirm = 1 url = http://www.ncbi.nlm.nih.gov/blast/Blast.cgi seq_label = QUERY PAGE = Nucleotides PROGRAM = blastn DATABASE = nr CLIENT = web CMD = put GBrowse-2.56/conf/volvox.conf000444001750001750 207613036764442 16301 0ustar00lsteinlstein000000000000[GENERAL] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $PERSISTENT/databases/volvox # just the basic track dumper plugin plugins = TrackDumper # list of tracks to turn on by default default features = ExampleFeatures # size of the region region segment = 10000 # examples to show in the introduction examples = ctgA # feature to show on startup initial landmark = ctgA:5000..10000 ######################## # Default glyph settings ######################## [TRACK DEFAULTS] glyph = generic height = 10 bgcolor = lightgrey fgcolor = black font2color = blue label density = 25 bump density = 100 # where to link to when user clicks in detailed view link = AUTO ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### [ExampleFeatures] feature = remark glyph = generic stranded = 1 bgcolor = blue height = 10 key = Example Features GBrowse-2.56/conf/yeast_chr1+2.conf000444001750001750 1644213036764442 17165 0ustar00lsteinlstein000000000000[GENERAL] description = Yeast chromosomes 1+2 (advanced) database = scaffolds initial landmark = chrI:143000..180000 # bring in the special Submitter plugin for the rubber-band select menu plugins = FastaDumper RestrictionAnnotator SequenceDumper TrackDumper Submitter autocomplete = 1 default tracks = Genes ORFs tRNAs CDS Transp Centro:overview GC:region # examples to show in the introduction examples = chrI chrII chrI:80,000..120,000 "membrane trafficking" NUT21 YAL063C # "automatic" classes to try when an unqualified identifier is given automatic classes = Symbol Gene Clone ################################# # database definitions ################################# [scaffolds:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_scaffolds search options = default +autocomplete [annotations:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_chr1+2 search options = default +autocomplete # Advanced feature: custom balloons custom balloons = [balloon] delayTime = 500 [balloon500] maxWidth = 500 delayTime = 50 # Advanced feature: an example of callbacks to be run remotely # by gbrowse_details for AJAX/iframe balloons [TOOLTIPS] intro = sub { my $args = shift; my $feat = $args->{feature}; my $name = $feat->display_name; my $type = $feat->primary_tag; my $class = $feat->class; my $extra = join(' ',$feat->each_tag_value('Note')) if $feat->has_tag('Note'); my $n = $type =~ /^[AEIOU]/i ? 'n' : ''; my $msg = "Hello, I am $name, a$n $type of class $class"; $msg .= "
    I am described as a $extra" if $extra; $msg .= "
    Click to see the sequence of $name"; return "" . "
    $name
    $msg
    "; } full_sequence = sub { my $args = shift; my $feat = $args->{feature}; my $name = $feat->display_name; my $seq = $feat->seq->seq; $seq =~ s/(\S{75})/$1\n/g; return "
    >$name\n$seq
    "; } # Advanced feature: # Pop up rubberband menus for submitting selected region to search engines... #include "detail_select_menu.conf" #include "submitter_plugin.conf" # Default glyph settings [TRACK DEFAULTS] glyph = generic database = annotations height = 8 bgcolor = cyan fgcolor = black label density = 25 bump density = 100 show summary = 99999 # go into summary mode when zoomed out to 100k # default pop-up balloon balloon hover = $name is a $type spanning $ref from $start to $end. Click for more details. ### TRACK CONFIGURATION #### # the remainder of the sections configure individual tracks [Centro:overview] feature = centromere bgcolor = blue glyph = dot fgcolor = black height = 8 point = 1 show summary = 0 # no summary of this one key = Centromeres [tRNA:overview] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 show summary = 0 # no summary of this one key = tRNAs [GC:region] glyph = dna global feature = 1 database = scaffolds height = 40 gc_window = auto do_gc = 1 strand = both fgcolor = red axis_color = blue show summary = 0 # no summary of this one key = GC Content [Genes] feature = gene glyph = segments bgcolor = yellow forwardcolor = yellow reversecolor = turquoise label = sub { my $f = shift; my $name = $f->display_name; my @aliases = sort $f->attributes('Alias'); $name .= " (@aliases)" if @aliases; $name; } height = 6 description = 0 balloon hover width = 350 balloon hover = sub { my $f = shift; return join ' ',$f->notes } balloon click width = 450 balloon click =

    This gene brought to you by SGD.
    Gene $name
    See gene details
    Ask SGD about $name
    Ask Wikipedia about $name
    Ask Google about $name
    key = Named gene [CDS] feature = gene glyph = cds description = 0 height = 26 sixframe = 1 label = sub {shift->name . " reading frame"} key = CDS balloon click width = 500 balloon hover width = 350 balloon hover = $name is a $type spanning $ref from $start to $end. Click to search Google for $name. balloon click = http://www.google.com/search?q=$name citation = This track shows CDS reading frames. [tRNAs] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 # Note: AJAX balloons -- edit the URL if your copy of gbrowse_details is not in /gb2 balloon hover = url:../../gbrowse_details/yeast_advanced?name=$name;class=$class;remote=intro balloon click = url:../../gbrowse_details/yeast_advanced?name=$name;class=$class;remote=full_sequence key = tRNAs [Transp] feature = LTR_retrotransposon glyph = segments bgcolor = yellow fgcolor = black height = 5 stranded = 1 balloon width = 375 key = Transposons [LTRs] feature = long_terminal_repeat fgcolor = black glyph = anchored_arrow height = 6 balloon width = 375 key = Long Terminal Repeats [Translation] glyph = translation global feature = 1 database = scaffolds height = 40 fgcolor = purple strand = +1 translation = 6frame key = 6-frame translation [TranslationF] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = purple strand = +1 translation = 3frame key = 3-frame translation (forward) [DNA/GC Content] glyph = dna global feature = 1 database = scaffolds height = 40 do_gc = 1 gc_window = auto strand = both fgcolor = red axis_color = blue [TranslationR] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = blue strand = -1 translation = 3frame key = 3-frame translation (reverse) [ncRNA] feature = RNAd rRNA:sgd snRNA:sgd snoRNA:sgd fgcolor = orange glyph = generic description = 1 key = Noncoding RNAs GBrowse-2.56/conf/yeast_renderfarm.conf000444001750001750 1617713036764442 20325 0ustar00lsteinlstein000000000000[GENERAL] description = Yeast 1+2 via renderfarm database = scaffolds # turn on remote rendering-- see [TRACK DEFAULTS] for the hosts # and ports the rendering slaves run on. renderfarm = 1 initial landmark = chrI:143000..180000 plugins = Aligner RestrictionAnnotator BatchDumper TrackDumper autocomplete = 1 default tracks = Genes ORFs tRNAs CDS Transp Centro:overview GC:region # examples to show in the introduction examples = chrI chrII chrI:80,000..120,000 "membrane trafficking" NUT21 YAL063C # "automatic" classes to try when an unqualified identifier is given automatic classes = Symbol Gene Clone ################################# # database definitions ################################# [scaffolds:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_scaffolds search options = default +autocomplete [annotations:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_chr1+2 search options = default +autocomplete # Advanced feature: custom balloons custom balloons = [balloon] delayTime = 500 [balloon500] maxWidth = 500 delayTime = 50 # Advanced feature: an example of callbacks to be run remotely # by gbrowse_details for AJAX/iframe balloons [TOOLTIPS] intro = sub { my $args = shift; my $feat = $args->{feature}; my $name = $feat->display_name; my $type = $feat->primary_tag; my $class = $feat->class; my $extra = join(' ',$feat->each_tag_value('Note')) if $feat->has_tag('Note'); my $n = $type =~ /^[AEIOU]/i ? 'n' : ''; my $msg = "Hello, I am $name, a$n $type of class $class"; $msg .= "
    I am described as a $extra" if $extra; $msg .= "
    Click to see the sequence of $name"; return "" . "
    $name
    $msg
    "; } full_sequence = sub { my $args = shift; my $feat = $args->{feature}; my $name = $feat->display_name; my $seq = $feat->seq->seq; $seq =~ s/(\S{75})/$1\n/g; return "
    >$name\n$seq
    "; } # Advanced feature: # Pop up rubberband menus for submitting selected region to search engines... #include "detail_select_menu.conf" #include "submitter_plugin.conf" # Default glyph settings [TRACK DEFAULTS] remote renderer = http://localhost:8101 http://localhost:8102 http://localhost:8103 database = annotations glyph = generic height = 8 bgcolor = cyan fgcolor = black label density = 25 bump density = 100 # default pop-up balloon balloon hover = $name is a $type spanning $ref from $start to $end. Click for more details. ### TRACK CONFIGURATION #### # the remainder of the sections configure individual tracks [Centro:overview] feature = centromere bgcolor = blue glyph = dot fgcolor = black height = 8 point = 1 key = Centromeres [tRNA:overview] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 key = tRNAs [GC:region] glyph = dna global feature = 1 database = scaffolds height = 40 gc_window = auto do_gc = 1 strand = both fgcolor = red axis_color = blue key = GC Content [Genes] feature = gene glyph = gene bgcolor = yellow forwardcolor = yellow reversecolor = turquoise label = sub { my $f = shift; my $name = $f->display_name; my @aliases = $f->attributes('Alias'); $name .= " (@aliases)" if @aliases; $name; } height = 6 description = 0 balloon hover width = 350 balloon hover = sub { my $f = shift; return join ' ',$f->notes } balloon click width = 450 balloon click =

    This gene brought to you by SGD.
    Gene $name
    See gene details
    Ask SGD about $name
    Ask Wikipedia about $name
    Ask Google about $name
    key = Named gene [CDS] feature = gene glyph = cds description = 0 height = 26 sixframe = 1 label = sub {shift->name . " reading frame"} key = CDS balloon click width = 500 balloon hover width = 350 balloon hover = $name is a $type spanning $ref from $start to $end. Click to search Google for $name. balloon click = http://www.google.com/search?q=$name citation = This track shows CDS reading frames. [tRNAs] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 # Note: AJAX balloons -- edit the URL if your copy of gbrowse_details is not in /gb2 balloon hover = url:../../gbrowse_details/yeast_advanced?name=$name;class=$class;remote=intro balloon click = url:../../gbrowse_details/yeast_advanced?name=$name;class=$class;remote=full_sequence key = tRNAs [Transp] feature = LTR_retrotransposon glyph = segments bgcolor = yellow fgcolor = black height = 5 stranded = 1 balloon width = 375 key = Transposons [LTRs] feature = long_terminal_repeat fgcolor = black glyph = anchored_arrow height = 6 balloon width = 375 key = Long Terminal Repeats [Translation] glyph = translation global feature = 1 database = scaffolds height = 40 fgcolor = purple strand = +1 translation = 6frame key = 6-frame translation [TranslationF] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = purple strand = +1 translation = 3frame key = 3-frame translation (forward) [DNA/GC Content] glyph = dna global feature = 1 database = scaffolds height = 40 do_gc = 1 gc_window = auto strand = both fgcolor = red axis_color = blue [TranslationR] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = blue strand = -1 translation = 3frame key = 3-frame translation (reverse) [ncRNA] feature = RNAd rRNA:sgd snRNA:sgd snoRNA:sgd fgcolor = orange glyph = generic description = 1 key = Noncoding RNAs GBrowse-2.56/conf/yeast_simple.conf000444001750001750 1014213036764442 17453 0ustar00lsteinlstein000000000000[GENERAL] description = Yeast chromosomes 1+2 (basic) database = scaffolds initial landmark = chrI:143000..180000 plugins = FilterTest RestrictionAnnotator TrackDumper FastaDumper autocomplete = 1 default tracks = Genes ORFs tRNAs CDS Transp Centro:overview GC:region # examples to show in the introduction examples = chrI chrII chrI:80,000..120,000 "membrane trafficking" NUT21 YAL063C # "automatic" classes to try when an unqualified identifier is given automatic classes = Symbol Gene Clone ################################# # database definitions ################################# [scaffolds:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_scaffolds search options = default +autocomplete [annotations:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/yeast_chr1+2 search options = default +autocomplete # Default glyph settings [TRACK DEFAULTS] glyph = generic database = annotations height = 8 bgcolor = cyan fgcolor = black label density = 25 bump density = 100 show summary = 99999 # go into summary mode when zoomed out to 100k ### TRACK CONFIGURATION #### # the remainder of the sections configure individual tracks [Centro:overview] feature = centromere bgcolor = blue glyph = dot fgcolor = black height = 8 point = 1 show summary = 0 # no summary of this one key = Centromeres [tRNA:overview] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 show summary = 0 # no summary of this one key = tRNAs [GC:region] glyph = dna global feature = 1 database = scaffolds height = 40 gc_window = auto do_gc = 1 strand = both fgcolor = red axis_color = blue show summary = 0 # no summary of this one key = GC Content [Genes] feature = gene glyph = gene bgcolor = yellow forwardcolor = yellow reversecolor = turquoise label = sub { my $f = shift; my $name = $f->display_name; my @aliases = sort $f->attributes('Alias'); $name .= " (@aliases)" if @aliases; $name; } height = 6 description = 0 key = Named gene [CDS] feature = gene glyph = cds description = 0 height = 26 sixframe = 1 label = sub {shift->name . " reading frame"} key = CDS citation = This track shows CDS reading frames. [tRNAs] feature = tRNA glyph = generic bgcolor = lightgray fgcolor = black height = 4 stranded = 1 description = 1 key = tRNAs [Transp] feature = LTR_retrotransposon glyph = segments bgcolor = yellow fgcolor = black height = 5 stranded = 1 key = Transposons [LTRs] feature = long_terminal_repeat fgcolor = black glyph = anchored_arrow height = 6 key = Long Terminal Repeats [Translation] glyph = translation global feature = 1 database = scaffolds height = 40 fgcolor = purple strand = +1 translation = 6frame key = 6-frame translation [TranslationF] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = purple strand = +1 translation = 3frame key = 3-frame translation (forward) [DNA/GC Content] glyph = dna global feature = 1 database = scaffolds height = 40 do_gc = 1 gc_window = auto strand = both fgcolor = red axis_color = blue [TranslationR] glyph = translation global feature = 1 database = scaffolds height = 20 fgcolor = blue strand = -1 translation = 3frame key = 3-frame translation (reverse) [ncRNA] feature = RNAd rRNA:sgd snRNA:sgd snoRNA:sgd fgcolor = orange glyph = generic description = 1 key = Noncoding RNAs GBrowse-2.56/conf/MobyServices000755001750001750 013036764442 16345 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/MobyServices/GbrowseServices.PMS000444001750001750 5755213036764442 22235 0ustar00lsteinlstein000000000000#!perl use Config; use File::Basename qw(&basename &dirname); use File::Spec; use FindBin '$Bin'; use Cwd; my %OPTIONS; if (open F,"$Bin/../../GGB.def") { while () { next if /^\#/; chomp; $OPTIONS{$1} = $2 if /^(\w+)\s*=\s*(.+)/; } close F; } $OPTIONS{CONF} ||= '/usr/local/apache/conf'; my $dir = dirname($0); $file = shift || File::Spec->catfile($dir,basename($0, '.PMS')); open OUT,">$file" or die "Can't create $file: $!"; print "Extracting $file (with variable substitutions)\n"; my $startperl = $Config{startperl} ne '#!perl' ? $Config{startperl} : "#!$Config{perlpath}"; print OUT <<"!GROK!THIS!"; $startperl -w package MobyServices::GbrowseServices; ################################################################### # Non-modperl users should change this variable if needed to point # to the directory in which the configuration files are stored. # \$CONF_DIR = '$OPTIONS{CONF}/gbrowse.conf'; # ################################################################### !GROK!THIS! # In the following, perl variables are not expanded during extraction. print OUT <<'!NO!SUBS!'; #==================================================================== #$Id: GbrowseServices.PMS,v 1.2 2004-01-07 22:21:49 markwilkinson Exp $ use strict; use Text::Shellwords; use Bio::DB::GFF; use SOAP::Lite; use MOBY::CommonSubs qw{:all}; use Bio::Graphics::Browser; use Bio::Graphics::Browser::Util; use vars qw(%dbh $CONFIG $authURI $CONF_DIR); sub _settings { $CONF_DIR = conf_dir($CONF_DIR); # conf_dir() is exported from Util.pm ## CONFIGURATION & INITIALIZATION ################################ # preliminaries -- read and/or refresh the configuration directory $CONFIG = open_config($CONF_DIR); # open_config() is exported from Util.pm my @sources = $CONFIG->sources; # get all data sources foreach (@sources){ # grab the database handle for each source $CONFIG->source($_); my $db = open_database($CONFIG); $dbh{$_}=$db; } open (IN, "$CONF_DIR/MobyServices/moby.conf") || die "\n**** GbrowseServices.pm couldn't open configuration file $CONF_DIR/MobyServices/moby.conf: $!\n"; while (){ chomp; next unless $_; # filter out blank lines next if m/^#/; # filter out comment lines last if $_ =~ /\[Namespace_Class_Mappings\]/; my @res = shellwords($_); # parse the tokens key = value1 value2 value3 $CONFIG->{MOBY}->{$res[0]} = [@res[2..scalar(@res)]]; # add them to the existing config with a new tag MOBY in key = \@values format } while (){ # now process the namespace mappings chomp; next unless $_; # filter out blank lines next if m/^#/; # filter out comment lines my @res = shellwords($_); # parse the tokens key = value1 value2 value3 $CONFIG->{'MOBY'}->{'NAMESPACE'}->{$res[0]} = [$res[2]]; # add them to the existing config with a new tag MOBY in key = \@values format } } sub _doValidationStuff { my $authURI = $CONFIG->{'MOBY'}->{'authURI'}; $authURI = shift(@$authURI); $authURI ||='unknown.org'; my $reference = $CONFIG->{'MOBY'}->{'Reference'}; $reference = shift(@$reference); $reference ||=''; unless ($reference){ print STDERR "\n\nMobyServices::GbrowseServices - you have not set a reference class in your moby.conf file\n\n"; return SOAP::Data->type('base64' => responseHeader($authURI) . responseFooter()); } my (@feat_namespaces) = keys %{$CONFIG->{MOBY}->{NAMESPACE}}; my @validNS = validateNamespaces($reference,@feat_namespaces); # ONLY do this if you are intending to be namespace aware! unless (scalar(@validNS)){ print STDERR "\n\nMobyServices::GbrowseServices - namespace $reference does not exist in the MOBY Namespace ontology\n\n"; return SOAP::Data->type('base64' => responseHeader($authURI) . responseFooter()); } return ($authURI, \@validNS); } sub GbrowseGetFeatureGFF2 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); my $gff = ""; foreach my $feat(@features){ (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; $gff .= $feat->gff_string."\n"; foreach my $sub($feat->sub_SeqFeature){ next unless $sub; $gff .= $sub->gff_string."\n"; } } $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetFeatureGFF3 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); my $gff = ""; foreach my $feat(@features){ $feat->version(3); # set to GFF3 (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; $gff .= $feat->gff_string."\n"; foreach my $sub($feat->sub_SeqFeature){ next unless $sub; $sub->version(3); $gff .= $sub->gff_string."\n"; } } $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetFeatureSequenceObject { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; # send empty response for empty input next; } else { my $namespace = getSimpleArticleNamespaceURI($input); # get the namespace $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); #invalid namespace treated as empty query my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; # map the namespace to our database group name unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; # if it is invlid, send empty respnse and tell the maintainer that something is goofy! print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); # get feature from DB my $gff = ""; foreach my $feat(@features){ $feat->version(3); # set to GFF3 (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; my $seq = $feat->seq; $seq =~ s/\s//g; my $length = $feat->length; my $objtype = $types{$feat->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceGFF2 { # DO THIS ONE!! my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $gff = join "\n", map {$_->gff_string} ($seg->get_SeqFeatures); $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceDNASequenceWithFeatures { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\S//g; my $length = $seg->length; # DNASequenceWithGFFFeatures my $mobyresp = " $seq $length "; foreach my $feat($seg->get_SeqFeatures){$mobyresp .=" " } my $gff = join "\n", map {$_->gff_string} ($seg->get_SeqFeatures); $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceGFF3 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $gff = join "\n", map {$_->version(3); $_->gff_string} ($seg->get_SeqFeatures); my $seq = $seg->seq; $seq =~ s/\s//g; $seq =~ s/(\S{70})/$1\n/g; my $fasta = ">$identifier\n$seq\n"; $MOBY_RESPONSE .= simpleResponse("\n$gff\n###FASTA\n$fasta\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceFasta { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; $seq =~ s/(\S{70})/$1\n/g; my $fasta = ">$identifier\n$seq\n"; $MOBY_RESPONSE .= simpleResponse("\n$fasta\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceSeqObj { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; my $length = $seg->length; my $objtype = $types{$seg->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetSomeFeatureSequence { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; my $length = $seg->length; my $objtype = $types{$seg->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } 1; #=========================================== !NO!SUBS! close OUT or die "Can't close $file: $!"; chmod 0755, $file or die "Can't reset permissions for $file: $!\n"; exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':'; GBrowse-2.56/conf/MobyServices/GbrowseServices.pm000444001750001750 5570613036764442 22211 0ustar00lsteinlstein000000000000#!/usr/bin/perl -w package MobyServices::GbrowseServices; ################################################################### # Non-modperl users should change this variable if needed to point # to the directory in which the configuration files are stored. # $CONF_DIR = '/usr/local/apache/conf/gbrowse.conf'; # ################################################################### #==================================================================== #$Id: GbrowseServices.pm,v 1.7 2008-10-03 19:35:27 lstein Exp $ use strict; use Text::Shellwords; use Bio::DB::GFF; use SOAP::Lite; use MOBY::CommonSubs qw{:all}; use Bio::Graphics::Browser; use Bio::Graphics::Browser::Util; use vars qw(%dbh $CONFIG $authURI $CONF_DIR); sub _settings { $CONF_DIR = conf_dir($CONF_DIR); # conf_dir() is exported from Util.pm ## CONFIGURATION & INITIALIZATION ################################ # preliminaries -- read and/or refresh the configuration directory $CONFIG = open_config($CONF_DIR); # open_config() is exported from Util.pm my @sources = $CONFIG->sources; # get all data sources foreach (@sources){ # grab the database handle for each source $CONFIG->source($_); my $db = open_database($CONFIG); $dbh{$_}=$db; } open (IN, "$CONF_DIR/MobyServices/moby.conf") || die "\n**** GbrowseServices.pm couldn't open configuration file $CONF_DIR/MobyServices/moby.conf: $!\n"; while (){ chomp; next unless $_; # filter out blank lines next if m/^#/; # filter out comment lines last if $_ =~ /\[Namespace_Class_Mappings\]/; my @res = shellwords($_); # parse the tokens key = value1 value2 value3 $CONFIG->{MOBY}->{$res[0]} = [@res[2..scalar(@res)]]; # add them to the existing config with a new tag MOBY in key = \@values format } while (){ # now process the namespace mappings chomp; next unless $_; # filter out blank lines next if m/^#/; # filter out comment lines my @res = shellwords($_); # parse the tokens key = value1 value2 value3 $CONFIG->{'MOBY'}->{'NAMESPACE'}->{$res[0]} = [$res[2]]; # add them to the existing config with a new tag MOBY in key = \@values format } } sub _doValidationStuff { my $authURI = $CONFIG->{'MOBY'}->{'authURI'}; $authURI = shift(@$authURI); $authURI ||='unknown.org'; my $reference = $CONFIG->{'MOBY'}->{'Reference'}; $reference = shift(@$reference); $reference ||=''; unless ($reference){ print STDERR "\n\nMobyServices::GbrowseServices - you have not set a reference class in your moby.conf file\n\n"; return SOAP::Data->type('base64' => responseHeader($authURI) . responseFooter()); } my (@feat_namespaces) = keys %{$CONFIG->{MOBY}->{NAMESPACE}}; my @validNS = validateNamespaces($reference,@feat_namespaces); # ONLY do this if you are intending to be namespace aware! unless (scalar(@validNS)){ print STDERR "\n\nMobyServices::GbrowseServices - namespace $reference does not exist in the MOBY Namespace ontology\n\n"; return SOAP::Data->type('base64' => responseHeader($authURI) . responseFooter()); } return ($authURI, \@validNS); } sub GbrowseGetFeatureGFF2 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); my $gff = ""; foreach my $feat(@features){ (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; $gff .= $feat->gff_string."\n"; foreach my $sub($feat->sub_SeqFeature){ next unless $sub; $gff .= $sub->gff_string."\n"; } } $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetFeatureGFF3 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); my $gff = ""; foreach my $feat(@features){ $feat->version(3); # set to GFF3 (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; $gff .= $feat->gff_string."\n"; foreach my $sub($feat->sub_SeqFeature){ next unless $sub; $sub->version(3); $gff .= $sub->gff_string."\n"; } } $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetFeatureSequenceObject { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; # send empty response for empty input next; } else { my $namespace = getSimpleArticleNamespaceURI($input); # get the namespace $namespace ||=""; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); #invalid namespace treated as empty query my ($identifier) = getSimpleArticleIDs($input); # note array output! # okay, we need to map the MOBY namespace back into our namespace system my $Groupname = $CONFIG->{MOBY}->{NAMESPACE}->{$namespace}; # map the namespace to our database group name unless ($Groupname){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; # if it is invlid, send empty respnse and tell the maintainer that something is goofy! print STDERR "** MOBY Services error - Trying to map apparently valid namespace: '$namespace' but not found\n"; next; } my @features = $db->get_feature_by_name(-class => $Groupname, -name => $identifier); # get feature from DB my $gff = ""; foreach my $feat(@features){ $feat->version(3); # set to GFF3 (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $feat; my $seq = $feat->seq; $seq =~ s/\s//g; my $length = $feat->length; my $objtype = $types{$feat->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceGFF2 { # DO THIS ONE!! my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $gff = join "\n", map {$_->gff_string} ($seg->get_SeqFeatures); $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceDNASequenceWithFeatures { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\S//g; my $length = $seg->length; # DNASequenceWithGFFFeatures my $mobyresp = " $seq $length "; foreach my $feat($seg->get_SeqFeatures){$mobyresp .=" " } my $gff = join "\n", map {$_->gff_string} ($seg->get_SeqFeatures); $MOBY_RESPONSE .= simpleResponse("\n$gff\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceGFF3 { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $gff = join "\n", map {$_->version(3); $_->gff_string} ($seg->get_SeqFeatures); my $seq = $seg->seq; $seq =~ s/\s//g; $seq =~ s/(\S{70})/$1\n/g; my $fasta = ">$identifier\n$seq\n"; $MOBY_RESPONSE .= simpleResponse("\n$gff\n###FASTA\n$fasta\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceFasta { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my $MOBY_RESPONSE; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; $seq =~ s/(\S{70})/$1\n/g; my $fasta = ">$identifier\n$seq\n"; $MOBY_RESPONSE .= simpleResponse("\n$fasta\n", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetReferenceSeqObj { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; my $length = $seg->length; my $objtype = $types{$seg->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } sub GbrowseGetSomeFeatureSequence { my ($caller, $data) = @_; _settings(); my ($authURI, $validNSs) = _doValidationStuff(); my %types = ('dna', 'DNASequence', 'rna', 'RNASequence', 'protein', 'AminoAcidSequence'); my $MOBY_RESPONSE = ""; foreach my $source($CONFIG->sources){ $CONFIG->source($source); # set the current source next unless (my $db = $dbh{$source}); # get the database object my (@inputs)= genericServiceInputParser($data); # ([SIMPLE, $queryID, $simple],...) next unless (scalar(@inputs)); foreach (@inputs){ my ($articleType, $qID, $input) = @{$_}; unless (($articleType == SIMPLE) && ($input)){ $MOBY_RESPONSE .= simpleResponse("", "", $qID) ; next; } else { my $namespace = getSimpleArticleNamespaceURI($input); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless validateThisNamespace($namespace, @{$validNSs}); my ($identifier) = getSimpleArticleIDs($input); # note array output! my $seg = $db->segment(-name => $identifier); (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $seg; my $seq = $seg->seq; $seq =~ s/\s//g; my $length = $seg->length; my $objtype = $types{$seg->alphabet}; (($MOBY_RESPONSE .= simpleResponse("", "", $qID)) && next) unless $objtype; $MOBY_RESPONSE .= simpleResponse(" $seq $length ", "", $qID); } } } #print STDERR (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter); return SOAP::Data->type('base64' => (responseHeader($authURI) . $MOBY_RESPONSE . responseFooter)); } 1; #=========================================== GBrowse-2.56/conf/MobyServices/b64_encoded_gif_renderer.pm000444001750001750 623213036764442 23632 0ustar00lsteinlstein000000000000package MobyServices::b64_encoded_gif_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); use File::Temp qw/ tempfile /; our @EXPORT_OK = qw(render type); use MIME::Base64; sub types { return ["b64_encoded_gif"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content; $content = &getStringContent($DOM); $content =~ s/^\s+//; $content =~ s/\s+$//; my $bindata = decode_base64($content); my ($fh, $filename) = tempfile( DIR => "$htmldir/$imgdir/", SUFFIX=> ".gif" ); $filename =~ /(\w+\.gif)$/; $filename = $1; binmode($fh); print $fh $bindata; close $fh; return (""); } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless ($_->localname eq "String"); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME b64_encoded_gif_renderer.pm - a renderer (HTML) for b64_encoded_gif type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a b64_encoded_gif (or ontological child of) object. =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::DOM object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/MobyServices/b64_encoded_jpeg_renderer.pm000444001750001750 624213036764442 24013 0ustar00lsteinlstein000000000000package MobyServices::b64_encoded_jpeg_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); use File::Temp qw/ tempfile /; our @EXPORT_OK = qw(render type); use MIME::Base64; sub types { return ["b64_encoded_jpeg"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content; $content = &getStringContent($DOM); $content =~ s/^\s+//; $content =~ s/\s+$//; my $bindata = decode_base64($content); my ($fh, $filename) = tempfile( DIR => "$htmldir/$imgdir/", SUFFIX=> ".jpg" ); $filename =~ /(\w+\.jpg)$/; $filename = $1; binmode($fh); print $fh $bindata; close $fh; return (""); } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless ($_->localname eq "String"); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME b64_encoded_jpeg_renderer.pm - a renderer (HTML) for b64_encoded_jpeg type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a b64_encoded_jpeg (or ontological child of) object. =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::DOM object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/MobyServices/moby.conf000444001750001750 346013036764442 20322 0ustar00lsteinlstein000000000000# "Reference" referrs to the Reference Class (usually "Sequence") that # is the top-level feature in the feature hierarchy. You must enter # the MOBY Namespace acting as an identifiers for these entries. # For example, if the database FREF column for a DNA record refers to # its EMBL accession then your moby namespace is "EMBL" # for a current list of all valid MOBY namespaces browse to: # http://mobycentral.cbr.nrc.ca/cgi-bin/types/Namespaces # # e.g. Reference = EMBL # # (for the demonstration Yeast database # use Reference = SGD_CHROMOSOME_ID) Reference = EMBL # your authURI is some URN that identifies you as a service provider # it can be anything unique to your hostname (e.g. your hostname!) # # e.g. authURI = your.domain.com authURI = # your contactEmail is some email address that will be associated with # any services, objects, namespaces, etc. that you register in # the MOBY Central web service registry. # # e.g. contactEmail = yourname@your.domain.com contactEmail = # your CGI_URL is the URL representing your servername and path to the # cgi-bin (or equivalent) folder into which you are installing # the gbrowse executables. # # e.g. CGI_URL = 'http://your.domain.com/cgi-bin/' CGI_URL = [Namespace_Class_Mappings] # the rest of this file simply maps MOBY Namespaces to the names # that you use internally in your database. For example, things that # you call "Gene", may correspond to Flybase genes, or Yeast genes, or # some other gene, so you must specify exactly the MOBY Namespace # (data type) you are referring to so that services can find you when # they have the proper identifier in-hand. # the format of this section is simply: # # MOBY_Namespace = GFF Groupname ('Class') # # e.g.: (these mappings are appropriate for the demonstration yeast DB) # # SGD_LOCUS = Gene # SGD_ORF = ORF GBrowse-2.56/conf/MobyServices/text_formatted_renderer.pm000444001750001750 616713036764442 23771 0ustar00lsteinlstein000000000000package MobyServices::text_formatted_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); our @EXPORT_OK = qw(render type); sub types { return ["text-formatted"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content=""; $content = &getStringContent($DOM); return ("
    ") unless $content;
    
        if ($content =~ /(\S{100})/){
    	    $content =~ s/(\S{100})/$1\/g;
        }
        if ($content =~ /\S/){
            return ("
    $content
    "); } else { return (" ", ); } } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless (($_->localname eq "String") || ($_->localname eq "Integer") || ($_->localname eq "DateTime") || ($_->localname eq "Float")); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME text_formatted_renderer.pm - a renderer (HTML) for text-formatted type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a text-formatted (or ontological child of) object. =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::DOM object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/MobyServices/text_html_renderer.pm000444001750001750 562313036764442 22744 0ustar00lsteinlstein000000000000package MobyServices::text_html_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); our @EXPORT_OK = qw(render type); sub types { return ["text-html"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content; $content = &getStringContent($DOM); $content =~ s/(\S{100})/$1\/g; return ("$content");# the 0 indicates that we have only rendered the top-level XML of this object } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless ($_->localname eq "String"); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME text_html_renderer.pm - a renderer (HTML) for text_html type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a text_html (or ontological child of) object. =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::DOM object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/MobyServices/text_plain_renderer.pm000444001750001750 731713036764442 23105 0ustar00lsteinlstein000000000000package MobyServices::text_plain_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); our @EXPORT_OK = qw(render type); sub types { return ["text-plain", "String", "Integer", "DateTime", "Float"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content = ""; my (%union, %isect); foreach my $e ($DOM->localname, ("String", "Integer", "DateTime", "Float")) { $union{$e}++ && $isect{$e}++ }; # get intersection of nodename and list of primitive nodes we can handle if (keys %isect){ # if the incoming node is one of the primitives keys will return something foreach my $subnode($DOM->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } } else { $content = &getStringContent($DOM); $content =~ s/^\s+//; $content =~ s/\s$//; # get rid of leading and trailing spaces since they are meaningless in a plaintext object } return ("$content");# the 0 indicates that we have only rendered the top-level XML of this object } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless (($_->localname eq "String") || ($_->localname eq "Integer") || ($_->localname eq "DateTime") || ($_->localname eq "Float")); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME text_plain_renderer.pm - a renderer (HTML) for text_plain type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a text_plain (or ontological child of) object. =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::DOM object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/MobyServices/text_xml_renderer.pm000444001750001750 636213036764442 22601 0ustar00lsteinlstein000000000000package MobyServices::text_xml_renderer; use strict; use XML::LibXML; use MOBY::MobyXMLConstants; our @ISA = qw(Exporter); our @EXPORT_OK = qw(render type); sub types { return ["text-xml"]; } sub render { my ($DOM, $htmldir,$imgdir) = @_; my $content; $content = &getStringContent($DOM); $content =~ s/]+)>/<$1>/g; # mask '>' and '<' in tags return ("
    $content
    ");# the 0 indicates that we have only rendered the top-level XML of this object } sub getStringContent { my ($ROOT) = @_; my $content; my @childnodes = $ROOT->childNodes; foreach (@childnodes){ next unless ($_->nodeType == ELEMENT_NODE); next unless ($_->localname eq "String"); my $article = $_->getAttributeNode('articleName'); $article = $_->getAttributeNode('moby:articleName') unless $article; next unless $article; next unless $article->getValue eq 'content'; # the articleName for String content of a text-xml node foreach my $subnode($_->childNodes){ # if it is correct, then get the text content next unless (($subnode->nodeType == TEXT_NODE) || ($subnode->nodeType == CDATA_SECTION_NODE)); $content .=$subnode->textContent; } $ROOT->removeChild($_); last; } return $content; } 1; =head1 NAME text_xml_renderer.pm - a renderer (HTML) for text_xml type MOBY Objects =head1 AUTHOR Please report all bugs to Mark Wilkinson (markw at illuminae.com) =head1 SYNOPSIS just put the renderer in your gbrowse.conf/MobyServices folder and it will work. =head1 DESCRIPTION This renderer returns HTML that fits between the tags in a web-page to display the content of a text_xml (or ontological child of) object. Without the renderer your browser will ignore the tags which are not part of the HTML specification. In consequence the xml document structure, element names and attributes/values will be invisible in the result output - which is probably not what you would expect... =head1 METHODS The module has two methods: =over =item type this returns a scalar indicating the MOBY Object Class that this renderer is designed to handle. Objects of this type, or objects that inherit from this type, will be passed to this renderer. =item render This is called with three pieces of data which may or may not be useful to your script: =over =item 1) $data - an XML::LibXML object representing the deserialized MOBY object =item 2) $htmldir - the full path to the directory serving your html e.g. /usr/local/apache/htdocs/ (this is the HTDOCS parameter you specified when you installed Gbrowse) =item 3) $imgdir - the additional path information to a writable directory for images e.g. /gbrowse/tmp (this is the folder specified in the tmpimages parameter in your organism.conf file) =back =back =head1 RETURNS The subroutine should return two pieces of data: =over =item 1) An HTML representation of the Object this will appear between tags in the webpage =item 2) A boolean indicating whether the renderer has parsed all sub-objects, or just the top level object '1' indicates that the renderer has fully parsed the Object XML '0' indicates that you need Gbrowse to follow child objects and render them independently =back =cut GBrowse-2.56/conf/languages000755001750001750 013036764442 15701 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/languages/POSIX.pm000444001750001750 7113713036764442 17327 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => <Search using a sequence name, gene name, locus%s, or other landmark. The wildcard character * is allowed. END NAVIGATION_INSTRUCTIONS => <Navigate by clicking one of the rulers to center on a location, or click and drag to select a region. Use the Scroll/Zoom buttons to change magnification and position. END EDIT_INSTRUCTIONS => < '%s from %s:%s..%s', CURRENTLY_SHOWING => '(Currently showing %s)', INSTRUCTIONS => 'Instructions', HIDE => 'Hide', FILE => 'File', SHOW => 'Show', SHOW_HEADER => 'Show banner', HIDE_HEADER => 'Hide banner', LANDMARK => 'Landmark or Region', BOOKMARK => 'Bookmark this', CHROM_SIZES => 'Get chrom sizes', EXPORT => 'Export as...', IMAGE_LINK => '...low-res PNG image', SVG_LINK => '...editable SVG image', PDF_LINK => '...high-res PDF', DUMP_GFF => '...GFF annotation table', DUMP_SEQ => '...FASTA sequence file', FILTER => 'Filter', TIMEOUT => <<'END', Your request timed out. You may have selected a region that is too large to display. Either turn off some tracks or try a smaller region. If you are experiencing persistent timeouts, please press the red "Reset" button. END GO => 'Go', FIND => 'Find', SEARCH => 'Search', DUMP => 'Download', HIGHLIGHT => 'Highlight', ANNOTATE => 'Annotate', SCROLL => 'Scroll/Zoom', RESET => 'Reset to defaults', FLIP => 'Flip', DOWNLOAD_FILE => 'Download File', DOWNLOAD => 'Download', DISPLAY_SETTINGS => 'Display Settings', TRACKS => 'Tracks', # FAVORITE MENU LINKS FAVORITES => 'Show Favorites Only', SHOWALL => 'Show Favorites and Others', SHOW_ACTIVE => 'Show Active Tracks Only', SHOW_ACTIVE_INACTIVE => 'Show Active & Inactive Tracks', REFRESH_FAV => 'Refresh Favorites', CLEAR_FAV => 'Clear All Favorites', SHOW_ACTIVE_TRACKS => 'Show Active Tracks Only', ADDED_TO => 'Add track to favorites', ############# SNAPSHOT_FORM => 'Snapshot Name', CURRENT_SNAPSHOT => 'Current Snapshot:', TIMESTAMP => 'Snapshot Timestamp [GMT]', SNAPSHOT_SELECT => 'Snapshots', SAVE_SNAPSHOT => 'Save Snapshot', LOAD_SNAPSHOT => 'Load Snapshot', SELECT_TRACKS => 'Select Tracks', TRACK_SELECT => 'Search for Specific Tracks', TRACK_NAME => 'Track name', EXTERNAL_TRACKS => 'External tracks italicized', OVERVIEW_TRACKS => '*Overview track', REGION_TRACKS => '**Region track', EXAMPLES => 'Examples', REGION_SIZE => 'Region Size (bp)', HELP => 'Help', HELP_WITH_BROWSER => 'Help with this browser', HELP_FORMAT_UPLOAD => 'Help with uploading custom tracks', CANCEL => 'Cancel', ABOUT => 'About GBrowse...', ABOUT_DSN => 'About this database...', ABOUT_ME => 'Show my user ID...', ABOUT_NAME => 'About %s...', REDISPLAY => 'Redisplay', CONFIGURE => 'Configure...', SUBTRACK_INSTRUCTIONS => 'Select the tracks you wish to display. Sort the tracks by clicking on the column headings, or by clicking and dragging rows into position.', SELECT_SUBTRACKS => 'showing %d/%d subtracks', TRACK_ID => 'Track ID=%s', EDIT => 'Edit File...', DELETE => 'Delete File', EDIT_TITLE => 'Enter/Edit Annotation data', IMAGE_WIDTH => 'Image Width', BETWEEN => 'Between', BENEATH => 'Beneath', LEFT => 'Left', RIGHT => 'Right', TRACK_NAMES => 'Track Name Table', ALPHABETIC => 'Alphabetic', VARYING => 'Varying', SHOW_GRID => 'Show grid', SET_OPTIONS => 'Configure tracks...', CLEAR_HIGHLIGHTING => 'Clear highlighting', CLEAR => 'Clear', UPDATE => 'Update', UPDATE_SETTINGS => 'Update Appearance', DUMPS => 'Reports & Analysis', DATA_SOURCE => 'Data Source', UPLOADED_TRACKS => 'Custom Tracks', UPLOAD_TITLE=> 'Upload your own data', UPLOAD_FILE => 'Upload a track file', MIRROR_FILE => 'Fetch track file from this URL', IMPORT_TRACK => 'Import a track URL', NEW_TRACK => 'Create a new track', FROM_TEXT => 'From text', FROM_FILE => 'From a file', FROM_URL => 'From a URL', REMOVE => 'Remove', KEY_POSITION => 'Key position', UPLOAD => 'Upload', IMPORT => 'Import', MIRROR => 'Mirror', NEW => 'New...', REMOTE_TITLE => 'Add remote annotations', #ipad IPAD_BALLOON => '\nTap feature again to see more details', # REMOTE_URL => 'Enter remote track URL', UPDATE_URLS => 'Update', PRESETS => '--Choose Preset URL--', FEATURES_TO_HIGHLIGHT => 'Highlight feature(s) (feature1 feature2...)', REGIONS_TO_HIGHLIGHT => 'Highlight regions (region1:start..end region2:start..end)', FEATURES_TO_HIGHLIGHT_HINT => 'Hint: use feature@color to select the color, as in \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Hint: use region@color to select the color, as in \'Chr1:10000..20000@lightblue\'', FEATURES_CLIPPED => 'Showing %s of %s features', FEATURES_CLIPPED_MAX => 'Showing %s of >%s features', FILE_INFO => 'Last modified %s. Annotated landmarks: %s', FOOTER_1 => < 'Generic genome browser version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'The following %d regions match your request.', POSSIBLE_TRUNCATION => 'Search results are limited to %d hits; list may be incomplete.', MATCHES_ON_REF => 'Matches on %s', SEQUENCE => 'sequence', SCORE => 'score=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', NAME => 'Name', TYPE => 'Type', SUBTYPE => 'subtype', DESCRIPTION => 'Description', POSITION => 'Position', SCORE => 'Match Score', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Settings for %s', UNDO => 'Undo Changes', REVERT => 'Revert to Defaults', REFRESH => 'Refresh', OPTIONS_TITLE => 'Track Options', SETTINGS_INSTRUCTIONS => <Show checkbox turns the track on and off. The Compact option forces the track to be condensed so that annotations will overlap. The Expand and Hyperexpand options turn on collision control using slower and faster layout algorithms. The Expand & label and Hyperexpand & label options force annotations to be labeled. If Auto is selected, the collision control and label options will be set automatically if space permits. To change the track order use the Change Track Order popup menu to assign an annotation to a track. To limit the number of annotations of this type shown, change the value of the Limit menu. END TRACK => 'Track', TRACK_TYPE => 'Track Type', SHOW => 'Show', FORMAT => 'Format', LIMIT => 'Max. features to show', ADJUST_ORDER => 'Adjust Order', CHANGE_ORDER => 'Change Track Order', AUTO => 'Auto', COMPACT => 'Compact', EXPAND => 'Expand', EXPAND_LABEL => 'Expand & Label', HYPEREXPAND => 'Hyperexpand', NO_LIMIT => 'No limit', OVERVIEW => 'Overview', EXTERNAL => 'External', ANALYSIS => 'Analysis', GENERAL => 'General', DETAILS => 'Details', REGION => 'Region', ALL_ON => 'All on', ALL_OFF => 'All off', #-------------- # HELP PAGES #-------------- OK => 'OK', CLOSE_WINDOW => 'Close this window', EXTERNAL => 'External Annotation Tracks', ACTIVATE => 'Please activate this track in order to view its information.', #-------------- # PLUGIN PAGES #-------------- BACK_TO_BROWSER => 'Back to Browser', PLUGIN_SEARCH_1 => '%s (via %s search)', PLUGIN_SEARCH_2 => '<%s search>', CONFIGURE_PLUGIN => 'Configure', BORING_PLUGIN => 'This plugin has no extra configuration settings.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'The landmark named %s is not recognized. See the help pages for suggestions.', TOO_BIG => 'Detailed view is limited to %s. Click and drag on one of the scalebars to make a smaller selection.', NO_LWP => "This server is not configured to fetch external URLs.", FETCH_FAILED => "Could not fetch %s: %s.", TOO_MANY_LANDMARKS => '%d landmarks. Too many to list.', SMALL_INTERVAL => 'Resizing small interval to %s bp', NO_SOURCES => 'There are no readable data sources configured. Perhaps you do not have permission to view them.', ADD_YOUR_OWN_TRACKS => 'Add custom tracks', ADD_DESCRIPTION => 'Click to add a description', ADD_TITLE => 'Click to edit the title', NO_DESCRIPTION => 'No description', CONFIGURATION => 'Configuration', BACKGROUND_COLOR => 'Fill color', FG_COLOR => 'Line color', HEIGHT => 'Height', PACKING => 'Spacing', GLYPH => 'Shape', XYPLOT_TYPE => 'plot style', WHISKERS_TYPE => 'whiskers subtype', BICOLOR_PIVOT => 'Switch colors when value crosses', BICOLOR_PIVOT_VALUE => 'Switch point value', BICOLOR_PIVOT_POS_COLOR => 'Color above switch point', BICOLOR_PIVOT_NEG_COLOR => 'Color below switch point', WHISKER_MEAN_COLOR => 'Color from 0 to mean value', WHISKER_STDEV_COLOR => 'Color from mean to stdev value', WHISKER_MAX_COLOR => 'Color from stdev to min/max value', AUTOSCALING => 'Y-axis scaling', SD_MULTIPLES => 'Number of standard deviations (SD) to show', SCALING => 'Fixed Y-axis range', SCALE_MIN => 'Minimum scale value', SCALE_MAX => 'Maximum scale value', MIN => 'Min', MAX => 'Max', SHOW_VARIANCE => 'Show variance band', APPLY_CONFIG => 'Apply config when view between', SHOW_SUMMARY => 'Show summary when region >', FEATURE_SUMMARY => 'Feature Density Summary', LINEWIDTH => 'Line width', STRANDED => 'Show strand', DEFAULT => '(default)', DYNAMIC_VALUE => 'Dynamically calculated', CHANGE => 'Change', CACHE_TRACKS => 'Cache tracks', SHOW_TOOLTIPS => 'Show tooltips', SEND_TO_GALAXY => 'Export to Galaxy', NO_DAS => 'Installation error: Bio::Das module must be installed for DAS URLs to work. Please inform this site\'s webmaster.', SHOW_OR_HIDE_TRACK => 'Show or hide this track', KILL_THIS_TRACK => 'Turn off this track', CONFIGURE_THIS_TRACK => 'Configure this track', POP_OUT => 'Pop out/in', DOWNLOAD_THIS_TRACK => 'Download this track', ABOUT_THIS_TRACK => 'About this track', SUBTRACKS_SHOWN => 'This track contains selectable subtracks. Click to modify the selection or change subtrack order.', SHOWING_SUBTRACKS => '(Showing %d of %d subtracks)', OVERLAP => 'Semi-transparent overlap', AUTO_COLORS => 'Set colors automatically', SHARE_THIS_TRACK => 'Share this track', SHARE_ALL => 'Share these tracks', SHARE => 'Share %s', SHARE_INSTRUCTIONS_BOOKMARK => <share this track with another user, copy the URL below and send it to him or her. END SHARE_INSTRUCTIONS_ONE_TRACK => <export this track to a different GBrowse genome browser, first copy the URL below, then go to the other GBrowse, select the "Upload and Share Tracks" tab, click the "From a URL" link and paste in the URL. END SHARE_INSTRUCTIONS_ALL_TRACKS => < < Distributed Annotation System (DAS) first copy the URL below, then go to the other browser and enter it as a new DAS source. Quantitative tracks ("wiggle" files) and uploaded files can not be shared using DAS. END SHARE_DAS_INSTRUCTIONS_ALL_TRACKS => < Distributed Annotation System (DAS) first copy the URL below, then go to the other browser and enter it as a new DAS source. Quantitative tracks ("wiggle" files) and uploaded files can not be shared using DAS. END SHARE_CUSTOM_TRACK_NO_CHANGE => <%s permissions, so it can be shared. END SHARE_CUSTOM_TRACK_CHANGED => <%s, so it can now be shared. END SHARE_SHARED_TRACK => <%s policy, so you are free to send the link to other users. END SHARE_GROUP_EMAIL_SUBJECT => < < <public and giving them this link or letting them search for the track by name, or by changing its permissions to group and adding the user you want by username. To do this, select the "Custom Tracks" page and choose the sharing policy you want with the drop-down menu in the "sharing" section, then type the user's name or ID in the input field provided. END CANT_SHARE => < 'Browser', CUSTOM_TRACKS_PAGE => 'Custom Tracks', COMMUNITY_TRACKS_PAGE => 'Community Tracks', SETTINGS_PAGE => 'Preferences', DOWNLOAD_TRACK_DATA_REGION => 'Download track data across region %s', DOWNLOAD_TRACK_DATA_CHROM => 'Download track data across ENTIRE chromosome %s', DOWNLOAD_TRACK_DATA_ALL => 'Download ALL DATA for this track', #------------------------- # LOGIN/ACCOUNT MANAGEMENT #------------------------- FORGOT_MY_PASSWORD => 'Forgot my password', EMAIL_MY_PASSWORD => 'E-mail my password', EDIT_ACCOUNT_DETAILS => '%s: Edit account details', CONTINUE => 'Continue', HAVE_OPENID => 'Have an OpenID?', WITH_OPENID => 'with your OpenID', SIGN_IN => 'Sign in', OPENID_PROMPT => "Select your OpenID provider's icon from the list below, or type your OpenID into the text box.", DONT_HAVE_OPENID => 'Don\'t have an OpenID?', GO_BACK => 'Go Back.', ALL_FIELDS_REQUIRED => 'All fields are required.', PASSWORDS_DO_NOT_MATCH => 'Passwords do not match.', LOG_IN => 'Log In', CHANGE_MY_EMAIL => 'Change my E-mail', CHANGE_MY_NAME => 'Change my Full Name', CHANGE_MY_PASSWORD => 'Change my Password', ADD_OPENID => 'Add OpenID to Account', REMOVE_OPENID => 'Remove OpenId from Account', LIST_REMOVE_OPENIDS => 'List/Remove OpenIDs', NEED_OPENID_TO_ACCESS => 'Sorry, but you need at least one active OpenID associated with this account in order to access %s.', DELETE_MY_ACCOUNT => 'Delete My Account', USERNAME => 'Username:', REALNAME => 'Your full name (optional):', EMAIL_TO_VALIDATE => 'E-mail (to validate your registration):', PASSWORD => 'Password:', RETYPE_PASSWORD => 'Retype Password:', CURRENT_EMAIL => 'Current E-mail:', NEW_EMAIL => 'New E-mail:', RETYPE_NEW_EMAIL => 'Retype New E-mail:', NEW_REALNAME => 'Your full name:', CURRENT_PASSWORD => 'Current Password:', NEW_PASSWORD => 'New Password:', RETYPE_NEW_PASSWORD => 'Retype New Password:', CURRENT_APP_PASSWORD => 'Current %s Password:', CURRENT_APP_USERNAME => 'Current %s Username:', TYPE_PROPER_OPENID => 'Please type in a proper OpenID.', REMEMBER_ME => 'Remember me', SUBMIT => 'Submit', REGISTER => 'Register', MY_ACCOUNT => 'My Account', FORGOTTEN_PASSWORD => 'Forgotten Password?', CLOSE => '[Close]', CANNOT_CONNECT_MAIL => 'Error: Cannot connect to mail server, an account has not been created.', USER_ALREADY_CREATED => 'Sorry, a user has already been created for the current session.

    Please log in with that account or
    ', CREATE_NEW_SESSION => 'Create a new session.', EMAIL_ALREADY_USED => 'The e-mail provided is already in use by another %s account.', MESSAGE_ALREADY_SENT => 'The e-mail provided has already been used ' . 'to create an account, however the account has not been confirmed.

    ' . 'Please choose one of the following:
    ' . '1. %s
    ' . '2. %s', RESEND_CONFIRM_EMAIL => 'Resend the Confirmation E-mail', DELETE_UNCONFIRMED => 'Delete the Unconfirmed Account', CONFIRMATION_EMAIL_SENT => 'A confirmation e-mail has been sent, please follow the attached link to complete the registration process.', ANOTHER_ACCOUNT_IN_USE => 'Another account is currently in use, please reload the page and log out before attempting to sign in.', CANNOT_CONNECT_NOT_SENT => 'Error: Cannot connect to mail server, your information has not been sent.', PROFILE_EMAIL_SENT => 'A message has been sent to your e-mail address with your profile information.

    Please follow the instructions provided to retrieve your account.', CONFIRM_ACCOUNT_PASSWORD => 'Confirm Account Password', ARE_YOU_SURE => 'Are you sure?', WARNING_DELETE_OPENID => 'Warning: Deleting your %s Account will remove all user information including any saved data or uploaded tracks. Once deleted, you will no longer have access to this %s Account or any of the information associated with it. Are you sure you wish to perform this action?', NO => 'No', YES => 'Yes', CONFIRM_ACCOUNT_DELETE => 'Confirm Account Deletion', WARNING_IRREVERSIBLE => 'Warning: This operation is irreversible.', NEW_EMAILS_DIFFERENT => 'New e-mails do not match, please check your spelling.', NEW_PASSWORDS_DIFFERENT => 'New passwords do not match, please check your spelling.', INCORRECT_USERNAME => 'Incorrect username provided, please check your spelling and try again.', PLEASE_CONFIRM_INFO => 'Please confirm your information.', EMAIL_CHANGE_SUCCESS => 'Your e-mail has been changed successfully.', PASSWORD_CHANGE_SUCCESS => 'Your password has been changed successfully.', OPENID_ADD_SUCCESS => 'Your OpenID has been added successfully.', OPENID_REMOVE_SUCCESS => 'Your OpenID has been removed successfully.', OPENID_ADD_FAILED => 'The OpenID could not be added: %s', OPERATION_SUCCESS => 'Operation completed successfully.', BACK => 'Back', CREATE_ACCOUNT => 'Create Account', OPENID_NOT_ASSOC => 'The OpenID provided is not associated with any active %s Account. If you would like to create an account now, please confirm or edit the information to set up your account below.', SUCCESS => 'Success', LOADING => 'Loading...', NO_OPENIDS_ASSOCIATED => 'There are no OpenIDs currently associated with this %s Account.', ADD_ONE => 'Add one.', ACCOUNT_CREATION_CONF => 'Account Creation Confirmation', THANKS_FOR_CREATING => 'Thank you for creating an account with %s, %s.' . '

    To complete the account creation process and to log into your %s ' . 'account, please type in your username and click the "Continue" button below.', MUST_TYPE_USERNAME => 'You must type in your username to continue.', INCORRECT_LINK => 'The link provided is either incorrect or expired.
    Please click continue to exit.', PENDING => 'pending', WELCOME => 'Welcome, %s', LOG_OUT_DESC => 'Click here to log out from %s', LOG_OUT => 'Log Out', CHANGE_SETTINGS_DESC => 'Click here to change your account settings', LOGIN_CREATE_DESC => 'Click here to log in or create a new account. This will allow you to access your settings and uploaded tracks from multiple computers.', LOGIN_REQUEST => 'Please log in %s', LOGIN => 'Log in', LOGIN_CREATE => 'Log in / create account', LOGIN_REQUIRED => 'You must log in to access this data source', #------------ # USER TRACKS #------------ UPLOADING => 'Uploading...', UPLOAD_ERROR => 'The server returned an error during upload', REMOVE_MESSAGE => '[Remove Message]', EDITING_FILE => 'Editing %s', FETCHING => 'fetching...', CANCELLING => 'Cancelling', NOT_FOUND => 'Not Found', ADMIN_MODE_WARNING => 'Admin mode: Uploaded tracks are public', SOURCE_FILES => 'Source files:', SHARE_WITH_OTHERS => 'Share with other users', RELOAD_FROM => '[reload from %s]', REMOVE_FROM_MY_SESSION => 'Remove from my session', INTERRUPTED_RESUME => 'Interrupted [Resume]', SHARING => 'Sharing:', TRACK_IS => 'Track is', SHARED_WITH_YOU => 'shared with you', SHARING_ADD_USER => 'Add', SHARING_PRIVATE => 'Private', SHARING_CASUAL => 'Casual', SHARING_GROUP => 'Group', SHARING_PUBLIC => 'Public', SHARING_HELP => 'Private - Visible only to me.
    '. 'Casual - Visible to me and anyone I send a link to, but not visible as a public track.
    '. 'Group - Visible to me and anyone I add to the sharing group. Search for users by typing a portion of their name or email address in the box to a right and click [Add]. An email will be sent to alert them that the track has been shared.
    '. 'Public - Visible to anyone.', UPLOADED_TRACKS_CATEGORY => 'Custom Tracks:Uploaded Tracks', SHARED_WITH_ME_CATEGORY => 'Custom Tracks:Shared with me', SHARE_WITH_THIS_LINK => 'Share with this link: ', USERS => 'user(s)', USED_BY => 'used by', PUBLIC_TRACKS => 'Public Tracks', COMMUNITY_TRACKS => 'Community Tracks', THERE_ARE_NO_AVAILABLE_TRACKS => 'There are no available unused %s tracks. Select "Custom Tracks" to see ones you\'ve already added to your session.', THERE_ARE_NO_TRACKS_YET => 'There are no %s tracks yet.', NO_PUBLIC_RESULTS => 'There are no community tracks that match "%s"', TOGGLE_DETAILS => 'Toggle Details', SHARED_WITH => 'shared with', NO_ONE => 'no one.', ENTER_SOMETHING_HERE => 'Enter a %s here.', USERNAME_OR_USER_ID => 'username or user ID', USER_ID => 'user ID', ADD_BUTTON => '[Add]', EDIT_BUTTON => '[edit]', OVERWRITE => 'If this file exists, overwrite it.', CHANGING_PERMISSIONS => 'Changing sharing permissions...', ADDING => 'Adding...', REMOVING => 'Removing...', ENTER_KEYWORD => 'Enter a keyword', OR_USER => 'or user', SHOWING => 'showing', N_TO_N_OUT_OF => '%s to %s out of', N_FILES => '%s files', FOUND_N_FILES => 'Found %s file(s)', NEXT_N => 'Next %s', PREVIOUS_N => 'Previous %s', UPLOADED_BY => 'uploaded by', MATCHING => 'matching "%s"', PAGE => 'page', FILTER => 'filter', #------ # MISC. #------ HIDE_DETAILS => 'Hide details', SHOW_DETAILS => 'Show details', WORKING => 'Working...', ZOOM_IN => 'Zoom in', RECENTER_ON_REGION => 'Recenter on this region', DUMP_AS_FASTA => 'Dump selection as FASTA', ZOOM => 'Zoom', ABOUT_GBROWSE => '

    This is the Generic Genome Browser version %s

    ' . '

    It is part of the Generic Model Organism (GMOD) ' . 'suite of genome analysis software tools.

    ' . '

    The software is copyright 2002-2010 Cold Spring Harbor Laboratory, ' . 'Ontario Institute for Cancer Research, ' . 'and the University of California, Berkeley.

    ', CHROM_SIZES_UNKNOWN => 'The chromosome sizes cannot be determined from this data source. Please contact the site administrator for help', CHROM_SIZE_FILE_ERROR => 'An error occurred when opening chromosome sizes file: %s', SPECIES => 'Species:', BUILD => 'Build:', SPECIES_AND_BUILD_INFO => 'Species and Build Information', MAINTAINED_BY => 'Maintained by %s', CREATED => 'Created %s', MODIFIED => 'Modified %s', NO_FURTHER_INFO_AVAILABLE => 'No further information on %s is available.', ABOUT_ME_TEXT => '

    User IDs

    '. '

    Your userID is %s

    '. '

    Your sessionID is %s

    '. '

    Your uploadID is %s

    ', CLICK_MODIFY_SUBTRACK_SEL => 'Click to modify subtrack selections.', CLICK_FOR_MORE => 'Click for more', PLUGIN_BASE_CLASS_DUMP => "This is the base class for all GBrowse plugins.\n". "The fact that you're seeing this means that the author of ". "this plugin hasn't yet implemented a real dump() method.\n", PLUGIN_BASE_CLASS_DESC => "This is the base class for all GBrowse plugins.\n". "The fact that you're seeing this means that the author of ". "this plugin hasn't yet entered a real description.\n", CHROM_NOT_FOUND => 'Configuration error: Chromosome/contig not found!', CHROM_NOT_FOUND_DETAILS => 'Cannot display %s because the chromosome/contig named %s is not defined in the database.', NOT_RECOGNIZED_PLUGIN => '%s is not a recognized plugin', NO_PLUGIN_SPECIFIED => 'No plugin was specified.', RULER_TOGGLE_TOOLTIP => 'Click to enable the ruler. Or, click and drag to reposition.', }; GBrowse-2.56/conf/languages/de.pm000444001750001750 2434413036764442 17013 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! # Guenther Weberndorfer { CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome Browser', SEARCH_INSTRUCTIONS => < < < 'Darstellung %s von %s, Position %s bis %s', INSTRUCTIONS => 'Anleitungen', HIDE => 'Ausblenden', SHOW => 'Zeigen', SHOW_INSTRUCTIONS => 'Anleitungen anzeigen', HIDE_INSTRUCTIONS => 'Anleitungen ausblenden', SHOW_HEADER => 'Banner zeigen', HIDE_HEADER => 'Banner ausblenden', LANDMARK => 'Landmark oder Region', BOOKMARK => 'Bookmark für diese Ansicht', IMAGE_LINK => 'Link zur Abbildung dieser Ansicht', SVG_LINK => 'Abbildung in Publikationsqualität', SVG_DESCRIPTION => < Der Folgende Link wird eine Abbildung im Scalable Vector Graphic (SVG) Format erzeugen. SVG Bilder bietet einige Vorteile gegenüber Raster basierten Formaten wie jpeg oder png:

    • Voll skalierbar ohne Verlust an Aufl&oum;sung.
    • Einzelne Features sind in gebräuchlich Vektor Grafik Programmen editierbar.
    • wenn notwendig ist eine Konvertierung in EPS zur Einreichung von Publikationen möglich

    Um SVG zu betrachten brauchen sie einen SVG fähigen Browser, das Adobe SVG Browser Plugin oder Programm zum Editieren oder Betrachten von SVG wie zum Beispiel Adobe Illustrator.

    Adobe's SVG Browser plugin: Macintosh | Windows
    Linux Anwendern sei der Batik SVG Viewer empfohlen.

    SVG Abbildung in einem neuen Browser Fenster öffnen

    Um diese Abbildung auf ihre lokale Festplatte zu speichern control-click (Macintosh) oder right-click (Windows) drücken und Speichern auswählen.

    END IMAGE_DESCRIPTION => < Um eine Abbildung dieser Ansicht in eine HTML Seite einzubetten folgendes URL durch cut and paste einfügen:

    <IMAGE src="%s" />
    

    Das Bild wird folgendermassen aussehen:

    !!!!!!! Wenn nur die Übersicht (Chromosomen oder Contig Ansicht) angezeigt wird, versuchen Sie die Grö&szilig;e der Region zu verringern

    END TIMEOUT => <<'END', Der Anfrage hat das Zeitlimit überschritten. Möglicherweise wurde eine Region gewählt, die zu gro&szilig; ist um angezeigt zu werden. Entweder kann man Tracks abschalten oder eine kleinere Region probieren. Drücken sie den roten "Reset" Knopf, wenn Sie dauernd timeouts bekommen. END GO => 'Los', FIND => 'Finden', SEARCH => 'Suche', DUMP => 'Dump', HIGHLIGHT => 'Markieren', ANNOTATE => 'Annotieren', SCROLL => 'Scroll/Zoom', RESET => 'Reset', FLIP => 'Umdrehen', DOWNLOAD_FILE => 'Download File', DOWNLOAD_DATA => 'Download Daten', DOWNLOAD => 'Download', DISPLAY_SETTINGS => 'Display Einstellungen', TRACKS => 'Tracks', EXTERNAL_TRACKS => 'Externe Tracks kursiv', OVERVIEW_TRACKS => '*', REGION_TRACKS => '**Track Region', EXAMPLES => 'Beispiele', REGION_SIZE => 'Größe der Region (bp)', HELP => 'Hilfe', HELP_FORMAT => 'Hilfe zum Datei Format', CANCEL => 'Abbrechen', ABOUT => 'Über...', REDISPLAY => 'Neu Zeichnen', CONFIGURE => 'Konfiguration...', CONFIGURE_TRACKS => 'Track Konfiguration...', EDIT => 'Datei Editieren...', DELETE => 'Datei Lö', EDIT_TITLE => 'Annotations Daten Eingeben/Editieren', IMAGE_WIDTH => 'Bild Weite', BETWEEN => 'Zwischen', BENEATH => 'Unter', LEFT => 'Links', RIGHT => 'Rechts', TRACK_NAMES => 'Track Name Tabelle', ALPHABETIC => 'Alphabetisch', VARYING => 'Variierend', SET_OPTIONS => 'Einstellung Track Optionen...', CLEAR_HIGHLIGHTING => 'Markierungen entfernen', UPDATE => 'Bild Neu Zeichen', DUMPS => 'Dumps, Suchen und andere Operationen', DATA_SOURCE => 'Daten Quelle', UPLOAD_TRACKS=>'Eigene Tracks hinzufügen', UPLOAD_TITLE=> 'Eigene Annotationen hochladen', UPLOAD_FILE => 'Datei hochladen', KEY_POSITION => 'Schlüssel Position', BROWSE => 'Durchsuchen...', UPLOAD => 'Hochladen', NEW => 'Neu...', REMOTE_TITLE => 'Remote Annotationen hinzufügen', REMOTE_URL => 'Eingabe Remote Annotations URL', UPDATE_URLS => 'Update URLs', PRESETS => '--Auswahl voreingestellter URLs--', FEATURES_TO_HIGHLIGHT => 'Markierte Feature(s) (Feature1 Feature2...)', REGIONS_TO_HIGHLIGHT => 'Markierte Regionen (region1:start..end region2:start..end)', FEATURES_TO_HIGHLIGHT_HINT => 'Hinweis: Verwende Feature@color um die Farbe auszuwählen wie zum Beispiel in \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Hinweis: Verwende Region@color um die Farbe auszuwählen wie zum Beispiel in \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*keine*', FILE_INFO => 'Letzte Änderung %s. Annotierte Landmarks: %s', FOOTER_1 => < 'Generic Genome Browser Version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Folgende %d Regionen entsprechen ihrer Abfrage.', POSSIBLE_TRUNCATION => 'Such Ergebnisse werden auf %d Treffer limiterit; die Liste ist möglicherweise unvollständig.', MATCHES_ON_REF => 'Treffer auf %s', SEQUENCE => 'Sequenz', SCORE => 'score=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Einstellungen für %s', UNDO => 'Ändnerungen Rückgängig', REVERT => 'Original Einstellungen Wiederherstellen', REFRESH => 'Erneuern', CANCEL_RETURN => 'Ändnerungen verwerfen und Zurück...', ACCEPT_RETURN => 'Ädnerungen akzeptieren und Zurück...', OPTIONS_TITLE => 'Track Optionen', SETTINGS_INSTRUCTIONS => <Zeigen Checkbox können Tracks an- und abgeschalten werden. Die Option Kompakt kondensiert die Darstellung des Track, soda&szilig; die Annotationen überlappen. Die Expandieren und Hyperexpandieren Optionen steuern die Kollisionskontrolle und verwenden langsamere und schnellere Layout Algorithmen. Die Expandieren & Label und Hyperexpand & Label Optionen erzeugen zwingend Label auf den Annotationen. Wenn Auto gewählt so wird Kollisionskontrolle und Label Optionen automatisch selektiert, wenn es der Platz erlaubt. Um die Reihenfolge der Tracks zu ändern kann das Track Reihenfolge Ändern Menü verwendet werden. Die Anzahl der Annotationen eines Typs kann üder die Limit Option gesteuert werden. END TRACK => 'Track', TRACK_TYPE => 'Track Typ', SHOW => 'Anzeigen', FORMAT => 'Format', LIMIT => 'Limit', ADJUST_ORDER => 'Reihenfolge Einstellen', CHANGE_ORDER => 'Track Reihenfolge Ändern', AUTO => 'Auto', COMPACT => 'Kompakt', EXPAND => 'Expandieren', EXPAND_LABEL => 'Expandieren & Label', HYPEREXPAND => 'Hyperexpandieren', HYPEREXPAND_LABEL =>'Hyperexpandieren & label', NO_LIMIT => 'Kein Limit', OVERVIEW => 'Überblick', EXTERNAL => 'Extern', ANALYSIS => 'Analyse', GENERAL => 'Allgemein', DETAILS => 'Details', REGION => 'Region', ALL_ON => 'Alles an', ALL_OFF => 'Alles aus', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Fenster schließen', TRACK_DESCRIPTIONS => 'Track Beschreibung und Zitate', BUILT_IN => 'Eingebaute Tracks diese Servers', EXTERNAL => 'Externe Annotations Tracks', ACTIVATE => 'Bitte diesen Track aktivieren, um seine Information anzuzeigen.', NO_EXTERNAL => 'Keine Externen Features geladen.', NO_CITATION => 'Keine Zusatzinformation verfügbar.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Über %s', BACK_TO_BROWSER => 'Zurück zum Browser', PLUGIN_SEARCH_1 => '%s (über %s Suche)', PLUGIN_SEARCH_2 => '<%s Suche>', CONFIGURE_PLUGIN => 'Konfiguration', BORING_PLUGIN => 'Diese Plugin hat keine zusätzlichen Konfigurations Einstellungen.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'Die Landmark %s wurde nicht erkannt. Vorschläge sind in den Hilfe Seiten zu finden.', TOO_BIG => 'Die Detail Ansicht ist limitiert auf %s. Klicken Sie in den Überblick um eine Region von %s Weite auszuwählen.', PURGED => "Die Datei mit dem Namen %s kann nicht gefunden werden. Möglicherweise wurde sie entfernt?.", NO_LWP => "Dieser Server wurde nicht Konfiguriert um externe URLs zu holen.", FETCH_FAILED => "Konnte nicht geholt werden %s: %s.", TOO_MANY_LANDMARKS => '%d Landmarks. Liste zu lang.', SMALL_INTERVAL => 'Kleines Intervall wird auf %s bp angepasst', NO_SOURCES => 'Es wurden keine lesbaren Datenquellen konfiguriert. Möglicherweise haben Sie nicht ausreichend Berechtigungen um sie zu sehen.', }; GBrowse-2.56/conf/languages/en.pm000444001750001750 7100713036764442 17023 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => <Search using a sequence name, gene name, locus%s, or other landmark. The wildcard character * is allowed. END NAVIGATION_INSTRUCTIONS => <Navigate by clicking one of the rulers to center on a location, or click and drag to select a region. Use the Scroll/Zoom buttons to change magnification and position. END EDIT_INSTRUCTIONS => < '%s from %s:%s..%s', CURRENTLY_SHOWING => '(Currently showing %s)', INSTRUCTIONS => 'Instructions', HIDE => 'Hide', FILE => 'File', SHOW => 'Show', SHOW_HEADER => 'Show banner', HIDE_HEADER => 'Hide banner', LANDMARK => 'Landmark or Region', BOOKMARK => 'Bookmark this', CHROM_SIZES => 'Get chrom sizes', EXPORT => 'Export as...', IMAGE_LINK => '...low-res PNG image', SVG_LINK => '...editable SVG image', PDF_LINK => '...high-res PDF', DUMP_GFF => '...GFF annotation table', DUMP_SEQ => '...FASTA sequence file', FILTER => 'Filter', TIMEOUT => <<'END', Your request timed out. You may have selected a region that is too large to display. Either turn off some tracks or try a smaller region. If you are experiencing persistent timeouts, please press the red "Reset" button. END GO => 'Go', FIND => 'Find', SEARCH => 'Search', DUMP => 'Download', HIGHLIGHT => 'Highlight', ANNOTATE => 'Annotate', SCROLL => 'Scroll/Zoom', RESET => 'Reset to defaults', FLIP => 'Flip', DOWNLOAD_FILE => 'Download File', DOWNLOAD => 'Download', DISPLAY_SETTINGS => 'Display Settings', TRACKS => 'Tracks', # FAVORITE MENU LINKS FAVORITES => 'Show Favorites Only', SHOWALL => 'Show Favorites and Others', SHOW_ACTIVE => 'Show Active Tracks Only', SHOW_ACTIVE_INACTIVE => 'Show Active & Inactive Tracks', REFRESH_FAV => 'Refresh Favorites', CLEAR_FAV => 'Clear All Favorites', SHOW_ACTIVE_TRACKS => 'Show Active Tracks Only', ADDED_TO => 'Add track to favorites', ############# SNAPSHOT_FORM => 'Snapshot Name', CURRENT_SNAPSHOT => 'Current Snapshot:', TIMESTAMP => 'Snapshot Timestamp [GMT]', SNAPSHOT_SELECT => 'Snapshots', SAVE_SNAPSHOT => 'Save Snapshot', LOAD_SNAPSHOT => 'Load Snapshot', SELECT_TRACKS => 'Select Tracks', TRACK_SELECT => 'Search for Specific Tracks', TRACK_NAME => 'Track name', EXTERNAL_TRACKS => 'External tracks italicized', OVERVIEW_TRACKS => '*Overview track', REGION_TRACKS => '**Region track', EXAMPLES => 'Examples', REGION_SIZE => 'Region Size (bp)', HELP => 'Help', HELP_WITH_BROWSER => 'Help with this browser', HELP_FORMAT_UPLOAD => 'Help with uploading custom tracks', CANCEL => 'Cancel', ABOUT => 'About GBrowse...', ABOUT_DSN => 'About this database...', ABOUT_ME => 'Show my user ID...', ABOUT_NAME => 'About %s...', REDISPLAY => 'Redisplay', CONFIGURE => 'Configure...', SUBTRACK_INSTRUCTIONS => 'Select the tracks you wish to display. Sort the tracks by clicking on the column headings, or by clicking and dragging rows into position.', SELECT_SUBTRACKS => 'showing %d/%d subtracks', EDIT => 'Edit File...', DELETE => 'Delete File', EDIT_TITLE => 'Enter/Edit Annotation data', IMAGE_WIDTH => 'Image Width', BETWEEN => 'Between', BENEATH => 'Beneath', LEFT => 'Left', RIGHT => 'Right', TRACK_NAMES => 'Track Name Table', ALPHABETIC => 'Alphabetic', VARYING => 'Varying', SHOW_GRID => 'Show grid', SET_OPTIONS => 'Configure tracks...', CLEAR_HIGHLIGHTING => 'Clear highlighting', CLEAR => 'Clear', UPDATE => 'Update', UPDATE_SETTINGS => 'Update Appearance', DUMPS => 'Reports & Analysis', DATA_SOURCE => 'Data Source', UPLOADED_TRACKS => 'Custom Tracks', UPLOAD_TITLE=> 'Upload your own data', UPLOAD_FILE => 'Upload a track file', MIRROR_FILE => 'Fetch track file from this URL', IMPORT_TRACK => 'Import a track URL', NEW_TRACK => 'Create a new track', FROM_TEXT => 'From text', FROM_FILE => 'From a file', FROM_URL => 'From a URL', REMOVE => 'Remove', KEY_POSITION => 'Key position', UPLOAD => 'Upload', IMPORT => 'Import', MIRROR => 'Mirror', NEW => 'New...', REMOTE_TITLE => 'Add remote annotations', #ipad IPAD_BALLOON => '\nTap feature again to see more details', # REMOTE_URL => 'Enter remote track URL', UPDATE_URLS => 'Update', PRESETS => '--Choose Preset URL--', FEATURES_TO_HIGHLIGHT => 'Highlight feature(s) (feature1 feature2...)', REGIONS_TO_HIGHLIGHT => 'Highlight regions (region1:start..end region2:start..end)', FEATURES_TO_HIGHLIGHT_HINT => 'Hint: use feature@color to select the color, as in \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Hint: use region@color to select the color, as in \'Chr1:10000..20000@lightblue\'', FEATURES_CLIPPED => 'Showing %s of %s features', FEATURES_CLIPPED_MAX => 'Showing %s of >%s features', FILE_INFO => 'Last modified %s. Annotated landmarks: %s', FOOTER_1 => < 'Generic genome browser version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'The following %d regions match your request.', POSSIBLE_TRUNCATION => 'Search results are limited to %d hits; list may be incomplete.', MATCHES_ON_REF => 'Matches on %s', SEQUENCE => 'sequence', SCORE => 'score=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', NAME => 'Name', TYPE => 'Type', SUBTYPE => 'subtype', DESCRIPTION => 'Description', POSITION => 'Position', SCORE => 'Match Score', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Settings for %s', UNDO => 'Undo Changes', REVERT => 'Revert to Defaults', REFRESH => 'Refresh', OPTIONS_TITLE => 'Track Options', SETTINGS_INSTRUCTIONS => <Show checkbox turns the track on and off. The Compact option forces the track to be condensed so that annotations will overlap. The Expand and Hyperexpand options turn on collision control using slower and faster layout algorithms. The Expand & label and Hyperexpand & label options force annotations to be labeled. If Auto is selected, the collision control and label options will be set automatically if space permits. To change the track order use the Change Track Order popup menu to assign an annotation to a track. To limit the number of annotations of this type shown, change the value of the Limit menu. END TRACK => 'Track', TRACK_TYPE => 'Track Type', SHOW => 'Show', FORMAT => 'Format', LIMIT => 'Max. features to show', ADJUST_ORDER => 'Adjust Order', CHANGE_ORDER => 'Change Track Order', AUTO => 'Auto', COMPACT => 'Compact', EXPAND => 'Expand', EXPAND_LABEL => 'Expand & Label', HYPEREXPAND => 'Hyperexpand', NO_LIMIT => 'No limit', OVERVIEW => 'Overview', EXTERNAL => 'External', ANALYSIS => 'Analysis', GENERAL => 'General', DETAILS => 'Details', REGION => 'Region', ALL_ON => 'All on', ALL_OFF => 'All off', #-------------- # HELP PAGES #-------------- OK => 'OK', CLOSE_WINDOW => 'Close this window', EXTERNAL => 'External Annotation Tracks', ACTIVATE => 'Please activate this track in order to view its information.', #-------------- # PLUGIN PAGES #-------------- BACK_TO_BROWSER => 'Back to Browser', PLUGIN_SEARCH_1 => '%s (via %s search)', PLUGIN_SEARCH_2 => '<%s search>', CONFIGURE_PLUGIN => 'Configure', BORING_PLUGIN => 'This plugin has no extra configuration settings.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'The landmark named %s is not recognized. See the help pages for suggestions.', TOO_BIG => 'Detailed view is limited to %s. Click and drag on one of the scalebars to make a smaller selection.', NO_LWP => "This server is not configured to fetch external URLs.", FETCH_FAILED => "Could not fetch %s: %s.", TOO_MANY_LANDMARKS => '%d landmarks. Too many to list.', SMALL_INTERVAL => 'Resizing small interval to %s bp', NO_SOURCES => 'There are no readable data sources configured. Perhaps you do not have permission to view them.', ADD_YOUR_OWN_TRACKS => 'Add custom tracks', ADD_DESCRIPTION => 'Click to add a description', ADD_TITLE => 'Click to edit the title', NO_DESCRIPTION => 'No description', CONFIGURATION => 'Configuration', BACKGROUND_COLOR => 'Fill color', FG_COLOR => 'Line color', HEIGHT => 'Height', PACKING => 'Spacing', GLYPH => 'Shape', XYPLOT_TYPE => 'plot style', WHISKERS_TYPE => 'whiskers subtype', BICOLOR_PIVOT => 'Switch colors when value crosses', BICOLOR_PIVOT_VALUE => 'Switch point value', BICOLOR_PIVOT_POS_COLOR => 'Color above switch point', BICOLOR_PIVOT_NEG_COLOR => 'Color below switch point', WHISKER_MEAN_COLOR => 'Color from 0 to mean value', WHISKER_STDEV_COLOR => 'Color from mean to stdev value', WHISKER_MAX_COLOR => 'Color from stdev to min/max value', AUTOSCALING => 'Y-axis scaling', SD_MULTIPLES => 'Number of standard deviations (SD) to show', SCALING => 'Fixed Y-axis range', SCALE_MIN => 'Minimum scale value', SCALE_MAX => 'Maximum scale value', MIN => 'Min', MAX => 'Max', SHOW_VARIANCE => 'Show variance band', APPLY_CONFIG => 'Apply config when view between', SHOW_SUMMARY => 'Show summary when region >', FEATURE_SUMMARY => 'Feature Density Summary', LINEWIDTH => 'Line width', STRANDED => 'Show strand', DEFAULT => '(default)', DYNAMIC_VALUE => 'Dynamically calculated', CHANGE => 'Change', CACHE_TRACKS => 'Cache tracks', SHOW_TOOLTIPS => 'Show tooltips', SEND_TO_GALAXY => 'Export to Galaxy', NO_DAS => 'Installation error: Bio::Das module must be installed for DAS URLs to work. Please inform this site\'s webmaster.', SHOW_OR_HIDE_TRACK => 'Show or hide this track', KILL_THIS_TRACK => 'Turn off this track', CONFIGURE_THIS_TRACK => 'Configure this track', DOWNLOAD_THIS_TRACK => 'Download this track', ABOUT_THIS_TRACK => 'About this track', SUBTRACKS_SHOWN => 'This track contains selectable subtracks. Click to modify the selection or change subtrack order.', SHOWING_SUBTRACKS => '(Showing %d of %d subtracks)', OVERLAP => 'Semi-transparent overlap', AUTO_COLORS => 'Set colors automatically', SHARE_THIS_TRACK => 'Share this track', SHARE_ALL => 'Share these tracks', SHARE => 'Share %s', SHARE_INSTRUCTIONS_BOOKMARK => <share this track with another user, copy the URL below and send it to him or her. END SHARE_INSTRUCTIONS_ONE_TRACK => <export this track to a different GBrowse genome browser, first copy the URL below, then go to the other GBrowse, select the "Upload and Share Tracks" tab, click the "From a URL" link and paste in the URL. END SHARE_INSTRUCTIONS_ALL_TRACKS => < < Distributed Annotation System (DAS) first copy the URL below, then go to the other browser and enter it as a new DAS source. Quantitative tracks ("wiggle" files) and uploaded files can not be shared using DAS. END SHARE_DAS_INSTRUCTIONS_ALL_TRACKS => < Distributed Annotation System (DAS) first copy the URL below, then go to the other browser and enter it as a new DAS source. Quantitative tracks ("wiggle" files) and uploaded files can not be shared using DAS. END SHARE_CUSTOM_TRACK_NO_CHANGE => <%s permissions, so it can be shared. END SHARE_CUSTOM_TRACK_CHANGED => <%s, so it can now be shared. END SHARE_SHARED_TRACK => <%s policy, so you are free to send the link to other users. END SHARE_GROUP_EMAIL_SUBJECT => < < <public and giving them this link or letting them search for the track by name, or by changing its permissions to group and adding the user you want by username. To do this, select the "Custom Tracks" page and choose the sharing policy you want with the drop-down menu in the "sharing" section, then type the user's name or ID in the input field provided. END CANT_SHARE => < 'Browser', CUSTOM_TRACKS_PAGE => 'Custom Tracks', COMMUNITY_TRACKS_PAGE => 'Community Tracks', SETTINGS_PAGE => 'Preferences', DOWNLOAD_TRACK_DATA_REGION => 'Download track data across region %s', DOWNLOAD_TRACK_DATA_CHROM => 'Download track data across ENTIRE chromosome %s', DOWNLOAD_TRACK_DATA_ALL => 'Download ALL DATA for this track', #------------------------- # LOGIN/ACCOUNT MANAGEMENT #------------------------- FORGOT_MY_PASSWORD => 'Forgot my password', EMAIL_MY_PASSWORD => 'E-mail my password', EDIT_ACCOUNT_DETAILS => '%s: Edit account details', CONTINUE => 'Continue', HAVE_OPENID => 'Have an OpenID?', WITH_OPENID => 'with your OpenID', SIGN_IN => 'Sign in', OPENID_PROMPT => "Select your OpenID provider's icon from the list below, or type your OpenID into the text box.", DONT_HAVE_OPENID => 'Don\'t have an OpenID?', GO_BACK => 'Go Back.', ALL_FIELDS_REQUIRED => 'All fields are required.', PASSWORDS_DO_NOT_MATCH => 'Passwords do not match.', LOG_IN => 'Log In', CHANGE_MY_EMAIL => 'Change my E-mail', CHANGE_MY_NAME => 'Change my Full Name', CHANGE_MY_PASSWORD => 'Change my Password', ADD_OPENID => 'Add OpenID to Account', REMOVE_OPENID => 'Remove OpenId from Account', LIST_REMOVE_OPENIDS => 'List/Remove OpenIDs', NEED_OPENID_TO_ACCESS => 'Sorry, but you need at least one active OpenID associated with this account in order to access %s.', DELETE_MY_ACCOUNT => 'Delete My Account', USERNAME => 'Username:', REALNAME => 'Your full name (optional):', EMAIL_TO_VALIDATE => 'E-mail (to validate your registration):', PASSWORD => 'Password:', RETYPE_PASSWORD => 'Retype Password:', CURRENT_EMAIL => 'Current E-mail:', NEW_EMAIL => 'New E-mail:', RETYPE_NEW_EMAIL => 'Retype New E-mail:', NEW_REALNAME => 'Your full name:', CURRENT_PASSWORD => 'Current Password:', NEW_PASSWORD => 'New Password:', RETYPE_NEW_PASSWORD => 'Retype New Password:', CURRENT_APP_PASSWORD => 'Current %s Password:', CURRENT_APP_USERNAME => 'Current %s Username:', TYPE_PROPER_OPENID => 'Please type in a proper OpenID.', REMEMBER_ME => 'Remember me', SUBMIT => 'Submit', REGISTER => 'Register', MY_ACCOUNT => 'My Account', FORGOTTEN_PASSWORD => 'Forgotten Password?', CLOSE => '[Close]', CANNOT_CONNECT_MAIL => 'Error: Cannot connect to mail server, an account has not been created.', USER_ALREADY_CREATED => 'Sorry, a user has already been created for the current session.

    Please log in with that account or
    ', CREATE_NEW_SESSION => 'Create a new session.', EMAIL_ALREADY_USED => 'The e-mail provided is already in use by another %s account.', MESSAGE_ALREADY_SENT => 'The e-mail provided has already been used ' . 'to create an account, however the account has not been confirmed.

    ' . 'Please choose one of the following:
    ' . '1. %s
    ' . '2. %s', RESEND_CONFIRM_EMAIL => 'Resend the Confirmation E-mail', DELETE_UNCONFIRMED => 'Delete the Unconfirmed Account', CONFIRMATION_EMAIL_SENT => 'A confirmation e-mail has been sent, please follow the attached link to complete the registration process.', ANOTHER_ACCOUNT_IN_USE => 'Another account is currently in use, please reload the page and log out before attempting to sign in.', CANNOT_CONNECT_NOT_SENT => 'Error: Cannot connect to mail server, your information has not been sent.', PROFILE_EMAIL_SENT => 'A message has been sent to your e-mail address with your profile information.

    Please follow the instructions provided to retrieve your account.', CONFIRM_ACCOUNT_PASSWORD => 'Confirm Account Password', ARE_YOU_SURE => 'Are you sure?', WARNING_DELETE_OPENID => 'Warning: Deleting your %s Account will remove all user information including any saved data or uploaded tracks. Once deleted, you will no longer have access to this %s Account or any of the information associated with it. Are you sure you wish to perform this action?', NO => 'No', YES => 'Yes', CONFIRM_ACCOUNT_DELETE => 'Confirm Account Deletion', WARNING_IRREVERSIBLE => 'Warning: This operation is irreversible.', NEW_EMAILS_DIFFERENT => 'New e-mails do not match, please check your spelling.', NEW_PASSWORDS_DIFFERENT => 'New passwords do not match, please check your spelling.', INCORRECT_USERNAME => 'Incorrect username provided, please check your spelling and try again.', PLEASE_CONFIRM_INFO => 'Please confirm your information.', EMAIL_CHANGE_SUCCESS => 'Your e-mail has been changed successfully.', PASSWORD_CHANGE_SUCCESS => 'Your password has been changed successfully.', OPENID_ADD_SUCCESS => 'Your OpenID has been added successfully.', OPENID_REMOVE_SUCCESS => 'Your OpenID has been removed successfully.', OPENID_ADD_FAILED => 'The OpenID could not be added: %s', OPERATION_SUCCESS => 'Operation completed successfully.', BACK => 'Back', CREATE_ACCOUNT => 'Create Account', OPENID_NOT_ASSOC => 'The OpenID provided is not associated with any active %s Account. If you would like to create an account now, please confirm or edit the information to set up your account below.', SUCCESS => 'Success', LOADING => 'Loading...', NO_OPENIDS_ASSOCIATED => 'There are no OpenIDs currently associated with this %s Account.', ADD_ONE => 'Add one.', ACCOUNT_CREATION_CONF => 'Account Creation Confirmation', THANKS_FOR_CREATING => 'Thank you for creating an account with %s, %s.' . '

    To complete the account creation process and to log into your %s ' . 'account, please type in your username and click the "Continue" button below.', MUST_TYPE_USERNAME => 'You must type in your username to continue.', INCORRECT_LINK => 'The link provided is either incorrect or expired.
    Please click continue to exit.', PENDING => 'pending', WELCOME => 'Welcome, %s', LOG_OUT_DESC => 'Click here to log out from %s', LOG_OUT => 'Log Out', CHANGE_SETTINGS_DESC => 'Click here to change your account settings', LOGIN_CREATE_DESC => 'Click here to log in or create a new account. This will allow you to access your settings and uploaded tracks from multiple computers.', LOGIN_REQUEST => 'Please log in %s', LOGIN => 'Log in', LOGIN_CREATE => 'Log in / create account', LOGIN_REQUIRED => 'You must log in to access this data source', #------------ # USER TRACKS #------------ UPLOADING => 'Uploading...', UPLOAD_ERROR => 'The server returned an error during upload', REMOVE_MESSAGE => '[Remove Message]', EDITING_FILE => 'Editing %s', FETCHING => 'fetching...', CANCELLING => 'Cancelling', NOT_FOUND => 'Not Found', ADMIN_MODE_WARNING => 'Admin mode: Uploaded tracks are public', SOURCE_FILES => 'Source files:', SHARE_WITH_OTHERS => 'Share with other users', RELOAD_FROM => '[reload from %s]', REMOVE_FROM_MY_SESSION => 'Remove from my session', INTERRUPTED_RESUME => 'Interrupted [Resume]', SHARING => 'Sharing:', TRACK_IS => 'Track is', SHARED_WITH_YOU => 'shared with you', SHARING_ADD_USER => 'Add', SHARING_PRIVATE => 'Private', SHARING_CASUAL => 'Casual', SHARING_GROUP => 'Group', SHARING_PUBLIC => 'Public', SHARING_HELP => 'Private - Visible only to me.
    '. 'Casual - Visible to me and anyone I send a link to, but not visible as a public track.
    '. 'Group - Visible to me and anyone I add to the sharing group. Search for users by typing a portion of their name or email address in the box to a right and click [Add]. An email will be sent to alert them that the track has been shared.
    '. 'Public - Visible to anyone.', UPLOADED_TRACKS_CATEGORY => 'Custom Tracks:Uploaded Tracks', SHARED_WITH_ME_CATEGORY => 'Custom Tracks:Shared with me', SHARE_WITH_THIS_LINK => 'Share with this link: ', USERS => 'user(s)', USED_BY => 'used by', PUBLIC_TRACKS => 'Public Tracks', COMMUNITY_TRACKS => 'Community Tracks', THERE_ARE_NO_AVAILABLE_TRACKS => 'There are no available unused %s tracks. Select "Custom Tracks" to see ones you\'ve already added to your session.', THERE_ARE_NO_TRACKS_YET => 'There are no %s tracks yet.', NO_PUBLIC_RESULTS => 'There are no community tracks that match "%s"', TOGGLE_DETAILS => 'Toggle Details', SHARED_WITH => 'shared with', NO_ONE => 'no one.', ENTER_SOMETHING_HERE => 'Enter a %s here.', USERNAME_OR_USER_ID => 'username or user ID', USER_ID => 'user ID', ADD_BUTTON => '[Add]', EDIT_BUTTON => '[edit]', OVERWRITE => 'If this file exists, overwrite it.', CHANGING_PERMISSIONS => 'Changing sharing permissions...', ADDING => 'Adding...', REMOVING => 'Removing...', ENTER_KEYWORD => 'Enter a keyword', OR_USER => 'or user', SHOWING => 'showing', N_TO_N_OUT_OF => '%s to %s out of', N_FILES => '%s files', FOUND_N_FILES => 'Found %s file(s)', NEXT_N => 'Next %s', PREVIOUS_N => 'Previous %s', UPLOADED_BY => 'uploaded by', MATCHING => 'matching "%s"', PAGE => 'page', FILTER => 'filter', #------ # MISC. #------ HIDE_DETAILS => 'Hide details', SHOW_DETAILS => 'Show details', WORKING => 'Working...', ZOOM_IN => 'Zoom in', RECENTER_ON_REGION => 'Recenter on this region', DUMP_AS_FASTA => 'Dump selection as FASTA', ZOOM => 'Zoom', ABOUT_GBROWSE => '

    This is the Generic Genome Browser version %s

    ' . '

    It is part of the Generic Model Organism (GMOD) ' . 'suite of genome analysis software tools.

    ' . '

    The software is copyright 2002-2010 Cold Spring Harbor Laboratory, ' . 'Ontario Institute for Cancer Research, ' . 'and the University of California, Berkeley.

    ', CHROM_SIZES_UNKNOWN => 'The chromosome sizes cannot be determined from this data source. Please contact the site administrator for help', CHROM_SIZE_FILE_ERROR => 'An error occurred when opening chromosome sizes file: %s', SPECIES => 'Species:', BUILD => 'Build:', SPECIES_AND_BUILD_INFO => 'Species and Build Information', MAINTAINED_BY => 'Maintained by %s', CREATED => 'Created %s', MODIFIED => 'Modified %s', NO_FURTHER_INFO_AVAILABLE => 'No further information on %s is available.', ABOUT_ME_TEXT => '

    User IDs

    '. '

    Your userID is %s

    '. '

    Your sessionID is %s

    '. '

    Your uploadID is %s

    ', CLICK_MODIFY_SUBTRACK_SEL => 'Click to modify subtrack selections.', CLICK_FOR_MORE => 'Click for more', PLUGIN_BASE_CLASS_DUMP => "This is the base class for all GBrowse plugins.\n". "The fact that you're seeing this means that the author of ". "this plugin hasn't yet implemented a real dump() method.\n", PLUGIN_BASE_CLASS_DESC => "This is the base class for all GBrowse plugins.\n". "The fact that you're seeing this means that the author of ". "this plugin hasn't yet entered a real description.\n", CHROM_NOT_FOUND => 'Configuration error: Chromosome/contig not found!', CHROM_NOT_FOUND_DETAILS => 'Cannot display %s because the chromosome/contig named %s is not defined in the database.', NOT_RECOGNIZED_PLUGIN => '%s is not a recognized plugin', NO_PLUGIN_SPECIFIED => 'No plugin was specified.', RULER_TOGGLE_TOOLTIP => 'Click to enable the ruler. Or, click and drag to reposition.', }; GBrowse-2.56/conf/languages/es.pm000444001750001750 2507413036764442 17033 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! # Translation by Marcela Tello-Ruiz { CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Buscador de genoma', SEARCH_INSTRUCTIONS => < <marcar esta página. END EDIT_INSTRUCTIONS => < 'Mostrando %s de %s, posiciones %s a %s', INSTRUCTIONS => 'Instrucciones', HIDE => 'Esconder', SHOW => 'Mostrar', SHOW_INSTRUCTIONS => 'Mostrar instrucciones', HIDE_INSTRUCTIONS => 'Ocultar instrucciones', SHOW_HEADER => 'Mostrar encabezado', HIDE_HEADER => 'Ocultar encabezado', LANDMARK => 'Punto o región de referencia', BOOKMARK => 'Marcar esta página', IMAGE_LINK => 'Ligar a imagen', SVG_LINK => 'Imagen de alta resolución', SVG_DESCRIPTION => < La siguiente liga generará esta imagen en un formato de Vector Escalable (SVG). Imagenes SVG ofrecen varias ventajas sobre las imágenes basadas en raster, tales como los formatos jpeg o png.

    • totalmente escalable sin pérdida en resolución
    • editable aspecto-por-aspecto en aplicaciones gráficas basadas en vectores
    • si es necesario, puede ser convertido en EPS para ser incluído en una publicación

    Para ver imagenes SVG, necesitas un buscador (browser) que sea capaz de aceptar SVG, el accesorio (plugin) para buscadores Adobe SVG, o una aplicación para ver o editar SVG tal como Adobe Illustrator.

    Accesorio (plugin) para buscadores Adobe SVG: Macintosh | Windows
    Usuarios de Linux pueden explorar el visualizador Batik SVG.

    Ver imagen SVG en una ventana distinta

    para guardar esta imagen en tu disco, pulsa la tecla de control (Macintosh) o el botón de la derecha de tu ratón (Windows) y selecciona la opción para guardar la liga correspondiente.

    END IMAGE_DESCRIPTION => < Para crear una imagen montada/incrustada de esta vista, corta y pega esta dirección (URL):

    <IMAGE src="%s" />
    

    La imagen se verá asi:

    Si sólo aparece la vista global (cromosoma o contig), trata de reducir el tamaño de la región.

    END TIMEOUT => <<'END', Tu solicitud expiró. Posiblemente seleccionaste una región muy grande para ver.Puedes eliminar algunas de las pistas que seleccionaste antes o intentar ver una región mas pequeña. Si esto te sucede continuamente, por favor presiona el botón rojo que dice "Reiniciar". END GO => 'Ir', FIND => 'Encontrar', SEARCH => 'Buscar', DUMP => 'Depositar', HIGHLIGHT => 'Resaltar', ANNOTATE => 'Anotar', SCROLL => 'Avanzar/Acercar', RESET => 'Reiniciar', FLIP => 'Dar la vuelta', DOWNLOAD_FILE => 'Bajar el documento', DOWNLOAD_DATA => 'Bajar los datos', DOWNLOAD => 'Bajar', DISPLAY_SETTINGS => 'Mostrar configuraciones', TRACKS => 'Pistas', EXTERNAL_TRACKS => 'Pistas externas en itálicas', OVERVIEW_TRACKS => '*Resumen de pistas', REGION_TRACKS => '**Pistas en región', EXAMPLES => 'Ejemplos', REGION_SIZE => 'Tamaño de la región (en pares de bases)', HELP => 'Ayuda', HELP_FORMAT => 'Ayuda con el formato del documento', CANCEL => 'Cancelar', ABOUT => 'Acerca de...', REDISPLAY => 'Volver a mostrar', CONFIGURE => 'Configurar...', CONFIGURE_TRACKS => 'Configurar pistas...', EDIT => 'Editar documento...', DELETE => 'Borrar documento', EDIT_TITLE => 'Insertar/Editar datos de anotación', IMAGE_WIDTH => 'Ancho de la imagen', BETWEEN => 'Entre dos puntos de referencia', BENEATH => 'Debajo', LEFT => 'Izquierda', RIGHT => 'Derecha', TRACK_NAMES => 'Nombres de las pistas', ALPHABETIC => 'Alfabético', VARYING => 'Variando/Variante', SET_OPTIONS => 'Definir Opciones para pistas...', CLEAR_HIGHLIGHTING => 'Eliminar resaltado', UPDATE => 'Actualizar imagen', DUMPS => 'Reportes & análisis', DATA_SOURCE => 'Fuente de datos', UPLOAD_TRACKS=>'Agregar tus propias pistas', UPLOAD_TITLE=> 'Subir tus anotaciones', UPLOAD_FILE => 'Subir un documento', KEY_POSITION => 'Posición de la clave', BROWSE => 'Buscar...', UPLOAD => 'Subir', NEW => 'Nuevo...', REMOTE_TITLE => 'Agregar anotaciones remotas', REMOTE_URL => 'Insertar anotación remota - Localizador (URL)', UPDATE_URLS => 'Actualizar URLs', PRESETS => '-Seleccionar URL pre-establecido--', FEATURES_TO_HIGHLIGHT => 'Resaltar propiedad(es) (propiedad1 propiedad2...)', REGIONS_TO_HIGHLIGHT => 'Resaltar regiones (region1:inicia..termina region2:inicia..termina)', FEATURES_TO_HIGHLIGHT_HINT => 'Idea: usar feature@color para seleccionar el color, como en \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Idea: usar region@color para seleccionar el color, como en \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*Ninguna pista*', FILE_INFO => '%s Modificados por última vez. Puntos de referencia anotados: %s', FOOTER_1 => < 'Versión genérica del buscador de genoma %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Las siguientes %d regiones coinciden con la que solicitaste.', POSSIBLE_TRUNCATION => 'Resultados de búsqueda están limitados a %d aciertos; la lista puede ser incompleta.', MATCHES_ON_REF => 'Cantidad de regiones que coinciden (hits) en %s', SEQUENCE => 'secuencia', SCORE => 'valor=%s', NOT_APPLICABLE => 'n/a', BP => 'pares de bases', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Configuración para %s', UNDO => 'Deshacer los cambios', REVERT => 'Revertir a la configuración pre-establecida', REFRESH => 'Refrescar', CANCEL_RETURN => 'Cancelar cambios y regresar...', ACCEPT_RETURN => 'Aceptar cambios y regresar...', OPTIONS_TITLE => 'Seguir la pista de opciones', SETTINGS_INSTRUCTIONS => <Mostrar enciende y apaga la pista. La opción Compactar obliga a condensar la pista, de manera que las anotaciones se sobrepondrán. Las opciones Expander e Hiperexpander encienden el control de colisión usando algoritmos de diseño más lentos y más rápidos. Las opciones Expander & etiqueta e Hiper-extender & etiqueta obligan a las anotaciones a ser marcadas. Si se selecciona Auto, el control de colisión y las opciones de etiquetado serán colocadas automáticamente si el espacio lo permite. Para cambiar el orden de las pistas usar el menú emergente Cambiar el orden de las pistas para asignar una anotación a una pista. Para limitar el número de anotaciones mostradas de este tipo, cambiar el valor del menú de Límite. END TRACK => 'Pista', TRACK_TYPE => 'Tipo de pista', SHOW => 'Mostrar', FORMAT => 'Formatear', LIMIT => 'Limitar', ADJUST_ORDER => 'Ajustar el orden', CHANGE_ORDER => 'Cambiar el orden', AUTO => 'Auto', COMPACT => 'Compacto', EXPAND => 'Extender', EXPAND_LABEL => 'Extender & etiquetar', HYPEREXPAND => 'Hiper-extender', HYPEREXPAND_LABEL =>'Hiper-extender & etiquetar', NO_LIMIT => 'Sin límite', OVERVIEW => 'Resumen', EXTERNAL => 'Externo', ANALYSIS => 'Análisis', GENERAL => 'General', DETAILS => 'Detalles', REGION => 'Región', ALL_ON => 'Todo encendido', ALL_OFF => 'Todo apagado', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Cerrar esta ventana', TRACK_DESCRIPTIONS => 'Seguir la pista de descripciones & citas', BUILT_IN => 'Pistas incluídas en este servidor', EXTERNAL => 'Pistas de anotación externas', ACTIVATE => 'Favor de activar esta pista para ver sus contenidos.', NO_EXTERNAL => 'Características externas no han sido cargadas.', NO_CITATION => 'No existe información adicional.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Acerca de %s', BACK_TO_BROWSER => 'Regresar al buscador', PLUGIN_SEARCH_1 => '%s (por medio de %s búsqueda)', PLUGIN_SEARCH_2 => '<%s busca>', CONFIGURE_PLUGIN => 'Configurar', BORING_PLUGIN => 'Este accesorio no tiene configuraciones adicionales.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'El punto de referencia denominado %s no es reconocido. Ver las páginas de ayuda para sugerencias.', TOO_BIG => 'La vista detallada se limita a %s bases. Pulsar en el esquema general para seleccionar una región de %s pares de bases de ancho.', PURGED => "No puedo encontrar el documento denominado %s. Tal vez ha sido eliminado?.", NO_LWP => "Este servidor no está configurado para importar URLs externos.", FETCH_FAILED => "No pude importar %s: %s.", TOO_MANY_LANDMARKS => '%d puntos de referencia. Demasiados para ennumerar.', SMALL_INTERVAL => 'Ajustando el tamaño pequeño del intervalo a %s pares de bases', NO_SOURCES => 'No hay fuentes de datos legibles configuradas. Es posible que no tengas permiso para verlas.', }; GBrowse-2.56/conf/languages/fr.pm000444001750001750 2455513036764442 17036 0ustar00lsteinlstein000000000000# translation from: Franck Aniere # do not remove the { } from the top and bottom of this page!!! { #---------- # MAIN PAGE #---------- CHARSET => 'ISO-8859-1', PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => < <ajoutez ce lien à vos favoris. END EDIT_INSTRUCTIONS => < 'Vue de %s depuis %s, positions %s à %s', INSTRUCTIONS => 'Instructions', HIDE => 'Cacher', SHOW => 'Montrer', SHOW_INSTRUCTIONS => 'Montrer les instructions', HIDE_INSTRUCTIONS => 'Cacher les instructions', SHOW_HEADER => 'Montrer l\'en-tête', HIDE_HEADER => 'Cacher l\'en-tête', LANDMARK => 'Référentiel ou Région', BOOKMARK => 'Ajouter cet affichage à vos favoris', IMAGE_LINK => 'Lien vers une image de cet affichage', SVG_LINK => 'Image haute qualité pour les publications', SVG_DESCRIPTION => < Le lien suivant permet de générer une image au format Scalable Vector Graphic (SVG). Les images SVG disposent de certains avantages sur les images bitmap (jpeg or png for exampe).

    • Possibilité de redimmensionner l'image sans perte de résolution
    • Edition objet par objet dans dans des applications de dessin vectoriel
    • Conversion au format EPS (Encapsulated PostScript) si nécessaire pour des soumissions de publications

    Pour voir des images SVG, vous devez disposer d'un navigateur qui sache les afficher, le plugin Adobe SVG, ou une application de visualisation/édition SVG telle qu'Adobe Illustrator.

    Plugin Adobe pour navigateurs : Macintosh | Windows
    Les utilisateurs de Linux peuvent regarder le Batik SVG Viewer.

    Voir l'image SVG dans une nouvelle fenêtre du navigateur.

    Pour Sauver cette image sur votre disque, control-click (Macintosh) ou bouton-droit de la souris (windows) et choisisser l'option pour sauver le lien sur disque.

    END IMAGE_DESCRIPTION => < Pour créer une image incrustée de cet affichage, il faut copier et coller cette URL dans une page HTML :

    <IMAGE src="%s" />
    

    L'image ressemblera à ceci :

    Si seul l'aperçu (affichage d'un chromosome ou contig) est visible, il faut essayer de réduire la taille de la région.

    END TIMEOUT => <<'END', Le délai alloué pour votre requête a expiré. Vous avez probablement choisi une région trop grande pour être affichée. Vous pouvez décocher quelques pistes ou essayer une région plus petite. Si le problème persiste, veuillez cliquer sur le bouton rouge ("Remise à zéro"). END GO => 'Lancer', FIND => 'Trouver', SEARCH => 'Chercher', DUMP => 'Sortie', HIGHLIGHT => 'Surligner', ANNOTATE => 'Annoter', SCROLL => 'Défil./Zoom', RESET => 'Remise à zéro', FLIP => 'Inversion', DOWNLOAD_FILE => 'Télécharger un fichier', DOWNLOAD_DATA => 'Télécharger des données', DOWNLOAD => 'Télécharger', DISPLAY_SETTINGS => 'Préférences d\'affichage', TRACKS => 'Pistes', EXTERNAL_TRACKS => '(Pistes externes en italique)', OVERVIEW_TRACKS => '*Piste d\'aperçu', REGION_TRACKS => '**Piste des régions', EXAMPLES => 'Exemples', REGION_SIZE => 'Taille de la région (pb)', HELP => 'Aide', HELP_FORMAT => 'Aide sur le format de fichiers', CANCEL => 'Annuler', ABOUT => 'A propos...', REDISPLAY => 'Rafraichir l\'affichage', CONFIGURE => 'Configurer...', CONFIGURE_TRACKS => 'Configurer les pistes...', EDIT => 'Editer le fichier...', DELETE => 'Effacer le fichier', EDIT_TITLE => 'Entrer/éditer des données d\'annotation', IMAGE_WIDTH => 'Largeur d\'image', BETWEEN => 'Entre les pistes', BENEATH => 'Sous l\'affichage', LEFT => 'Left', RIGHT => 'Right', TRACK_NAMES => 'Tableau des pistes', ALPHABETIC => 'Tri alphabétique', VARYING => 'Pas de tri', SET_OPTIONS => 'Configurer les pistes...', CLEAR_HIGHLIGHTING => 'Supprimer le surlignage', UPDATE => 'Mise à jour de l\'image', DUMPS => 'Sorties, recherches et autres opérations', DATA_SOURCE => 'Source de données', UPLOAD_TRACKS =>'Ajouter vos propres pistes', UPLOAD_TITLE => 'Ajouter vos propres annotations', UPLOAD_FILE => 'Ajouter un fichier', KEY_POSITION => 'Position des légendes', BROWSE => 'Parcourir...', UPLOAD => 'Ajouter', NEW => 'Nouveau...', REMOTE_TITLE => 'Ajouter des annotations distantes', REMOTE_URL => 'Entrer une URL pour des annotations distantes', UPDATE_URLS => 'Mettre à jour les URLs', PRESETS => "--Choix d'une URL prédéfinie--", FEATURES_TO_HIGHLIGHT => 'Surligner les informations (info1 info2...)', REGIONS_TO_HIGHLIGHT => 'Surligner les régions (région1:début..fin région2:début..fin)', FEATURES_TO_HIGHLIGHT_HINT => 'Astuce : utilisez information@couleur pour choisir la couleur, par exemple \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Astuce : utilisez région@couleur pour choisir la couleur, par exemple \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*aucune*', FILE_INFO => 'Dernière modif. %s. Référentiel annoté : %s', FOOTER_1 => < 'Generic genome browser version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Les %d régions suivantes correspondent à votre requête.', POSSIBLE_TRUNCATION => 'Les résultats de la recherche sont limités à %d hits ; la liste risque d\'être incomplète.', MATCHES_ON_REF => 'Correspondance avec %s', SEQUENCE => 'séquence', SCORE => 'score=%s', NOT_APPLICABLE => 'n/a', BP => 'pb', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Paramètres pour %s', UNDO => 'Annuler les modifications', REVERT => 'Valeurs par défaut', REFRESH => 'Rafraichir', CANCEL_RETURN => 'Annuler les modifications et revenir...', ACCEPT_RETURN => 'Accepter les modifications et revenir...', OPTIONS_TITLE => 'Options de pistes', SETTINGS_INSTRUCTIONS => <Voir active ou désctive la piste. L'option Compacter force la piste à être consensée pour que les annotations se chevauchent. Les options 'Etendre' et Hyperétendre activent un contrôle de collision qui utilise des algorithmes de mise en page plus lents et plus rapides. Les options Etendre & étiqueter et Hyperétendre & étiqueter rend obligatoire l'étiquetage des annotations. Si Auto est sélectionné, le contrôle de collision et les options d'étiquetage seront réglées automatiquements si l'espace le permet. Pour changer l'ordre des pistes, utilisez le menu Changer l'ordre des pistes pour assigner une annotation à une piste. Pour limiter le nombre d'annotations de ce type devant être affichées, il faut changer la valeur du menu Limite. END TRACK => 'Piste', TRACK_TYPE => 'Type de Piste', SHOW => 'Voir', FORMAT => 'Format', LIMIT => 'Limite', ADJUST_ORDER => 'Ajuster l\'ordre', CHANGE_ORDER => 'Changer l\'ordre des pistes', AUTO => 'Auto', COMPACT => 'Compacter', EXPAND => 'Etendre', EXPAND_LABEL => 'Etendre & étiqueter', HYPEREXPAND => 'Hyperétendre', HYPEREXPAND_LABEL =>'Hyperétendre & étiqueter', NO_LIMIT => 'Pas de limite', OVERVIEW => 'Aperçu', EXTERNAL => 'Externe', ANALYSIS => 'Analyse', GENERAL => 'Général', DETAILS => 'Détails', REGION => 'Région', ALL_ON => 'Tout activer', ALL_OFF => 'Tout désactiver', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Fermer cette fenêtre', TRACK_DESCRIPTIONS => 'Description de la piste citations', BUILT_IN => 'Pistes disponibles sur ce serveur', EXTERNAL => 'Pistes d\'annotation externes', ACTIVATE => 'Veuillez activer cette piste pour voir ses informations.', NO_EXTERNAL => 'Il n\'y a pas de caractéristiques externes chargées.', NO_CITATION => 'Il n\'y a pas d\'informations supplémentaires disponibles.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'A propos de %s', BACK_TO_BROWSER => 'Retour au Browser', PLUGIN_SEARCH_1 => '%s (via la recherche %s)', PLUGIN_SEARCH_2 => '< Recherche %s >', CONFIGURE_PLUGIN => 'Configurer', BORING_PLUGIN => "Ce module n'a pas de paramètres de configuration supplémentaires.", #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => "Le référentiel %s n'est pas reconnu. Voyez l\'aide pour des suggestions.", TOO_BIG => 'La vue détaillée est limitée à %s bases. Cliquez sur la vue d\'ensemble pour sélectionner une région de largeur %s pb.', PURGED => "Impossible de trouver le fichier nommé %s. Peut être a-t-il été supprimé ?", NO_LWP => "Ce serveur n\'est pas configuré pour ramener des URLs externes.", FETCH_FAILED => "Je n\'ai pas pu retrouver %s: %s.", TOO_MANY_LANDMARKS => '%d référentiels. La liste est trop grande.', SMALL_INTERVAL => 'Redimmensionnement du petit intervalle à %s pb', NO_SOURCES => 'Vous n\'avez pas configuré de sources de données. Peut-être n\'avez-vous pas les droits pour les voir.', }; GBrowse-2.56/conf/languages/is.pm000444001750001750 2301513036764442 17030 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { #Icelandic translation done by Gudmundur A. Thorisson #$Id: is.pm,v 1.7 2006-07-14 12:38:52 lstein Exp $ CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => < < < 'Sýni %s á %s,frá %s til %s', INSTRUCTIONS => 'Leiðbeiningar', HIDE => 'Fela', SHOW => 'Sýna', SHOW_INSTRUCTIONS => 'Sýna leiðbeiningar', HIDE_INSTRUCTIONS => 'Fela leiðbeiningar', SHOW_HEADER => 'Sýna haus', HIDE_HEADER => 'Fela haus', LANDMARK => 'Kennileiti eða svæði', BOOKMARK => 'Vista sem bókamerki', IMAGE_LINK => 'Fá vefslóð á mynd', SVG_LINK => 'Mynd sem hentar til birtingar', SVG_DESCRIPTION => < Eftirfarandi slóð mynd býr til þessa sömu mynd á Scalable Vector Graphic (SVG) sniði. SVG býður upp á nokkra umfram "raster"-byggðar myndir eins og jpeg eða png.

    • hægt að breyta stærð án þess að tapa upplausn
    • hægt að vinna með myndirnar í myndvinnsluforritum sem höndla vector-grafík, til dæmis færa til annoteringar ef vill
    • ef nauðsyn krefur er hægt að breyta yfir í EPS-snið til að senda til birtingar í vísindaritum

    Til að skoða SVG-myndir þarftu að hafa vafra sem styður SVG-sniðið, td. Adobe "plugin" fyrir vefvafra, eða Adobe Illustrator myndvinnsluforritið.

    Adobe "plugin": Macintosh | Windows
    Linuxnotendur geta skoðað þennan hér: Batik SVG Viewer.

    Skoða SVG-mynd í nýjum vafraglugga

    Til að vista þessa mynd á harða diskinn hjá þér, Ctrl-klikkaðu (Macintosh) eða hægri-klikkaðu (Windows) og veldu "Save link to disk".

    END IMAGE_DESCRIPTION => < Til að setja þessa mynd á heimasíðu, afritið þessa vefslóð og setjið í HTML-kóðann svona:

    <IMAGE src="%s" />
    

    Myndin mun líta svona út:

    Ef aðeins yfirlitsmyndin sést að ofan, reynið að minnka stærðina á svæðinu

    END TIMEOUT => <<'END', Fyrirspurn þín tók of langan tíma. Þú gætir hafa valið svæði sem er of stórt til að sýna. Prófaðu að slökkva á einhverjum brautanna, eða minnka svæðið. Ef þetta gerist trekk í trekk, vinsamlega ýttu á "Endursetja" takkann. END GO => 'Keyra', FIND => 'Finna', SEARCH => 'Leita', DUMP => 'Vista', HIGHLIGHT => 'Merkja', ANNOTATE => 'Annotera', SCROLL => 'Skrun/Zoom', RESET => 'Endursetja', FLIP => 'Snúa við', DOWNLOAD_FILE => 'Vista skrá', DOWNLOAD_DATA => 'Vista gögn', DOWNLOAD => 'Vista', DISPLAY_SETTINGS => 'Stillinga glugga', TRACKS => 'Brautir', EXTERNAL_TRACKS => "(Utanaðkomandi brautir skáletraðar)
    *Yfirlitsbraut", OVERVIEW_TRACKS => '*Yfirlitsbraut', REGION_TRACKS => '**Svæðisbraut', EXAMPLES => 'Dæmi', REGION_SIZE => 'Stærð svæðis (bp)', HELP => 'Hjálp', HELP_FORMAT => 'Hjálp fyrir skjásnið', CANCEL => 'Hætta við', ABOUT => 'Um...', REDISPLAY => 'Sýna aftur', CONFIGURE => 'Stillingar...', EDIT => 'Breyta skrá...', DELETE => 'Eyða skrá', EDIT_TITLE => 'Bæta við eða breyta annoteringum', IMAGE_WIDTH => 'Breidd myndar', BETWEEN => 'Milli', BENEATH => 'Undir', LEFT => 'Vinstri', RIGHT => 'Hægri', TRACK_NAMES => 'Tafla yfir nöfn á brautum', ALPHABETIC => 'Stafrófsröð', VARYING => 'Breytilegt', SET_OPTIONS => 'Breyta stillingum fyrir brautir...', UPDATE => 'Uppfæra mynd', DUMPS => 'Dump, leitir og aðrar aðgerðir', DATA_SOURCE => 'Gagnalind', UPLOAD_TRACKS => 'Bæta við eigin brautum', UPLOAD_TITLE=> 'Vista eigin annoteringar á vef', UPLOAD_FILE => 'Vista eigin skrá á vef', KEY_POSITION => 'Staðsetning lykils', BROWSE => 'Vafra...', UPLOAD => 'Hlaða upp', NEW => 'Nýtt...', REMOTE_TITLE => 'Bæta við eigin annoteringum', REMOTE_URL => 'Slá inn vefslóð fyrir utanaðkomandi annoteringar', UPDATE_URLS => 'Uppfæra vefslóðir', PRESETS => '--Velja fyrirfram uppsettar vefslóðir--', FEATURES_TO_HIGHLIGHT => 'Kennileiti sem merkja á (kennileiti1, kennileiti2...)', FEATURES_TO_HIGHLIGHT_HINT => 'Vísbending: notaðu kennileiti@litur til að velja litinn, t.d. \'NUT21@lightblue\' ', REGIONS_TO_HIGHLIGHT => 'Merkja svæði (svæði1:start..end svæði2:start..end)', REGIONS_TO_HIGHLIGHT_HINT => 'Vísbending: notaðu svæði@litur, t.d. \'Chr1:1000..2000@lightblue\'', NO_TRACKS => '*engar*', FILE_INFO => 'Síðast uppfært %s. Annoteruð kennileiti: %s', FOOTER_1 => < 'Generic genome browser version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Eftirfarandi %d svæði samsvara fyrirspurninni.', POSSIBLE_TRUNCATION => 'Niðurstöður leitur eru takmarkaðir við %s atriði; listinn er hugsanlega ekki tæmandi', MATCHES_ON_REF => ' Fundið á %s', SEQUENCE => 'röð;', SCORE => 'skor=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Stillingar fyrir %s', UNDO => 'Afturkalla breytingar', REVERT => 'Breyta yfir i sjálfgefnar stillingar', REFRESH => 'Hlaða síðu aftur', CANCEL_RETURN => 'Hætta við breytingar og fara til baka...', ACCEPT_RETURN => 'Virkja breytingar og fara til baka...', OPTIONS_TITLE => 'Brautarstillingar', SETTINGS_INSTRUCTIONS => <Sýna segir til um hvort braut er sýnileg eða ekki. Samþjappað þjappar brautinni saman a eina línu þannig að annoteringar munu skarast. Breiða úr og Breiða meira úr hindra annoteringar í að rekast hver á aðra, með hægvirkari og hraðvirkari algorithmum Breiða úr & merkja og Breiða meira úr & mergja setur merki (e. labels) á allar annoteringar. Ef Sjálfvirkt er valið eru árekstrar- og merkjastillingar settar eftir því sem pláss leyfir. Til að breyta því hvernig brautirnar raðast upp, notið Breyta uppöðun brauta til að setja tiltekna annoteringu á brautina. Til að takmarka hversu margar annoteringar af tiltekinni tegund eru sýndar, notið Takmarka fjölda valmyndina. END TRACK => 'Braut', TRACK_TYPE => 'Tegund brautar', SHOW => 'Sýna', FORMAT => 'Snið', LIMIT => 'Takmarka fjölda', ADJUST_ORDER => 'Stilla uppröðun brauta', CHANGE_ORDER => 'Breyta uppröðun brauta', AUTO => 'Sjálfvirkt', COMPACT => 'Samþjappað', EXPAND => 'Breiða úr', EXPAND_LABEL => 'Breiða úr & merkja', HYPEREXPAND => 'Breiða meira úr', HYPEREXPAND_LABEL =>'Breiða meira úr & merkja', NO_LIMIT => 'Engin takmörkun', OVERVIEW => 'Yfirlit', GENERAL => 'Almennt', DETAILS => 'Nánar', ALL_ON => 'Virkja allar', ALL_OFF => 'Afvirkja allar', ANALYSIS => 'Greining', REGION => 'Svæði', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Loka þessum glugga', TRACK_DESCRIPTIONS => 'Lýsingar og titlar á brautum', BUILT_IN => 'Brautir innbyggðar í þennan vefþjón', EXTERNAL => 'Utanaðkomandi annoteringarbrautir', ACTIVATE => 'Vinsamlega virkjið þessa braut til að sjá hvað er á henni...', NO_EXTERNAL => 'Engar utanaðkomandi annoteringar hlaðnar inn.', NO_CITATION => 'Engar frekari upplýsingar fáanlegar.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Um %s', BACK_TO_BROWSER => 'Aftur til GBrowse', PLUGIN_SEARCH_1 => '%s (leit með %s)', PLUGIN_SEARCH_2 => '<%s leit>', CONFIGURE_PLUGIN => 'Stilla', BORING_PLUGIN => 'Þessi plugin hefur engar auka stillimöguleika.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'Kennileitið %s fannst ekki. Sjá hjálparsíður fyrir uppástungur.', TOO_BIG => 'Nánari sýn er takmörkuð við %s bp. Smellið á yfirlitsmyndina til velja svæði sem er %s bp að stærð.', PURGED => "Finn ekki skrána %s. Hefur henni verið hent?", NO_LWP => "Þessi vefþjónn er ekki stilltur til að ná í utanaðkomandi vefslóðir", FETCH_FAILED => "Gat ekki náð í %s: %s.", TOO_MANY_LANDMARKS => '%d kennileiti. Of mörg til að telja upp!.', SMALL_INTERVAL => 'Breyti stærð svæðis í %s bp', CLEAR_HIGHLIGHTING => 'Fjarlægja merkingar', CONFIGURE_TRACKS => 'Stilla brautir...', NO_SOURCES => 'Engar aðgengilegar gagnalindir stilltar. Kannske hefur þú ekki leyfi til að skoða þær', }; GBrowse-2.56/conf/languages/it.pm000444001750001750 2343513036764442 17037 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! # Translation by: Marco Mangone { CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Visualizzatore Genomico', SEARCH_INSTRUCTIONS => < <salvare questo collegamento tra i preferiti. END EDIT_INSTRUCTIONS => < 'Mappa di %s da %s, posizione %s - %s', INTRUCTIONS => 'Istruzioni', HIDE => 'Nascondi', SHOW => 'Mostra', SHOW_INSTRUCTIONS => 'Mostra Istruzioni', HIDE_INSTRUCTIONS => 'Nascondi Istruzioni', SHOW_HEADER => 'Mostra banner', HIDE_HEADER => 'Nascondi banner', LANDMARK => 'Elemento Genomico o Regione', BOOKMARK => 'Aggiungi ai Preferiti', IMAGE_LINK => "Vai all'Immagine", SVG_LINK => 'Immagine ad Alta Risoluzione', GO => 'Vai', FIND => 'Cerca', DUMP => 'Scarica', ANNOTATE => 'Annota', SCROLL => 'Sfoglia/Zoom', RESET => 'Ripristina', DOWNLOAD_FILE => 'Scarica File', DOWNLOAD_DATA => 'Scarica dati', DOWNLOAD => 'Scarica', DISPLAY_SETTINGS => 'Visualizza parametri', TRACKS => 'Tracce', ALPHABETIC => 'Alphabetico', BENEATH => 'Sotto', BETWEEN => 'In Mezzo', FLIP => 'Gira', HIDE_HEADER => 'Nascondi Banner', HIDE_INSTRUCTIONS => 'Nascondi Instruzioni', HIGHLIGHT => 'Evidenzia', EXTERNAL_TRACKS => '(Tracce esterne in corsivo)', EXAMPLES => 'Esempi', HELP => 'Guida', HELP_FORMAT => 'Aiuto con in formati dei files', CANCEL => 'Annulla', ABOUT => 'Informazioni...', REDISPLAY => 'Rivisualizza', CONFIGURE => 'Configura', EDIT => 'Modifica file', DELETE => 'Cancella file', EDIT_TITLE => 'Inserisci/modifica dati', IMAGE_WIDTH => 'Lunghezza immagine', SET_OPTIONS => 'Configura opzioni delle tracce...', UPDATE => 'Aggiorna immagine', DUMPS => 'Scaricamento, Ricerca e altre operazioni', DATA_SOURCE => 'Origine dei dati', UPLOAD_TITLE=> 'Carica le tue annotazioni', UPLOAD_FILE => 'Carica un file', BROWSE => 'Sfoglia...', UPLOAD => 'Carica', REMOTE_TITLE => 'Aggiungi annotazioni remote', REMOTE_URL => 'Inserisci URL di annotazioni remote', UPDATE_URLS => 'Aggiorna URLs', PRESETS => '--Scegli URL predefinito--', FILE_INFO => 'Ultima modifica %s. Oggetti annotati: %s', FOOTER_1 => < 'Visualizzatore genomico generico versione %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Le seguenti %d regioni soddisfano la tua richiesta', POSSIBLE_TRUNCATION => 'I risultati della ricerca sono limitati a %d\' valori; La lista potrebbe essere incompleta', MATCHES_ON_REF => 'Corrispondenza su %s', SEQUENCE => 'sequenza', SCORE => 'punteggio=%s', NOT_APPLICABLE => '..', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Configurazione per %s', UNDO => 'Annulla modifiche', REVERT => 'Torna alla configurazione standard', REFRESH => 'Aggiorna', CANCEL_RETURN => 'Annulla modifiche e torna indietro...', ACCEPT_RETURN => 'Accetta le modifiche e torna indietro...', OPTIONS_TITLE => 'Opzioni di traccia', SETTINGS_INSTRUCTIONS => <Mostra attiva o disattiva la traccia. L' opzione Compatto forza la compressione delle tracce sì che le annotazioni vengano sovrapposte. Le opzioni Espandi e Iper-espandi attivano il controllo di collisione utilizzando algoritmi di allineamento rispettivamente lenti o veloci. Le opzioni Espandi & Etichetta e Iper-espandi & Etichetta servono a contrassegnare le annotazioni. Selezionando Automatico, il controllo di collisione e le opzioni di etichettatura vengono attivate automaticamente, spazio consentendo. Per cambiare l'ordine delle tracce, usare il menu Cambia ordine delle tracce per assegnare un'annotazione ad una traccia. Per limitare il numero di annotazioni di questo tipo visualizzate, cambiare il valore del menu Limiti. END IMAGE_DESCRIPTION => < Per creare una immagine allegata usando questa immagine 'taglia e incolla' questo Indirizzo Internet in una pagina ipertestuale:

    <IMAGE src="%s" />
    

    L`immagine rassomigliera` a questa:

    Se l`immagine mostrata (sia cromosomica o del contiguo) e` parziale o incompleta, prova a ridurre la grandezza della regione.

    END SVG_DESCRIPTION => < Il Seguente link ipertestuale generera` questa immagine in formato vettoriale Scalabile (SVG). Il formato SVG offre molti vantaggi rispetto a il formato jpeg oppure png.

    • e` completamente scalabile senza perdita di risoluzione
    • e` completamente editabile usando i comuni programmi di grafica vettoriale
    • se necessario, puo` essere convertito in formato EPS per necessita` di pubblicazione

    Per poter vedere una immagine in formato SVG e` necessario avere in browser compatibile e il Plug-in di Adobe chiamato 'SVG browser' oppure una applicazione che permette di leggere files con le estensioni .SVG come Adobe Illustrator.

    Adobe's SVG browser plugin: Macintosh | Windows
    Gli utenti Linux possono utilizzare il Visualizzatore SVG di Batik SVG.

    Apri l`immagine in una nuova finestra

    Per salvare questa immagine nel disco rigido premi control (utenti Machintosh) oppure tasto destro del mouse (utenti Windows) e seleziona l`opzione 'salva' su disco rigido.

    END SVG_LINK => 'Immagine in qualita` di pubblicazione', TIMEOUT => <<'END', La tua richiesta e` espirata. Tu potresti aver selezionato una regione troppo grande da mostrare in una schermata. Puoi o de-selezionare alcune tracce oppure provare con una regione piu` piccola. Se il problema si ripropone Either turn off some tracks or try a smaller region. If you are experiencing persistent timeouts, please press the red "Reset" button. END TRACK_NAMES => 'Tavola nomi tracce', IMAGE_LINK => 'Collega questa schermata ad un`immagine', VARYING => 'Variazione', INSTRUCTIONS => 'Istruzioni', KEY_POSITION => 'Posizione tasto', LEFT => 'Sinistra', RIGHT => 'Destra', NEW => 'Nuovo...', POSSIBLE_TRUNCATION => 'I risulati di questa ricerca sono limitati a %d ; Questa lista potrebbe essere incompleta.', SEARCH => 'Cerca', SHOW_HEADER => 'Mostra Banner', SHOW_INSTRUCTIONS => 'Mostra Istruzioni', TRACK => 'Traccia', TRACK_TYPE => 'Tipo traccia', SHOW => 'Mostra', FORMAT => 'Formato', LIMIT => 'Limiti', ADJUST_ORDER => 'Riordina', CHANGE_ORDER => 'Cambia l\'ordine delle tracce', AUTO => 'Automatico', COMPACT => 'Compatto', EXPAND => 'Espandi', EXPAND_LABEL => 'Espandi & Etichetta', HYPEREXPAND => 'Iper-espandi', HYPEREXPAND_LABEL =>'Iper-espandi & Etichetta', NO_LIMIT => 'Senza limiti', OVERVIEW => 'Panoramica', EXTERNAL => 'Esterna', ANALYSIS => 'Analisi', GENERAL => 'Generale', DETAILS => 'Dettagli', ALL_ON => 'Mostra tutto', ALL_OFF => 'Nascondi tutto', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Chiudi la finestra', TRACK_DESCRIPTIONS => 'Descrizione delle tracce & Citazioni', BUILT_IN => 'Tracce annotate su questo server', EXTERNAL => 'Tracce annotate esternamente', ACTIVATE => 'Attivare questa traccia per visualizzare le relative informazioni.', NO_EXTERNAL => 'Nessuna caratteristica esterna è caricata.', NO_CITATION => 'Informazioni addizionali non disponibili.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Informazioni su %s', BACK_TO_BROWSER => 'Torna al Visualizzatore', PLUGIN_SEARCH_1 => '%s (mediante ricerca %s)', PLUGIN_SEARCH_2 => '<ricerca %s>', CONFIGURE_PLUGIN => 'Configura', BORING_PLUGIN => 'Questo plugin non ha alcuna configurazione extra.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => "L'oggetto %s è sconosciuto. Vedi la pagina di aiuto per suggerimenti.", TOO_BIG => "Visualizzazione dei dettagli limitata a %s basi. Fare clic sull'immagine per selezionare una regione di %s bp.", PURGED => "Non trovo il file %s. Non sarà stato cancellato?.", NO_LWP => "Questo server non è configurato per accedere ad URL esterni.", FETCH_FAILED => "Non riesco a prelevare %s: %s.", TOO_MANY_LANDMARKS => '%d punti sono troppi per elencarli singolarmente.', SMALL_INTERVAL => 'Computazione piccolo intervallo a %s pb', NO_SOURCES =>'input dati non e` stato configurato oppure non hai il permesso di vederli', }; GBrowse-2.56/conf/languages/ja.pm000444001750001750 2362613036764442 17017 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { # Translated by Toshiaki Katayama # Sat Jun 12 23:11:24 JST 2004 CHARSET => 'euc-jp', #---------- # MAIN PAGE #---------- PAGE_TITLE => '¥²¥Î¥à¥Ö¥é¥¦¥¶¡¼', SEARCH_INSTRUCTIONS => < < < '%s ¤ÎÈϰϤò %s ¤«¤éɽ¼¨¡¢±ö´ðÈÖ¹æ %s ¤«¤é %s', INSTRUCTIONS => 'ÀâÌÀ', HIDE => '±£¤¹', SHOW => 'ɽ¼¨', SHOW_INSTRUCTIONS => 'ÀâÌÀ¤òɽ¼¨', HIDE_INSTRUCTIONS => 'ÀâÌÀ¤ò±£¤¹', SHOW_HEADER => '¥Ð¥Ê¡¼¤òɽ¼¨', HIDE_HEADER => '¥Ð¥Ê¡¼¤ò±£¤¹', LANDMARK => '¥é¥ó¥É¥Þ¡¼¥¯¤Þ¤¿¤ÏÎΰè', BOOKMARK => '¤³¤Îɽ¼¨¤ò¥Ö¥Ã¥¯¥Þ¡¼¥¯', IMAGE_LINK => '¤³¤Î²èÁü¤Ø¤Î¥ê¥ó¥¯', SVG_LINK => '¹âÉʼÁSVG²èÁü', SVG_DESCRIPTION => < ¢ª SVG ²èÁü¤ò¿·¤·¤¤¥¦¥£¥ó¥É¥¦¤Çɽ¼¨

    ¤³¤Î¥ê¥ó¥¯¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È SVG (Scalable Vector Graphic) ¥Õ¥©¡¼¥Þ¥Ã¥È¤Î²èÁü¤¬ À¸À®¤µ¤ì¤Þ¤¹¡£SVG ²èÁü¤Ë¤Ï jpeg ¤ä png ¤Ê¤É¤Î¥é¥¹¥¿²èÁü¤ÈÈæ³Ó¤·¤Æ ¼¡¤Î¤è¤¦¤ÊÍøÅÀ¤¬¤¢¤ê¤Þ¤¹¡£

    • ²òÁüÅÙ¤òµ¾À·¤Ë¤»¤º¡¢¼«Í³¤Ë¥µ¥¤¥º¤òÊѹ¹¤Ç¤­¤ë
    • °ìÈÌŪ¤Ê²èÁü½èÍý¥½¥Õ¥È¤òÍøÍѤ·¤Æ¡¢¥Õ¥£¡¼¥Á¥ã¡¼¤´¤È¤Ë¼«Í³¤ÊÊÔ½¸¤¬¤Ç¤­¤ë
    • ÏÀʸÅê¹ÆÍѤʤɡ¢É¬Íפ˱þ¤¸¤Æ EPS ¥Õ¥©¡¼¥Þ¥Ã¥È¤ËÊÑ´¹¤Ç¤­¤ë

    SVG ²èÁü¤ò¸«¤ë¤¿¤á¤Ë¤Ï¡¢Adobe SVG browser ¥×¥é¥°¥¤¥ó¤Ê¤É¤Î SVG Âбþ ¥Ö¥é¥¦¥¶¤¬¡¢ÊÔ½¸¤¹¤ë¤¿¤á¤Ë¤Ï¡¢Adobe Illustrator ¤Ê¤É¤Î¥½¥Õ¥È¥¦¥§¥¢¤¬ ɬÍפˤʤê¤Þ¤¹¡£

    SVG ²èÁü¤òÊݸ¤¹¤ë¤Ë¤Ï¡¢¾åµ­¤Î¥ê¥ó¥¯¤ò Macintosh ¤Î¾ì¹ç¥³¥ó¥È¥í¡¼¥ë¥­¡¼¤ò ²¡¤·¤Ê¤¬¤é¥¯¥ê¥Ã¥¯¡¢Windows ¤Î¾ì¹ç±¦¥¯¥ê¥Ã¥¯¤·¤Æ¡¢¥ê¥ó¥¯Àè¤ò¥Ç¥£¥¹¥¯¤ËÊݸ¤¹¤ë ¥ª¥×¥·¥ç¥ó¤òÁª¤Ó¤Þ¤¹¡£

    END IMAGE_DESCRIPTION => < ¤³¤Î²èÁü¤ò HTML ¥Ú¡¼¥¸¤ËËä¤á¹þ¤à¤Ë¤Ï¡¢¼¡¤Î URL ¤ò¥³¥Ô¡¼¡õ¥Ú¡¼¥¹¥È¤·¤Þ¤¹:

    <IMAGE src="%s" />
    

    ²èÁü¤Ï¤³¤Î¤è¤¦¤Ëɽ¼¨¤µ¤ì¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹:

    ¤â¤·¡ÊÀ÷¿§ÂΤ䥳¥ó¥Æ¥£¥°¤Ê¤É¡Ë¥ª¡¼¥Ð¡¼¥Ó¥å¡¼¤·¤«É½¼¨¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¡¢ Îΰè¤Î¥µ¥¤¥º¤ò½Ì¤á¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£

    END TIMEOUT => <<'END', ½èÍý¤¬¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿¡£ ÁªÂò¤·¤¿Îΰ褬°ìÅÙ¤Ëɽ¼¨¤¹¤ë¤Ë¤Ï¹­¤¹¤®¤¿²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹¡£ ɽ¼¨Îΰè¤ò¶¹¤á¤ë¤«ÉÔÍפʹàÌܤòɽ¼¨¤·¤Ê¤¤¤è¤¦¤Ë¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£ ¥¿¥¤¥à¥¢¥¦¥È¤¬Â³¤¯¾ì¹ç¤ÏÀÖ¿§¤Î¡Ö¥ê¥»¥Ã¥È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£ END GO => '¼Â¹Ô', FIND => '¸¡º÷', SEARCH => '¸¡º÷', DUMP => '½ÐÎÏ', HIGHLIGHT => '¶¯Ä´', ANNOTATE => '²òÀÏ', SCROLL => '¥¹¥¯¥í¡¼¥ë/¥º¡¼¥à', RESET => '¥ê¥»¥Ã¥È', FLIP => 'ȿž', DOWNLOAD_FILE => '¥Õ¥¡¥¤¥ë¤ò¥À¥¦¥ó¥í¡¼¥É', DOWNLOAD_DATA => '¥Ç¡¼¥¿¤ò¥À¥¦¥ó¥í¡¼¥É', DOWNLOAD => '¥À¥¦¥ó¥í¡¼¥É', DISPLAY_SETTINGS => 'ɽ¼¨ÀßÄê', TRACKS => 'ɽ¼¨¹àÌÜ', EXTERNAL_TRACKS => '(³°Éô¤Î¹àÌܤϼÐÂÎɽ¼¨)', OVERVIEW_TRACKS => '*¥ª¡¼¥Ð¡¼¥Ó¥å¡¼¤Î¹àÌÜ', REGION_TRACKS => '**Îΰè¤Î¹àÌÜ', EXAMPLES => 'Îã', REGION_SIZE => 'Îΰè¤Î¥µ¥¤¥º (bp)', HELP => '¥Ø¥ë¥×', HELP_FORMAT => '¥Õ¥¡¥¤¥ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¤Ä¤¤¤Æ¥Ø¥ë¥×', CANCEL => '¼è¤ê¾Ã¤·', ABOUT => '²òÀâ...', REDISPLAY => 'ºÆÉÁ²è', CONFIGURE => 'ÀßÄê...', CONFIGURE_TRACKS => '¹àÌܤÎÀßÄê...', EDIT => '¥Õ¥¡¥¤¥ë¤òÊÔ½¸...', DELETE => '¥Õ¥¡¥¤¥ë¤òºï½ü', EDIT_TITLE => '¥¢¥Î¥Æ¡¼¥·¥ç¥ó¥Ç¡¼¥¿¤ÎÆþÎÏ/ÊÔ½¸', IMAGE_WIDTH => '²èÁü¤Î²£Éý', BETWEEN => '¹àÌÜ´Ö', BENEATH => '²¼Ã¼', LEFT => 'º¸Ã¼', RIGHT => '±¦Ã¼', TRACK_NAMES => '¹àÌÜ̾¥ê¥¹¥È', ALPHABETIC => '̾Á°½ç', VARYING => '¼ïÎàÊÌ', SET_OPTIONS => '¹àÌÜËè¤ÎÀßÄê...', CLEAR_HIGHLIGHTING => '¶¯Ä´É½¼¨¤ò²ò½ü', UPDATE => '²èÁü¤ò¹¹¿·', DUMPS => '½ÐÎϤä²òÀϤʤɤÎÁàºî', DATA_SOURCE => '¥Ç¡¼¥¿¥½¡¼¥¹', UPLOAD_TRACKS => '¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ÎÄɲÃ', UPLOAD_TITLE => 'ÆÈ¼«¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ò¥¢¥Ã¥×¥í¡¼¥É', UPLOAD_FILE => '¥¢¥Ã¥×¥í¡¼¥É¤¹¤ë¥Õ¥¡¥¤¥ë', KEY_POSITION => '¹àÌܤÎɽ¼¨°ÌÃÖ', BROWSE => 'ÁªÂò...', UPLOAD => '¥¢¥Ã¥×¥í¡¼¥É', NEW => '¿·µ¬...', REMOTE_TITLE => '³°Éô¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÄɲÃ', REMOTE_URL => '³°Éô¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ÎURL', UPDATE_URLS => 'URL¤ò¹¹¿·', PRESETS => '--¥ê¥¹¥È¤«¤é URL ¤òÁªÂò--', FEATURES_TO_HIGHLIGHT => '¥Õ¥£¡¼¥Á¥ã¡¼¤ò¶¯Ä´É½¼¨ (feature1@color1 feature2@color2 ...)', REGIONS_TO_HIGHLIGHT => 'Îΰè¤ò¶¯Ä´É½¼¨ (region1:start..end@color1 region2:start..end@color2 ...)', FEATURES_TO_HIGHLIGHT_HINT => '¥Ò¥ó¥È¡§ ¥Õ¥£¡¼¥Á¥ã¡¼¡Ê°äÅÁ»Ò̾Åù¡Ë¤ò¶¯Ä´É½¼¨¤¹¤ë¤Ë¤Ï¡Ö¥Õ¥£¡¼¥Á¥ã¡¼@¿§¡×¤ò \'NUT21@lightblue\' ¤Î½ñ¼°¤Ç»ØÄê', REGIONS_TO_HIGHLIGHT_HINT => '¥Ò¥ó¥È¡§ Îΰè¤ò¶¯Ä´É½¼¨¤¹¤ë¤Ë¤Ï¡ÖÎΰè@¿§¡×¤ò \'Chr1:10000..20000@lightblue\' ¤Î½ñ¼°¤Ç»ØÄê', NO_TRACKS => '(¤Ê¤·)', FILE_INFO => 'ºÇ½ª¹¹¿·Æü %s / ¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤µ¤ì¤¿¥é¥ó¥É¥Þ¡¼¥¯: %s', FOOTER_1 => < 'Generic genome browser ¥Ð¡¼¥¸¥ç¥ó %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => '°Ê²¼¤Î %d Îΰ褬¥Þ¥Ã¥Á¤·¤Þ¤·¤¿¡£', POSSIBLE_TRUNCATION => '¸¡º÷·ë²ÌÃæ %d ·ï¤òɽ¼¨ (Á´Éôɽ¼¨¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤¬¤¢¤ê¤Þ¤¹)', MATCHES_ON_REF => '%s ¤Ë¥Þ¥Ã¥Á', SEQUENCE => 'ÇÛÎó', SCORE => '¥¹¥³¥¢=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => '%s ¤ÎÀßÄê', UNDO => 'Êѹ¹¤Î¼è¤ê¾Ã¤·', REVERT => '¥Ç¥Õ¥©¥ë¥ÈÃͤËÌ᤹', REFRESH => '¹¹¿·', CANCEL_RETURN => 'Êѹ¹¤ò¼è¤ê¾Ã¤·¤ÆÌá¤ë...', ACCEPT_RETURN => 'Êѹ¹¤òŬÍѤ·¤ÆÌá¤ë...', OPTIONS_TITLE => '¹àÌܤΥª¥×¥·¥ç¥ó', SETTINGS_INSTRUCTIONS => <ɽ¼¨
    ¥Á¥§¥Ã¥¯¥Ü¥Ã¥¯¥¹¤Ç¹àÌܤò¥ª¥ó¡¦¥ª¥Õ¤·¤Þ¤¹¡£ ´Ê°× ¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¹àÌܤò½Ì¤á¤ÆÉ½¼¨¤¹¤ë¤¿¤á ¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤¬¥ª¡¼¥Ð¡¼¥é¥Ã¥×¤¹¤ë²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹¡£ ³ÈÄ¥ ¤È ÆÃÊÌ ¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤Î ¥ì¥¤¥¢¥¦¥È¤ËÃÙ¤¤¤Þ¤¿¤Ï®¤¤½Å¤Ê¤ê¸¡½Ð¥¢¥ë¥´¥ê¥º¥à¤ò»È¤¤¤Þ¤¹¡£ ³ÈÄ¥ & ¥é¥Ù¥ë ¤È ÆÃÊÌ & ¥é¥Ù¥ë ¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤Ëɬ¤º¥é¥Ù¥ë¤ò¤Ä¤±¤Þ¤¹¡£ ¼«Æ° ¤òÁª¤ó¤À¾ì¹ç¤Ë¤Ï¡¢¥¹¥Ú¡¼¥¹¤¬¤¢¤ë¸Â¤ê¡¢ ½Å¤Ê¤ê¸¡½Ð¤È¥é¥Ù¥ëµ¡Ç½¤¬¼«Æ°Åª¤ËÍ­¸ú¤Ë¤Ê¤ê¤Þ¤¹¡£ ¹àÌܤνçÈÖ¤òÊѹ¹¤¹¤ë¤Ë¤Ï ½çÈÖ¤ÎÊѹ¹ ¥Ý¥Ã¥×¥¢¥Ã¥×¥á¥Ë¥å¡¼¤ò »È¤Ã¤Æ¤½¤Î°ÌÃÖ¤Ëɽ¼¨¤·¤¿¤¤¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ò»ØÄꤷ¤Þ¤¹¡£ ɽ¼¨¤µ¤ì¤ë¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤Î¿ô¤òÀ©¸Â¤¹¤ë¤Ë¤Ï ¥ê¥ß¥Ã¥È ¥á¥Ë¥å¡¼¤Î ÃͤòÊѹ¹¤·¤Þ¤¹¡£ END TRACK => '¹àÌÜ', TRACK_TYPE => '¹àÌܤΥ¿¥¤¥×', SHOW => 'ɽ¼¨', FORMAT => '¥Õ¥©¡¼¥Þ¥Ã¥È', LIMIT => '¥ê¥ß¥Ã¥È', ADJUST_ORDER => '½çÈÖ¤ÎÄ´À°', CHANGE_ORDER => '½çÈÖ¤ÎÊѹ¹', AUTO => '¼«Æ°', COMPACT => '´Ê°×', EXPAND => '³ÈÄ¥', EXPAND_LABEL => '³ÈÄ¥ & ¥é¥Ù¥ë', HYPEREXPAND => 'ÆÃÊÌ', HYPEREXPAND_LABEL => 'ÆÃÊÌ & ¥é¥Ù¥ë', NO_LIMIT => '̵À©¸Â', OVERVIEW => '¥ª¡¼¥Ð¡¼¥Ó¥å¡¼', EXTERNAL => 'ÄɲùàÌÜ', ANALYSIS => '²òÀϹàÌÜ', GENERAL => '°ìÈ̹àÌÜ', DETAILS => '¾ÜºÙ¥Ó¥å¡¼', REGION => 'Îΰè', ALL_ON => 'Á´¤Æ¥ª¥ó', ALL_OFF => 'Á´¤Æ¥ª¥Õ', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => '¤³¤Î¥¦¥£¥ó¥É¥¦¤òÊĤ¸¤ë', TRACK_DESCRIPTIONS => '¹àÌܤβòÀâ¤È°úÍÑ', BUILT_IN => '¤³¤Î¥µ¡¼¥Ð¤Ë¤¢¤ë¹àÌÜ', # EXTERNAL => '³°Éô¤Î¥¢¥Î¥Æ¡¼¥·¥ç¥ó¹àÌÜ', ACTIVATE => '¤³¤Î¹àÌܤξðÊó¤ò¸«¤ë¤Ë¤Ï¤³¤Î¹àÌܤòÍ­¸ú¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£', NO_EXTERNAL => '³°Éô¤Î¥Õ¥£¡¼¥Á¥ã¡¼¤Ï¥í¡¼¥É¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£', NO_CITATION => '¾¤Î¾ðÊó¤Ï¤¢¤ê¤Þ¤»¤ó¡£', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => '%s ¤Ë¤Ä¤¤¤Æ', BACK_TO_BROWSER => '¥Ö¥é¥¦¥¶¤ËÌá¤ë', PLUGIN_SEARCH_1 => '%s (%s ¤Ë¤è¤ë¸¡º÷)', PLUGIN_SEARCH_2 => '<%s ¸¡º÷>', CONFIGURE_PLUGIN => 'ÀßÄê', BORING_PLUGIN => '¤³¤Î¥×¥é¥°¥¤¥ó¤Ë¤Ï¤½¤Î¾¤ÎÀßÄê¹àÌܤϤ¢¤ê¤Þ¤»¤ó¡£', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => '%s ¤È¤¤¤¦¥é¥ó¥É¥Þ¡¼¥¯¤Ïǧ¼±¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿¡£¥Ø¥ë¥×¥Ú¡¼¥¸¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£', TOO_BIG => '¾ÜºÙ¥Ó¥å¡¼¤Ï %s ¤Þ¤Ç¤Ç¤¹¡£¥ª¡¼¥Ð¡¼¥Ó¥å¡¼¤ò¥¯¥ê¥Ã¥¯¤·¤Æ %s ¤ÎÎΰè¤òÁª¤ó¤Ç¤¯¤À¤µ¤¤¡£', PURGED => '%s ¤È¤¤¤¦Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤Ï¸«¤¢¤¿¤ê¤Þ¤»¤ó¡£¤¹¤Ç¤Ë¾Ã¤µ¤ì¤Æ¤·¤Þ¤Ã¤¿²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹¡£', NO_LWP => '¤³¤Î¥µ¡¼¥Ð¤Ï³°Éô¤Î URL ¤«¤é¾ðÊó¤ò¼è¤ì¤ë¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó¡£', FETCH_FAILED => '%s ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: %s.', TOO_MANY_LANDMARKS => '¥é¥ó¥É¥Þ¡¼¥¯¿ô %d ¤Ï¿¤¹¤®¤ë¤¿¤áɽ¼¨¤ò¾Êά¤·¤Þ¤¹¡£', SMALL_INTERVAL => '¾®¤µ¤Ê´Ö³Ö¤ò %s bp ¤Ë¥ê¥µ¥¤¥º¤·¤Þ¤·¤¿¡£', NO_SOURCES => 'ɽ¼¨²Äǽ¤Ê¥Ç¡¼¥¿¥½¡¼¥¹¤¬¤¢¤ê¤Þ¤»¤ó¡£¥Ç¡¼¥¿¤Î±ÜÍ÷¤¬µö²Ä¤µ¤ì¤Æ¤¤¤Ê¤¤²ÄǽÀ­¤â¤¢¤ê¤Þ¤¹¡£' }; GBrowse-2.56/conf/languages/ko.pm000444001750001750 2136713036764442 17036 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! # translated by Linus Taejoon Kwon (linusben bawi org) # Last modified : 2002-10-06 { CHARSET => 'euc-kr', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome Browser', SEARCH_INSTRUCTIONS => < <ÀÌ ¸µÅ©¸¦ Áñ°Üã±â¿¡ Ãß°¡Çϼ¼¿ä. END EDIT_INSTRUCTIONS => < 'ÀÌ %s Á¤º¸´Â %s ÀÇ %s - %s »çÀÌÀÇ Á¤º¸ÀÔ´Ï´Ù', INSTRUCTIONS => '¼³¸í', HIDE => '¼û±â±â', SHOW => 'º¸¿©ÁÖ±â', SHOW_INSTRUCTIONS => '¼³¸í º¸±â', HIDE_INSTRUCTIONS => '¼³¸í ¼û±â±â', SHOW_HEADER => 'Á¦¸ñ º¸±â', HIDE_HEADER => 'Á¦¸ñ ¼û±â±â', LANDMARK => 'Ç¥Áö ȤÀº ¿µ¿ª', BOOKMARK => 'Áñ°Üã±â Ãß°¡', IMAGE_LINK => 'À̹ÌÁö ¸µÅ©', SVG_LINK => '°íÇØ»óµµ À̹ÌÁö', SVG_DESCRIPTION => < ÀÌ ¸µÅ©ÀÇ À̹ÌÁö´Â SVG(Scalable Vector Graphics) Çü½ÄÀ¸·Î »ý¼ºµË´Ï´Ù. SVG À̹ÌÁö´Â jpeg À̳ª png ¿Í °°Àº Á¡À¸·Î ÀÌ·ç¾îÁø À̹ÌÁöº¸´Ù ¸î ´ÙÀ½°ú °°Àº ¸î°¡Áö ÀåÁ¡À» °¡Áö°í ÀÖ½À´Ï´Ù.

    • ÇØ»óµµ ¼Õ½Ç ¾øÀÌ À̹ÌÁöÀÇ Å©±â Á¶ÀýÀÌ °¡´ÉÇÕ´Ï´Ù.
    • ÀϹÝÀûÀÎ ¹éÅÍ ±â¹ÝÀÇ ±×·¡ÇÈ ÇÁ·Î±×·¥¿¡¼­ feature º°·Î ÆíÁýÀÌ °¡´ÉÇÕ´Ï´Ù.
    • ÇÊ¿äÇÒ ¶§ ³í¹® ÃâÆÇÀ» À§ÇÑ EPS Æ÷¸äÀ¸·Î º¯È¯ÇÒ ¼ö ÀÖ½À´Ï´Ù.

    SVG À̹ÌÁö¸¦ º¸±â À§Çؼ­´Â SVG Çü½ÄÀ» Áö¿øÇÏ´Â ºê·¯¿ìÀú³ª Adobe »ç¿¡¼­ Áö¿øÇÏ´Â SVG ºê¶ó¿ìÀú Ç÷¯±×ÀÎ, ¶Ç´Â SVG À̹ÌÁö¸¦ º¸°í ÆíÁýÇÒ ¼ö ÀÖ´Â Adobe Illustrator ¿Í °°Àº º°µµÀÇ ÇÁ·Î±×·¥ÀÌ ÇÊ¿äÇÕ´Ï´Ù.

    Adobe ȍ˂ SVG browser plugin: Macintosh | Windows
    Linux »ç¿ëÀÚµéÀº Batik SVG Viewer¸¦ º¸¼¼¿ä.

    SVG À̹ÌÁö¸¦ »õ ºê¶ó¿ìÀú â¿¡¼­ º¾´Ï´Ù

    ÀÌ ±×¸²À» ÇÏµå µð½ºÅ©¿¡ ÀúÀåÇÏ·Á¸é, control-click (Macintosh) ¶Ç´Â ¸¶¿ì½º ¿À¸¥ÂÊ ¹öư Ŭ¸¯ (Windows) ÀÌÈÄ ´Ù¸¥ À̸§À¸·Î ±×¸² ÀúÀåÀ» ¼±ÅÃÇϼ¼¿ä.

    END IMAGE_DESCRIPTION => < ÀÌ È­¸é¿¡ Æ÷ÇÔµÈ À̹ÌÁö¸¦ ´Ù¸¥ °÷¿¡¼­ »ç¿ëÇÏ°í ½Í´Ù¸é, ¾Æ·¡ÀÇ URL ÁÖ¼Ò¸¦ HTML ÆäÀÌÁö¿¡ º¹»çÇØ¼­ ºÙ¿© ³ÖÀ¸¼¼¿ä:

    <IMAGE src="%s" />
    

    ÀÌ À̹ÌÁö´Â ´ÙÀ½°ú °°ÀÌ º¸ÀÏ °Ì´Ï´Ù:

    ¸¸¾à °³·«ÀûÀÎ ±×¸²(chromosome À̳ª contig view)¸¸ º¸Àδٸé, ¿µ¿ªÀÇ Å©±â¸¦ ÁÙ¿©º¸½Ã±â ¹Ù¶ø´Ï´Ù.

    END TIMEOUT => <<'END', ¿äû¿¡ ´ëÇÑ ½Ã°£ÀÌ ÃʰúµÇ¾ú½À´Ï´Ù. ³Ê¹« ³ÐÀº ¿µ¿ªÀ» ¼±ÅÃÇϽŠ°Í °°½À´Ï´Ù. ¸î¸î Á¤º¸¸¦ º¸ÀÌÁö ¾Ê°Ô Çϰųª ¼±Åà ¿µ¿ªÀ» ÁÙ¿©¼­ ´Ù½Ã ½ÃµµÇغ¸½Ã±â ¹Ù¶ø´Ï´Ù. ¸¸¾à °è¼Ó ½Ã°£ Ãʰú ¹®Á¦°¡ ¹ß»ýÇÏ¸é »¡°£ »öÀÇ "ÃʱâÈ­" ¹öưÀ» ´­·¯º¸¼¼¿ä. END GO => '½ÇÇà', FIND => 'ã±â', SEARCH => '°Ë»ö', DUMP => '³»·Á¹Þ±â(dump)', HIGHLIGHT => 'ÇÏÀ̶óÀÌÆ®', ANNOTATE => 'Annotate', SCROLL => 'À̵¿/È®´ë', RESET => 'ÃʱâÈ­', FLIP => 'µÚÁý±â(flip)', DOWNLOAD_FILE => 'ÆÄÀÏ ³»·Á¹Þ±â', DOWNLOAD_DATA => 'µ¥ÀÌÅÍ ³»·Á¹Þ±â', DOWNLOAD => '³»·Á¹Þ±â', DISPLAY_SETTINGS => 'È­¸é ¼³Á¤', TRACKS => 'Ç¥½Ã Á¤º¸', EXTERNAL_TRACKS => '(¿ÜºÎ Á¤º¸´Â ÀÌÅÚ¸¯À¸·Î Ç¥½ÃµË´Ï´Ù)', OVERVIEW_TRACKS => '*°³·«ÀûÀÎ Á¤º¸', EXAMPLES => '¿¹Á¦', HELP => 'µµ¿ò¸»', HELP_FORMAT => 'ÆÄÀÏ Çü½ÄÀÇ µµ¿ò¸»', CANCEL => 'Ãë¼Ò', ABOUT => 'Ãß°¡ Á¤º¸...', REDISPLAY => '»õ·Î °íħ', CONFIGURE => '¼³Á¤...', EDIT => 'ÆÄÀÏ ¼öÁ¤...', DELETE => 'ÆÄÀÏ »èÁ¦', EDIT_TITLE => 'Anotation Á¤º¸ ÀÔ·Â/ÆíÁý', IMAGE_WIDTH => 'À̹ÌÁö ³ÐÀÌ', BETWEEN => 'Áß°£¿¡ Ç¥½Ã', BENEATH => '¹Ø¿¡ Ç¥½Ã', LEFT => '¿ÞÂÊ', RIGHT => '¿À¸¥ÂÊ', TRACK_NAMES => 'Á¤º¸ À̸§Ç¥', ALPHABETIC => '¾ËÆÄºª¼ø', VARYING => '¼³Á¤¼ø', SET_OPTIONS => 'Ç¥½Ã Á¤º¸ ¼³Á¤...', UPDATE => '±×¸² ´Ù½ÃºÎ¸£±â', DUMPS => '³»·Á¹Þ±â, °Ë»ö ¹× ±âŸ ±â´É', DATA_SOURCE => 'µ¥ÀÌÅÍ Ãâó', UPLOAD_TRACKS=> '³ª¸¸ÀÇ Á¤º¸ Ãß°¡Çϱâ', UPLOAD_TITLE=> '°³ÀÎ annotation Á¤º¸ µî·Ï', UPLOAD_FILE => 'ÆÄÀÏ ¿Ã¸®±â', KEY_POSITION => 'Á¤º¸ Ãâ·Â À§Ä¡', BROWSE => '°Ë»ö...', UPLOAD => '¿Ã¸®±â', NEW => '»õ·Î ¸¸µé±â...', REMOTE_TITLE => '¿ø°Ý annotation Á¤º¸ Ãß°¡', REMOTE_URL => '¿ø°Ý annotation Á¤º¸ÀÇ URLÀ» ÀÔ·ÂÇϼ¼¿ä', UPDATE_URLS => 'URL Á¤º¸ °»½Å', PRESETS => '--URL ¼±ÅÃ--', NO_TRACKS => '*Á¤º¸¾øÀ½*', FILE_INFO => 'ÃÖÁ¾ ¼öÁ¤ %s. annotation Ç¥Áö %s', FOOTER_1 => < 'Generic genome browser ¹öÀü %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => '%d °³ÀÇ ¿µ¿ªÀÌ °Ë»öµÇ¾ú½À´Ï´Ù.', POSSIBLE_TRUNCATION => '°Ë»ö °á°ú°¡ % °³·Î Á¦ÇѵǾú½À´Ï´Ù; ¸ñ·ÏÀÌ ¿ÏÀüÇÏÁö ¾Ê½À´Ï´Ù.', MATCHES_ON_REF => '%s¿¡ ÀÏÄ¡ÇÕ´Ï´Ù', SEQUENCE => '¼­¿­', SCORE => 'score=%s', NOT_APPLICABLE => 'n/a', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => '%sÀ» ¼³Á¤ÇÕ´Ï´Ù', UNDO => 'º¯°æ ³»¿ë Ãë¼Ò', REVERT => '±âº»°ªÀ¸·Î', REFRESH => '»õ·Î °íħ', CANCEL_RETURN => 'º¯°æ ³»¿ë Ãë¼ÒÇÏ°í µ¹¾Æ°¡±â...', ACCEPT_RETURN => 'º¯°æ ³»¿ë ÀúÀåÇÏ°í µ¹¾Æ°¡±â...', OPTIONS_TITLE => '¼±Åà Á¤º¸', SETTINGS_INSTRUCTIONS => <º¸±â
    üũ¹Ú½º¸¦ ÀÌ¿ëÇÏ¿© ¼±Åà Á¤º¸ Ç¥½Ã ¿©ºÎ¸¦ °áÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. °£´ÜÈ÷ ¿É¼ÇÀº ¼±Åà Á¤º¸¸¦ °£´ÜÇÑ ÇüÅ·Πº¸¿©Áֱ⠶§¹®¿¡ annotation Á¤º¸°¡ °ãÄ¡°Ô µË´Ï´Ù. ÀÌ ¶§ È®Àå °ú Ãß°¡ È®Àå ¿É¼ÇÀ» »ç¿ëÇÏ¸é °ãÄ¡´Â ºÎºÐÀÇ Á¤º¸¸¦ º¼ ¼ö ÀÖ½À´Ï´Ù. È®Àå ¹× À̸§ Ç¥½Ã ¿É¼Ç°ú Ãß°¡ È®Àå ¹× À̸§ Ç¥½Ã ¿É¼ÇÀ» ¼±ÅÃÇϸé annotation Á¤º¸¸¦ °°ÀÌ Ç¥½ÃÇÒ ¼ö ÀÖ½À´Ï´Ù. ¸¸¾à ÀÚµ¿À» ¼±ÅÃÇÑ´Ù¸é, ¿©¹éÀÌ Çã¿ëÇÏ´Â Çѵµ ³»¿¡¼­ °ãħ ¹× À̸§ Ç¥½Ã°¡ ÀÚµ¿À¸·Î ÀÌ·ç¾î Áý´Ï´Ù. Ç¥½Ã Á¤º¸ ¼ø¼­¸¦ º¯°æÇÏ°í ½Í´Ù¸é Ç¥½Ã Á¤º¸ ¼ø¼­ º¯°æ ÆË¾÷ ¸Þ´º¸¦ ÀÌ¿ëÇÏ¿© °¢°¢ÀÇ Ãß°¡ Á¤º¸ °ø°£¿¡ annotationÀ» ÁöÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÇöÀç º¸¿©Áö´Â annotationÀÇ ¼ö¸¦ Á¦ÇÑÇϱâ À§Çؼ­´Â Á¦ÇÑ ¸Þ´ºÀÇ °ªÀ» º¯°æÇÏ¸é µË´Ï´Ù. END TRACK => '¼±Åà Á¤º¸', TRACK_TYPE => '¼±Åà Á¤º¸ Á¾·ù', SHOW => 'º¸±â', FORMAT => 'Çü½Ä', LIMIT => 'Á¦ÇÑ', ADJUST_ORDER => '¼ø¼­ °áÁ¤', CHANGE_ORDER => 'Ç¥½Ã Á¤º¸ ¼ø¼­ º¯°æ', AUTO => 'ÀÚµ¿', COMPACT => '°£´ÜÈ÷', EXPAND => 'È®Àå', EXPAND_LABEL => 'È®Àå ¹× À̸§ Ç¥½Ã', HYPEREXPAND => 'Ãß°¡È®Àå', HYPEREXPAND_LABEL =>'Ãß°¡È®Àå ¹× À̸§ Ç¥½Ã', NO_LIMIT => 'Á¦ÇÑ ¾øÀ½', OVERVIEW => '°³¿ä(overview)', EXTERNAL => '¿ÜºÎ(external)', ANALYSIS => 'ºÐ¼®', GENERAL => 'ÀϹÝ(general)', DETAILS => '¼¼ºÎ(details)', ALL_ON => '¸ðµÎ Äѱâ', ALL_OFF => '¸ðµÎ ²ô±â', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => '⠴ݱâ', TRACK_DESCRIPTIONS => 'Ãß°¡ Á¤º¸ ¼³¸í ¹× Âü°í ÀÚ·á', BUILT_IN => 'ÀÌ ¼­¹ö¿¡ ÀúÀåµÈ Ãß°¡ Á¤º¸', EXTERNAL => '¿ÜºÎ annotation Ãß°¡ Á¤º¸', ACTIVATE => 'Á¤º¸¸¦ º¸±â À§Çؼ­´Â ÀÌ Ãß°¡ Á¤º¸¸¦ ¼±ÅÃÇϼ¼¿ä', NO_EXTERNAL => '¿ÜºÎ ±â´ÉÀ» ºÒ·¯¿Ã ¼ö ¾ø½À´Ï´Ù.', NO_CITATION => 'Ãß°¡ÀûÀÎ Á¤º¸°¡ ¾ø½À´Ï´Ù', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => '%s ¿¡ ´ëÇÏ¿©', BACK_TO_BROWSER => 'ºê¶ó¿ìÀú·Î µ¹¾Æ°¡±â', PLUGIN_SEARCH_1 => '(%s °Ë»öÀ» ÅëÇÑ) %s', PLUGIN_SEARCH_2 => '<%s °Ë»ö >', CONFIGURE_PLUGIN => '¼³Á¤', BORING_PLUGIN => 'ÀÌ Ç÷¯±×ÀÎÀº Ãß°¡ÀûÀÎ ¼³Á¤À» ÇÒ ¼ö ¾ø½À´Ï´Ù', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => '%s Ç¥Áö Á¤º¸¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù. µµ¿ò¸» Á¤º¸¸¦ Âü°íÇϽñ⠹ٶø´Ï´Ù.', TOO_BIG => 'ÀÚ¼¼È÷ º¸±â´Â %s °³ÀÇ ¿°±â±îÁö Àû¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. %s ¿µ¿ªÀ» º¸´Ù ³Ð°Ô º¸½Ã·Á¸é Àüüº¸±â¸¦ Ŭ¸¯Çϼ¼¿ä.', PURGED => "%s ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù.", NO_LWP => "ÀÌ ¼­¹ö´Â ¿ÜºÎ URLÀ» ó¸®ÇÒ ¼ö ÀÖµµ·Ï ¼³Á¤µÇÁö ¾Ê¾Ò½À´Ï´Ù.", FETCH_FAILED => "%s Á¤º¸¸¦ ó¸®ÇÒ ¼ö ¾ø½À´Ï´Ù: %s.", TOO_MANY_LANDMARKS => '%d °³ÀÇ Ç¥Áö´Â ³Ê¹« ¸¹¾Æ Ç¥½ÃÇÒ ¼ö ¾ø½À´Ï´Ù.', SMALL_INTERVAL => 'ÀÛÀº °£°ÝÀ» %s bp·Î ÀçÁ¶Á¤ÇÕ´Ï´Ù', NO_SOURCES => 'ÀÐÀ» ¼ö ÀÖ´Â µ¥ÀÌÅÍ ¼Ò½º°¡ ¼³Á¤µÇ¾î ÀÖÁö ¾Ê½À´Ï´Ù. º¼ ¼ö ÀÖ´Â ±ÇÇÑÀÌ ÁÖ¾îÁöÁö ¾ÊÀº °Í °°½À´Ï´Ù.', }; GBrowse-2.56/conf/languages/nl.pm000444001750001750 2351713036764442 17035 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { #Dutch translation done by Marc Logghe CHARSET => 'ISO-8859-1', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', INSTRUCTIONS => 'Instructies', HIDE => 'Verbergen', SEARCH_INSTRUCTIONS => < <voeg deze koppeling toe aan uw favorieten. END EDIT_INSTRUCTIONS => < 'Weergave van %s van %s, posities %s tot %s', LANDMARK => 'Mijlpaal of Gebied', BOOKMARK => 'Toevoegen aan Favorieten', KEY_POSITION => 'Positie van Legende', BETWEEN => 'Tussen', BENEATH => 'Onder', LEFT => 'Links', RIGHT => 'Rechts', TRACK_NAMES => 'Lijst Baannamen', ALPHABETIC => 'Alfabetisch', VARYING => 'Willekeurig', FLIP => 'Omkeren', HIDE_HEADER => 'Koptekst Verbergen', HIDE_INSTRUCTIONS => 'Instructies Verbergen', HIGHLIGHT => 'Markeren', IMAGE_DESCRIPTION => < Om een ingebed plaatje van dit beeld te bekomen, knip en plak de volgende URL in een HTML pagina:

    <IMAGE src="%s" />
    

    Het plaatje zal er dan als volgt uitzien:

    Indien enkel het overzicht (chromosoom of contig) zichtbaar is, probeer dan de regio te verkleinen

    END IMAGE_LINK => 'Koppeling Beeld', POSSIBLE_TRUNCATION => 'Aantal resultaten is beperkt tot %d hits; lijst is mogelijks onvolledig', SHOW_HEADER => 'Koptekst Tonen', SVG_DESCRIPTION => < Deze koppeling zal een beeldje genereren in het 'Scalable Vector Graphic' (SVG) formaat. SVG beelden hebben verschillende voordelen in vergelijking met rasterbeelden zoals jpeg of png.

    • grootte kan vrij aangepast worden zonder resolutieverlies
    • elk individueel onderdeel kan opgemaakt worden in vector georiënteerde grafische applicaties
    • kan, indien nodig, omgezet geworden in EPS formaat ter indiening van een publicatie

    Om SVG beelden te bekijken moet, ofwel je browser SVG ondersteunen, ofwel moet de Adobe SVG browser plugin, of andere SVG applicatie zoals Adobe Illustrator, geïnstalleerd zijn.

    Adobe's SVG browser plugin: Macintosh | Windows
    Linux gebruikers kunnen eventueel de Batik SVG Viewer uitproberen.

    Bekijk het SVG beeld in een nieuw venster

    Om dit plaatje op schijf te bewaren, CTRL-klik (Macintosh) of rechts-klik (Windows) en selecteer de optie om op schijf bewaren.

    END SVG_LINK => 'Beeld van Publicatiekwaliteit', TIMEOUT => <<'END', Uw vraag heeft de ingestelde blokkeertijd overschreden. Misschien heeft u een gebied geselecteerd dat te groot is om afgebeeld te worden. Probeer opnieuw na het deselecteren van een aantal banen of beperk uw selectie tot een kleiner gebied. Indien dergelijke blokkeringen zich hardnekkig blijven manifesteren, gelieve op de rode "Reset" knop te drukken. END GO => 'Doorgaan', FIND => 'Vinden', SEARCH => 'Zoeken', DUMP => 'Dumpen', ANNOTATE => 'Annoteren', SCROLL => 'Scrollen/Inzoomen', RESET => 'Reset', DOWNLOAD_FILE => 'Downloaden Bestand', DOWNLOAD_DATA => 'Downloaden Gegevens', DOWNLOAD => 'Downloaden', DISPLAY_SETTINGS => 'Weergave Instellingen', TRACKS => 'Banen', EXTERNAL_TRACKS => '(Externe banen cursief)', EXAMPLES => 'Voorbeelden', REGION_SIZE => 'Lengte van het Gebied (bp)', HELP => 'Hulp', HELP_FORMAT => 'Hulp met Bestandsformaat', CANCEL => 'Annuleren', ABOUT => 'Over...', REDISPLAY => 'Nieuwe Weergave', CONFIGURE => 'Configureren...', CONFIGURE_TRACKS => 'Configuren banen...', EDIT => 'Aanpassen Bestand...', DELETE => 'Wissen Bestand', EDIT_TITLE => 'Invoeren/Aanpassen Annotatie gegevens', IMAGE_WIDTH => 'Beeldbreedte', SET_OPTIONS => 'Baaninstellingen...', CLEAR_HIGHLIGHTING => 'Fluo Markering afzetten', UPDATE => 'Beeld Vernieuwen', DUMPS => 'Dumps, Zoekopdrachten en meer', DATA_SOURCE => 'Gegevensbron', UPLOAD_TITLE=> 'Uploaden eigen Annotaties', UPLOAD_FILE => 'Uploaden bestand', BROWSE => 'Browse...', UPLOAD => 'Uploaden', NEW => 'Nieuw...', REMOTE_TITLE => 'Toevoegen Annotaties op afstand', REMOTE_URL => 'Invoeren URL Annotaties op afstand', UPDATE_URLS => 'Bijwerken URLs', PRESETS => '--Kies Preset URL--', FEATURES_TO_HIGHLIGHT => 'Fluo Markeren kenmerk(en) (kenmerk1 kenmerk2...)', REGIONS_TO_HIGHLIGHT => 'Fluo Markeren gebieden (gebied1:begin..einde gebied2:begin..einde)', FEATURES_TO_HIGHLIGHT_HINT => 'Tip: gebruik kenmerk@kleur om de kleur te selecteren, zoals in \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Tip: gebruik gebied@kleur om de kleur te selecteren, zoals in \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*geen*', FILE_INFO => 'Recentste veranderingen op %s. Geannoteerde mijlpalen: %s', FOOTER_1 => < 'Generic genome browser versie %s', ALL_OFF => 'Alles uit', ALL_ON => 'Alles aan', ANALYSIS => 'Analyse', DETAILS => 'Details', GENERAL => 'Algemeen', REGION => 'Gebied', NO_SOURCES => 'Geen gegevensbronnen', OVERVIEW => 'Overzicht', OVERVIEW_TRACKS => 'Overzichtsbanen', REGION_TRACKS => '**Gebiedsbanen', UPLOAD_TRACKS => 'Upload banen', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'De volgende %d gebieden voldoen aan uw aanvraag.', MATCHES_ON_REF => 'Matches op %s', SEQUENCE => 'sequentie', SCORE => 'score=%s', NOT_APPLICABLE => 'nvt', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Instellingen voor %s', UNDO => 'Annuleren', REVERT => 'Standaardwaarden', REFRESH => 'Verversen', CANCEL_RETURN => 'Annuleren en Terug...', ACCEPT_RETURN => 'Aanvaarden en Terug...', OPTIONS_TITLE => 'Baaninstellingen', SETTINGS_INSTRUCTIONS => <Toon checkbox zet een baan aan of uit. In de Formaat kolom kan via de Compact optie de baan gecondenseerd worden, zodat annotaties elkaar overlappen. De Uitgeklapt en Extra Uitgeklapt opties zetten de 'botsingscontrole' aan, gebruik makend van tragere en snellere layout algorithmen. De Uitgeklapt & Label en Extra Uitgeklapt & Label opties zorgen ervoor dat de annotaties daarbij ook nog worden gelabeled. Bij de selectie van Auto, gebeuren de 'botsingscontrole' en label opties automatisch, enkel indien voldoende ruimte voorhanden is. Om de volgorde van de banen te veranderen gebruik het Volgorde Veranderen popup menu waar een annotatie kan toegekend worden aan een baan. Om het aantal getoonde annotaties van dit type te beperken, verander de waarde via het Grens menu. END TRACK => 'Baan', TRACK_TYPE => 'Baantype', SHOW => 'Tonen', SHOW_INSTRUCTIONS => 'Instructies Tonen', FORMAT => 'Formaat', LIMIT => 'Grens', ADJUST_ORDER => 'Volgorde Bijstellen', CHANGE_ORDER => 'Volgorde Veranderen', AUTO => 'Auto', COMPACT => 'Compact', EXPAND => 'Uitgeklapt', EXPAND_LABEL => 'Uitgeklapt & Label', HYPEREXPAND => 'Extra Uitgeklapt', HYPEREXPAND_LABEL =>'Extra Uitgeklapt & Label', NO_LIMIT => 'Geen Grens', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Sluit dit venster', TRACK_DESCRIPTIONS => 'Baanbeschrijvingen & Citaties', BUILT_IN => 'Banen in deze Server ingebouwd', EXTERNAL => 'Banen met Externe Annotaties', ACTIVATE => 'Gelieve deze baan te activeren om de informatie te kunnen bekijken.', NO_EXTERNAL => 'Geen externe kenmerken geladen.', NO_CITATION => 'Geen additionele informatie beschikbaar.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Over %s', BACK_TO_BROWSER => 'Terug naar Browser', PLUGIN_SEARCH_1 => '%s (via %s zoeken)', PLUGIN_SEARCH_2 => '<%s zoeken>', CONFIGURE_PLUGIN => 'Configuren', BORING_PLUGIN => 'Deze plugin heeft geen extra configuratie instellingen.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'De mijlpaal met de naam %s werd niet gevonden. Zie eventueel de hulppagina\'s voor suggesties.', TOO_BIG => 'Gedetailleerd beeld is beperkt tot %s basen. Klik op het overzicht om een gebied te selecteren van %s breed.', PURGED => "Het bestand %s kon niet gevonden worden. Misschien werd het verwijderd ?.", NO_LWP => "Deze server werd niet geconfigureerd om externe URL's op te halen.", FETCH_FAILED => "Kon %s niet ophalen: %s.", TOO_MANY_LANDMARKS => '%d mijlpalen. Te veel om op te lijsten.', SMALL_INTERVAL => 'Grootte van klein interval bijgesteld tot %s bp', }; GBrowse-2.56/conf/languages/pl.pm000444001750001750 2332513036764442 17034 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { # Translation to the polish language. # Translated by Szymon M. Kielbasa , 14-NOV-2005, V0.1 CHARSET => 'UTF-8', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => < < < 'Widoczne %s z sekwencji %s, fragment od %s do %s', INSTRUCTIONS => 'Wskazówki', HIDE => 'Ukryj', SHOW => 'Pokaż', SHOW_INSTRUCTIONS => 'Pokaż wskazówki', HIDE_INSTRUCTIONS => 'Ukryj wskazówki', SHOW_HEADER => 'Pokaż nagłówek', HIDE_HEADER => 'Ukryj nagłówek', LANDMARK => 'Nazwa lub fragment', BOOKMARK => 'Zakładka', IMAGE_LINK => 'Odnośnik do rysunku', SVG_LINK => 'Rysunek wektorowy (SVG)', SVG_DESCRIPTION => < Poniższy odnośnik generuje rysunek w wektorowym, skalowalnym formacie SVG (Scalable Vector Graphic). Rysunki w tym formacie mogą być łatwiej obrabiane programami graficznymi (na poziomie adnotacji, nie pikseli). Ponadto, konwersja z formatu SVG do używanego powszechnie w publikacjach formatu EPS zapewnia wynik o znacznie wyższej jakości.

    Aby zobaczyć rysunki w formacie SVG konieczne jest użycie przeglądarki wspierającej ten format. Adobe dostarcza wtyczkę do przeglądarek, jak i oprogramowanie do edycji rysunków w formacie SVG.

    Wtyczki SVG z Adobe: Macintosh | Windows.
    Użytkownicy systemów opartych na Linux mogą użyć Batik SVG Viewer.

    Otwórz rysunek SVG w nowym oknie.

    Aby zapisać ten rysunek na dysku przytrzymaj "control" podczas naciskania przycisku myszki (Macintosh), lub użyj prawego guzika myszki i opcji "save link to disk" (Windows).

    END IMAGE_DESCRIPTION => < Jeśli użyjesz wewnątrz strony HTML:

    <IMAGE src="%s" />
    

    otrzymasz poniższy rysunek:

    Jeśli ukazujesz wyłącznie ścieżkę orientacyjną, możesz zmniejszyć wielkość.

    END TIMEOUT => <<'END', Czas oczekiwania na dane zostaÅ‚ przekroczony. Prawdopodobnie wybrany przez Ciebie fragment posiada zbyt wiele adnotacji. Spróbuj zmniejszyć fragment lub ogranicz liczbÄ™ Å›cieżek. JeÅ›li problem siÄ™ powtarza, użycie przycisku Skasuj może okazać siÄ™ pomocne. END GO => 'Idź', FIND => 'Szukaj', SEARCH => 'Szukaj', DUMP => 'Display', HIGHLIGHT => 'Wyróżnij', ANNOTATE => 'Annotate', SCROLL => 'Przewijanie/powiÄ™kszenie', RESET => 'Skasuj', FLIP => 'Skieruj oÅ› przeciwnie', DOWNLOAD_FILE => 'ZaÅ‚aduj plik', DOWNLOAD_DATA => 'ZaÅ‚aduj dane', DOWNLOAD => 'ZaÅ‚aduj', DISPLAY_SETTINGS => 'Ustawienia', TRACKS => 'Åšcieżki', EXTERNAL_TRACKS => 'ZewnÄ™trzne Å›cieżki kursywÄ…', OVERVIEW_TRACKS => '*Åšcieżka orientacyjna', REGION_TRACKS => '**Region track', EXAMPLES => 'PrzykÅ‚ady', REGION_SIZE => 'Rozmiar fragmentu (bp)', HELP => 'Pomoc', HELP_FORMAT => 'Pomoc: formaty plików danych', CANCEL => 'Anuluj', ABOUT => 'O...', REDISPLAY => 'OdÅ›wież', CONFIGURE => 'Ustawienia...', CONFIGURE_TRACKS => 'Ustawienia Å›cieżek...', EDIT => 'Edytuj plik...', DELETE => 'UsuÅ„ plik', EDIT_TITLE => 'Wpisz/zmieÅ„ plik adnotacji', IMAGE_WIDTH => 'Szerokość rysunku [punkty]', BETWEEN => 'nad Å›cieżkÄ…', BENEATH => 'u doÅ‚u rysunku', LEFT => 'lewostronne', RIGHT => 'prawostronne', TRACK_NAMES => 'Kolejność Å›cieżek', ALPHABETIC => 'alfabetyczna', VARYING => 'inna', SET_OPTIONS => 'Ustawienia Å›cieżek...', CLEAR_HIGHLIGHTING => 'Wyłącz wyróżnianie', UPDATE => 'OdÅ›wież', DUMPS => 'Raporty i analizy', DATA_SOURCE => 'ŹródÅ‚o danych', UPLOAD_TRACKS=>'Dodaj wÅ‚asne Å›cieżki', UPLOAD_TITLE=> 'ZaÅ‚aduj wÅ‚asne adnotacje', UPLOAD_FILE => 'ZaÅ‚aduj plik', KEY_POSITION => 'PoÅ‚ożenie opisów', BROWSE => 'PrzeglÄ…daj...', UPLOAD => 'ZaÅ‚aduj', NEW => 'Nowy...', REMOTE_TITLE => 'Dodaj zewnÄ™trzne adnotacje', REMOTE_URL => 'Adres zewnÄ™trznych adnotacji (URL)', UPDATE_URLS => 'OdÅ›wież URLs', PRESETS => '--Wybierz URL--', FEATURES_TO_HIGHLIGHT => 'Wyróżnij adnotacje (adnotacja1 adnotacja2...)', REGIONS_TO_HIGHLIGHT => 'Wyróżnij fragmenty sekwencji (sekwencja1:od..do sekwencja2:od..do)', FEATURES_TO_HIGHLIGHT_HINT => 'Wskazówka: by wybrać kolor wyróżnienia użyj adnotacja@kolor (np. \'NUT21@lightblue\')', REGIONS_TO_HIGHLIGHT_HINT => 'Wskazówka: by wybrać kolor wyróżnienia użyj sekwencja:od..do@kolor (np. \'Chr1:10000..20000@lightblue\')', NO_TRACKS => '*brak*', FILE_INFO => 'Ostatnia zmiana %s. Liczba adnotacji: %s', FOOTER_1 => < 'Generic genome browser, wersja %s.', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'Liczba adnotacji pasujÄ…cych do poszukiwanej nazwy: %d.', POSSIBLE_TRUNCATION => 'Lista wyników poszukiwania może nie być kompletna (liczba wyników jest ograniczona do %d).', MATCHES_ON_REF => 'Adnotacje na sekwencji %s', SEQUENCE => 'sekwencja', SCORE => 'punkty=%s', NOT_APPLICABLE => 'n.d.', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'Ustawienia %s', UNDO => 'Cofnij zmiany', REVERT => 'Ustawienia standardowe', REFRESH => 'OdÅ›wież', CANCEL_RETURN => 'Anuluj zmiany...', ACCEPT_RETURN => 'Zatwierdź zmiany...', OPTIONS_TITLE => 'Ustawienia Å›cieżek', SETTINGS_INSTRUCTIONS => <Widoczność włącza lub wyłącza ukazywanie wybranej Å›cieżki. W kolumnie Format definiowany jest sposób prezentacji adnotacji. Format gÄ™sty pozwala różnym adnotacjom nachodzić na siebie. Formaty rzadki i bardzo rzadki używajÄ… różnych metod ukÅ‚adania w kolejnych wierszach nakÅ‚adajÄ…cych siÄ™ adnotacji. Ponadto możliwe jest włączenie szczegółowych opisów adnotacji. Format domyÅ›lny dobiera rodzaj prezentacji automatycznie, w zależnoÅ›ci od iloÅ›ci dostÄ™pnego miejsca. Kolumna Limit pozwala na ograniczenie liczby adnotacji pokazywanych w wybranej Å›cieżce. Kolejność Å›cieżek umożliwia zmianÄ™ porzÄ…dku w jakim Å›cieżki sÄ… wyÅ›wietlane na rysunku. END TRACK => 'Åšcieżka', TRACK_TYPE => 'Typ Å›cieżki', SHOW => 'Widoczność', FORMAT => 'Format', LIMIT => 'Limit', ADJUST_ORDER => 'ZmieÅ„ kolejność', CHANGE_ORDER => 'Kolejność Å›cieżek', AUTO => 'DomyÅ›lny', COMPACT => 'GÄ™sty', EXPAND => 'Rzadki', EXPAND_LABEL => 'Rzadki, z opisem', HYPEREXPAND => 'Bardzo rzadki', HYPEREXPAND_LABEL =>'Bardzo rzadki, z opisem', NO_LIMIT => 'Bez ograniczeÅ„', OVERVIEW => 'PrzeglÄ…d', ANALYSIS => 'Analiza', GENERAL => 'Ogólnie', DETAILS => 'Szczegóły', REGION => 'Region', ALL_ON => 'Włącz wszystko', ALL_OFF => 'Wyłącz wszystko', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Zamknij to okno', TRACK_DESCRIPTIONS => 'Opisy Å›cieżek, referencje', BUILT_IN => 'Åšcieżki udostÄ™pniane przez ten serwer', EXTERNAL => 'Åšcieżki zewnÄ™trzne', ACTIVATE => 'Włącz Å›cieżkÄ™ aby zobaczyć jej adnotacje.', NO_EXTERNAL => 'Nie zaÅ‚adowano zewnÄ™trznych adnotacji.', NO_CITATION => 'Brak dalszych referencji.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'O wtyczce %s', BACK_TO_BROWSER => 'Powrót', PLUGIN_SEARCH_1 => '%s (via %s search)', PLUGIN_SEARCH_2 => '<%s search>', CONFIGURE_PLUGIN => 'Ustawienia', BORING_PLUGIN => 'Ta wtyczka nie umożliwia ustawiania niczego.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'Nazwa/fragment "%s" nie zostaÅ‚a odnaleziona.', TOO_BIG => 'Szczegóły sÄ… widoczne dla fragmentów o dÅ‚ugoÅ›ci do %s. Wybierz na Å›cieżce orientacyjnej miejsce by zobaczyć otaczajÄ…ce %s.', PURGED => "Nie można odnaleźć pliku %s. Może zostaÅ‚ usuniÄ™ty?.", NO_LWP => "Ten serwer nie zostaÅ‚ skonfigurowany do pozyskiwania zewnÄ™trznych adnotacji URL.", FETCH_FAILED => "Nie można pozyskać %s: %s.", TOO_MANY_LANDMARKS => '%d nazw/fragmentów. Zbyt wiele by wymienić.', SMALL_INTERVAL => 'Zbyt krótki fragment zostaÅ‚ powiÄ™kszony do %s bp.', NO_SOURCES => 'Nie ma dostÄ™pnych źródeÅ‚ danych. Być może nie posiadasz stosownych praw dostÄ™pu.', }; GBrowse-2.56/conf/languages/ru.pm000444001750001750 2374413036764442 17054 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! { #Russian translation done by Mikhail Pachkov CHARSET => 'KOI*-R', #---------- # MAIN PAGE #---------- PAGE_TITLE => 'Genome browser', SEARCH_INSTRUCTIONS => < < < 'ðÏËÁÚÁÎÏ %s ÉÚ %s, ËÏÏÒÄÉÎÁÔÙ %s..%s', INSTRUCTIONS => 'éÎÓÔÒÕËÃÉÉ', HIDE => 'óËÒÙÔØ', SHOW => 'ðÏËÁÚÁÔØ', SHOW_INSTRUCTIONS => 'ðÏËÁÚÁÔØ ÉÎÓÔÒÕËÃÉÉ', HIDE_INSTRUCTIONS => 'óËÒÙÔØ ÉÎÓÔÒÕËÃÉÉ', SHOW_HEADER => 'ðÏËÁÚÁÔØ ÚÁÇÏÌÏ×ÏË', HIDE_HEADER => 'óËÒÙÔØ ÚÁÇÏÌÏ×ÏË', LANDMARK => 'õÞÁÓÔÏË ÉÌÉ ïÒÉÅÎÔÉÒ', BOOKMARK => 'óÄÅÌÁÔØ ÚÁËÌÁÄËÕ', IMAGE_LINK => 'óÓÙÌËÁ ÎÁ ÉÚÏÂÒÁÖÅÎÉÅ', SVG_LINK => 'éÚÏÂÒÁÖÅÎÉÅ ×ÙÓÏËÏÇÏ ÒÁÚÒÅÛÅÎÉÑ', SVG_DESCRIPTION => < üÔÁ ÓÓÙÌËÁ ÎÁ ÉÚÏÂÒÁÖÅÎÉÅ × ÆÏÒÍÁÔÅ Scalable Vector Graphic (SVG). æÏÒÍÁÔ SVG ÏÂÌÁÄÁÅÔ ÎÅËÏÔÏÒÙÍÉ ÐÒÅÉÍÕÝÅÓÔ×ÁÍÉ × ÓÒÁ×ÎÅÎÉÉ Ó raster based ÆÏÒÍÁÔÁÍÉ, ÔÁËÉÍÉ ËÁË jpeg É png.

    • ÍÁÓÛÔÁÂÉÒÕÅÍÏÓÔØ ÂÅÚ ÐÏÔÅÒÉ ÒÁÚÒÅÛÅÎÉÑ
    • ÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ ËÏÍÐÏÎÅÎÔÙ ÉÚÏÂÒÁÖÅÎÉÑ × ÏÂÙÞÎÙÈ ÒÅÄÁËÔÏÒÁÈ ×ÅËÔÏÒÎÏÊ ÇÒÁÆÉËÉ
    • ÐÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ, ÍÏÖÅÔ ÂÙÔØ ÐÅÒÅ×ÅÄÅÎ × ÆÏÒÍÁÔ EPS ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ × ÐÕÂÌÉËÁÃÉÑÈ

    äÌÑ ÐÒÏÓÍÏÔÒÁ SVG ÉÚÏÂÒÁÖÅÎÉÊ ÎÅÏÂÈÏÄÉÍ ÂÒÏÕÚÅÒ ÐÏÄÄÅÒÖÉ×ÁÀÝÉÊ ÆÏÒÍÁÔ SVG, Adobe SVG ÐÌÁÇÉÎ ÄÌÑ ÂÒÏÕÚÅÒÁ ÉÌÉ ÐÒÏÇÒÁÍÍÁ ÄÌÑ ÐÒÏÓÍÏÔÒÁ/ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ SVG, ÔÁËÁÑ ËÁË Adobe Illustrator.

    Adobe's SVG ÐÌÁÇÉÎ ÄÌÑ ÂÒÏÕÚÅÒÁ: Macintosh | Windows
    ðÏÌØÚÏ×ÁÔÅÌÉ Linux ÍÏÇÕÔ ÐÏÐÒÏÂÏ×ÁÔØ Batik SVG Viewer.

    ïÔËÒÙÔØ SVG ÉÚÏÂÒÁÖÅÎÉÅ × ÎÏ×ÏÍ ÏËÎÅ

    þÔÏÂÙ ÓÏÈÒÁÎÉÔØ ÉÚÏÂÒÁÖÅÎÉÅ ÎÁÖÍÉÔÅ CTRL É ËÌÉËÎÉÔÅ ÎÁ ÓÓÙÌËÕ (Macintosh) ÉÌÉ ËÌÉËÎÉÔÅ ÐÒÁ×ÏÊ ËÎÏÐËÏÊ ÍÙÛÉ (Windows) É ×ÙÂÅÒÅÔÅ ÐÕÎËÔ "óÏÈÒÁÎÉÔØ ÓÓÙÌËÕ ÎÁ ÄÉÓË".

    END IMAGE_DESCRIPTION => < þÔÏÂÙ ×ÓÔÁ×ÉÔØ ÜÔÏ ÉÚÏÂÒÁÖÅÎÉÅ × ÄÒÕÇÕÀ ×ÅÂ-ÓÔÒÁÎÉÃÕ, ÓËÏÐÉÒÕÊÔÅ É ×ÓÔÁרÔÅ ÜÔÕ ÓÓÙÌËÕ × ×ÁÛÕ HTML ÓÔÒÁÎÉÃÕ:

    <IMAGE src="%s" />
    

    éÚÏÂÒÁÖÅÎÉÅ ÂÕÄÅÔ ×ÙÇÌÑÄÅÔØ ×ÏÔ ÔÁË:

    åÓÌÉ ÐÏËÁÚÁÎ ÔÏÌØËÏ ÏÂÝÉÊ ×ÉÄ (ÈÒÏÍÏÓÏÍÁ ÉÌÉ ÎÅÐÒÅÒÙ×ÎÙÅ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔÉ), ÔÏ ÐÏÐÒÏÂÕÊÔÅ ÕÍÅÎØÛÉÔØ ÍÁÓÛÔÁÂ.

    END TIMEOUT => <<'END', ÷ÒÅÍÑ ÏÖÉÄÁÎÉÑ ÉÓÔÅËÌÏ. ÷ÏÚÍÏÖÎÏ ×ÙÂÒÁÎÎÙÊ ÒÅÇÉÏÎ ÓÌÉÛËÏÍ ×ÅÌÉË. óÏËÒÁÔÉÔÅ ÞÉÓÌÏ ÏÔÏÂÒÁÖÁÅÍÙÈ ÁÎÎÏÔÁÃÉÊ ÉÌÉ ÐÏÐÒÏÂÕÊÔÅ ÍÅÎØÛÉÊ ÍÁÓÛÔÁÂ. åÓÌÉ ×Ù ÐÏÓÔÏÑÎÎÏ ÐÏÌÕÞÁÅÔÅ ÜÔÏ ÓÏÏÂÝÅÎÉÅ, ÔÏ ÎÁÖÍÉÔÅ ËÒÁÓÎÕÀ ËÎÏÐËÕ "óÂÒÏÓ". END GO => 'ðÒÉÍÅÎÉÔØ', FIND => 'îÁÊÔÉ', SEARCH => 'ðÏÉÓË', DUMP => 'ðÏËÁÚÁÔØ', HIGHLIGHT => '÷ÙÄÅÌÉÔØ', ANNOTATE => '÷ÓÔÁ×ÉÔØ ÐÒÉÍÅÞÁÎÉÑ', SCROLL => 'ðÒÏËÒÕÔËÁ/íÁÓÛÔÁÂÉÒÏ×ÁÎÉÅ', RESET => 'óÂÒÏÓ', FLIP => 'ðÅÒÅ×ÅÒÎÕÔØ', DOWNLOAD_FILE => 'úÁÇÒÕÚÉÔØ æÁÊÌ', DOWNLOAD_DATA => 'úÁÇÒÕÚÉÔØ äÁÎÎÙÅ', DOWNLOAD => 'úÁÇÒÕÚÉÔØ', DISPLAY_SETTINGS => 'ðÏËÁÚÁÔØ îÁÓÔÒÏÊËÉ', TRACKS => 'áÎÎÏÔÁÃÉÉ', EXTERNAL_TRACKS => 'úÁÇÒÕÖÅÎÎÙÅ ÁÎÎÏÔÁÃÉÉ ×ÙÄÅÌÅÎÙ ÎÁËÌÏÎÎÙÍ ÛÒÉÆÔÏÍ', OVERVIEW_TRACKS => '*ïÂÝÁÑ ÁÎÎÏÔÁÃÉÑ', REGION_TRACKS => '**áÎÎÏÔÁÃÉÑ ÕÞÁÓÔËÁ', EXAMPLES => 'ðÒÉÍÅÒÙ', REGION_SIZE => 'òÁÚÍÅÒ ÕÞÁÓÔËÁ (ÂÐ)', HELP => 'ðÏÍÏÝØ', HELP_FORMAT => 'óÐÒÁ×ËÁ ÐÏ æÏÒÍÁÔÕ æÁÊÌÏ×', CANCEL => 'ïÔÍÅÎÁ', ABOUT => 'ï ÐÒÏÇÒÁÍÍÅ', REDISPLAY => 'ïÂÎÏ×ÉÔØ ÉÚÏÂÒÁÖÅÎÉÅ', CONFIGURE => 'ëÏÎÆÉÇÕÒÉÒÏ×ÁÔØ...', CONFIGURE_TRACKS => 'ëÏÎÆÉÇÕÒÉÒÏ×ÁÔØ ÁÎÎÏÔÁÃÉÀ...', EDIT => 'òÅÄÁËÔÉÒÏ×ÁÔØ ÆÁÊÌ...', DELETE => 'óÔÅÒÅÔØ ÆÁÊÌ', EDIT_TITLE => '÷×ÅÓÔÉ/òÅÄÁËÔÉÒÏ×ÁÔØ æÁÊÌ Ó áÎÎÏÔÁÃÉÑÍÉ', IMAGE_WIDTH => 'ûÉÒÉÎÁ éÚÏÂÒÁÖÅÎÉÑ', BETWEEN => 'íÅÖÄÕ', BENEATH => 'ðÏÄ', LEFT => 'óÌÅ×Á', RIGHT => 'óÐÒÁ×Á', TRACK_NAMES => 'óÐÉÓÏË áÎÎÏÔÁÃÉÊ', ALPHABETIC => 'ðÏ ÁÌÆÁ×ÉÔÕ', VARYING => 'óÍÅÛÁÎÎÙÊ', SET_OPTIONS => 'îÁÓÔÒÏÊËÁ ÁÎÎÏÔÁÃÉÊ', CLEAR_HIGHLIGHTING => 'õÂÒÁÔØ ×ÙÄÅÌÅÎÉÅ', UPDATE => 'ïÂÎÏ×ÉÔØ ÉÚÏÂÒÁÖÅÎÉÅ', DUMPS => 'éÎÆÏÒÍÁÃÉÑ & áÎÁÌÉÚ', DATA_SOURCE => 'éÓÈÏÄÎÙÅ ÄÁÎÎÙÅ', UPLOAD_TRACKS=>'äÏÂÁ×ÉÔØ Ó×ÏÀ ÁÎÎÏÔÁÃÉÀ', UPLOAD_TITLE=> 'úÁÇÒÕÚÉÔØ ×ÁÛÕ ÁÎÎÏÔÁÃÉÀ', UPLOAD_FILE => 'úÁÇÒÕÚÉÔØ ÆÁÊÌ ÎÁ ÓÅÒ×ÅÒ', KEY_POSITION => 'ðÏÌÏÖÅÎÉÅ ÎÁÚ×ÁÎÉÑ', BROWSE => 'ë ÆÁÊÌÁÍ', UPLOAD => 'úÁÇÒÕÚÉÔØ', NEW => 'îÏ×ÙÊ', REMOTE_TITLE => 'äÏÂÁ×ÉÔØ ×ÎÅÛÎÀÀ ÁÎÎÏÔÁÃÉÀ', REMOTE_URL => '÷×ÅÄÉÔÅ URL ×ÎÅÛÎÅÊ ÁÎÎÏÔÁÃÉÉ', UPDATE_URLS => 'ïÂÎÏ×ÉÔØ URL-Ù', PRESETS => '--÷ÙÂÒÁÔØ ÉÚ ÉÍÅÀÝÉÈÓÑ URL-Ï×--', FEATURES_TO_HIGHLIGHT => '÷ÙÄÅÌÉÔØ ÜÌÅÍÅÎÔ(Ù) (ÜÌÅÍÅÎÔ1 ÜÌÅÍÅÎÔ2 ...)', REGIONS_TO_HIGHLIGHT => '÷ÙÄÅÌÉÔØ ÕÞÁÓÔËÉ (ÕÞÁÓÔÏË1:ÎÁÞÁÌÏ..ËÏÎÅà ÕÞÁÓÔÏË2:ÎÁÞÁÌÏ..ËÏÎÅÃ)', FEATURES_TO_HIGHLIGHT_HINT => 'ðÏÄÓËÁÚËÁ: Ã×ÅÔ ÜÌÅÍÅÎÔÁ ÍÏÖÎÏ ÚÁÄÁÔØ Ó ÐÏÍÏÝØÀ ËÏÎÓÔÒÕËÃÉÉ ÜÌÅÍÅÎÔ@Ã×ÅÔ, ÎÁÐÒÉÍÅÒ \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'ðÏÄÓËÁÚËÁ: Ã×ÅÔ ÕÞÁÓÔËÁ ÍÏÖÎÏ ÚÁÄÁÔØ Ó ÐÏÍÏÝØÀ ËÏÎÓÔÒÕËÃÉÉ ÕÞÁÓÔÏË@Ã×ÅÔ, ÎÁÐÒÉÍÅÒ \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*ÐÕÓÔÏ*', FILE_INFO => 'äÁÔÁ ÐÏÓÌÅÄÎÅÇÏ ÉÚÍÅÎÅÎÉÑ %s. %s ', FOOTER_1 => < 'Generic genome browser ×ÅÒÓÉÑ %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'îÁÊÄÅÎÏ %d ÕÞÁÓÔËÏ×, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÈ ×ÁÛÅÍÕ ÚÁÐÒÏÓÕ.', POSSIBLE_TRUNCATION => 'ðÏËÁÚÁÎÏ ÔÏÌØËÏ %d ÒÅÓÕÌØÔÁÔÏ× ÐÏÉÓËÁ; ÓÐÉÓÏË ÍÏÖÅÔ ÂÙÔØ ÎÅÐÏÌÎÙÍ.', MATCHES_ON_REF => 'óÏ×ÐÁÄÅÎÉÑ ÄÌÑ %s', SEQUENCE => 'ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ', SCORE => 'ÏÃÅÎËÁ=%s', NOT_APPLICABLE => 'ÎÅÐÒÉÍÅÎÉÍÏ', BP => 'ÂÐ', #-------------- # SETTINGS PAGE #-------------- SETTINGS => 'îÁÓÔÒÏÊËÉ ÄÌÑ %s', UNDO => 'ïÔÍÅÎÉÔØ ÉÚÍÅÎÅÎÉÑ', REVERT => '÷ÅÒÎÕÔØÓÑ Ë ÎÁÓÔÒÏÊËÁÍ ÐÏ ÕÍÏÌÞÁÎÉÀ', REFRESH => 'ïÂÎÏ×ÉÔØ', CANCEL_RETURN => 'ïÔÍÅÎÉÔØ éÚÍÅÎÅÎÉÑ É ÷ÅÒÎÕÔØÓÑ...', ACCEPT_RETURN => 'ðÒÉÎÑÔØ éÚÍÅÎÅÎÉÑ É ÷ÅÒÎÕÔØÓÑ...', OPTIONS_TITLE => 'îÁÓÔÒÏÉÔØ áÎÎÏÔÁÃÉÉ', SETTINGS_INSTRUCTIONS => <ðÏËÁÚÁÔØ ×ËÌÀÞÁÅÔ/×ÙËÌÀÞÁÅÔ ÐÏËÁÚ ÁÎÎÏÔÁÃÉÉ. ïÐÃÉÑ ëÏÍÐÁËÔÎÏ ×ËÌÀÞÁÅÔ ËÏÍÐÁËÔÎÙÊ ÐÏËÁÚ ÁÎÎÏÔÁÃÉÉ, ËÏÇÄÁ ÒÁÚÌÉÞÎÙÅ ÞÁÓÔÉ ÐÅÒÅËÒÙ×ÁÀÔÓÑ. ïÐÃÉÉ ðÏÄÒÏÂÎÏ É ó×ÅÒÈÐÏÄÒÏÂÎÏ ×ËÌÀÞÁÀÔ ËÏÎÔÒÏÌØ ÐÌÏÔÎÏÓÔÉ, Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ ÍÅÄÌÅÎÎÏÇÏ É ÂÙÓÔÒÏÇÏ ÁÌÇÏÒÉÔÍÏ×. ðÏÄÒÏÂÎÏ Ó ËÏÍÍÅÎÔÁÒÉÑÍÉ É ó×ÅÒÈÐÏÄÒÏÂÎÏ Ó ËÏÍÍÅÎÔÁÒÉÑÍÉ - ×ËÌÀÞÁÀÔ ÐÏËÁÚ ËÏÍÍÅÎÔÁÒÉÅ×. á×ÔÏ - ËÏÎÔÒÏÌØ ÐÌÏÔÎÏÓÔÉ É ÐÏËÁÚ ËÏÍÍÅÎÔÁÒÉÅ× ÂÕÄÕÔ ×ËÌÀÞÅÎÙ Á×ÔÏÍÁÔÉÞÅÓËÉ ÐÒÉ ÄÏÓÔÁÔÏÞÎÏÍ ËÏÌÉÞÅÓÔ×Å ÍÅÓÔÁ. þÔÏÂÙ ÐÏÍÅÎÑÔØ ÐÏÒÑÄÏË ÒÁÓÐÏÌÏÖÅÎÉÑ ÁÎÎÏÔÁÃÉÊ ÉÓÐÏÌØÚÕÊÔÅ ×ÙÐÁÄÁÀÝÅÅ ÍÅÎÀ éÚÍÅÎÉÔØ ÐÏÒÑÄÏË ÒÁÓÐÏÌÏÖÅÎÉÑ. þÔÏÂÙ ÏÇÒÁÎÉÞÉÔØ ÞÉÓÌÏ ÐÏËÁÚÁÎÎÙÈ ÜÌÅÍÅÎÔÏ× ÏÄÎÏÇÏ ÔÉÐÁ ÉÓÐÏÌØÚÕÊÔÅ ÍÅÎÀ ïÇÒÁÎÉÞÉÔØ. END TRACK => 'áÎÎÏÔÁÃÉÑ', TRACK_TYPE => 'ôÉÐ', SHOW => 'ðÏËÁÚÁÔØ', FORMAT => 'æÏÒÍÁÔ', LIMIT => 'ïÇÒÁÎÉÞÉÔØ', ADJUST_ORDER => 'éÓÐÒÁ×ÉÔØ ÐÏÒÑÄÏË', CHANGE_ORDER => 'éÚÍÅÎÉÔØ ÐÏÒÑÄÏË', AUTO => 'á×ÔÏ', COMPACT => 'ëÏÍÐÁËÔÎÏ', EXPAND => 'ðÏÄÒÏÂÎÏ', EXPAND_LABEL => 'ðÏÄÒÏÂÎÏ Ó ËÏÍÍÅÎÔÁÒÉÑÍÉ', HYPEREXPAND => 'ó×ÅÒÈÐÏÄÒÏÂÎÏ', HYPEREXPAND_LABEL =>'ó×ÅÒÈÐÏÄÒÏÂÎÏ Ó ËÏÍÍÅÎÔÁÒÉÑÍÉ', NO_LIMIT => 'îÅ ÏÇÒÁÎÉÞÅÎÏ', OVERVIEW => 'ïÂÝÉÊ ×ÉÄ', ANALYSIS => 'áÎÁÌÉÚ', GENERAL => 'ïÂÝÉÅ ÁÎÎÏÔÁÃÉÉ', DETAILS => 'äÅÔÁÌØÎÙÊ ×ÉÄ', REGION => 'õÞÁÓÔÏË', ALL_ON => '÷ËÌÀÞÉÔØ ×ÓÅ', ALL_OFF => '÷ÙËÌÀÞÉÔØ ×ÓÅ', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'úÁËÒÙÔØ ÜÔÏ ÏËÎÏ', TRACK_DESCRIPTIONS => 'ïÐÉÓÁÎÉÅ ÁÎÎÏÔÁÃÉÉ É ÓÓÙÌËÉ', BUILT_IN => 'áÎÎÏÔÁÃÉÉ ÈÒÁÎÑÝÉÅÓÑ ÎÁ ÓÅÒ×ÅÒÅ', EXTERNAL => '÷ÎÅÛÎÉÅ ÁÎÎÏÔÁÃÉÉ', ACTIVATE => 'ðÏÖÁÌÕÊÓÔÁ ÁËÔÉ×ÉÒÕÊÔÅ ÜÔÕ ÁÎÎÏÔÁÃÉÀ ÄÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÐÒÏÓÍÏÔÒÅÔØ ÉÎÆÏÒÍÁÃÉÀ Ï ÎÅÊ.', NO_EXTERNAL => '÷ÎÅÛÎÉÈ ÁÎÎÏÔÁÃÉÊ ÎÅ ÚÁÇÒÕÖÅÎÏ', NO_CITATION => 'îÅÔ ÎÉËÁËÏÊ ÄÏÐÏÌÎÉÔÅÌØÎÏÊ ÉÎÆÏÒÍÁÃÉÉ.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'ï %s', BACK_TO_BROWSER => 'îÁÚÁÄ Ë âÒÏÕÚÅÒÕ', PLUGIN_SEARCH_1 => '%s (via %s search)', PLUGIN_SEARCH_2 => '<%s search>', CONFIGURE_PLUGIN => 'ëÏÎÆÉÇÕÒÉÒÏ×ÁÔØ', BORING_PLUGIN => 'õ ÜÔÏÇÏ ÐÌÁÇÉÎÁ ÎÅÔ ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÎÁÓÔÒÏÅË.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'ïÒÉÅÎÔÉÒ Ó ÉÍÅÎÅÍ %s ÎÅ ÎÁÊÄÅÎ. ðÏÓÍÏÔÒÉÔÅ ÓÐÒÁ×ÏÞÎÕÀ ÉÎÆÏÒÍÁÃÉÀ ÄÌÑ ÐÏÍÏÝÉ.', TOO_BIG => 'äÅÔÁÌØÎÏÅ ÉÚÏÂÒÁÖÅÎÉÅ ÏÇÒÁÎÉÞÅÎÏ %s ÂÐ. ýÅÌËÎÉÔÅ ÎÁ ÏÂÝÉÊ ×ÉÄ ÞÔÏÂÙ ×ÙÂÒÁÔØ ÕÞÁÓÔÏË ÛÉÒÉÎÏÊ %s.', PURGED => "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÆÁÊÌ %s. ÷ÏÚÍÏÖÎÏ ÏÎ ÂÙÌ ÕÄÁÌÅÎ?.", NO_LWP => "üÔÏÔ ÓÅÒ×ÅÒ ÎÅ ÎÁÓÔÒÏÅÎ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ×ÎÅÛÎÉÈ URLs.", FETCH_FAILED => "îÅÔ ÄÏÓÔÕÐÁ Ë %s: %s.", TOO_MANY_LANDMARKS => 'ÏÂßÅËÔÏ×: %d. óÐÉÓÏË ÓÌÉÛËÏÍ ×ÅÌÉË ÄÌÑ ÐÏËÁÚÁ.', SMALL_INTERVAL => 'íÁÓÛÔÁÂÉÒÕÅÍ ÍÁÌÙÊ ÒÁÚÍÅÒ ÄÏ %s ÂÐ', NO_SOURCES => 'îÅ ÚÁÄÁÎÙ ÉÓÔÏÞÎÉËÉ ÄÁÎÎÙÈ. ÷ÏÚÍÏÖÎÏ Õ ×ÁÓ ÎÅÔ ÐÒÁ× ÎÁ ÐÒÏÓÍÏÔÒ.', }; GBrowse-2.56/conf/languages/zh.pm000444001750001750 1637713036764442 17053 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! # translation by Jack Chen { CHARSET => 'Big5', #---------- # MAIN PAGE #---------- PAGE_TITLE => '°ò¦]²Õ¬yÄý¾¹', SEARCH_INSTRUCTIONS => < < < 'Åã¥Ü %s °_©l¤_ %s, ¦ì¸m±q %s ¨ì %s', INSTRUCTIONS => '´£¥Ü', HIDE => 'ÁôÂÃ', SHOW => 'Åã¥Ü', SHOW_INSTRUCTIONS => 'Åã¥Ü´£¥Ü', HIDE_INSTRUCTIONS => 'ÁôÂô£¥Ü', SHOW_HEADER => 'Åã¥Ü©ïÀY', HIDE_HEADER => 'ÁôÂéïÀY', LANDMARK => '¼Ð»x©Î°Ï°ì', BOOKMARK => '³]¸m®ÑÅÒ', IMAGE_LINK => '¹Ï§ÎÃì±µ', SVG_LINK => '°ª½è¶q¹Ï§Î', SVG_DESCRIPTION => < ¥H¤UÃì±µ¥i¥Í¦¨SVG®æ¦¡ªº¹Ï§Î¡C SVG®æ¦¡¤ñjpeg©Îpng®æ¦¡¦³¦h­«ÀuÂI.

    • ¯à©ñ¤jÁY¤p¡M¤£¼vÅT²M´·«×¡C
    • ¥i§Q¥Î¤@¨Ç³n¥ó¶i¦æ½s¿è¡C
    • ¥iÂà´«¦¨EPS®æ¦¡¨Ñµoªí

    »Ý¥ÎSVG¯S§O³n¥ó¬yÄý¡M ¦pAdobe SVG ¬yÄý¾¹´¡¥ó¡M ©ÎAdobe Illustrator¡C

    Adobe's SVG ¬yÄý¾¹´¡¥ó¡R Macintosh | Windows
    Linux¥Î¤á¥i¹Á¸Õ¨Ï¥ÎBatik SVG ¬yÄý¾¹.

    ¦b·sµøµ¡?Æ[¹îSVG¹Ï¹³

    «öcontrol-click (Macintosh) ©Î¹«¼Ð¥kÀ»(Windows) ¨Ã¿ï¾Ü¾A·í¿ï¶µ¤U¸ü¹Ï¹³

    END IMAGE_DESCRIPTION => < ¦p»Ý²£¥Í¦¹¹Ï¹³ªºÃì±µ¡M«þ¨©URL¡R

    <IMAGE src="%s" />
    

    ¦¹¹Ï¹³À³¬O³o¼Ë¡R

    ¦p¿ï¾Ü²¤Äý(¬V¦âÅé©Îcontig)¡M¾¨¶qÁY¤pÆ[¹î°Ï°ì¡C

    END TIMEOUT => <<'END', ¶W®É¡C§A¥i¯à¿ï¾Üªº°Ï°ì¹L¤j¡C­nÁ×§K¶W®É¡M§A¥iÃö±¼¤@¨Ç¼Æ¾Ú¹D¡M¿ï¾Ü¸û¤p°Ï°ì¡M©ÎÂIÀ»"¦^°õ"Áä¡C END GO => '°õ¦æ', FIND => '´M§ä', SEARCH => '¬d¸ß', DUMP => 'Åã¥Ü', HIGHLIGHT => '±j½Õ', ANNOTATE => 'µù¸Ñ', SCROLL => '¨÷°Ê/ÁY©ñ', RESET => '­«¸m', FLIP => 'ÄA­Ë', DOWNLOAD_FILE => '¤U¸ü¤å¥ó', DOWNLOAD_DATA => '¤U¸ü¼Æ¾Ú', DOWNLOAD => '¤U¸ü', DISPLAY_SETTINGS => 'Åã¥Ü³]¸m', TRACKS => '¼Æ¾Ú¹D', EXTERNAL_TRACKS => '¥~¨Ó¼Æ¾Ú¹D(±×Åé)', OVERVIEW_TRACKS => '*·§Äý¼Æ¾Ú¹D', REGION_TRACKS => '**?°ì?Õu¹D', EXAMPLES => '½d¨Ò', REGION_SIZE => '?°ì¤j¤p(bp)', HELP => 'À°§U', HELP_FORMAT => 'À°§U¤å¥ó®æ¦¡', CANCEL => '¨ú®ø', ABOUT => 'Ãö©ó...', REDISPLAY => '­«·sÅã¥Ü', CONFIGURE => '°t¸m...', CONFIGURE_TRACKS => '°t¸m?Õu¹D', EDIT => '½s¿è¤å¥ó...', DELETE => '§R°£', EDIT_TITLE => '¿é¤J/½s¿èµùÄÀ¼Æ¾Ú', IMAGE_WIDTH => '¹Ï¹³¼e«×', BETWEEN => '¤§¶¡', BENEATH => '¤U­±', LEFT => '¥ª­±', RIGHT => '¥k­±', TRACK_NAMES => '¼Æ¾Ú¹D¦WºÙªí', ALPHABETIC => '¦r¥À', VARYING => 'ÅܤÆ', SET_OPTIONS => '³]©w¯S©º¼Æ¾Ú¿ï¶µ...', CLEAR_HIGHLIGHTING => 'Î`­ì', UPDATE => '§ó·s¹Ï¹³', DUMPS => 'Âà¦s¡M ¬d¸ß¤Î¨ä¥L¿ï¾Ü', DATA_SOURCE => '¼Æ¾Ú¨Ó·½', UPLOAD_TRACKS=>'¤W¸ü¼Æ¾Ú¹D', UPLOAD_TITLE=> '¤W¸üµùÄÀ', UPLOAD_FILE => '¤W¸ü¤å¥ó', KEY_POSITION => 'µù¸Ñ¦ì¸m', BROWSE => '¬yÄý', UPLOAD => '¤W¸ü', NEW => '·s', REMOTE_TITLE => '¼W¥[»·µ{µù¸Ñ', REMOTE_URL => '¿é¤J»·µ{µù¸Ñºô§}', UPDATE_URLS => '§ó·sºô§}', PRESETS => '--¿ï¾Ü·í«eºô§}--', FEATURES_TO_HIGHLIGHT => '»Ý??ªº¯S©º', REGIONS_TO_HIGHLIGHT => '»Ý??ªº?°ì', FEATURES_TO_HIGHLIGHT_HINT => '·t¥Ü¡G¥Î¯S©º@?¦â????¦â¡A¦p\'NUT21@²H?\'\'', REGIONS_TO_HIGHLIGHT_HINT => '·t¥Ü¡G¥Î¯S©º@?¦â????¦â¡A¦p\'Chr1:10000..20000@²H?\'\'', NO_TRACKS => '*ªÅ¥Õ*', FILE_INFO => '³Ìªñ­×§ï¤_ %s. µùÄÀ¼Ð»x¬°: %s', FOOTER_1 => < '³q¥Î°ò¦]²Õ¬yÄý¾¹ª©¥» %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => '¥H¤U°Ï°ì %dº¡¨¬§Aªº­n¨D.', POSSIBLE_TRUNCATION => '·j´Mµ²ªG­­©ó %d ¦¸¡C¤@¨Çµ²ªG·|¯à¤£§¹¥þ', MATCHES_ON_REF => '²Å¦X¤_ %s', SEQUENCE => '§Ç¦C', SCORE => '¿n¤À=%s', NOT_APPLICABLE => 'µLÃö', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => '%s ªº³]¸m', UNDO => '´_­ì', REVERT => 'ªð¦^¯Ê·l­È', REFRESH => '§ó·s«Ì¹õ', CANCEL_RETURN => '¨ú®ø§ïÅܨêð¦^...', ACCEPT_RETURN => '±µ¨ü§ïÅܨêð¦^...', OPTIONS_TITLE => '¯S©º¼Æ¾Ú¿ï¶µ', SETTINGS_INSTRUCTIONS => <Åã¥Ü­t³d¥´¶}©MÃö³¬¸ô®|. ºòÁY ­¢¨Ï¸ô®|ÁY¤p¥H«KµùÄÀ¥i¥H­«­¡. The ÂX®i ©M ³q¹LÃì±µ ¿ï¶µ§Q¥ÎºC³t©M§Ö³t®i¶}ºâªk¶}±Ò¸I¼²±±¨î. ÂX®i ©M ¼Ð°O ¡M¥H¤Î ³q¹LÃì±µªºÂX®i©M¼Ð°Ol ­¢¨ÏµùÄÀ³Q¼Ð°O¤W. ¦pªG ¿ï¾Ü¦Û°Ê , ¸I¼²±±¨î©M¼Ð°O¿ï¶µ ±N·|³Q¦Û°Ê¿ï¥Î. ¦p­n§ïÅܸô®|ªº¶¶§Ç¡M¥i¨Ï¥Î §ïÅܸô®|¶¶§Ç µæ³æ. ¦p¥Î­­¨îµùÄÀ¼Æ¶q, «h§ïÅÜ ·¥­­ ªº­È. END TRACK => '¼Æ¾Ú¹D', TRACK_TYPE => '¼Æ¾Ú¹DÃþ«¬', SHOW => 'Åã¥Ü', FORMAT => '®æ¦¡', LIMIT => '·¥­­', ADJUST_ORDER => '½Õ¾ã¶¶§Ç', CHANGE_ORDER => '§ïÅܯS©º¼Æ¾Ú¶¶§Ç', AUTO => '¦Û°Ê', COMPACT => 'ºòÁY', EXPAND => 'ÂX®i', EXPAND_LABEL => 'ÂX®i¨Ã¼Ð°O', HYPEREXPAND => '³q¹LÃì±µÂX®i', HYPEREXPAND_LABEL =>'³q¹LÃì±µÂX®i¨Ã¼Ð°O', NO_LIMIT => 'µLÃä¬É', OVERVIEW => '·§Äý', ANALYSIS => '¤ÀªR', GENERAL => '·§?', DETAILS => '²Ó¸`', REGION => '?°ì', ALL_ON => '¥þ¿ï', ALL_OFF => '¥þÃö', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => 'Ãö³¬µ¡¤f', TRACK_DESCRIPTIONS => '¯S©º¼Æ¾Úªº´y­z¤Î¤Þ¥Î', BUILT_IN => '³o­ÓªA°È¾¹ªº¤º³¡¯S©º¼Æ¾Ú', EXTERNAL => '¥~³¡µùÄÀ¯S©º¼Æ¾Ú', ACTIVATE => '½Ð¿E¬¡³o?©º¼Æ¾Ú¥H«K¾\Ū¬ÛÃö«H®§.', NO_EXTERNAL => '¨S¦³¸ü¤J¥~³¡¯S¼x.', NO_CITATION => 'µL¶i¤@¨B¬ÛÃö«H®§.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => 'Ãö©ó %s', BACK_TO_BROWSER => 'ªð¦^¬yÄý¾¹', PLUGIN_SEARCH_1 => '%s (³q¹L %s ¬d¸ß)', PLUGIN_SEARCH_2 => '<%s ¬d¸ß>', CONFIGURE_PLUGIN => '°t¸m', BORING_PLUGIN => '³o­Ó´¡¤J³n¥óµLÃB¥~°t¸m.', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => '³o?¼Ð»x %s µLªkÃѧO. ½Ð°Ñ¾\À°§Uºô­¶.', TOO_BIG => '¸Ô²Ó¾\Ū½d³ò§½­­©ó %s ½p°ò. ÂIÀ»Â²¤¶¨Ã ¿ï¾Ü°Ï°ì %s bp ¼e.', PURGED => "§ä¤£¨ì¤å¥ó %s. ¥i¯à¤w³Q§R°£ ?.", NO_LWP => "³o­ÓªA°È¾¹¤£¯àÀò¨ú¥~³¡ºô§}.", FETCH_FAILED => "¤£¯àÀò¨ú %s: %s.", TOO_MANY_LANDMARKS => '%d ¼Ð»x. ¤Ó¦h¦Ó¦C¤£¥X.', SMALL_INTERVAL => '±N°Ï°ìÁY¤p¨ì %s bp', NO_SOURCES => '§ä¤£¨ì¥iŪªº¼Æ¾Ú¡C©Î³\§A¨S¦³¾\ŪÅv­­¡C', }; GBrowse-2.56/conf/languages/zh_cn.pm000444001750001750 1760513036764442 17526 0ustar00lsteinlstein000000000000# do not remove the { } from the top and bottom of this page!!! #Simple_Chinese language module by Li DaoFeng #Modified from Tradition_Chinese version by Jack Chen { CHARSET => 'GB2312', #---------- # MAIN PAGE #---------- PAGE_TITLE => '»ùÒò×éä¯ÀÀÆ÷', SEARCH_INSTRUCTIONS => < < < '´Ó%s ÖÐÏÔʾ %s, λÖÃ´Ó %s µ½ %s', INSTRUCTIONS => '½éÉÜ', HIDE => 'Òþ²Ø', SHOW => 'ÏÔʾ', SHOW_INSTRUCTIONS => 'ÏÔʾ½éÉÜ', HIDE_INSTRUCTIONS => 'Òþ²Ø½éÉÜ', SHOW_HEADER => 'ÏÔʾ±êÌâ', HIDE_HEADER => 'Òþ²Ø±êÌâ', LANDMARK => '±êÖ¾»òÇøÓò', BOOKMARK => 'Ìí¼Óµ½ÊéÇ©', IMAGE_LINK => 'ͼÏñÁ´½Ó', SVG_LINK => '¸ßÖÊÁ¿Í¼Ïñ', SVG_DESCRIPTION => < ÏÂÃæµÄÁ´½Ó½«²úÉúSVG¸ñʽµÄͼÏñ¡£SVG¸ñʽ¶Ô±Èjpg»òpng¸ñʽÓÐÐí¶àÓŵ㡣

    • ²»Ó°ÏìͼÏñÖÊÁ¿µÄÇé¿öϸıäͼÏñ´óС
    • ¿ÉÒÔÓÃÆÕͨͼÏñÈí¼þ½øÐб༭
    • Èç¹ûÓÐÐèÒª¿ÉÒÔת»»³ÉEPS¸ñʽ¹°·¢±íÖ®Óá£

    ÒªÏÔʾSVGͼÏñ, ÐèÒªä¯ÀÀÆ÷Ö§³ÖSVG, ÀýÈç¿ÉÒÔʹÓÃAdobe SVG ä¯ÀÀÆ÷²å¼þ, »òÕß Adobe IllustratorµÄSVGµÄ²é¿´ºÍ±à¼­Èí¼þ¡£

    AdobeµÄ SVG ä¯ÀÀÆ÷²å¼þ: Macintosh | Windows
    LinuxÓû§¿ÉÒÔ³¢ÊÔ Batik SVG ²é¿´Æ÷.

    ÔÚÐÂä¯ÀÀÆ÷´°¿ÚÖв鿴SVGͼÏñ

    °´control-click (Macintosh) »ò Êó±êÓÒ¼ü (Windows) ºóÑ¡ÔñÊʵ±Ñ¡Ïî¿ÉÒÔͼÏñ±£´æµ½´ÅÅÌ¡£

    END IMAGE_DESCRIPTION => < Éú³ÉǶÊÖÍøÒ³µÄͼÏñ, ¼ôÇв¢Õ³ÌùͼÏñµÄURLµ½HTMLÒ³Ãæ:

    <IMAGE src="%s" />
    

    ͼÏñ¿´ÆðÀ´Ó¦¸ÃÊÇÕâÑù:

    Èç¹ûÑ¡ÔñÏÔʾ¸ÅÒª (ȾɫÌå »ò contig), ¾¡Á¿ËõС²é¿´ÇøÓò¡£

    END TIMEOUT => <<'END', ÇëÇó³¬Ê±¡£ÄúÑ¡ÔñÏÔʾµÄÇøÓò¿ÉÄÜÌ«´ó¶ø²»ÄÜÏÔʾ¡£ ³¢ÊԹصôһЩÊý¾ÝµÀ »ò Ñ¡ÔñÉÔСµÄÇøÓò. Èç¹ûÈÔÈ»³¬Ê±£¬Çë°´ºìÉ«µÄ "ÖØÖÃ" °´Å¥¡£ END GO => 'Ö´ÐÐ', FIND => 'ѰÕÒ', SEARCH => '²éѯ', DUMP => 'ÏÔʾ', HIGHLIGHT => '¸ßÁÁ', ANNOTATE => '×¢ÊÍ', SCROLL => '¾í¶¯/Ëõ·Å', RESET => 'ÖØÖÃ', FLIP => 'µßµ¹', DOWNLOAD_FILE => 'ÏÂÔØÎļþ', DOWNLOAD_DATA => 'ÏÂÔØÊý¾Ý', DOWNLOAD => 'ÏÂÔØ', DISPLAY_SETTINGS => 'ÏÔʾÉèÖÃ', TRACKS => 'Êý¾ÝµÀ', EXTERNAL_TRACKS => 'ÍⲿÊý¾ÝµÀ£¨Ð±Ì壩', OVERVIEW_TRACKS => '*Êý¾ÝµÀ¸ÅÒª', REGION_TRACKS => '**Êý¾ÝµÀÇøÓò', EXAMPLES => '·¶Àý', REGION_SIZE => 'ÇøÓò´óС (bp)', HELP => '°ïÖú', HELP_FORMAT => '°ïÖúÎļþ¸ñʽ', CANCEL => 'È¡Ïû', ABOUT => '¹ØÓÚ...', REDISPLAY => 'ÖØÐÂÏÔʾ', CONFIGURE => 'ÅäÖÃ...', CONFIGURE_TRACKS => 'ÅäÖÃÊý¾ÝµÀ...', EDIT => '±à¼­Îļþ...', DELETE => 'ɾ³ýÎļþ', EDIT_TITLE => '½øÈë/±à¼­ ×¢ÊÍÊý¾Ý', IMAGE_WIDTH => 'ͼÏñ¿í¶È', BETWEEN => 'Ö®¼ä', BENEATH => 'ÏÂÃæ', LEFT => '×óÃæ', RIGHT => 'ÓÒÃæ', TRACK_NAMES => 'Êý¾ÝµÀÃû³Æ±í', ALPHABETIC => '×Öĸ', VARYING => '±ä»¯', SHOW_GRID => 'ÏÔÊ¾Íø¸ñ', SET_OPTIONS => 'Éè¶¨ÌØÕ÷Êý¾ÝÑ¡Ïî...', CLEAR_HIGHLIGHTING => 'Çå³ý¸ßÁÁ', UPDATE => '¸üÐÂͼÏñ', DUMPS => '±£´æ£¬²éѯ¼°ÆäËüÑ¡Ôñ', DATA_SOURCE => 'Êý¾ÝÀ´Ô´', UPLOAD_TRACKS=>'ÉÏ´«Äú×Ô¼ºµÄÊý¾ÝµÀ', UPLOAD_TITLE=> 'ÉÏ´«Äú×Ô¼ºµÄ×¢ÊÍ', UPLOAD_FILE => 'ÉÏ´«Ò»¸öÎļþ', KEY_POSITION => '×¢ÊÍλÖÃ', BROWSE => 'ä¯ÀÀ...', UPLOAD => 'ÉÏ´«', NEW => 'ÐÂÔö...', REMOTE_TITLE => 'Ìí¼ÓÔ¶³Ì×¢ÊÍ', REMOTE_URL => '¼üÈëÔ¶³Ì×¢ÊÍÍøÖ·', UPDATE_URLS => '¸üÐÂÍøÖ·', PRESETS => '--Ñ¡Ôñµ±Ç°ÍøÖ·--', FEATURES_TO_HIGHLIGHT => '¸ßÁÁÌØÐÔ (ÌØÐÔ1 ÌØÐÔ2...)', REGIONS_TO_HIGHLIGHT => '¸ßÁÁÇøÓò (ÇøÓò1:Æðʼ..½áÊø ÇøÓò2:Æðʼ..½áÊø)', FEATURES_TO_HIGHLIGHT_HINT => 'Ìáʾ: ÓÃÌØÕ÷@color Ñ¡ÔñÑÕÉ«, Èç \'NUT21@lightblue\'', REGIONS_TO_HIGHLIGHT_HINT => 'Ìáʾ: ÓÃÌØÕ÷@color Ñ¡ÔñÑÕÉ«, Èç \'Chr1:10000..20000@lightblue\'', NO_TRACKS => '*¿Õ°×*', FILE_INFO => '×îºóÐÞ¸Ä %s. ×¢ÊͱêÖ¾: %s', FOOTER_1 => < 'Generic genome browser version %s', #---------------------- # MULTIPLE MATCHES PAGE #---------------------- HIT_COUNT => 'ÏÂÁÐ %d ÇøÓò·ûºÏÄúµÄÒªÇó', POSSIBLE_TRUNCATION => 'ËÑË÷½á¹û¿ÉÄÜÏÞÓÚ %d ´Î; ½á¹ûÁбí¿ÉÄܲ»ÍêÈ«¡£', MATCHES_ON_REF => '·ûºÏÓÚ %s', SEQUENCE => 'ÐòÁÐ', SCORE => 'µÃ·Ö=%s', NOT_APPLICABLE => 'ÎÞ¹Ø ', BP => 'bp', #-------------- # SETTINGS PAGE #-------------- SETTINGS => '%s µÄÉèÖÃ', UNDO => '³·Ïû¸ü¸Ä', REVERT => '»Ø¸´µ½Ä¬ÈÏÖµ', REFRESH => 'Ë¢ÐÂ', CANCEL_RETURN => 'È¡Ïû¸ü¸Ä²¢·µ»Ø...', ACCEPT_RETURN => '½ÓÊܸü¸Ä²¢·µ»Ø...', OPTIONS_TITLE => 'ÌØÕ÷Êý¾ÝÑ¡Ïî', SETTINGS_INSTRUCTIONS => <ÏÔʾ ¸´Ñ¡¿ò¿ÉÒÔÖ´ÐÐÊý¾ÝµÀµÄ´ò¿ªºÍ¹Ø±Õ¡£ The ½ôËõ Ñ¡ÏîÇ¿ÖÆ½ôËõÊý¾ÝµÀ£¬ËùÒÔÓÐЩעÊÍ»áÖØµþ¡£À©Õ¹ ºÍ ͨ¹ýÁ´½Ó Ñ¡ÏîÀûÓÿìËÙ»òÂýËٹ滮Ëã·¨¿ªÆôÅö¿ØÖÆ¡£À©Õ¹ ºÍ ±ê¼Ç ÒÔ¼° ͨ¹ýÁ´½ÓµÄÀ©Õ¹ºÍ±ê¼Ç Ñ¡ÏîÇ¿ÖÆ×¢Êͱ»±ê¼Ç¡£ Èç¹ûÑ¡ÔñÁË×Ô¶¯ Ñ¡Ïî, ¿Õ¼äÔÊÐíµÄÌõ¼þÏÂÅöײ¿ØÖƺͱê¼ÇÑ¡Ï»áÉèÖÃΪ×Ô¶¯¡£ Òª¸Ä±äÊý¾ÝµÀµÄ˳Ðò¿ÉÒÔʹÓà ¸ü¸ÄÊý¾ÝµÀ˳Ðò µ¯³ö²Ëµ¥ ²¢ÎªÊý¾ÝµÀ·ÖÅäÒ»¸ö×¢ÊÍ. ÒªÏÞ֯עÊ͵ÄÊýÄ¿, ¸ü¸Ä ÏÞÖÆ ²Ëµ¥µÄÖµ¡£ END TRACK => 'Êý¾ÝµÀ', TRACK_TYPE => 'Êý¾ÝµÀÀàÐÍ', SHOW => 'ÏÔʾ', FORMAT => '¸ñʽ', LIMIT => 'ÏÞÖÆ', ADJUST_ORDER => '˳Ðòµ÷Õû', CHANGE_ORDER => '¸ü¸ÄÊý¾ÝµÀ˳Ðò', AUTO => '×Ô¶¯', COMPACT => '½ôËõ', EXPAND => 'À©Õ¹', EXPAND_LABEL => 'À©Õ¹²¢±ê¼Ç', HYPEREXPAND => 'ͨ¹ýÁ´½ÓÀ©Õ¹', HYPEREXPAND_LABEL =>'ͨ¹ýÁ´½ÓÀ©Õ¹²¢±ê¼Ç', NO_LIMIT => 'ÎÞÏÞÖÆ', OVERVIEW => '¸ÅÒª', EXTERNAL => 'ÍⲿµÄ', ANALYSIS => '·ÖÎö', GENERAL => '¸ÅÒª', DETAILS => 'ϸ½Ú', REGION => 'ÇøÓò', ALL_ON => 'È«²¿´ò¿ª', ALL_OFF => 'È«²¿¹Ø±Õ', #-------------- # HELP PAGES #-------------- CLOSE_WINDOW => '¹Ø±Õ´°¿Ú', TRACK_DESCRIPTIONS => 'ÌØÕ÷Êý¾ÝµÄÃèÊöºÍÒýÓÃ', BUILT_IN => 'Õâ¸ö·þÎñÆ÷ÄÚÔÚµÄÌØÕ÷Êý¾Ý', EXTERNAL => 'ÍⲿעÊÍÌØÕ÷Êý¾Ý', ACTIVATE => 'Ç뼤»î´ËÌØÕ÷Êý¾Ý²¢²é¿´Ïà¹ØÐÅÏ¢', NO_EXTERNAL => 'ûÓÐÔØÈëÍâ²¿ÌØÕ÷', NO_CITATION => 'ûÓжîÍâµÄÏà¹ØÐÅÏ¢.', #-------------- # PLUGIN PAGES #-------------- ABOUT_PLUGIN => '¹ØÓÚ %s', BACK_TO_BROWSER => '·µ»Øµ½ä¯ÀÀÆ÷', PLUGIN_SEARCH_1 => '%s (ͨ¹ý %s ËÑË÷)', PLUGIN_SEARCH_2 => '<%s ²éѯ>', CONFIGURE_PLUGIN => 'ÅäÖÃ', BORING_PLUGIN => '´Ë²å¼þÎÞÐè¶îÍâÉèÖÃ', #-------------- # ERROR MESSAGES #-------------- NOT_FOUND => 'ÎÞ·¨Ê¶±ðÃûΪ %s µÄ±êÖ¾¡£ Çë²é¿´°ïÖúÒ³Ãæ¡£', TOO_BIG => 'ϸ½Ú²é¿´·¶Î§ÏÞÖÆÔÚ %s ¼î»ù¡£ ÔÚ¸ÅÒªÖеã»÷Ñ¡Ôñ %s ¿íµÄÇøÓò.', PURGED => "ÕÒ²»µ½Îļþ %s ¡£ ¿ÉÄÜÒѱ»É¾³ý?", NO_LWP => "´Ë·þÎñÆ÷²»Ö§³Ö»ñÈ¡Íâ²¿ÍøÖ·", FETCH_FAILED => "²»ÄÜ»ñÈ¡ %s: %s.", TOO_MANY_LANDMARKS => '%d ±êÖ¾¡£ Ì«¶à¶øÁв»³öÀ´¡£', SMALL_INTERVAL => '½«ÇøÓòËõСµ½ %s bp', NO_SOURCES => 'ûÓÐÅäÖÿɶÁµÄÊý¾ÝÔ´. »òÕßÄãûÓÐȨÏ޲鿴ËüÃÇ', }; GBrowse-2.56/conf/plugins000755001750001750 013036764442 15414 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/plugins/AlignTwoSequences.pm000444001750001750 1700013036764442 21525 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::AlignTwoSequences; # $Id: AlignTwoSequences.pm,v 1.2 2003-08-27 21:17:46 markwilkinson Exp $ use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(:standard *table); use vars '$VERSION','@ISA','$blast_executable'; =head1 NAME Bio::Graphics::Browser2::Plugin::AlignTwoSequences -- a plugin that executes NCBI's bl2seq on the current view =head1 SYNOPSIS in 0X.organism.conf: [AlignTwoSequences:plugin] bl2seq_executable = /usr/local/BLAST/bl2seq =head1 DESCRIPTION This Gbrowse plugin will take a sequence (entered in the configuration screen) and BLAST it against the current display, with hits as new sequence features. You must, of course, have the NCBI Blast suite of programs installed, you must have configured the plugin to be visible, and you must set a single plugin parameter in the 0X.organism.conf file: [AlignTwoSequences:plugin] bl2seq_executable = /path/to/your/bl2seq =cut $blast_executable = ""; $VERSION = '0.02'; @ISA = qw(Bio::Graphics::Browser2::Plugin); my @COLORS = qw(red green blue orange cyan black turquoise brown indigo wheat yellow emerald); sub name { "Blast Against Displayed Sequence" } sub description { p("This plugin will take an input sequence - entered in the 'Configure' scren - and run bl2seq (a Blast sequence alignment) ", "against any sequence raised in the current view as new features."). p("This plugin was written by Mark Wilkinson."); } sub type { 'annotator' } sub init { my $self = shift; my $conf = $self->browser_config; $blast_executable = $conf->plugin_setting('bl2seq_executable'); } sub config_defaults { my $self = shift; return {sequence_to_blast => '', p => 'blastn', g => 'T', G => -1, E => -1, X => 0, W => 0, M => 'BLOSUM62', q => -3, r => 1, F => 'T', e => 10, S => 3, 'm' => 'F', Y => 0, t => 0, U => 'F', }; } sub reconfigure { my $self = shift; my $current = $self->configuration; $current->{'sequence_to_blast'} = $self->config_param('sequence_to_blast'); $current->{'p'} = $self->config_param('p'); $current->{'g'} = $self->config_param('g'); $current->{'G'} = $self->config_param('G'); $current->{'E'} = $self->config_param('E'); $current->{'X'} = $self->config_param('X'); $current->{'W'} = $self->config_param('W'); $current->{'M'} = $self->config_param('M'); $current->{'q'} = $self->config_param('q'); $current->{'r'} = $self->config_param('r'); $current->{'F'} = $self->config_param('F'); $current->{'e'} = $self->config_param('e'); $current->{'S'} = $self->config_param('S'); $current->{'m'} = $self->config_param('m'); $current->{'Y'} = $self->config_param('Y'); $current->{'t'} = $self->config_param('t'); $current->{'U'} = $self->config_param('U'); } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $form = h3("Default bl2seq values have been selected for you"). table({-border => 0},TR([ td([b("Sequence To Align"), textfield(-name => $self->config_name('sequence_to_blast'),-size => 100, -value=>$current_config->{'sequence_to_blast'})]), td(["Blast Program: ", popup_menu($self->config_name('p'),['blastn','tblastx'], $current_config->{'p'})]), td("Gapped: ").td(radio_group( -name=>$self->config_name('g'), -values=>['T','F'],-default=>$current_config->{'g'})), td(["Gap Penalty: ", textfield(-name=>$self->config_name('G'),-default=>$current_config->{'G'},-size=>3,-maxlength=>3)]), td(["Extend Penalty: ", textfield(-name=>$self->config_name('E'),-default=>$current_config->{'E'},-size=>3,-maxlength=>3)]), td(["Dropoff value: ", textfield(-name=>$self->config_name('X'),-default=>$current_config->{'X'},-size=>3,-maxlength=>3)]), td(["Word size: " , textfield(-name=>$self->config_name('W'),-default=>$current_config->{'W'},-size=>3,-maxlength=>3)]), td(["Matrix: ", popup_menu($self->config_name('M'), ['BLOSUM62'],$current_config->{'M'})]), td(["Mismatch Penalty: ", textfield(-name=>$self->config_name('q'),-default=>$current_config->{'q'},-size=>3,-maxlength=>3)]), td(["Match Reward: ", textfield(-name=>$self->config_name('r'),-default=>$current_config->{'r'},-size=>3,-maxlength=>3)]), td("Filter query: ").td(radio_group(-name=>$self->config_name('F'), -values=>['T','F'],-default=>$current_config->{'F'})), td(["Expect: ", textfield(-name=>$self->config_name('e'),-default=>$current_config->{'e'},-size=>10,-maxlength=>10)]), td(["Strands to search: ", textfield(-name=>$self->config_name('S'),-default=>$current_config->{'S'},-size=>1,-maxlength=>1)]), td(["Search Space: ", textfield(-name=>$self->config_name('Y'),-default=>$current_config->{'Y'},-size=>3,-maxlength=>3)]), td(["Length of largest intron: ", textfield(-name=>$self->config_name('t'),-default=>$current_config->{'t'},-size=>3,-maxlength=>3)]), td("Filter Lower Case: ").td(radio_group(-name=>$self->config_name('U'), -values=>['T','F'],-default=>$current_config->{'U'})) ])); return $form; } sub annotate { my $self = shift; my $segment = shift; my $ref = $segment->ref; my $abs_start = $segment->start; my $dna = $segment->seq; my $conf = $self->configuration; my $feature_list = Bio::Graphics::FeatureFile->new(-smart_features => 1); $feature_list->add_type(bl2seq=>{glyph => 'alignment', key => "BLAST alignment", fgcolor => 'brown', bgcolor => 'brown', point => 0, 'link' => 'AUTO', orient => 'N', }); # I should add a "link" section to the feature # with the configuration set to open up an alignment window # of some kind via an [AlignTwoSequences:plugin]section... my $file = $self->do_blast($dna); use Bio::SearchIO; my $searchio = new Bio::SearchIO(-format => 'blast', -file => $file); while( my $result = $searchio->next_result ) { while( my $hit = $result->next_hit ) { while( my $hsp = $hit->next_hsp ) { my $start = $abs_start + $hsp->start; my $stop = $abs_start + $hsp->end; my $feature = Bio::Graphics::Feature->new( -start=>$start, -type => "bl2seq", -subtype => "similarity", -desc => "Blast alignment", -source => "NCBI_Blast", -strand => "0", -stop=>$stop, -ref=>$ref, -name=>'bl2seq'); $feature_list->add_feature($feature,'bl2seq'); } } } unlink $file; return $feature_list; } sub do_blast { my ($self, $dna) = @_; use File::Temp; use File::Temp qw/ tempfile tempdir /; my ($fh_q, $filename_q) = tempfile(); my ($fh_t, $filename_t) = tempfile(); my $seq2 = $self->configuration->{'sequence_to_blast'}; print $fh_q ">seq1\n$dna\n"; print $fh_t ">seq2\n$seq2\n"; open IN, "$blast_executable -i $filename_q -j $filename_t -p blastn |" || die "can't execute the blast bl2seq call $!\n"; my $result = join "", ; my ($fh_r, $filename_r) = tempfile(); print $fh_r $result; unlink $filename_q; unlink $filename_t; return $filename_r; } 1; GBrowse-2.56/conf/plugins/Aligner.pm000444001750001750 3220213036764442 17507 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::Aligner; # $Id: Aligner.pm,v 1.13 2008-09-18 15:27:07 lstein Exp $ use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(table a TR td th p popup_menu radio_group checkbox checkbox_group h1 h2 pre); use Bio::Graphics::Browser2::Realign 'align_segs'; use Bio::Graphics::Browser2::PadAlignment; use Bio::Graphics::Browser2::Util 'shellwords'; use constant DEBUG => 0; use constant DEFAULT_RAGGED_ENDS => (0,10,25,50,100,150,500); use vars '$VERSION','@ISA'; $VERSION = '0.23'; @ISA = qw(Bio::Graphics::Browser2::Plugin); use constant TARGET => 0; use constant SRC_START => 1; use constant SRC_END => 2; use constant TGT_START => 3; use constant TGT_END => 4; sub name { "Alignments" } sub description { p("This plugin prints out a multiple alignment of the selected features.", 'It was written by',a({-href=>'mailto:lstein@cshl.org'},'Lincoln Stein.') ); } sub init { my $self = shift; my $browser_conf = $self->browser_config; my @alignable = shellwords($browser_conf->plugin_setting('alignable_tracks')); @alignable = grep {$browser_conf->setting($_=>'draw_target') } $browser_conf->labels unless @alignable; $self->{alignable} = \@alignable; my @upcase = shellwords($browser_conf->plugin_setting('upcase_tracks')); $self->{upcase} = \@upcase; my @ragged = shellwords($browser_conf->plugin_setting('ragged_ends')); @ragged = DEFAULT_RAGGED_ENDS unless @ragged; $self->{ragged} = \@ragged; $self->{upcase_default} = $browser_conf->plugin_setting('upcase_default'); $self->{align_default} = $browser_conf->plugin_setting('align_default') ? [shellwords($browser_conf->plugin_setting('align_default'))] : \@alignable; $self->{ragged_default} = $browser_conf->plugin_setting('ragged_default'); } sub config_defaults { my $self = shift; return { align => @{$self->{align_default}} ? $self->{align_default} : $self->{alignable}, upcase => $self->{upcase}[0] }; } sub configure_form { my $self = shift; my $current = $self->configuration; my $browser = $self->browser_config; my $html; if ($self->{upcase}) { my %labels = map {$_ => $browser->setting($_=>'key') || $_} @{$self->{upcase}}; $html .= TR( th('Features to render uppercase:'), td(radio_group(-name => $self->config_name('upcase'), -values => ['none',@{$self->{upcase}}], -default => $current->{upcase} || $self->{upcase_default} || 'none', -labels => \%labels, @{$self->{upcase}} > 4 ? (-cols => 4) : () )) ); } if ($self->{alignable} && @{$self->{alignable}}) { my %labels = map {$_ => $browser->setting($_=>'key') || $_} @{$self->{alignable}}; $html .= TR( th('Features to include in alignment:'), td(checkbox_group(-name => $self->config_name('align'), -values => $self->{alignable}, -defaults => $current->{align}, -labels => \%labels, @{$self->{alignable}} > 4 ? (-cols => 4) : () ))); } $html .= TR( th({-colspan=>2,-align=>'left'}, 'Allow up to',popup_menu(-name => $self->config_name('ragged'), -values => $self->{ragged}, -default => $current->{ragged} || $self->{ragged_default} || 0), ' bp of unaligned sequence at ends.') ); return $html ? table({-class=>'searchtitle'},$html) : undef; } sub reconfigure { my $self = shift; my $current = $self->configuration; my @align = $self->config_param('align'); my $upcase = $self->config_param('upcase'); $current->{align} = \@align; $current->{upcase} = $upcase eq 'none' ? undef : $upcase; $current->{ragged} = $self->config_param('ragged'); $current->{flip} = $self->config_param('flip'); } sub mime_type { 'text/html' } sub dump { my $self = shift; my $segment = shift; unless ($segment) { print "No sequence specified.\n"; exit 0; } my $database = $self->database; my $browser = $self->browser_config; my $configuration = $self->configuration; # $configuration->{flip} = $self->page_settings->{flip}; my $flipped = $configuration->{flip} ? " (reverse complemented)" :''; print h1("Alignments for $segment$flipped"); my $ref_dna = lc $segment->dna; if ($segment->strand < 0) { # don't ask $ref_dna = reversec($ref_dna); $configuration->{flip} = 1; } my ($abs_start,$abs_end) = ($segment->start,$segment->end); # do upcasing if (my $upcase_track = $configuration->{upcase}) { my @upcase_types = shellwords($browser->setting($upcase_track=>'feature')); my @upcase_features = $segment->features(-types=>\@upcase_types); for my $f (@upcase_features) { my @segments = $f->segments; @segments = $f unless @segments; for my $s (@segments) { my $upstart = $s->low-$abs_start; my $uplength = $s->length; $upstart = 0 if $upstart < 0; $uplength = length($ref_dna) if $uplength > length($ref_dna); substr($ref_dna,$upstart,$uplength) =~ tr/a-z/A-Z/; } } } # here's where we handle aligned objects my @feature_types = map {shellwords($browser->setting($_=>'feature'))} @{$configuration->{align}}; my @features = $segment->features(-types=>\@feature_types); my (@segments,%strands); for my $f (@features) { warn "f strand = ",$f->strand if DEBUG; my @s = $f->segments; @s = $f unless @s; @s = grep {$abs_start<=$_->abs_end && $abs_end>=$_->abs_start} @s; for my $s (@s) { my $target = $s->target; my ($src_start,$src_end) = ($s->start,$s->end); my ($tgt_start,$tgt_end) = ($target->start,$target->end); my $flip_bug; unless (exists $strands{$target}) { my $strand = $f->strand; if ($tgt_start > $tgt_end) { $strand = -1; ($tgt_start,$tgt_end) = ($tgt_end,$tgt_start); $flip_bug++; } $strands{$target} = $strand; $strands{$target->seq_id} = $strand; } # Realign the segment a bit my ($sdna,$tdna) = ($s->dna,$target->dna); if ($flip_bug) { $sdna = reversec($sdna); $tdna = reversec($tdna); } warn "raw alignment:\n" if DEBUG; warn $sdna,"\n",$tdna,"\n" if DEBUG; warn "Realigning [$target,$src_start,$src_end,$tgt_start,$tgt_end].\n" if DEBUG; my @result = $self->realign($sdna,$tdna); foreach (@result) { warn "=========> [$target,@$_]\n" if DEBUG; my $a = $strands{$target} >= 0 ? [$target->seq_id,$_->[0]+$src_start,$_->[1]+$src_start,$_->[2]+$tgt_start,$_->[3]+$tgt_start] : [$target->seq_id,$src_end-$_->[1],$src_end-$_->[0],$_->[2]+$tgt_start,$_->[3]+$tgt_start]; warn "[$target,$_->[0]+$src_start,$_->[1]+$src_start,$tgt_end-$_->[3],$tgt_end-$_->[2]]" if DEBUG; warn "=========> [@$a]\n" if DEBUG; warn substr($sdna, $_->[0],$_->[1]-$_->[0]+1),"\n" if DEBUG; warn substr($tdna,$_->[2],$_->[3]-$_->[2]+1),"\n" if DEBUG; push @segments,$a; } } } # We're now going to do all the alignments my %clip; for my $seg (@segments) { warn "clipping [@$seg]\n" if DEBUG; my $target = $seg->[TARGET]; # left clipping if ( (my $delta = $seg->[SRC_START] - $abs_start) < 0 ) { warn "clip left $delta" if DEBUG; $seg->[SRC_START] = $abs_start; if ($strands{$target} >= 0) { $seg->[TGT_START] -= $delta; } warn "Left clipping gives [@$seg]\n" if DEBUG; } # right clipping if ( (my $delta = $abs_end - $seg->[SRC_END]) < 0) { warn "clip right $delta" if DEBUG; $seg->[SRC_END] = $abs_end; if ($strands{$target} < 0) { $seg->[TGT_START] -= $delta; } warn "Right clipping gives [@$seg]\n" if DEBUG; } my $length = $seg->[SRC_END]-$seg->[SRC_START]+1; $seg->[TGT_END] = $seg->[TGT_START]+$length-1; warn "Clipping gives [@$seg]\n" if DEBUG; $clip{$target}{low} = $seg->[TGT_START] if !defined $clip{$target}{low} || $clip{$target}{low} > $seg->[TGT_START]; $clip{$target}{high} = $seg->[TGT_END] if !defined $clip{$target}{high} || $seg->[TGT_END] > $clip{$target}{high}; } my $ragged = $configuration->{ragged} || 0; # sort aligned sequences from left to right and store them in the data structure # needed by Bio::Graphics::Browser2::PadAlignment my @sequences = ($segment->seq_id => $ref_dna); my %seqs; for my $t (sort {$clip{$a}{low}<=>$clip{$b}{low}} keys %clip) { # adjust for ragged ends $clip{$t}{low} -= $ragged; $clip{$t}{high} += $ragged; $clip{$t}{low} = 1 if $clip{$t}{low} < 1; my @order = $strands{$t}>=0?('low','high'):('high','low'); my $dna = lc $database->dna($t,@{$clip{$t}}{@order}); push @sequences,($t => $dna); # dna() api gives implicit reversec # sanity check - needed for adjusting for ragged ends warn "$t low = $clip{$t}{low}, dna = $dna\n" if DEBUG; warn "expected ",$clip{$t}{high}-$clip{$t}{low}+1," and got ",length($dna) if DEBUG; $clip{$t}{high} = $clip{$t}{low}+length($dna)-1 if $clip{$t}{high} > $clip{$t}{low}+length($dna)-1; } for my $seg (@segments) { my ($target,$src_start,$src_end,$tgt_start,$tgt_end) = @$seg; warn "clip high = $clip{$target}{high}" if DEBUG; warn "was [$target,$src_start,$src_end,$tgt_start,$tgt_end]" if DEBUG; $seg->[SRC_START] -= $abs_start; $seg->[SRC_END] -= $abs_start; if ($strands{$target} >= 0) { $seg->[TGT_START] -= $clip{$target}{low}; $seg->[TGT_END] -= $clip{$target}{low}; } else { @{$seg}[TGT_START,TGT_END] = ($clip{$target}{high} - $seg->[TGT_END], $clip{$target}{high} - $seg->[TGT_START]); } ($target,$src_start,$src_end,$tgt_start,$tgt_end) = @$seg; warn "is [$target,$src_start,$src_end,$tgt_start,$tgt_end]" if DEBUG; } # remove segments that got clipped out of existence @segments = grep { $_->[SRC_START]<=$_->[SRC_END] } @segments; if (DEBUG) { warn "DEBUG:"; my %sequences = @sequences; foreach (@segments) { my ($t,$s,$e,$ts,$te) = @$_; warn "[@$_]\n"; warn substr($sequences{$segment->display_name},$s,$e-$s+1),"\n"; warn substr($sequences{$t},$ts,$te-$ts+1),"\n"; } } my $align = Bio::Graphics::Browser2::PadAlignment->new(\@sequences,\@segments); my %offsets = map {$_ => $strands{$_} >= 0 ? $clip{$_}{low} : -$clip{$_}{low}} keys %clip; $offsets{$segment->display_name} = $abs_start; print pre($align->alignment(\%offsets,{show_mismatches => 1, flip => $configuration->{flip}} )); } sub realign { my $self = shift; my ($src,$tgt) = @_; warn join "\n",Bio::Graphics::Browser2::Realign::align($src,$tgt) if DEBUG; return align_segs($src,$tgt); } sub reversec { my $dna = reverse shift; $dna =~ tr/gatcGATC/ctagCTAG/; $dna; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::Aligner - Dump multiple alignments from GBrowse =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugins = Aligner # and later [Aligner:plugin] alignable_tracks = EST upcase_tracks = CDS Motifs upcase_default = CDS =head1 DESCRIPTION The Aligner plugin dumps multiple nucleotide-to-nucleotide alignments in text form. For it to work properly, the genomic DNA must be loaded, as well as the DNAs for each of the aligned objects. In addition, the GFF load file must represent both the source and the target of the alignment using the Target notation. For example: ctgA est match 1050 3202 . + . Target EST:agt830.5 1 554 ctgA est HSP 1050 1500 . + . Target EST:agt830.5 1 451 ctgA est HSP 3000 3202 . + . Target EST:agt830.5 452 654 =head1 OPTIONS The following options are recognized. They must be placed into a configuration file section named [Aligner:plugin]. Option Description alignable_tracks Space-delimited list of tracks to include in the multiple alignment. The genome is always included. If this option is not present, then gbrowse will automatically include any track that has the "draw_target" option set. upcase_tracks Space-delimited list of tracks that will be used to UPCASE the genomic DNA. This is very useful if you want to embed the positions of coding regions or other features inside the multiple alignment. Uppercasing will not be turned on by default. The user must press the "Configure" button, and select which of the uppercase tracks are to be activated from a radiolist. upcase_default A space-delimited list of tracks that will be uppercased by default. ragged_default A small integer indicating that the aligner should include some unaligned bases from the end of each sequence. This is useful for seeing the sequencing primer or cloning site in ESTs. =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elstein@cshl.orgE. Copyright (c) 2001 Cold Spring Harbor Laboratory. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/AttributeHiliter.pm000444001750001750 1213013036764442 21410 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::AttributeHiliter; # $Id: AttributeHiliter.pm,v 1.3 2009-05-22 14:33:38 lstein Exp $ use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::Util 'shellwords'; use CGI qw(:standard); use constant DEBUG => 0; use vars qw($VERSION @ISA); my @COLORS = ('',qw( red brown magenta maroon pink orange yellow tan teal cyan lime green blue lightgrey grey darkgrey )); $VERSION = '0.01'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Selected Properties" } sub description { p("This plugin highlights features whose properties match certain criteria.", "It was written by Lincoln Stein."); } sub type { 'highlighter' } # This routine is a bit more complicated than it needs to be because of # an optimization. What it does is to compile the highlighting pattern specified # by the current configuration into a subroutine called "memoized_sub" and then # invoke it. On subsequent invocations if the config hasn't changed, the # compiled subroutine is reinvoked. Otherwise a new sub is compiled. The compiled # sub can be seen by setting the DEBUG constant at the top of this file to true. sub highlight { my $self = shift; my $feature = shift; my $config = $self->configuration; return unless %$config; return $self->{memoized_sub}->($feature) if $self->{memoized_sub} && $self->{memoized_config} eq join ' ',%$config; my $sub = "sub { \n"; $sub .= " my \$feature = shift;\n"; for my $attribute (keys %$config) { my ($color,$text) = split(/\s+/,$config->{$attribute},2); next unless defined $color && defined $text; warn "trying to colorize $attribute with text=$text, color = $color\n" if DEBUG; my $regexp = quotemeta($text); if ($attribute eq 'Feature Name') { $sub .= " return '$color' if \$feature->display_name =~ /$regexp/i;\n"; } elsif ($attribute eq 'Feature Type') { $sub .= " return '$color' if \$feature->type =~ /$regexp/i;\n"; } elsif (defined $attribute) { $sub .= " return unless \$feature->can('attributes');\n"; $sub .= " foreach (\$feature->attributes('$attribute')) { return '$color' if /$regexp/i }\n"; } } $sub .= " return\n}"; warn $sub if DEBUG; $self->{memoized_sub} = eval $sub or warn $@; $self->{memoized_config} = join ' ',%$config; return $self->{memoized_sub}->($feature) if $self->{memoized_sub}; return; } sub config_defaults { my $self = shift; return { }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; my %c; foreach my $param ($self->config_param) { warn "param = $param" if DEBUG; my ($operation,$attribute) = $param =~ /(match|color)\.(.+)/ or next; $c{$attribute}{$operation} = $self->config_param($param); } foreach my $attribute (keys %c) { if ( (my $match_text = $c{$attribute}{match}) && (my $match_color = $c{$attribute}{color})) { $current_config->{$attribute} = "$match_color $match_text"; } else { delete $current_config->{$attribute}; } } delete $self->{memoized_sub}; } sub configure_form { my $self = shift; my $current_config = $self->configuration; my @attributes = shellwords $self->browser_config->plugin_setting('attributes'); unshift @attributes,'Feature Name','Feature Type'; my @rows; push @rows,TR({-class=>'searchtitle'},th(['Property','Text to Match','Highlight Color'])); for my $attribute (@attributes) { next unless $attribute; my ($color,$text) = split(/\s+/,$current_config->{$attribute}||'',2); push @rows,TR( th({-class=>'searchtitle',-align=>'RIGHT'},$attribute), td({-align=>'CENTER'},textfield(-name => $self->config_name("match.$attribute"), -default => $text, -size => 60)), td(popup_menu(-name => $self->config_name("color.$attribute"), -values=> \@COLORS, -default => $color, ))) } return table({-width=>'10%',-border=>0},@rows); } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::AttributeHiliter -- hilite features based on attributes =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugin = AttributeHiliter [AttributeHiliter:plugin] attributes = Note prediction_status tissue_source =head1 DESCRIPTION This plugin creates a configuration page that prompts the user to select features to hilite based on their attributes (also known as feature tags in BioPerl parlance). You specify which attributes to present in a [AttributeHiliter:plugin] configuration track with a single "attributes" option. The value of this option is a space-delimited list of attributes to present to the user. A more sophisticated example using popup menus to select particular attributes from a controlled vocabulary would be easy to write. =head1 OPTIONS None =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elincoln.stein@gmail.comE. Copyright (c) 2009 Ontario Institute for Cancer Research This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/BatchDumper.pm000444001750001750 1745513036764442 20341 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::BatchDumper; use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Seq::RichSeq; use Bio::SeqIO; use Bio::Seq; use Bio::Graphics::Browser2::TrackDumper::RichSeqMaker; use CGI qw(:standard *pre); use POSIX; use vars qw($VERSION @ISA); use constant DEBUG => 0; $VERSION = 1.0; # module label is xml? my @FORMATS = ( 'fasta' => ['Fasta', undef], 'genbank' => ['Genbank', undef], 'embl' => ['EMBL', undef], 'gcg' => ['GCG', undef], 'raw' => ['Raw sequence', undef], 'bsml' => ['BSML (XML)', 'xml'], 'gff' => ['GFF', undef], 'gff3' => ['GFF3', undef], ); # initialize @ORDER using the even-numbered elements of the array # and grepping for those that load successfully (some of the # modules depend on optional XML modules). my @ORDER = grep { my $module = "Bio::SeqIO::$_"; warn "trying to load $module\n" if DEBUG; eval "require $module; 1"; } grep { ! /gff/i } map { $FORMATS[2*$_] } (0..@FORMATS/2-1); unshift @ORDER,'gff','gff3'; @ORDER = sort @ORDER; # initialize %FORMATS and %LABELS from @FORMATS my %FORMATS = @FORMATS; my %LABELS = map { $_ => $FORMATS{$_}[0] } keys %FORMATS; $VERSION = '0.20'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Sequence File" } sub description { p("The Sequence file plugin dumps out the currently displayed genomic segment", "or the segments corresponding to the given accessions, in the requested format."). p("This plugin was written by Lincoln Stein and Jason Stajich."); } sub dump { my $self = shift; my $segment = shift; my @more_feature_sets = @_; my $browser = $self->browser_config; my $config = $self->configuration; my $wantsorted = $config->{'wantsorted'}; my @segments = map { ( $self->renderer->name2segments($_,$self->database) ) } split /\s+/m, $config->{sequence_IDs}||''; # take the original segment if no segments were found/entered via the sequence_IDs textarea field @segments = $segment if $segment && !@segments; my $mime_type = $self->mime_type; unless (@segments) { print start_html($self->name) if $mime_type =~ /html/; print "No sequence specified.\n"; print end_html if $mime_type =~ /html/; exit 0; } my @filter = $self->selected_features; # special case for GFF dumping if ($config->{fileformat} =~ /gff(3?)/) { $self->gff_dump($1,@segments,@more_feature_sets); return; } foreach my $segment ( @segments ) { my $iterator = $segment->get_seq_stream(-types => \@filter); my $seq = Bio::Graphics::Browser2::TrackDumper::RichSeqMaker->stream_to_rich_seq($segment,$iterator); $seq->desc($segment->as_string); $segment = $seq; } # for the external viewer (like VNTI) the best import format is genbank (?) $config->{'fileformat'} = 'Genbank' if ($config->{'format'} eq 'external_viewer'); my $flip = $config->{fileformat} =~ /^(fasta|raw)$/ && (defined $config->{flip} ? $config->{flip} : $self->page_settings->{flip}); if ($flip) { foreach (@segments) { $_ = $_->revcom; $_->desc($_->desc . " (reverse complemented)"); } } my $out = new Bio::SeqIO(-format => $config->{'fileformat'},-fh=>\*STDOUT); if ($mime_type =~ /html/) { print start_html('Batch Sequence'); foreach my $segment (@segments) { my $label = $segment->desc; print h1($label),"\n", start_pre(); $out->write_seq($segment); print end_pre(); } print end_html; } else { $out->write_seq($_) for @segments; } undef $out; } sub mime_type { my $self = shift; my $config = $self->configuration; return 'text/plain' if $config->{format} eq 'text'; return 'text/xml' if $config->{format} eq 'html' && $FORMATS{$config->{fileformat}}[1]; # this flag indicates xml return 'text/html' if $config->{format} eq 'html'; return 'application/chemical-na' if $config->{format} eq 'external_viewer'; return wantarray ? ('application/octet-stream','dumped_region') : 'application/octet-stream' if $config->{format} eq 'todisk'; return 'text/plain'; # default } sub config_defaults { my $self = shift; return { format => 'html', fileformat => 'fasta', wantsorted => 0, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; $current_config->{flip} = ''; foreach my $p ( $self->config_param() ) { $current_config->{$p} = $self->config_param($p); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my @choices = TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Output", td(radio_group('-name' => $self->config_name('format'), '-values' => [qw(text html external_viewer todisk)], '-default'=> $current_config->{'format'}, -labels => {'html' => 'html/xml', 'external_viewer' => 'GenBank Helper Application', 'todisk' => 'Save to Disk', }, '-override' => 1)))); my $browser = $self->browser_config(); # this to be fixed as more general push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Sequence File Format", td(popup_menu('-name' => $self->config_name('fileformat'), '-values' => \@ORDER, '-labels' => \%LABELS, '-default'=> $current_config->{'fileformat'} )))); push @choices,TR({-class=>'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Orientation", td(checkbox(-name => $self->config_name('flip'), -label => 'Flip (Fasta and raw sequence only)', -checked => $self->page_settings->{flip}, -override => 1)))); push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'}, "Sorted SubLocations (for VectorNTI input of GenBank)", td(popup_menu('-name' => $self->config_name('wantsorted'), '-values' => [qw(0 1)], '-labels' => { '0' => 'No', '1' => 'Yes'}, '-default'=> $current_config->{'wantsorted'} )))); push @choices, TR({-class=>'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},'Sequence IDs','

    (Entry overrides chosen segment)

    ', td(textarea(-name=>$self->config_name('sequence_IDs'), -rows=>20, -columns=>20, )))); my $html= table(@choices); $html; } sub gff_dump { my $self = shift; my ($gff3_flag,$segment,@extra) = @_; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $date = localtime; my $mime_type = $self->mime_type; my $html = $mime_type =~ /html/; print start_html($segment) if $html; my @feature_types = $self->selected_features; print h1($segment),start_pre() if $html; print "##gff-version ",$gff3_flag || 2,"\n"; print "##date $date\n"; print "##sequence-region ",join(' ',$segment->ref,$segment->start,$segment->stop),"\n"; print "##source gbrowse BatchDumper\n"; print $gff3_flag ? "##See http://song.sourceforge.net/gff3.shtml\n" : "##See http://www.sanger.ac.uk/Software/formats/GFF/\n"; print "##NOTE: Selected features dumped.\n"; my $iterator = $segment->get_seq_stream(-types=>\@feature_types) or return; do_dump($gff3_flag,$iterator); for my $set (@extra) { do_dump($gff3_flag,$set->get_seq_stream) if $set->can('get_seq_stream'); } print end_pre() if $html; print end_html() if $html; } sub do_dump { my $gff3 = shift; my $iterator = shift; while (my $f = $iterator->next_seq) { eval {$f->version($gff3 || 2)}; my $s = $f->gff_string(1); chomp $s; print "$s\n"; for my $ss ($f->sub_SeqFeature) { my $string = $ss->gff_string; chomp $string; print "$string\n"; } } } 1; GBrowse-2.56/conf/plugins/Blat.pm000444001750001750 1437713036764442 17025 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::Blat; # $Id: Blat.pm - Sean O'Keeffe use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Feature; use File::Temp qw/ tempfile /; use CGI qw(:standard *table); use CGI::Carp qw(fatalsToBrowser); use vars '$VERSION','@ISA','$blat_executable','$twobit_dir','$host','$port'; =head1 NAME Bio::Graphics::Browser2::Plugin::Blat -- plugin to map sequences against the genome =head1 SYNOPSIS in human.conf: [Blat:plugin] blat_executable = /usr/local/gfClient 2bit_dir = /project/gbrowse/2bit_genomes host = blat.server.host.name port = 17780 in mouse.conf: [Blat:plugin] blat_executable = /usr/local/gfClient 2bit_dir = /project/gbrowse/2bit_genomes host = blat.server.host.name port = 17781 =head1 DESCRIPTION This Gbrowse plugin will take a sequence (entered in the configuration screen) and BLAT it against the genome of the current organism ( port from conf file). You must, of course, have the Blat server(gfServer) and client(gfClient) installed, and you must set plugin parameters in the conf file: [Blat:plugin] blat_executable = /path/to/your/blat_client The plugin only works with default psl output format for the moment. =head1 AUTHOR Sean O'Keeffe Eokeeffe@molgen.mpg.deE. =cut $blat_executable = ""; $twobit_dir = ""; $host = ""; $port = ""; $VERSION = '0.02'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "BLAT Alignment" } sub description { p("This plugin will take an input DNA sequence and run BLAT's gfClient (a Blat client to a local server)."); } sub type { 'finder' } sub init { my $self = shift; my $conf = $self->browser_config; $blat_executable = $conf->plugin_setting('blat_executable'); $twobit_dir = $conf->plugin_setting('2bit_dir'); $host = $conf->plugin_setting('host'); $port = $conf->plugin_setting('port'); } sub config_defaults { my $self = shift; return {'sequence_to_blat' => '', 'hits' => '5'} } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $form .= h3("Enter parameters below for alignment of sequences using a Client to a local BLAT Server:") .start_table({-border => 0}) .TR([ td(b("Input sequence type:"), popup_menu(-align=>'center', -name=>$self->config_name('q'),-values=>['dna', 'rna'])) ]) .TR([ td([b("Input Sequence To Align:"), textarea(-align=>'center', -name=>$self->config_name('sequence_to_blat'),-rows=>10,-cols=>80,-value=>$current_config->{'sequence_to_blat'})]) ]); $form .= end_table(); $form .= start_table({-border => 0}) . Tr(td(p())) . Tr(td(p())) . Tr(td(p())) . end_table(); $form .= start_table({-border => 0}) .TR([ td(b("Minimum Percent Identity:"), textfield(-align=>'center', -name=>$self->config_name('minIdentity'),-size=>10, -value=>'90')) ]) .TR([ td(b("Number of Hits to Return:"), textfield(-align=>'center', -name=>$self->config_name('hits'),-size=>10, -value=>$current_config->{'hits'})) ]); $form .= end_table(); return $form; } sub find { my $self = shift; my ($i,@hit_starts,@block_sizes,@results); my $query = $self->config_param('sequence_to_blat'); my $hits = int($self->config_param('hits')); my $minIdentity = int($self->config_param('minIdentity')); my $q = ($self->config_param('q') eq 'rna') ? 'rna' : 'dna'; my ($i_f, $in_file) = tempfile(); my ($o_f, $out_file) = tempfile(); if ($query !~ /^\s*>/) { print $i_f ">segment\n";} # add FASTA defline if needed print $i_f $query; # print it to a temp file my $error = `$blat_executable $host $port $twobit_dir -minIdentity=$minIdentity -nohead -q=$q $in_file $out_file 2>&1 > /dev/null`; die "$error" if $error; open (IN, "$out_file") || die "couldn't open $out_file $!\n"; my $hit_count = 0; my @blat_hits; # indexes each blat hit array of @blat_hits use constant { MATCHES => 0, MISMATCHES => 1, REP_MATCHES => 2, N_COUNT => 3, Q_NUM_INSERT => 4, Q_BASE_INSERT => 5, T_NUM_INSERT => 6, T_BASE_INSERT => 7, STRAND => 8, Q_NAME => 9, Q_LENGTH => 10, Q_START => 11, Q_END => 12, T_NAME => 13, T_LENGTH => 14, T_START => 15, T_END => 16, BLOCK_COUNT => 17, BLOCK_SIZES => 18, Q_STARTS => 19, T_STARTS => 20, }; while() { push (@blat_hits, [ split ]); } for my $hit ( # sort hits in descending order by calculated score sort { ($b->[MATCHES]+$b->[MISMATCHES]+$b->[REP_MATCHES])/$b->[Q_LENGTH] <=> ($a->[MATCHES]+$a->[MISMATCHES]+$a->[REP_MATCHES])/$a->[Q_LENGTH] } @blat_hits ) { last if ++$hit_count > $hits; $hit->[BLOCK_SIZES] =~ s/\,$//; # remove trailing comma from block_sizes string $hit->[T_STARTS] =~ s/\,$//; # .. and from t_starts string my $score = sprintf "%.2f", ( 100 * ( $hit->[MATCHES] + $hit->[MISMATCHES] + $hit->[REP_MATCHES] ) / $hit->[Q_LENGTH] ); my $percent_id = sprintf "%.2f", ( 100 * ($hit->[MATCHES] + $hit->[REP_MATCHES]) / ($hit->[MATCHES] + $hit->[MISMATCHES] + $hit->[REP_MATCHES])); my $alignment = Bio::Graphics::Feature->new(-start=>$hit->[T_START]+1, -end =>$hit->[T_END], -ref => $hit->[T_NAME], -type=>'BLAT', -name => "Alignment$hit_count", -strand => ($hit->[STRAND] eq '+') ? 1 : -1, -score => $score ); @hit_starts = map { $_ + 1 } split(",", $hit->[T_STARTS]); @block_sizes = split(",", $hit->[BLOCK_SIZES]); for($i=0;$i<$hit->[BLOCK_COUNT];$i++){ # if multihit alignments (block_count > 1), aggregate. my $sub_alignment = Bio::Graphics::Feature->new(-start=>$hit_starts[$i], -end =>($hit_starts[$i]+$block_sizes[$i]), -ref => $hit->[T_NAME], -type=>'BLAT', -name => 'Alignment', -strand => ($hit->[STRAND] eq '+') ? 1 : -1, -score => $percent_id ); $alignment->add_segment($sub_alignment); } push @results, $alignment; } unlink $in_file; unlink $out_file; return (\@results, @results ? '' : 'No alignments found'); } 1; =head1 AUTHOR Sean O'Keeffe Eokeeffe@molgen.mpg.deE. =cut GBrowse-2.56/conf/plugins/CMapDumper.pm000444001750001750 1525413036764442 20133 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::CMapDumper; # $Id: CMapDumper.pm,v 1.2 2005-12-09 22:19:09 mwz444 Exp $ use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(:standard *sup); use vars '$VERSION', '@ISA'; $VERSION = '0.80'; @ISA = qw/ Bio::Graphics::Browser2::Plugin /; sub name { "CMap File" } sub description { p("Dumps a CMap readable file."); } sub config_defaults { my $self = shift; return { version => 2, mode => 'selected', disposition => 'view', coords => 'absolute', }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; delete $current_config->{embed}; foreach my $p ( $self->config_param() ) { $current_config->{$p} = $self->config_param($p); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $html; $html .= p( 'Coordinates', radio_group( -name => $self->config_name('coords'), -values => [ 'absolute', 'relative' ], -labels => { absolute => 'relative to chromosome/contig/clone', relative => 'relative to dumped segment (start at 1)' }, -default => $current_config->{coords}, -override => 1 ) ); autoEscape(0); $html .= p( radio_group( -name => $self->config_name('disposition'), -values => [ 'view', 'save', 'edit' ], -labels => { view => 'View', save => 'Save to File', edit => 'Edit' . sup('**'), } ) ); $html .= p( 'Where should the feature type be taken from (suggested: Method)?', radio_group( -name => $self->config_name('feature_type_source'), -values => [ 'method', 'source' ], -labels => { method => 'Method', source => 'Source', } ) ); autoEscape(1); $html .= p( sup('*'), "To edit, install a helper application for MIME type", cite('application/x-cmap'), ); $html; } sub mime_type { my $self = shift; my $config = $self->configuration; my $ps = $self->page_settings; my $base = join '_', @{$ps}{qw(ref start stop)}; return $config->{disposition} eq 'view' ? 'text/plain' : $config->{disposition} eq 'save' ? ( 'application/octet-stream', "$base" ) : $config->{disposition} eq 'edit' ? "application/x-cmap" : 'text/plain'; } sub dump { my $self = shift; my ( $segment, @more_feature_sets ) = @_; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $config = $self->configuration; my $version = $config->{version} || 2; my $mode = $config->{mode} || 'selected'; my $db = $self->database; my $whole_segment = $db->segment( Accession => $segment->ref ) || $db->segment( $segment->ref ); my $ft_source = $config->{feature_type_source}; my $coords = $config->{coords}; my $embed = $config->{embed}; $segment->refseq($segment) if $coords eq 'relative'; print join( "\t", 'map_name', 'map_start', 'map_stop', 'feature_name', 'feature_start', 'feature_stop', 'feature_direction', 'feature_type_accession' ) . "\n"; my @args; if ( $mode eq 'selected' ) { my @feature_types = $self->selected_features; @args = ( -types => \@feature_types ); } my @feats = (); my $ref_name = $segment->{'sourceseq'}; my $ref_start = $segment->start; my $ref_stop = $segment->stop; my $offset = $segment->start - $segment->abs_start; my ( $feature_name, $feature_start, $feature_stop, $strand_str, $feature_type ); my $iterator = $segment->get_seq_stream(@args); while ( my $f = $iterator->next_seq ) { $feature_name = $f->{'group'}->name; $feature_start = $f->{'start'} + $offset; $feature_stop = $f->{'stop'} + $offset; $strand_str = $f->{'fstrand'}; if ( $ft_source eq 'source' ) { $feature_type = $f->{'type'}->source(); } else { $feature_type = $f->{'type'}->method(); } $self->print_feature_row( map_name => $ref_name, map_start => $ref_start, map_stop => $ref_stop, feature_name => $feature_name, feature_stop => $feature_stop, feature_start => $feature_start, strand_value => $strand_str, feature_type_aid => $feature_type, ); for my $set (@more_feature_sets) { if ( $set->can('get_seq_stream') ) { my @feats = (); my $iterator = $set->get_seq_stream; while ( my $f = $iterator->next_seq ) { $feature_name = $f->{'group'}->name; $feature_start = $f->{'start'} + $offset; $feature_stop = $f->{'stop'} + $offset; $strand_str = $f->{'fstrand'}; $feature_type = $f->{'type'}->method(); $self->print_feature_row( map_name => $ref_name, map_start => $ref_start, map_stop => $ref_stop, feature_name => $feature_name, feature_stop => $feature_stop, feature_start => $feature_start, strand_value => $strand_str, feature_type_aid => $feature_type, ); } } } } if ($embed) { my $dna = $segment->dna; $dna =~ s/(\S{60})/$1\n/g; print ">$segment\n$dna\n" if $dna; } } sub print_feature_row { my $self = shift; my %args = @_; my $map_name = $args{'map_name'}; my $map_start = $args{'map_start'}; my $map_stop = $args{'map_stop'}; my $feature_name = $args{'feature_name'}; my $feature_stop = $args{'feature_stop'}; my $feature_start = $args{'feature_start'}; my $strand_value = $args{'strand_value'}; my $feature_type_aid = $args{'feature_type_aid'}; my $feature_direction = ( $strand_value eq '-' ) ? -1 : 1; print join( "\t", $map_name, $map_start, $map_stop, $feature_name, $feature_start, $feature_stop, $feature_direction, $feature_type_aid ) . "\n"; } 1; GBrowse-2.56/conf/plugins/CreateBlastDB.pm000444001750001750 713613036764442 20515 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::CreateBlastDB; # $Id: CreateBlastDB.pm,v 1.1 2003-11-17 22:01:38 markwilkinson Exp $ =head1 NAME Bio::Graphics::Browser2::Plugin::CreateBlastDB -- a plugin that creates a Blast-formatted database from a Bio::DB::GFF database =head1 SYNOPSIS in 0X.organism.conf: [CreateBlastDB:plugin] formatdb_executable = /usr/local/BLAST/formatdb blast_db_folder = /home/username/my/blast_db/folder blast_db_name = myname.fas =head1 DESCRIPTION This Gbrowse plugin will take a sequence database, extract all sequences in it, and create a Blast-formatted database in the folder configured in the 0X.organism.conf file You must, of course, have the NCBI Blast suite of programs installed, you must have configured the plugin to be visible, and you must set two parameters in the 0X.organism.conf file: [CreateBlastDB:plugin] formatdb_executable = /usr/local/BLAST/formatdb blast_db_folder = /home/username/my/blast_db/folder blast_db_name = myname.fas =cut use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Feature; use DBI; use CGI qw(:standard *table); use vars '$VERSION','@ISA', '$formatdb', '$outdir', '$dbname'; $VERSION = '0.15'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Blast Database" } sub description { p("This will dump EVERY sequence out of the Bio::DB::GFF database and then run a BLAST formatdb on these sequences. ", "This, of course, requires that you have the Blast binaries installed and configured in your 0X.organism.conf file."). p("This plugin was written by Mark Wilkinson."); } sub type { 'dumper' } sub mime_type { return "text/html"; } sub init { my $self = shift; my $conf = $self->browser_config; $formatdb = $conf->plugin_setting('formatdb_executable'); $outdir = $conf->plugin_setting('blast_db_folder'); $dbname = $conf->plugin_setting('blast_db_name'); $outdir || die "No Configured Blast Database Folder"; die "Blast Database Folder $outdir does not exist" unless (-e $outdir); die "Blast Database Folder $outdir is not a folder" unless (-d $outdir); open OUT, ">$outdir/$dbname" || die "can't create/overwrite fasta file $outdir/$dbname: $!\n"; } sub config_defaults { my $self = shift; return { }; } # we have no stable configuration # sub reconfigure { } sub configure_form { my $self = shift; return "

    nothing to configure

    " } sub dump { my $self = shift; my $segment = shift; my $db = $self->database or die "I do not have a database"; my $dbh = $db->features_db; my $sth = $dbh->prepare("select fref,foffset,fdna from fdna order by fref,foffset") or die "Couldn't prepare ",$db->errstr; $sth->execute or die "Couldn't execute ",$db->errstr; my ($current_ref,$offset,$dna,@results); while (my ($ref,$off,$d) = $sth->fetchrow_array) { if (!defined($current_ref)) { $dna = ''; $current_ref = $ref } if ($current_ref ne $ref) { open OUT, ">>$outdir/$dbname" || die "can't open fasta file $outdir/$dbname for writing: $!\n"; print OUT ">$ref\n$dna\n\n"; $dna = ''; close OUT; } $current_ref = $ref; $dna .= lc $d; } print "

    Executing $formatdb -t 'Bio::DB::GFF Blast Database' -i $outdir/$dbname -p F -o T -a F

    "; my $res = system ("$formatdb -t 'Bio::DB::GFF Blast Database' -i $outdir/$dbname -p F -o T -a F"); unless ($res == -1){ print "

    Blast Database Created Successfully

    "; } else { print "Database Formatting Failed: $!\n"; } } 1; GBrowse-2.56/conf/plugins/FBTableDumper.pm000444001750001750 642713036764442 20534 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::FBTableDumper; # FBTableDumper.pm v1 2006 V.Strelets at FlyBase.org # derived from GFFDumper by L.Stein use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(:standard *sup); use vars '$VERSION','@ISA'; $VERSION = '0.80'; @ISA = qw/ Bio::Graphics::Browser2::Plugin /; sub name { "HTML table view" } sub description { p("FlyBase table view dumper"); } sub config_defaults { my $self = shift; return { version => 2, mode => 'selected', disposition => 'view', coords => 'absolute', }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; foreach my $p ( $self->config_param() ) { $current_config->{$p} = $self->config_param($p); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $html = p('Dump', popup_menu(-name => $self->config_name('mode'), -values => ['selected','all'], -default => $current_config->{mode}, -override => 1, ), '  features'); autoEscape(1); $html; } sub mime_type { my $self = shift; return 'text/html'; } sub dump { my $self = shift; my ($segment, @more_feature_sets) = @_; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $config = $self->configuration; my $version = $config->{version} || 3; my $mode = $config->{mode} || 'selected'; my $db = $self->database; my $whole_segment = $db->segment(Accession => $segment->ref) || $db->segment($segment->ref); my $coords = $config->{coords}; $segment->refseq($segment) if $coords eq 'relative'; my $date = localtime; print "## FlyBase table view dump
    \n"; print "## date $date
    \n"; print "## sequence-region ",join(' ',$segment->ref,$segment->start,$segment->stop),"
    \n"; print ''; my $iterator = $segment->get_seq_stream(); my %Out= (); while ( my $f = $iterator->next_seq ) { my $s = $f->gff_string(1); # the flag is for GFF3 subfeature recursion chomp $s; my($ref,$source,$method,$start,$stop,$score,$strand,$phase,$note) = split(/[\t]+/,$s); my $id= ($note=~/ID=([^;]+)/i) ? $1 : '-'; next if( $id eq '-' ); next if( $note=~/Parent=/i ); my $name= ($note=~/Name=([^;]+)/i) ? $1 : $id; if($note=~/Symbol=([^,;]+)/i) { $name.= ' '.$1; } my $key= $source.':'.$method; if( exists $Out{$key} ) { $Out{$key}.= "\t"; } $Out{$key}.= ''; if( $id=~/^FB[a-z]{2}\d+$/ ) { $name= ''.$name.''; } $Out{$key}.= ''; $note=~s/(\S);(\S)/$1; $2/g; $Out{$key}.= ''; } foreach my $key ( sort keys %Out ) { my($source,$method)= split(":",$key); print '\n"; my @strs= split("\t",$Out{$key}); foreach( @strs ) { print ''.$_."\n"; } } print "
    Seq.locationSymbol/Name/IDNote(s)
    '.$ref.':'.$start.'..'.$stop.'['.$strand.'] '.$name.' '.$note.'
    '.$source.':'.$method."
    \n"; return; } 1; GBrowse-2.56/conf/plugins/FastaDumper.pm000444001750001750 2076313036764442 20352 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::FastaDumper; # $Id: FastaDumper.pm,v 1.11 2005-12-09 22:19:09 mwz444 Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::Markup; use CGI qw(:standard ); use constant DEBUG => 0; use vars qw($VERSION @ISA @MARKUPS %LABELS $BACKGROUNDUPPER %COLORNAMES $PANEL); my @COLORS = qw(red brown magenta maroon pink orange yellow tan teal cyan lime green blue lightgrey grey darkgrey ); BEGIN { $BACKGROUNDUPPER = 'YELLOW'; @MARKUPS = ( undef, # none "UPPERCASE", # for uppercase 'Font-weight: bold', 'Text-decoration: underline', 'Font-style: italic', 'FGCOLOR %s', 'BGCOLOR %s', ); %LABELS = ( 0 => 'None', 1 => 'CAPS', 2 => 'Bold', 3 => 'Underline', 4 => 'Italics', 5 => 'Font', 6 => 'Bkg', ); } $VERSION = '0.30'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Decorated FASTA File" } sub description { p("The marked-up FASTA dumper plugin dumps out the currently displayed genomic segment", "in FASTA format."). p("This plugin was written by Lincoln Stein and Jason Stajich."); } sub dump { my $self = shift; my $segment = shift; unless ($segment) { my $mime_type = $self->mime_type; print start_html($self->name) if $mime_type =~ /html/; print "No sequence specified.\n"; print end_html if $mime_type =~ /html/; exit 0; } my $config = $self->configuration; my $dna = lc $segment->dna; my $browser = $self->browser_config(); warn("====== beginning dump =====\n") if DEBUG; warn "length of dna = ",length($dna) if DEBUG; my %types; my $flip = defined $config->{flip} ? $config->{flip} : $self->page_settings->{flip}; if ($flip) { $dna = reverse $dna; $dna =~ tr/gatcGATC/ctagCTAG/; } my $markup = Bio::Graphics::Browser2::Markup->new; while( my ($type,$val) = each %{$config} ) { next unless $val; next if $type =~ /\.(f|b)gcolor$/i; next if $type =~ /format$/; next if $type =~ /orientation$/; warn "configuring $type => $val\n" if DEBUG; my $style = $MARKUPS[$val] || ''; if ($style =~ /^(F|B)GCOLOR/) { $style = sprintf($style,$config->{"$type.\L$1\Egcolor"}); } next if $config->{format} eq 'text' && $style ne 'UPPERCASE'; (my $feature_type = $type) =~ s/^[^.]+\.//; # there may be several feature types defined for each track my @types = $browser->label2type($feature_type) or next; for my $t (@types) { $markup->add_style($t => $style); warn "adding style $t => $style\n" if DEBUG } foreach (@types) { $types{$_}++ }; } my @regions_to_markup = $self->make_markup($segment,[keys %types],$markup,$flip) if %types; # add a newline every 60 positions $markup->add_style('newline',"\n"); push @regions_to_markup,map {['newline',60*$_]} (1..length($dna)/60); $markup->markup(\$dna,\@regions_to_markup); my $label = "$segment"; $label .= " (reverse complemented)" if $flip; # HTML formatting if ($config->{format} eq 'html') { print start_html($segment); #,h1($label); print pre(">$label\n$dna"); print end_html; } # text/plain formatting else { print ">$label\n"; print $dna; } warn("====== end of dump =====\n") if DEBUG; } sub mime_type { my $self = shift; my $config = $self->configuration; return $config->{format} eq 'html' ? 'text/html' : 'text/plain'; } sub config_defaults { my $self = shift; return { format => 'html' }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; %$current_config = (); foreach my $param ( $self->config_param() ) { warn "param = $param\n" if DEBUG; next if $param =~/\.(f|b)gcolor$/; my $value = $self->config_param($param) or next; $current_config->{$param} = $value; warn "current_config($param) = $current_config->{$param}\n" if DEBUG; } # handle colors specially for my $type (keys %$current_config) { next unless $current_config->{$type} =~ /^\d+$/; next unless $MARKUPS[$current_config->{$type}] =~ /^(F|B)GCOLOR/; my $color_key = lc("$1gcolor"); $current_config->{"$type.$color_key"} = $self->config_param("$type.$color_key"); warn "current_config($type.$color_key) = ",$current_config->{"$type.$color_key"},"\n" if DEBUG; } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my @choices = TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Output", td(radio_group(-name => $self->config_name('format'), -values => [qw(text html)], -default => $current_config->{'format'}, -override => 1)) ) ); push @choices,TR({-class=>'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Orientation", td(checkbox(-name => $self->config_name('flip'), -label => 'Flip', -checked => $self->page_settings->{flip}, -override => 1)))); my $browser = $self->browser_config(); # this to be fixed as more general my @labels; foreach ( $browser->labels() ) { push @labels, $_ unless ! defined $browser->setting($_,'feature'); } autoEscape(0); my %selected = map {$_=>1} ($self->selected_tracks); foreach my $featuretype ( @labels ) { next if ! $selected{$featuretype}; my $realtext = $browser->setting($featuretype,'key') || $featuretype; push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'}, $realtext, td(join (' ', radio_group(-name => $self->config_name($featuretype), -values => [ (sort keys %LABELS)[0..4] ], -labels => \%LABELS, -default => $current_config->{$featuretype} || 0), radio_group(-name => $self->config_name($featuretype), -values => 5, -labels => \%LABELS, -default => $current_config->{$featuretype} || 0), popup_menu(-name => $self->config_name("$featuretype.fgcolor"), -values => \@COLORS, -default => $current_config->{"$featuretype.fgcolor"}), radio_group(-name => $self->config_name($featuretype), -values => 6, -labels => \%LABELS, -default => $current_config->{$featuretype} || 0), popup_menu(-name => $self->config_name("$featuretype.bgcolor"), -values => \@COLORS, -default => $current_config->{"$featuretype.bgcolor"} ), )))); } autoEscape(1); my $html= table({-width=>'100%'},@choices); $html; } sub make_markup { my $self = shift; my ($segment,$types,$markup,$flip) = @_; my @regions_to_markup; warn("segment length is ".$segment->length()."\n") if DEBUG; my $iterator = $segment->get_seq_stream(-types=>$types, -automerge=>1) or return; my $segment_start = $segment->start; my $segment_end = $segment->end; my $segment_length = $segment->length; while (my $markupregion = $iterator->next_seq) { warn "got feature $markupregion\n" if DEBUG; # handle both sub seqfeatures and split locations... # somebody rescue me from this insanity! my @parts = eval { $markupregion->sub_SeqFeature } ; @parts = eval { my $id = $markupregion->location->seq_id; my @subs = $markupregion->location->sub_Location; grep {$id eq $_->seq_id} @subs } unless @parts; @parts = ($markupregion) unless @parts; for my $p (@parts) { my $start = $p->start - $segment_start; my $end = $start + $p->length; $start++ if $p->strand < 0; ($start,$end) = map {$segment_length-$_} ($end,$start) if $flip; warn("$p ". $p->location->to_FTstring() . " type is ".$p->primary_tag) if DEBUG; $start = 0 if $start < 0; # this can happen $end = $segment->length if $end > $segment->length; warn "annotating $p $start..$end" if DEBUG; my $style_symbol; foreach ($p->type,$p->method,$markupregion->type,$markupregion->method) { $style_symbol ||= $markup->valid_symbol($_) ? $_ : undef; } warn "style symbol for $p is $style_symbol, and style is ",$markup->style($style_symbol),"\n" if DEBUG; next unless $style_symbol; warn "[$style_symbol,$start,$end]\n" if DEBUG; push @regions_to_markup,[$style_symbol,$start,$end]; } } @regions_to_markup; } 1; GBrowse-2.56/conf/plugins/FilterTest.pm000444001750001750 677213036764442 20210 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::FilterTest; # $Id: FilterTest.pm,v 1.3 2009-05-22 21:37:09 lstein Exp $ # Filter plugin to filter features from the ORFs track use strict; use vars qw($VERSION @ISA); use constant DEBUG => 0; use Bio::Graphics::Browser2::Plugin; use CGI qw(:standard *pre); $VERSION = '0.O1'; @ISA = qw(Bio::Graphics::Browser2::Plugin); my @FILTERS = ( [ 'Only ORFs on Watson strand', q{ $_[0]->name =~ /w$/i} ], [ 'Only ORFs on Crick strand', q{ $_[0]->name =~ /c$/i} ], [ 'ORF length < ', q{ $_[0]->length < $value } ], [ 'ORF length >= ', q{ $_[0]->length >= $value } ], ); my %LABELS = map { $_ => $FILTERS[$_][0] } ( 0 .. $#FILTERS ); sub new { my $class = shift; bless { original_key => undef }, $class; } sub name { 'Genes'; } sub type { 'filter'; } sub description { my $key = shift ()->name; p("This Filter plugin filters the features from the ORFS track ($key)") . p("This plugin was written by Marc Logghe."); } sub filter { my $self = shift; my $track = shift; # track label my $key = shift; my $config = $self->configuration; my $source = $self->browser_config; return unless $source; return unless $track eq $self->name; return unless $config->{filter_on} eq 'yes'; my $value = $config->{filter_value}; # pass closure to browser object for filtering my $filter = eval "sub { $FILTERS[$config->{filter}][1] }"; warn $@ if $@; return $filter,"$key (filter incorrect)" if $@; # error occurred my $new_key = $FILTERS[ $config->{filter} ][1] =~ m/\$value/ ? "$key ($FILTERS[$config->{filter}][0] $value)" : "$key ($FILTERS[$config->{filter}][0])" ; return $filter,$new_key; } sub config_defaults { my $self = shift; return { filter_on => 'no', filter => 0, filter_value => 150 }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; my $objtype = $self->objtype(); foreach my $p ( param() ) { my ($c) = ( $p =~ /$objtype\.(\S+)/ ) or next; $current_config->{$c} = param($p); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $objtype = $self->objtype(); my @choices = TR( { -class => 'searchtitle' }, th( { -align => 'RIGHT', -width => '25%' }, 'Filter on', td( radio_group( -name => "$objtype.filter_on", -values => [qw(yes no)], -default => $current_config->{'filter_on'}, -override => 1 ) ) ) ); push @choices, TR( { -class => 'searchtitle' }, th( { -align => 'RIGHT', -width => '25%' }, 'Filter', td( popup_menu( -name => "$objtype.filter", -values => [ 0 .. $#FILTERS ], -labels => \%LABELS, -default => $current_config->{'filter'} ), textfield( -name => "$objtype.filter_value", -default => $current_config->{filter_value} ) ) ) ); my $html = table(@choices); $html; } sub objtype { ( split ( /::/, ref(shift) ) )[-1]; } 1; GBrowse-2.56/conf/plugins/GeneFinder.pm000444001750001750 1014613036764442 20137 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::GeneFinder; # $Id: GeneFinder.pm,v 1.3 2005-12-09 22:19:09 mwz444 Exp $ # test plugin use strict; use File::Temp 'tempfile'; use File::Spec; use Bio::Graphics::Browser2::Plugin; use Bio::SeqFeature::Generic; use CGI qw(:standard *table); use vars '$VERSION','@ISA'; $VERSION = '0.2'; use constant GENEFINDER => 'gfcode'; # must be in the path somewhere use constant GFTABLES => 'gftables'; # must be in the gbrowse.conf directory @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "GeneFinder Features" } sub description { p("This plugin is a front end to Phil Green's GeneFinder program."). p("It is an early work in progress."). p("Please build and install the 'gfcode' program (located in the contrib directory) before using this plugin."); } sub type { 'annotator' } sub init { } sub config_defaults { my $self = shift; return { }; } sub reconfigure { my $self = shift; return; } sub configure_form { my $self = shift; return; } sub annotate { my $self = shift; my $segment = shift; my $dna = $segment->seq; my $abs_start = $segment->start; # write DNA out into a tempfile my ($fh,$filename) = tempfile('gfXXXXXXX', SUFFIX => '.fa', UNLINK => 1, DIR => File::Spec->tmpdir, ); print $fh ">segment\n"; print $fh $dna; close $fh; my $gftables = File::Spec->catfile($self->config_path(),GFTABLES); my $command = join ' ',GENEFINDER,$gftables,$filename; open (F,"$command |") or die "Couldn't open genefinder. Did you install the gfcode program and the gftables config file?: $!"; my $atgheight = sub { my $f = shift; return int($f->score/5 * 20); }; my $atgtop = sub { return (20-$atgheight->(@_)); }; my $feature_list = Bio::Graphics::FeatureFile->new; $feature_list->add_type(splice => {glyph => 'splice_site', key => 'GF splice acceptor/donor', bump => 0, direction => sub { my $f = shift; my $method = $f->primary_tag; return 'right' if $method eq 'splice5'; return 'left' if $method eq 'splice3'; }, height => 30, height_fraction => sub { my $f = shift; my $score = abs($f->score); $score = 4 if $score > 4; return $score/4; }, fgcolor => sub { my $f = shift; my $method = $f->primary_tag; return 'red' if $method eq 'splice5'; return 'blue' if $method eq 'splice3'; } } ); $feature_list->add_type(startplus => {glyph => 'generic', key => 'GF start site (+)', height => $atgheight, pad_top => $atgtop, bump => 0, bgcolor => 'red', fgcolor => 'red'} ); $feature_list->add_type(codingplus => {glyph => 'generic', key => 'GF coding segment (+)', strand_arrow => 1, bgcolor => 'yellow'}); $feature_list->add_type(startminus => {glyph => 'generic', key => 'GF start site (-)', bump => 0, height => $atgheight, pad_top => $atgtop, bgcolor => 'blue', fgcolor => 'blue'} ); $feature_list->add_type(codingminus => {glyph => 'generic', key => 'GF coding segment (-)', strand_arrow => 1, bgcolor => 'yellow'}); while () { next if /^\#/; my (undef,$source,$method,$start,$end,$score,$strand) = split "\t"; next unless defined $method; my $type = $method =~ /splice/ ? 'splice' : $method eq 'atg' && $strand eq '+' ? 'startplus' : $method eq 'atg' && $strand eq '-' ? 'startminus' : $method =~ /coding/ && $strand eq '+' ? 'codingplus' : $method =~ /coding/ && $strand eq '-' ? 'codingminus' : ''; next unless $type; my $f = Bio::SeqFeature::Generic->new(-start => $abs_start + $start, -end => $abs_start + $end, -strand => $strand eq '-' ? -1 : +1, -source => $source, -score => $score, -primary=> $method); $feature_list->add_feature($f,$type); } close F; return $feature_list; } 1; GBrowse-2.56/conf/plugins/LDAPAuthenticate.pm000444001750001750 1300213036764442 21202 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::LDAPAuthenticate; # $Id$ use strict; use base 'Bio::Graphics::Browser2::Plugin::AuthPlugin'; use Net::LDAP; use Carp 'croak'; #use constant SERVER => 'ldap.res.oicr.on.ca'; #use constant PEOPLE_BASE => 'ou=People,dc=oicr,dc=on,dc=ca'; #use constant GROUPS_BASE => 'ou=Groups,dc=oicr,dc=on,dc=ca'; sub authenticate { my $self = shift; my ($name,$password) = $self->credentials; my $ldap = $self->_ldap_connect or return; # possibly bind to the server if a root DN and password are needed $self->_initial_bind($ldap); # do a search to get the user dn with which to bind my $search = $ldap->search( base => $self->people_base, filter => "(&(objectClass=posixAccount)(uid=$name))" ) or die $@; return unless $search->count == 1; my $entry = $search->entry(0); # now attempt to authenticate with the password my $message = $ldap->bind($entry->dn, password => $password); return if $message->is_error; # get user's full name from the gecos and/or cn/sn fields my ($gecos) = $entry->get('gecos'); $gecos =~ s/,+$//; # trailing unused fields my $fullname = join ' ',($entry->get('cn'),$entry->get('sn')); $ldap->unbind; return ($name,$gecos||$fullname||$name); } sub user_in_group { my $self = shift; my ($user,$group) = @_; my $ldap = $self->_ldap_connect or return; # do an anonymous search for the posix group with the # indicated uid member. my $search = $ldap->search( base => $self->groups_base, filter => "(&(objectClass=posixGroup)(memberUid=$user))" ); my @entries = $search->entries; my %groups = map {$_->get('cn')=>1} @entries; $ldap->unbind; return $groups{$group}; } sub _ldap_connect { my $self = shift; my $ldap = Net::LDAP->new($self->server); unless ($ldap) { warn "Could not connect to server ",$self->server; return; } return $ldap; } sub _initial_bind { my $self = shift; my $ldap = shift; my $bind_dn = $self->bind_dn or return; my $bind_pass = $self->bind_pass or return; my $message = $ldap->bind($bind_dn,password=>$bind_pass); return unless $message->is_error; my $text = $message->error_text; warn <required_setting('ldap server'); } sub people_base { return shift->required_setting('people base'); } sub groups_base { return shift->required_setting('groups base'); } sub bind_dn { return shift->setting('bind dn'); } sub bind_pass { return shift->setting('bind pass'); } sub required_setting { my $self = shift; my $option = shift; my $value = $self->setting($option); croak "You must set the '$option' option in the [LDAPAuthenticate:plugin] section of GBrowse.conf\n" unless defined $value; return $value; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::LDAPAuthenticate - Authenticate user against an LDAP server =head1 SYNOPSIS In the GBrowse.conf configuration file: authentication plugin = LDAPAuthenticate [LDAPAuthenticate:plugin] login hint = your foobar corp account ldap server = ldap.foobar.com people base = ou=People,dc=foobar,dc=ny,dc=usa groups base = ou=Groups,dc=foobar,dc=ny,dc=usa # the following only needed if the LDAP server forbids anonymous (unbound) searches: bind dn = uid=root,ou=People,dc=foobar,dc=ny,dc=usa bind pass = xyzzy =head1 DESCRIPTION This plugin uses hard-coded values to authenticate users against an LDAP database. Users can log in using their Unix login names and passwords (LDAP "posixAccount"). Groups are authorized against the posixGroup memberUID fields. =head1 CONFIGURATION For this plugin to work, you must configure an [LDAPAuthenticate:plugin] section in the main GBrowse.conf file. It will look like this: [LDAPAuthenticate:plugin] login hint = your foobar corp account ldap server = ldap.foobar.com people base = ou=People,dc=foobar,dc=ny,dc=usa groups base = ou=Groups,dc=foobar,dc=ny,dc=usa B (optional) is displayed to the user so that he knows what account credentials he or she is being asked for. B (required) is the address of the LDAP server you wish to contact. If the server is running on a non-standard, port, you can indicate it as "ldap.foobar.com:1118". B (required) is the search base for the People records where the provided user id will be found. B (required) is the search base for the Group records where the user's group membership can be determined. In addition, if your LDAP server requires a username and password to bind to B permitting searches, then you will need to provide: B (optional) the distinguished name of the LDAP user to bind to. This is often called the LDAP "root" user. B (optional) the password of the LDAP user to bind to. Note that providing this bind user's account name and password in a file that is readable by the web server can be considered a security risk. Consider allowing anonymous searches on the LDAP server, or else create an unprivileged user account for the initial binding step. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Copyright (c) 2011 Ontario Institute for Cancer Research This library is free software distributed under the Perl Artistic License v2; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/OligoFinder.pm000444001750001750 1150213036764442 20327 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::OligoFinder; # $Id: OligoFinder.pm,v 1.9 2004-08-23 15:56:31 lstein Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Feature; use Text::Shellwords; use DBI; use CGI qw(:standard *table); use vars '$VERSION','@ISA'; $VERSION = '0.15'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Short Oligos" } sub description { p("The oligo finder plugin finds oligos between 11 and 50 bp in length.", "It does a slow search, making it suitable only for small (<150 MB) genomes.", "[NOTE TO SYSADMINS: The browser must use the Bio::DB::GFF schema for this plugin to work.]"). p("This plugin was written by Lincoln Stein."); } sub type { 'finder' } sub config_defaults { my $self = shift; return { }; } # we have no stable configuration # sub reconfigure { } sub configure_form { my $self = shift; my $oligo = $self->config_param('searcholigo'); my $msg = $oligo && !$self->valid_oligo($oligo) ? font({-color=>'red'},"Invalid oligo: either too short or not DNA") : ''; return $msg . table(TR({-class=>'searchtitle'}, th({-colspan=>2,-align=>'LEFT'}, 'Enter an oligonucleotide between 12 and 50 bp in length.', 'The browser will identify all genomic regions that contain', 'this oligo. This is NOT a fast algorithm, so have patience.')), TR({-class=>'searchbody'}, th('Enter oligo:'), td(textfield(-name=>$self->config_name('searcholigo'), -size=>50,-width=>50)) ) ); } # find() returns undef unless the OligoFinder.searcholigo parameter # is specified and valid. Returning undef signals the browser to invoke the # configure_form() method. # If successful, it returns an array ref of Bio::SeqFeatureI objects. sub find { my $self = shift; my $segments = shift; # current segments - can search inside them or ignore # In this example we do a global search. my $oligo = lc $self->config_param('searcholigo'); $self->auto_find($oligo); } # auto_find() does the actual work # It is also called by the main page as a last resort when the user # types something into the search box that isn't recognized. sub auto_find { my $self = shift; my $oligo = lc shift; $self->valid_oligo($oligo) or return; (my $reversec = $oligo) =~ tr/gatcGATC/ctagCTAG/; $reversec = reverse $reversec; my $length = length $oligo; my $db = $self->database or die "I do not have a database"; my $dbi = $db->features_db; my @chroms = $self->get_chroms($db); my $in = join ',',map {$dbi->quote($_)} @chroms; my $sth = $dbi->prepare("select fref,foffset,fdna from fdna where fref in ($in) order by fref,foffset", { 'mysql_use_result' => 1}) or die "Couldn't prepare ",$db->errstr; $sth->execute or die "Couldn't execute ",$db->errstr; my $bit_to_keep = length($oligo) - 1; my ($current_ref,$offset,$dna,@results); while (my ($ref,$off,$d) = $sth->fetchrow_array) { if (!defined($current_ref) or $current_ref ne $ref) { $offset = 0; $dna = ''; } $current_ref = $ref; # truncate all but the last length(oligo)-1 bases substr($dna,0,length($dna)-$bit_to_keep) = ''; $offset = $off - length($dna); $dna .= lc $d; my @forward = $self->exact_matches($dna,$oligo); my @reverse = $self->exact_matches($dna,$reversec); for ([$oligo=>\@forward],[$reversec=>\@reverse]) { my ($name,$pos) = @$_; for my $p (@$pos) { push @results, Bio::Graphics::Feature->new(-ref => $ref, -type => 'oligo', -name => $name, -start => $offset+$p+1, -score => '100%', -end => $offset+$p+length($oligo), -factory=> $db, ) } } } return \@results; } sub exact_matches { my $self = shift; my ($dna,$oligo) = @_; my @results; my $offset = 0; while ((my $i = index($dna,$oligo,$offset)) >= 0) { push @results,$i; $offset = $i+length($oligo); } @results; } # This is a slowish query, so cache the results per-source. # Bio::DB::GFF has no concept of the reference DNA, so we just look # inside segments of DNA that are more than 20K in length and hence # likely to represent genomic. sub get_chroms { my $self = shift; my $db = shift; my $dbi = $db->features_db; my $source = $self->browser_config(); my $chroms; my @chroms = shellwords($self->browser_config->plugin_setting('search_segments')); if (@chroms) { $chroms = \@chroms; } else { return @{$self->{chroms}{$source}} if ref($self->{chroms}{$source}); $chroms = $dbi->selectcol_arrayref('select fref from fdna group by fref having count(fref)>10'); } $self->{chroms}{$source} = $chroms; return @$chroms; } # return true if a valid oligo sub valid_oligo { my $self = shift; my $oligo = shift or return; return $oligo =~ /^[gatcn]{11,50}$/i } 1; GBrowse-2.56/conf/plugins/PamAuthenticate.pm000444001750001750 347713036764442 21176 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::PamAuthenticate; # $Id$ use strict; use base 'Bio::Graphics::Browser2::Plugin::AuthPlugin'; use Authen::Simple::PAM; use User::grent; use User::pwent; use constant DEFAULT_PAM_SERVICE => 'gbrowse'; sub authenticate { my $self = shift; my ($name,$password) = $self->credentials; my $service_name = $self->setting('pam service name') || 'gbrowse'; my $pam = Authen::Simple::PAM->new( service => $service_name ) or return; if ($pam->authenticate($name,$password)) { my $fullname = $self->_get_fullname($name); return ($name,$fullname||$name); } else { return; } } sub user_in_group { my $self = shift; my ($user,$group) = @_; if ($self->_is_primary_group($user,$group)) { return 1; } my $members = $self->_group_members($group) or return; return $members->{$user}; } sub _get_fullname { my $self = shift; my $username = shift; my $u = getpwnam($username) or return; my ($fullname,$office,$phone1,$phone2) = split /\s*,\s*/, $u->gecos; return $fullname; } sub _is_primary_group { my $self = shift; my ($user,$group) = @_; my $gid = eval {getgrnam($group)->gid}; defined $gid or return; my $ugid= eval {getpwnam($user)->gid}; defined $ugid or return; return $gid == $ugid; } sub _group_members { my $self = shift; my $group = shift; return $self->{groupcache}{$group} if exists $self->{groupcache}{$group}; $self->{groupcache}{$group} = {}; if (my $gr = getgrnam($group)) { my $members = $gr->members; foreach (@$members) { $self->{groupcache}{$group}{$_}++; } } return $self->{groupcache}{$group}; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::PamAuthenticate - Authenticate user via Pluggable Authentication Modules =head1 SYNOPSIS GBrowse-2.56/conf/plugins/PrimerDesigner.pm000444001750001750 15610613036764442 21077 0ustar00lsteinlstein000000000000# $Id: PrimerDesigner.pm,v 1.11 2007-03-31 14:33:36 sheldon_mckay Exp $ =head1 NAME Bio::Graphics::Browser2::Plugin::PrimerDesigner -- a plugin to design PCR primers with primer3 =head1 SYNOPSIS This module is not used directly =head1 DESCRIPTION PrimerDesigner.pm uses the Bio::PrimerDesigner API for primer3 to design PCR primers for features or target coordinates in gbrowse. =head1 PRIMER3 Compile a primer3 (v. 0.9 or later) binary executable for your OS and copy it to the default path usr/local/bin with the name primer3. Source code for primer3 can be obtained from http://frodo.wi.mit.edu/primer3/primer3_code.html. =head1 Designing Primers =head2 Targeting a feature or coordinate The target for PCR primer design is selected by clicking on an image map. For aggregate features such as gene models, etc, there is a mousover menu to select the individual part of the whole feature =head2 Design Paramaters The Provided set of reasonable default primer attributes will work in most cases. Product size will vary by target feature size. A suggested PCR product size range is calculated based on the selected feature. If this field is left blank, a series of increasing PCR product sizes is cycled until products big enough to flank the target feature are found. This will not necessarily find the best primers, just the first ones that produce a big enough product to flank the target. If the primers are flagged as low quality, more optimal optimal primers may be found by specifying a specific size-range. =head1 Bio::Graphics::Browser This plugin contains an additional package Bio::Graphics::Browser2::faux. This class inherits from Bio::Graphics::Browser. Its purpose is to keep the Bio::Graphics::Browser funtionality and configuration data while overriding image_map-related funtions required for this plugin. =head1 TO-DO Add support for ePCR-based scanning for false priming =head1 FEEDBACK See the GMOD website for information on bug submission http://www.gmod.org. =head1 AUTHOR - Sheldon McKay Email mckays@cshl.edi =head1 SEE ALSO Bio::PrimerDesigner (www.cpan.org) primer3 (http://frodo.wi.mit.edu/primer3/primer3_code.html) =cut package Bio::Graphics::Browser2::Plugin::PrimerDesigner; use strict; use Data::Dumper; use POSIX qw/isdigit/; use Bio::Graphics::Panel; use Bio::PrimerDesigner; use Bio::PrimerDesigner::Tables; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::Util; #use Bio::Graphics::Browser; #No longer available in Gbrowse 2 use Bio::Graphics::Feature; use Bio::Graphics::FeatureFile; use CGI qw/:standard escape/; #use CGI::Pretty 'html3'; #use CGI::Carp 'fatalsToBrowser'; use CGI::Toggle; use Math::Round 'nearest'; use Carp qw/cluck/; use constant BINARY => 'primer3'; use constant BINPATH => '/usr/local/bin'; use constant METHOD => 'local'; use constant IMAGE_PAD => 25; use constant MAXRANGE => 300; use constant IMAGEWIDTH => 800; use constant DEFAULT_SEG_SIZE => 10000; use constant STYLE => '/gbrowse2/css/gbrowse.css'; #use vars '@ISA'; use vars qw/@ISA $PNG $CALL/; @ISA = qw/Bio::Graphics::Browser2::Plugin/; # Arg, modperl END { if ($ENV{'MOD_PERL'}) { CGI::Delete_all(); } } sub name { 'PCR primers'; } sub description { p( "This plugin uses PRIMER3 to pick PCR primers to amplify selected " . "features or sequences." . " This plugin was written by Sheldon McKay (mckays\@cshl.edu)" ); } sub type { 'dumper'; } sub verb { #Remove the Configure button when designing primers. The plugin doesn't need #the option anyway, and it will only confuse people if left on the page. #$CALL keeps track of how many times the module is run so it doesn't attach #multiple events. Otherwise, the javascript will run about 3 times. #This is a cheat. Since there's no way to make javascript calls from ajax, #code gets inserted here instead because GBrowse runs this no matter what. #unless ($CALL) { #my $detail_select_menu = detail_select_menu(); #print < #var oPrimerDesigner = { }; #oPrimerDesigner.removeConfigureButton = function () { #var plugin_select = document.getElementById('plugin'); #var config_button = document.getElementsByName('plugin_action')[0]; #var i = plugin_select.selectedIndex; #if (plugin_select.options[i].text == 'Design PCR primers') #config_button.style.display = 'none'; #plugin_select.onchange = function () { #var i = this.selectedIndex; #if (this.options[i].text == 'Design PCR primers') { #config_button.style.display = 'none'; #} else { #config_button.style.display = 'inline'; #} #} #} #if (window.addEventListener) { // W3C standard #window.addEventListener('load', oPrimerDesigner.removeConfigureButton, false); // NB **not** 'onload' #} #else if (window.attachEvent) { // Microsoft #window.attachEvent('onload', oPrimerDesigner.removeConfigureButton); #} # #JS #$CALL++; #} 'Design'; } sub mime_type { 'text/html'; } sub is_zoom { return param('span') unless param('configured'); } sub reconfigure { my $self = shift; my $conf = $self->configuration; $conf->{size_range} = undef; $conf->{target} = undef; $conf->{lb} = undef; $conf->{rb} = undef; my $target = $self->config_param('target'); my $lb = $self->config_param('lb'); my $rb = $self->config_param('rb'); if ($lb && $rb) { my $min_size = $rb - $lb + 40; my $max_size = $min_size + MAXRANGE; # round to nearest 50 bp $conf->{size_range} = join '-', map {$_||=50} nearest(50, $min_size, $max_size); # make sure target is within the selected region if (!$target || $target < $lb || $target > $rb) { $target = int( ($lb+$rb)/2 ); } } $conf->{target} = $target; $conf->{lb} = $lb; $conf->{rb} = $rb; $conf->{span} = is_zoom; $conf->{name} = $self->config_param('name'); $self->configuration($conf); } sub my_url { my $self = shift; my $url = $self->{url}; return $url if $url; $url = self_url(); $url =~ s/\?.+//; return $self->{url} = $url; } sub configure_form { my $self = shift; my ($segment,$target,$lb,$rb,$feats) = @_; #($segment) = @{ $self->segments } unless $segment; ($segment) = $self->segments unless $segment; $segment ||= fatal_error("This plugin requires a sequence region"); my $browser = $self->browser_config; my $conf = $self->configuration; my $no_buttons = 1 if !($lb || $rb) || $feats; # make sure the target is not stale for the initial config delete $conf->{target} if !($lb || $rb); my @feature_types = $self->selected_features; my @args = ( -types => \@feature_types ); $target ||= $self->focus($segment); $rb ||= $target; $lb ||= $target; # primer design params my $atts = $self->primer3_params($lb,$rb) unless $no_buttons; my $table_width = IMAGEWIDTH + 50; my ( $image, $map, $zoom_menu ) = $self->new_segment_map( $segment, $feats, $lb, $rb ); my $message = ''; my $start = $segment->start; my $end = $segment->end; my $ref = $segment->ref; my $name = $conf->{name} || "$ref:$start..$end"; my $length = unit_label( $segment->length ); my $html = h2("Showing $length from $ref, positions $start to $end"); $html .= hidden( -name => 'plugin', -value => 'PrimerDesigner' ) . hidden( -name => 'plugin_action', -value => 'Go' ) . hidden( -name => 'ref', -value => $segment->ref ) . hidden( -name => 'start', -value => $segment->start ) . hidden( -name => 'stop', -value => $segment->stop ); $html .= hidden( -name => $self->config_name('lb'), -value => $lb) if $lb; $html .= hidden( -name => $self->config_name('rb'), -value => $rb) if $rb; $html .= hidden( -name => $self->config_name('target'), -value => $target) if $target; my $map_text = $self->map_header; my $on = 1 unless $feats; my $no_target = li("There currently is no target region selected.") if ($rb - $lb) < 3; #my $no_target = li("Click and drag on the ruler to select a PCR target."); my $has_buttons = li("The size of potential PCR products can be adjusted via the 'Product size range' option below") unless $no_buttons; my $flanked = $no_target ? 'red line' : 'shaded region'; my $boundaries = li("The boundaries of the shaded target region can be adjusted by clicking on the lower scalebar") unless $no_target; my $click_feat = $no_target ? li("Click on a sequence feature to select") : li("Click on a different sequence feature to change the selection"); my $zone = $self->toggle( { on => $on, override => 0 }, 'Targetting information', font( {-size => -1}, ul( $no_target, li("PCR primers will flank the $flanked."), $click_feat, $boundaries, $has_buttons ) ) ) . br; $html .= table( { -style => "width:${table_width}px" }, Tr( { -class => 'searchtitle' }, [ #NML: map text does nothing at the moment. not even sure what it's supposed to do #It doesn't appear in the functional 1.7 version #th($map_text) . th($zoom_menu), td( { -class => 'searchbody', -colspan => 2 }, $image . br), td( { -class => 'searchbody', -colspan => 2}, $zone ) ] ) ); unless ($no_buttons) { my @col1 = grep {/Primer|Tm|Product/} keys %$atts; my @col2 = grep { !/Primer|Tm|Product/ } keys %$atts; @col1 = ( ( grep { $atts->{$_} =~ /Opt\./ } @col1 ), ( grep { $atts->{$_} !~ /Opt\./ } @col1 ) ); my @rows = ( td( { -colspan => 4 }, h3($message) ), td( { -colspan => 4 }, hr ) ); for ( 0 .. 4 ) { push @rows, td( [ $col1[$_], $atts->{ $col1[$_] }, $col2[$_], $atts->{ $col2[$_] } ] ); } $html .= table( { -style => "width:${table_width}px" }, Tr( \@rows ) ); $html .= br . submit( -name => 'configured', -value => 'Design Primers' ) . ' ' . reset('Reset Parameters') . ' ' . $self->back_button; } (my $action = self_url()) =~ s/\?.+//; $html = start_form( -method => 'POST', -name => 'mainform', -action => $action ). $html . end_form; #die Dumper $html; # if this is the first config, exit before form and buttons # are printed by gbrowse if ($no_buttons && !$feats) { my $style = $browser->setting('stylesheet') || STYLE; print start_html( -style => $style, -title => 'PCR Primers'), $html, $map, $browser->footer; exit; } #my $form = textfield(-name => $self->config_name('foo'), #-value => $conf->{foo}) #. #textfield(-name => $self->config_name('bar'), #-value => $conf->{bar}); #return $form; return $feats ? ($html,$map) : $html.$map; } sub map_header { my $recenter = a( { -href => '#', -title => 'Click the top scale-bar to recenter the image' }, 'recenter' ); my $select_t = a( { -href => '#', -title => 'Click a sequence feature below to select a target' }, 'select a PCR target' ); return "Click on the map to $recenter or $select_t"; } sub dump { my ( $self, $segment ) = @_; my $conf = $self->configuration; #print Dumper $conf; $self->reconfigure; #print Dumper $conf; # dumpers provide their own headers, so make sure boiler plate # stuff is included #my $style_sheet = $self->browser_config->setting('stylesheet') || STYLE; my $style_sheet = $self->browser_config->plugin_setting('stylesheet') || STYLE; print start_html( -style => $style_sheet, -title => 'PCR Primers' ); print $self->browser_config->header_html; # reset off-scale target if required delete $conf->{target} if $conf->{target} && ($conf->{target} > $segment->end - 1000 || $conf->{target} < $segment->start + 1000); delete $conf->{lb} if $conf->{lb} && ($conf->{lb} > $segment->end - 1000 || $conf->{lb} < $segment->start); delete $conf->{rb} if $conf->{rb} && ($conf->{rb} < $segment->start + 1000 || $conf->{rb} > $segment->end); delete $conf->{target} unless $conf->{lb} && $conf->{rb}; #print Dumper $conf; my $target = $self->focus($segment); my $lb = $conf->{lb} || $target; my $rb = $conf->{rb} || $target; # check for a zoom request my $segment_size = $self->is_zoom; # Make room if target region is too close to the ends my ($new_start,$new_end); if ($rb >= $segment->end - 500) { $new_end = $rb + 500; } if ($lb <= $segment->start + 500) { $new_start = $lb - 500; } #print 'dump 1: '.$segment->start.' '.$segment->end.'
    '; # NML: this is causing the panel to zoom beyond the segment boundaries #if ($new_start || $new_end) { #$segment = $self->database->segment( -name => $segment->ref, #-start => ($new_start || $segment->start), #-end => ($new_end || $segment->end) ); #$segment_size = $segment->length; #} #NML: kludgy fix to get details panel to draw at an appropriate length #Otherwise, it spills past the browser window $self->renderer->set_details_multiplier(1); my $maxrange = MAXRANGE; print < var oPrimerDesigner = { }; oPrimerDesigner.removePanButtons = function () { /*Get rid of panleft and panright buttons */ /*until I can figure out a way to get them working*/ var imgs = document.getElementsByTagName('img'); for (i=0; i overview_stop) { newStart = Math.round(overview_stop - view_length); newStop = overview_stop; } } else { if (direction == 'zoom') { var detail_length = detail_stop - detail_start; var value = detail_length * length_units; var addMargin = Math.round((value - detail_length)/2); newStart = Math.round(detail_start - addMargin); newStop = Math.round(detail_stop + addMargin); } else if (direction == 'set span') { var value = length_units*1; var addMargin = Math.floor((value - (detail_stop - detail_start))/2); newStart = Math.round(detail_start - addMargin); newStop = Math.round(detail_stop + addMargin); } if ((newStop - newStart) > (overview_stop - overview_start)) { newStart = overview_start; newStop = overview_stop; } if (newStart < overview_start ) { newStart = overview_start; newStop = newStart + value - 1; } else if (newStop > overview_stop ) { newStart = overview_stop - value + 1; newStop = overview_stop; } } oPrimerDesigner.createNewFormElement(mainform, "view_start", newStart); oPrimerDesigner.createNewFormElement(mainform, "view_stop", newStop); mainform.action = mainform.action + '?plugin='+plugin+';action=Go;view_start='+newStart+';view_stop='+newStop; mainform.submit(); } oPrimerDesigner.designPrimers = function () { //var mainform = document.getElementsByName('mainform')[0]; //var conf = oPrimerDesigner.createNewFormElement(mainform, "configured", "Design Primers"); //mainform.setAttribute("target", "_blank"); //mainform.submit(); /*Remove these after submit or else will generate a bug where user*/ /*tries to scroll or zoom without closing rubber band menu first, */ /*causing form to unintentionally be resubmitted */ //mainform.removeChild(conf); //mainform.removeAttribute("target"); } oPrimerDesigner.selectRegion = function () { SelectArea.prototype.cancelRubber(); var size_range = document.getElementById('product_size_range'); var plugin = document.getElementsByName('plugin')[0].value; var select_start = currentSelectArea.selectSequenceStart; var select_end = currentSelectArea.selectSequenceEnd; var min_size = select_end - select_start + 40; var max_size = min_size + $maxrange; var x = []; var sizes = [min_size, max_size]; for (i=0;i < sizes.length;i++) { var n = sizes[i]; x.push(Math.ceil(sizes[i]/50.0) * 50); } var lb = document.getElementsByName(plugin+'.lb')[0] var rb = document.getElementsByName(plugin+'.rb')[0]; var target = document.getElementsByName(plugin+'.target')[0]; oPrimerDesigner.lb = lb.value; oPrimerDesigner.rb = rb.value; oPrimerDesigner.target = target.value; oPrimerDesigner.size_range = size_range.value; size_range.value = x[0]+'-'+x[1]; lb.value = select_start; rb.value = select_end; if (target.value == undefined || target.value < select_start || target.value > select_end) { target.value = parseInt( (select_start+select_end)/2 ); } var mainform = document.getElementsByName('mainform')[0]; mainform.submit(); } oPrimerDesigner.unselectRegion = function () { var plugin = document.getElementsByName('plugin')[0].value; var size_range = document.getElementById('product_size_range'); if (oPrimerDesigner.size_range != undefined) { size_range.value = oPrimerDesigner.size_range; } if (oPrimerDesigner.lb != undefined) { document.getElementsByName(plugin+'.lb')[0].value = oPrimerDesigner.lb; } if (oPrimerDesigner.rb != undefined) { document.getElementsByName(plugin+'.rb')[0].value = oPrimerDesigner.rb; } if (oPrimerDesigner.target != undefined) { document.getElementsByName(plugin+'.target')[0].value = oPrimerDesigner.target; } SelectArea.prototype.cancelRubber(); } if (window.addEventListener) { // W3C standard window.addEventListener('load', oPrimerDesigner.removePanButtons, false); // NB **not** 'onload' } else if (window.attachEvent) { // Microsoft window.attachEvent('onload', oPrimerDesigner.removePanButtons); } JS #if (param('configured') ) { #print 'param configured
    '; #} #if ($self->get_primer3_params()) { #print 'got primer3 params
    '; #} else { #print Dumper param(); #} #if (param('configured') && $self->get_primer3_params()) { #print Dumper $conf; #} # design the primers if required $self->design_primers( $segment, $lb, $rb) if param('configured') && $self->get_primer3_params(); # or print the config form print $self->configure_form($segment,$target,$lb,$rb); my $render = $self->renderer; my $segment_info = $render->segment_info_object; my $div = $render->render_search_form_objects(); $div = join('', split("\n", $div)); $div =~ s/'/\\'/g; my $segment_info_string = join(',', map { my $val = $segment_info->{$_}; $val = isdigit($val) ? $val : "\'$val\'"; "'$_': $val" } (keys %$segment_info) ); #my $detail_select_menu = detail_select_menu(); print < Controller.segment_info = { $segment_info_string }; /*helper function to create a form*/ oPrimerDesigner.getNewSubmitForm = function (){ var submitForm = document.createElement("form"); document.body.appendChild(submitForm); submitForm.method = "post"; return submitForm; } /*helper function to add elements to the form*/ oPrimerDesigner.createNewFormElement = function (inputForm, elementName, elementValue){ var newElement = document.createElement('input'); newElement.name = elementName; newElement.type = 'hidden'; newElement.value= elementValue inputForm.appendChild(newElement); return newElement; } /*Create submit form to get rubberband working*/ //oPrimerDesigner.submitForm = oPrimerDesigner.getNewSubmitForm(); //oPrimerDesigner.createNewFormElement(oPrimerDesigner.submitForm, "force_submit", "0"); //oPrimerDesigner.createNewFormElement(oPrimerDesigner.submitForm, "plugin_action", "Go"); //oPrimerDesigner.createNewFormElement(oPrimerDesigner.submitForm, "plugin", document.getElementsByName('plugin')[0].value); //oPrimerDesigner.submitForm.style.display = 'none'; //var div = document.createElement('div'); //div.innerHTML = '$div'; //div.setAttribute('id', 'search_form_objects'); //oPrimerDesigner.submitForm.appendChild(div); //document.searchform = oPrimerDesigner.submitForm; oPrimerDesigner.details_panel = document.getElementById('primer_panel'); if (window.addEventListener) { // W3C standard oPrimerDesigner.details_panel.addEventListener('mouseup', oPrimerDesigner.selectRegion, false); } else if (window.attachEvent) { // Microsoft oPrimerDesigner.details_panel.attachEvent('onmouseup', oPrimerDesigner.selectRegion); } JS } sub detail_select_menu { <
    SELECTION [X]
    Design primers for this region
    Zoom in
    Recenter on this region
    DETAILS } sub design_primers { my ( $self, $segment, $lb, $rb ) = @_; my $conf = $self->configuration; my %atts = $self->get_primer3_params($lb,$rb); my $target = $self->focus($segment); my $tlength = $rb - $lb || 1; my $offset = $segment->start - 1; my $tstart = $lb - $offset; my $exclude = join ',', $tstart, $tlength if $tlength > 1; $tstart += int(($rb - $lb)/2); my $ptarget = join ',', $tstart,1; # make the segment a manageable size if (!$ptarget && $segment->length > DEFAULT_SEG_SIZE) { $segment = $self->refocus($segment, $target, DEFAULT_SEG_SIZE); } my $dna = $segment->seq; if ( ref $dna && $dna->can('seq') ) { $dna = $dna->seq; } elsif ( ref $dna ) { fatal_error( "Unsure what to do with object $dna. I was expecting a sequence string" ) } elsif ( !$dna ) { fatal_error("There is no DNA sequence in the database"); } # unless a product size range range is specified, just keep looking # until we find some primers that flank the target my $size_range = $conf->{size_range} || join ' ', qw/ 100-300 301-400 401-500 501-600 601-700 701-800 801-900 901-1000 1001-1200 1201-1400 1401-1600 1601-1800 1801-2000 2001-2400 2401-2600 2601-2800 2801-3200 3201-3600 3601-4000/; $atts{seq} = $dna; $atts{id} = $segment->ref; $atts{target} = $ptarget; $atts{excluded} = $exclude if $exclude; $atts{PRIMER_PRODUCT_SIZE_RANGE} = $size_range; # get a PCR object my $pcr = Bio::PrimerDesigner->new( program => BINARY, method => METHOD ); $pcr or fatal_error(pre(Bio::PrimerDesigner->error)); my $binpath = BINPATH; my $method = $binpath =~ /http/i ? 'remote' : METHOD; if ( $method eq 'local' && $binpath ) { $pcr->binary_path($binpath) or fatal_error(pre($pcr->error)); } else { $pcr->url($binpath) or fatal_error(pre($pcr->error)); } my $res = $pcr->design(%atts) or fatal_error(pre($pcr->error)); $self->primer_results( $res, $segment, $lb, $rb ); } sub primer_results { my ( $self, $res, $segment, $lb, $rb ) = @_; my $conf = $self->configuration; my $target = $self->focus($segment); my $offset = $segment->start; my $ref = $segment->ref; my $num = grep {/^\d+$/} keys %$res; my $raw_output = pre($res->raw_output); $raw_output =~ s/^(SEQUENCE=\w{25}).+$/$1... \(truncated for display only\)/m; # Give up if primer3 failed fatal_error("No primers found:".pre($raw_output)) unless $res->left; my @attributes = qw/ left right startleft startright tmleft tmright qual lqual rqual leftgc rightgc lselfany lselfend rselfany rselfend/; my ( @rows, @feats ); my $text = "This value should be less than 1 for best results but don\'t worry too much"; #my $Primer_Pair_Quality = 'Primer_Pair_Quality '.a( { -href => 'javascript:void(0)', -title => $text}, '[?]'); my $Primer_Pair_Quality = 'Primer_Pair_Quality '.a( { -href => "javascript:alert(\"$text\")" }, '[?]'); my $spacer = td( {-width => 25}, ' '); for my $n ( 1 .. $num ) { my %r; for (@attributes) { $r{$_} = $res->$_($n); } next unless $r{left}; $r{prod} = $r{startright} - $r{startleft}; $r{startleft} += $offset; $r{startright} += $offset; for (qw/ qual lqual rqual /) { $r{$_} =~ s/^(\S{6}).+/$1/; # low primer pair quality warning if ( $r{$_} > 1 ) { my $msg = quality_warning(); $msg = "alert('$msg')"; $r{$_} = a( { -href => 'javascript:void(0)', -title => 'Low quality warning', -onclick => $msg }, b( font( { -color => 'red' }, $r{$_} ) ) ); } } push @feats, Bio::Graphics::Feature->new( -start => $r{startleft}-20, -stop => $r{startright}+20, -type => 'Primer', -name => "PCR primer set $n" ); push @rows, Tr( [ $spacer . th( { -class => 'searchtitle', -align => 'left' }, [ qw/Set Primer/, "Sequence (5'->3')", qw/Tm %GC Coord Quality Product/, $Primer_Pair_Quality ] ), $spacer . td( [ $n, 'left', $r{left}, $r{tmleft}, $r{leftgc}, $r{startleft}, $r{lqual}, ' ', ' ' ] ), $spacer . td( [ ' ', 'right', $r{right}, $r{tmright}, $r{rightgc}, $r{startright}, $r{rqual}, $r{prod}, $r{qual} ] ), $spacer . td( { -colspan => 9 }, $self->toggle( {on => 0, override => 1}, "PRIMER3-style report for set $n", primer3_report( $self, $segment, $res, \%r )).br ) ] ); } my $featurefile = Bio::Graphics::FeatureFile->new(); my $options = { bgcolor => 'red', glyph => 'primers', height => 10, label => 1 }; $featurefile->set('primers',glyph=>'primers'); $featurefile->set('primers',label=>'1'); $featurefile->set('primers',height=>'10'); $featurefile->set('primers',bgcolor=>'red'); #$featurefile->add_type( 'Primers' => $options ); for my $f (@feats) { $featurefile->add_feature( $f => 'Primers' ); } my $width = IMAGEWIDTH; my $back = Tr( $spacer . td( { -colspan => 9,}, $self->back_button )); unshift @rows, $back if @rows > 3; my $tlength = $rb - $lb; my ($config_html, $map) = $self->configure_form($segment,$target,$lb,$rb,$featurefile); unshift @rows, Tr( [ $spacer . td(h1({-align => 'center'},"Predicted PCR primers ") ), $spacer . td($config_html) ] ); print table( { -style => "width:900px" }, [ @rows, Tr( $spacer . td( { -colspan => 9, -class => 'searchtitle' }, $self->toggle( {on => 0, override => 1}, 'PRIMER3 raw output', $raw_output)) ), $back ] ), $map; exit(0); } # GENERATE A PRIMER_3-STYLE REPORT # contributed by Russell Smithies # russell.smithies@agresearch.co.nz sub primer3_report { my $self = shift; my $sub_segment = shift; my $sub_res = shift; my %sub_r = %{ shift @_ }; my @target = split( /\,/, $sub_res->TARGET ); my $start = $sub_segment->start; my $end = $sub_segment->end; my $ref = $sub_segment->ref; # tweak the names to be coords for the target rather than the displayed region my $start_name = $start + $target[0]; my $end_name = $end + $target[0] + $target[1]; my $name = "$ref:$start_name..$end_name"; my $offset; if ( ( $sub_r{startright} - $start ) < length( $sub_res->SEQUENCE ) ) { $offset = 100; } else { $offset = 0; } # trim this much off the front of the displayed sequence to keep it a reasonable size my $trunc = $sub_r{startleft} - $start - $offset; my $rs; $rs = "
    ";
      $rs .= "\n\n";
      $rs .= "No mispriming library specified\n";
      $rs .= "Using 1-based sequence positions\n\n";
    
      # set width of name field
      my $max_name_length = length( $name . '|RIGHT  ' );
      $rs .= sprintf(
        sprintf( "%s ", '%-' . $max_name_length . 's' )
            . " %5s %5s %4s %5s %5s %4s  %-30s\n",
        'OLIGO', 'start', 'len', 'tm', 'gc%', 'any', '3\'', 'seq', );
      $rs .= sprintf(
        sprintf( "%s ", '%-' . $max_name_length . 's' )
            . " %5d %5d %4s %5s %5s %4s  %-30s\n",
        $name . '|LEFT',        $sub_r{startleft} - $start - $trunc,
        length( $sub_r{left} ), $sub_r{tmleft},
        $sub_r{leftgc},         $sub_r{lselfany},
        $sub_r{lselfend},       $sub_r{left}
      );
      $rs .= sprintf(
        sprintf( "%s ", '%-' . $max_name_length . 's' )
            . " %5d %5d %4s %5s %5s %4s  %-30s\n",
        $name . '|RIGHT',        $sub_r{startright} - $start - $trunc,
        length( $sub_r{right} ), $sub_r{tmright},
        $sub_r{rightgc},         $sub_r{rselfany},
        $sub_r{rselfend},        $sub_r{right}
      );
      $rs .= "\n";
      $rs .= sprintf( "PRODUCT SIZE  : %-4d\n", $sub_r{prod} );
      $rs .= sprintf( "TARGET REGION : %s\n", "$ref:$start_name..$end_name" );
      $rs .= sprintf(
        "TARGETS (start\, len)\*: %d\,%d\n",
        $target[0] - $trunc,
        $target[1]
      );
      $rs .= "\n";
    
      # mark the primers and target on the alignments track
      my $sub_alignments .= " " x ( $sub_r{startleft} - $start - $trunc );
    
      # left primer
      $sub_alignments .= ">" x length( $sub_r{left} );
      $sub_alignments .= " " x ( $target[0] - length($sub_alignments) - $trunc );
    
      # target area
      $sub_alignments .= "*" x $target[1];
      $sub_alignments
          .= " " x ( $sub_r{startright} - $start - length($sub_alignments) -
            length( $sub_r{right} ) - $trunc + 1 );
    
      # right primer
      $sub_alignments .= "<" x length( $sub_r{right} );
    
      my $dna = $sub_res->SEQUENCE;
    
      # trim displayed sequence
      $dna = substr( $dna, $trunc );
      $dna = substr( $dna, 0, ( $sub_r{prod} + $offset + $offset ) );
    
      # hack to place alignment track below sequence
      $dna =~ s/(.{1,60})/$1;/g;
      my @dna_bits = split( /;/, $dna );
      $sub_alignments =~ s/(.{1,60})/$1;/g;
      my @alignment_bits = split( /;/, $sub_alignments );
    
      my $i = 0;
    
      # print sequence and alignments
      while ( $i <= $#dna_bits ) {
        $alignment_bits[$i] ||= '';
        $rs .= sprintf( "%3d %s\n", ( $i * 60 + 1 ), $dna_bits[$i] );
        $rs .= "    " . $alignment_bits[$i] . "\n";
        $rs .= "\n";
        $i++;
      }
      $rs .= "
    "; return $rs; } sub unit_label { my $value = shift; $value >= 1e9 ? sprintf( "%.4g Gbp", $value / 1e9 ) : $value >= 1e6 ? sprintf( "%.4g Mbp", $value / 1e6 ) : $value >= 1e3 ? sprintf( "%.4g kbp", $value / 1e3 ) : sprintf( "%.4g bp", $value ); } sub new_segment_map { my ( $self, $segment, $feats, $lb, $rb ) = @_; my $render = $self->renderer; my $seg = $render->region->seg; #my @tracks = grep !/overview/, $self->selected_tracks; my $config = $self->browser_config; my $zoom_levels = $config->setting('zoom levels') || '1000 10000 100000 200000'; my @zoom_levels = split /\s+/, $zoom_levels; my %zoom_labels; for my $zoom (@zoom_levels) { $zoom_labels{$zoom} = $render->unit_label($zoom); } my $zoom_menu = $self->zoom_menu($segment); # if the primer design is done, zoom in to the PCR products my $target; my @extra_args; if ($feats) { $zoom_menu = ''; my @feature_types = $feats->types; for my $type (@feature_types) { my $features = $feats->features($type); my %options = $feats->style($type); } push @extra_args, ('tracks', $feats); $target = $self->focus($segment); my ($longest) = map {$_->length} sort { $b->length <=> $a->length } $feats->features('Primers'); $segment = $self->refocus( $segment, $target, $longest+2000 ); } else { $target = $self->focus($segment); } my $postgrid_callback = sub { my $gd = shift; my $panel = shift; my $left = $panel->pad_left; my $top = $panel->top; my $bottom = $panel->bottom; my ($mstart, $mend) = $panel->location2pixel($target, $target+1); my ($hstart, $hend) = $panel->location2pixel($lb,$rb); # first shaded #if ($feats) { unless ( $hend-$hstart < 2 ) { $gd->filledRectangle( $left + $hstart, $top, $left + $hend, $bottom, $panel->translate_color('lightgrey')); } #} # then the red center line $gd->filledRectangle( $left + $mstart, $top, $left + $mend, $bottom, $panel->translate_color('red')); }; push @extra_args, ('postgrid', $postgrid_callback); #my $panel = $render->render_panel($segment,\%args); my $panel = $render->render_panel($segment,\@extra_args); return ($panel, ' ', $zoom_menu); } # center the segment on the target coordinate sub refocus { my ( $self, $segment, $target, $window ) = @_; my $db = $self->database; my ($whole_seq) = $db->segment( $segment->ref ); my $abs_end = $whole_seq->end; $window ||= $self->configuration->{span} || $segment->length; my $half = int( $window / 2 + 0.5 ); $target = int( $target + 0.5 ); # We must not fall of the ends of the ref. sequence my $nstart = $target < $half ? 1 : $target - $half; my $nend = $target + $half - 1; $nend = $abs_end if $nend > $abs_end; ($segment) = $db->segment( -name => $segment->ref, -start => $nstart, -end => $nend ); return $segment; } sub _target { my $segment = shift; my $span = abs( $segment->end - $segment->start ); return int( $span / 2 + 0.5 ) + $segment->start; } # find the target sub focus { my ( $self, $segment ) = @_; my $conf = $self->configuration; my $target; if ( $target = $conf->{target} ) { return $target; } return $conf->{target} = _target($segment); } # slurp the BOULDER_IO params sub get_primer3_params { my $self = shift; return %{ $self->{atts} } if $self->{atts}; for ( grep {/PRIMER_/} param() ) { $self->{atts}->{$_} = param($_) if param($_); param( $_, '' ); } return %{ $self->{atts} } if $self->{atts}; } # form elements stolen and modified from the primer3 website sub primer3_params { my $self = shift; my $conf = $self->configuration; my $target = shift; my $help = 'http://frodo.wi.mit.edu/cgi-bin/primer3/primer3_www_help.cgi'; my $msg = "Format xxx-xxx\\nBy default, the smallest " . "product size to flank the feature will be selected\\n" . "Use this option to force a particular amplicon size and.or " . "reduce computation time"; my $sr = $conf->{size_range} || ''; my %table = ( b(qq( Primer sets:) ), qq(), b(qq( Primer Size) ), qq(Min. Opt. Max. ), b(qq( Primer Tm) ), qq(Min. Opt. Max. ), b(qq(Product size range:) ), qq(), b(qq( Max 3\' Stability:) ), qq(), b(qq( Pair Max Mispriming:) ), qq(), b(qq( Primer GC%) ), qq(Min. Opt. Max. ), b(qq( Max Self Complementarity:) ), qq(), b(qq( Max 3\' Self Complementarity:) ), qq(), b(qq( Max Poly-X:) ), qq() ); return \%table; } sub toggle { my $self = shift; my ($state,$section_head,@body) = @_; #my ($label) = $self->browser_config->tr($section_head) || $section_head; my ($label) = $self->renderer->tr($section_head) || $section_head; #return $self->renderer->toggle_section($state,$label,b($label),@body); return $self->toggle_section($state,$label,b($label),@body); } #Gbrowse's toggle function isn't displaying the $show_ctrl html for #PrimerDesigner when hidden. When a section is minimized, everything #including the header disappears making it impossible to re-toggle #This fixes the problem. { no warnings 'redefine'; sub toggle_section { my $self = shift; my %config = ref $_[0] eq 'HASH' ? %{shift()} : (); my ($name,$section_title,@section_body) = @_; my $visible = $config{on}; my $buttons = $self->renderer->data_source->button_url; my $plus = "$buttons/plus.png"; my $minus = "$buttons/minus.png"; my $break = div({-id=>"${name}_break", -style=>$visible ? 'display:none' : 'display:block' },' '); my $show_ctl = div({-id=>"${name}_show", -class=>'ctl_hidden', -style=>$visible ? 'display:none' : 'display:inline', -onClick=>"visibility('$name',1)" }, img({-src=>$plus,-alt=>'+'}).' '.span({-class=>'tctl'},$section_title)); my $js = <<"JS"; var d = document.getElementById('$name').style.display; var i = this.childNodes[1]; if (d == 'inline' || d == 'block') { document.getElementById('$name').style.display = 'none'; i.src = '$plus'; } else { document.getElementById('$name').style.display = 'inline'; i.src = '$minus'; } JS my $hide_ctl = div({-id=>"${name}_hide", -class=>'ctl_visible', -style=>$visible ? 'display:inline' : 'display:none', #-onClick=>"visibility('$name',0)" -onClick=> $js }, img({-src=>$minus,-alt=>'-'}).' '.span({-class=>'tctl',-id=>"${name}_title"},$section_title)); my $content = div({-id => $name, -style=>$visible ? 'display:inline' : 'display:none', -class => 'el_visible'}, @section_body); my @result = $config{nodiv} ? (div({-style=>'float:left'}, $show_ctl.$hide_ctl),$content) :$config{tight}? (div({-style=>'float:left;position:absolute;z-index:10'}, $show_ctl.$hide_ctl).$break,$content) : div($show_ctl.$hide_ctl,$content); return wantarray ? @result : "@result"; } } sub quality_warning { my $msg = <renderer($segment); my $render = $self->renderer; return $render->slidertable($segment); } sub renderer { my $self = shift; my $segment = shift; my $config = $self->browser_config || {}; my $render = $self->{render}; if ($render) { $render->current_segment($segment); return $render; } my $globals = Bio::Graphics::Browser2->open_globals; $self->{render} = PrimerDesigner::Render->new($config); $self->{render} = bless $segment, 'PrimerDesigner::Render'; $self->{render}->current_segment($segment); return $self->{render}; } sub back_button { my $url = shift->my_url; button( -onclick => "window.location='$url'", -name => 'Return to Browser' ); } sub fatal_error { #my $self = shift; print CGI::header('text/plain'),"@_\n"; exit 0; } 1; # A package to override some Bio::Graphics::Browser2::Render # image mapping methods #package Bio::Graphics::Browser2::faux; package PrimerDesigner::Render; use CGI qw/:standard unescape/; use warnings; use strict; use Carp qw/cluck/; use Bio::Root::Storable; use Data::Dumper; use vars '@ISA'; # controls the resolution of the recentering map use constant RULER_INTERVALS => 100; use constant DEFAULT_SEG_SIZE => 10000; use constant DEFAULT_FINE_ZOOM => '20%'; use constant BUTTONSDIR => '/gbrowse/images/buttons'; use constant OVERVIEW_RATIO => 0.9; use constant DEBUG => 0; use constant DEFAULT_RANGES => q(100 500 1000 5000 10000 25000 100000 200000 400000); @ISA = qw/Bio::Graphics::Browser2::Render::HTML/; sub new { my $class = shift; my $browser = shift; my %browser_data = %{$browser}; # just the config data, not the object return bless \%browser_data, $class; } sub error { ''; } sub make_feat_link { my $self = shift; my $feat = shift; my ($start, $end ) = @_; my $fref = $feat->ref; my $fstart = $feat->start; my $fend = $feat->stop; $start ||= $fstart; $end ||= $fend; # segment >= DEFAULT_SEG_SIZE my $padding = int((DEFAULT_SEG_SIZE - $feat->length)/2) + 1; my ($pad) = sort {$b<=>$a} 1000, $padding; $start -= $pad; $end += $pad; my $p = 'PrimerDesigner'; my $url = "?plugin=$p;plugin_action=Go;ref=$fref;start=$start;stop=$end;"; $url .= "$p.lb=$fstart;$p.rb=$fend"; return $url; } sub make_map { my $self = shift; my ( $boxes, $centering_map, $panel ) = @_; my $map = qq(\n\n); my $topruler = shift @$boxes; $map .= $self->make_centering_map($topruler); my $bottomruler = pop @$boxes; $map .= $self->make_boundary_map($bottomruler); my @link_sets; my $link_set_idx = 0; for my $box (@$boxes) { my ( $feat, $x1, $y1, $x2, $y2, $track ) = @$box; next unless $feat->can('primary_tag'); next if $feat->primary_tag eq 'Primer'; my $fclass = $feat->class || 'feature'; my $fname = $feat->name || 'unnamed'; my $fstart = $feat->start; my $fend = $feat->stop; my $pl = $panel->pad_left; my $half = int(($topruler->[5]->length/2) + 0.5); my $link = $self->make_feat_link( $feat ); my $href = qq{href="$link"}; # give each subfeature its own link my @parts = $feat->sub_SeqFeature if $feat->can('sub_SeqFeature'); if ( @parts > 1 ) { my $last_end; for my $part (sort {$a->start <=> $b->start} @parts) { my $pstart = $part->start; my $pend = $part->end; my $ptype = lc $part->primary_tag; my $no_overlap = 0; # intervals between parts select the whole (aggregate) feature $last_end ||= $pend; if ($pstart > $last_end) { my $istart = $last_end + 1; my $iend = $pstart - 1; my ($ix1,$ix2) = map { $_ + $pl } $panel->location2pixel( $istart, $iend ); # skip it if the box will be less than 2 pixels wide if ($ix2 - $ix1 > 1) { my $title = qq{title="select $fclass $fname"}; $map .= qq(\n); $no_overlap = $ix2; } } my ( $px1, $px2 ) = map { $_ + $pl } $panel->location2pixel( $pstart, $pend ); $px1++ if $px1 == $no_overlap; my $phref = $self->make_feat_link( $part, $pstart, $pend ); $phref = qq{href="$phref"}; my $title = qq{title="select this $ptype"}; $map .= qq(\n); $last_end = $pend; } } else { my $title = qq{title="select $fclass $fname"}; $map .= qq(\n); } } $map .= "\n"; return $map; } sub make_centering_map { my $self = shift; my $ruler = shift; my $bottom = shift; # true if this is the lower scale-bar my ( $rfeat, $x1, $y1, $x2, $y2, $track ) = @$ruler; my $rlength = $x2 - $x1 or return; my $length = $rfeat->length; my $start = $rfeat->start; my $stop = $rfeat->stop; my $panel = $track->panel; my $pl = $panel->pad_left; my $middle; if ($bottom) { $middle = param('PrimerDesigner.target'); $middle ||= int(($start+$stop)/2 + 0.5); } # divide into RULER_INTERVAL intervals my $portion = $length / RULER_INTERVALS; my $rportion = $rlength / RULER_INTERVALS; my $ref = $rfeat->seq_id; my $source = $self->source; my $plugin = 'PrimerDesigner'; my $offset = $start - int( $length / 2 ); my @lines; while (1) { my $end = $offset + $length; my $center = $offset + $length/2; my $sstart = $center - $portion/2; my $send = $center + $portion/2; $_ = int $_ for ($start,$end,$center,$sstart,$send); my ( $X1, $X2 ) = map { $_ + $pl } $panel->location2pixel( $sstart, $send ); # fall of the end... last if $center >= $stop + ($length / 2); my ($url,$title_text); my $p = 'PrimerDesigner'; my $rb = param("$p.rb"); $rb = $1 if $rb && $rb =~ /\=(\d+)/; my $lb = param("$p.lb"); $lb = $1 if $lb && $lb =~ /\=(\d+)/; my $target = param("$p.target"); # left side of the lower ruler if ($middle && $sstart <= $middle) { $url = "?ref=$ref;start=$start;stop=$stop;plugin=$plugin;plugin_action=Go;$p.lb=$center;"; $url .= "$p.rb=$rb;" if $rb; $url .= "$p.target=$target;" if $target; $url = qq(href="$url"); $title_text = "set left target boundary to $center"; } # right side of the lower ruler elsif ($middle) { $url = "?ref=$ref;start=$start;stop=$stop;plugin=$plugin;plugin_action=Go;$p.rb=$center"; $url .= ";$p.lb=$lb" if $lb; $url .= "$p.target=$target;" if $target; $url = qq(href="$url"); $title_text = "set right target boundary to $center"; } # top ruler else { $url = "?ref=$ref;start=$offset;stop=$end;plugin=$plugin;plugin_action=Go;"; # We can retain an off-center target if it is still reasonable if ($target && $target > $offset + 1000 && $target < $end - 1000 ) { $url .= "$p.target=$target;"; } if ($lb && $lb > $offset + 500) { $url .= "$p.lb=$lb;"; } if ($rb && $rb < $end - 500) { $url .= "$p.rb=$rb;"; } $url = qq(href="$url"); $title_text = "recenter at $center"; } my $map_line = qq(recenter\n); push @lines, $map_line; $offset += int $portion; } return join '', @lines; } sub make_boundary_map { my $self = shift; $self->make_centering_map(@_, 1); } sub current_segment { my $self = shift; my $segment = shift; return $self->{segment} = $segment if $segment; return $self->{segment}; } sub unit_label { my ( $self, $value ) = @_; my $unit = $self->setting('units') || 'bp'; my $divider = $self->setting('unit_divider') || 1; $value /= $divider; my $abs = abs($value); my $label; $label = $abs >= 1e9 ? sprintf( "%.4g G%s", $value / 1e9, $unit ) : $abs >= 1e6 ? sprintf( "%.4g M%s", $value / 1e6, $unit ) : $abs >= 1e3 ? sprintf( "%.4g k%s", $value / 1e3, $unit ) : $abs >= 1 ? sprintf( "%.4g %s", $value, $unit ) : $abs >= 1e-2 ? sprintf( "%.4g c%s", $value * 100, $unit ) : $abs >= 1e-3 ? sprintf( "%.4g m%s", $value * 1e3, $unit ) : $abs >= 1e-6 ? sprintf( "%.4g u%s", $value * 1e6, $unit ) : $abs >= 1e-9 ? sprintf( "%.4g n%s", $value * 1e9, $unit ) : sprintf( "%.4g p%s", $value * 1e12, $unit ); if (wantarray) { return split ' ', $label; } else { return $label; } } sub slidertable { my $self = shift; my $state = $self->state; my $segment = shift; # try to avoid reopening the database -- recover segment # and whole segment lengths from our stored state if available my $span = $state->{view_stop} - $state->{view_start} + 1; my $max = $self->thin_whole_segment->length; my $buttonsDir = $self->data_source->button_url; my $half_title = $self->data_source->unit_label(int $span/2); my $full_title = $self->data_source->unit_label($span); my $half = int $span/2; my $full = $span; my $fine_zoom = $self->get_zoomincrement(); my $fine_point = do { no warnings 'numeric'; $fine_zoom/100 }; my $show = $self->translate('Show').' '; my @lines = (image_button( -src => "$buttonsDir/green_l2.gif", -name=>"left $full", -title => "left $full_title", #-onClick => "Controller.scroll('left', 1)" -onClick => "oPrimerDesigner.scroll('left', 1)" ), ' ', image_button(-src=>"$buttonsDir/green_l1.gif",-name=>"left $half", -title=>"left $half_title", #-onClick => "Controller.scroll('left', 0.5)" -onClick => "oPrimerDesigner.scroll('left', 0.5)" ), ' ', image_button(-src=>"$buttonsDir/mminus.png", -name=>"zoom out $fine_zoom", -style=>'background-color: transparent', -title=>"zoom out $fine_zoom", #-onClick => "Controller.update_coordinates(this.name)" -onClick => "oPrimerDesigner.scroll('zoom', $fine_point+1)" ), ' ', $self->zoomBar($span,$max,$show), #$self->zoomBar($segment), ' ', image_button(-src=>"$buttonsDir/mplus.png", -name=>"zoom in $fine_zoom", -style=>'background-color: transparent', -title=>"zoom in $fine_zoom", #-onClick => "Controller.update_coordinates(this.name)", -onClick => "oPrimerDesigner.scroll('zoom',1-$fine_point)" ), ' ', image_button(-src=>"$buttonsDir/green_r1.gif",-name=>"right $half", -title=>"right $half_title", #-onClick => "Controller.scroll('right', 0.5)" -onClick => "oPrimerDesigner.scroll('right', 0.5)" ), ' ', image_button(-src=>"$buttonsDir/green_r2.gif",-name=>"right $full", -title=>"right $full_title", #-onClick => "Controller.scroll('right', 1)" -onClick => "oPrimerDesigner.scroll('right', 1)" ), ' ', ); my $str = join('', @lines); return span({-id=>'span'},$str); } sub get_zoomincrement { my $self = shift; my $zoom = $self->setting('fine zoom') || DEFAULT_FINE_ZOOM; $zoom; } sub zoomBar { my $self = shift; my ($length,$max,$item_label) = @_; $item_label ||= ''; my %seen; my @r = sort {$a<=>$b} $self->data_source->get_ranges(); $max *= $self->data_source->unit_divider; my @ranges = grep {!$seen{$self->data_source->unit_label($_)}++ && $_<=$max} sort {$b<=>$a} @r,$length; my %labels = map {$_=>$item_label.$self->data_source->unit_label($_)} @ranges; return popup_menu(-class => 'searchtitle', -name => 'span', -values => \@ranges, -labels => \%labels, -default => $length, -force => 1, -onChange => "oPrimerDesigner.scroll('set span',this.options[this.selectedIndex].value)", ); } #NML: holdovers from Bio::Graphics::Browser #need to see if there are contemporary versions in new modules sub fatal_error { #my $self = shift; print CGI::header('text/plain'),"@_\n"; exit 0; } sub render_panel { my $render = shift; my $segment = shift; #my $postgrid = shift; my $extra_args = shift; my @panels; my $region = $render->region; my $features = $region->features; my $title = $render->generate_title($features); my $output; my @post_load = $render->get_post_load_functions; $output .= $render->render_html_start($title,@post_load); $output .= $render->render_busy_signal; push @panels, $output; #my %extra_args = @$extra_args; #my $postgrid = $extra_args{'postgrid'}; my $scale_bar_html = $render->scale_bar( $segment, 'detail', $extra_args ); push @panels, div({-id=>'primer_panel', -style=>'padding:12px;position:relative'}, $scale_bar_html, $render->render_detailview_panels($segment) ); my $main_page = join('',@panels); my $tracks = $render->render_tracks_section; return $render->sender_tabbed_pages($main_page,$tracks); return $main_page; } sub sender_tabbed_pages { my $self = shift; my ($main_html,$tracks_html,$community_tracks_html,$custom_tracks_html,$settings_html,) = @_; my $uses_database = $self->user_tracks->database; my $main_title = $self->translate('MAIN_PAGE'); my $tracks_title = $self->translate('SELECT_TRACKS'); my $community_tracks_title = $self->translate('COMMUNITY_TRACKS_PAGE') if $uses_database; my $custom_tracks_title = $self->translate('CUSTOM_TRACKS_PAGE'); my $settings_title = $self->translate('SETTINGS_PAGE'); my $html = ''; $html .= div({-id=>'tabbed_section', -class=>'tabbed'}, #div({-id=>'tabbed_menu',-class=>'tabmenu'}, span({style=>'display:none', id=>'main_page_select'}, $main_title), span({style=>'display:none', id=>'track_page_select'}, $tracks_title), #$uses_database? span({id=>'community_tracks_page_select'}, $community_tracks_title) : "", #span({id=>'custom_tracks_page_select'}, $custom_tracks_title), #span({id=>'settings_page_select'}, $settings_title), #), div({-id=>'main_page', -class=>'tabbody'}, $main_html), #div({-id=>'track_page', -class=>'tabbody'}, $tracks_html), #$uses_database?div({-id=>'community_tracks_page',-class=>'tabbody'}, $community_tracks_html) : "", #div({-id=>'custom_tracks_page', -class=>'tabbody'}, $custom_tracks_html), #div({-id=>'settings_page', -class=>'tabbody'}, $settings_html), ); return $html; } 1; GBrowse-2.56/conf/plugins/ProteinDumper.pm000444001750001750 2100713036764442 20724 0ustar00lsteinlstein000000000000# $Id: ProteinDumper.pm,v 1.5 2006-08-30 02:37:07 lstein Exp $ # # BioPerl module for Bio::Graphics::Browser2::Plugin::ProteinDumper # # Cared for by Aaron Mackey # # You may distribute this module under the same terms as perl itself # POD documentation - main docs before the code =head1 NAME Bio::Graphics::Browser2::Plugin::ProteinDumper - A plugin for dumping translated protein sequences in various formats =head1 SYNOPSIS Give standard usage here =head1 DESCRIPTION This is a plugin to the Generic Model Organism Database browse used by Bio::Graphics::Browser to dump protein translations of genes from an annotated region in the requested flatfile format. Currently the feature formats are =head1 FEEDBACK See the GMOD website for information on bug submission http://www.gmod.org. =head1 AUTHOR - Aaron Mackey Email amackey@pcbi.upenn.edu =head1 CONTRIBUTORS Based on the SequenceDumper plugin written by Jason Stajich =head1 APPENDIX The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _ =cut # Let the code begin... package Bio::Graphics::Browser2::Plugin::ProteinDumper; # $Id: ProteinDumper.pm,v 1.5 2006-08-30 02:37:07 lstein Exp $ # Protein Dumper plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::SeqIO; use Bio::Tools::CodonTable; use CGI qw(:standard *pre); use vars qw($VERSION @ISA); use constant DEBUG => 0; # module label is xml? my @FORMATS = ( 'fasta' => ['Fasta', undef], 'genbank' => ['Genbank', undef], 'embl' => ['EMBL', undef], 'gcg' => ['GCG', undef], 'raw' => ['Raw sequence', undef], 'game' => ['GAME (XML)', 'xml'], 'bsml' => ['BSML (XML)', 'xml'], ); # initialize @ORDER using the even-numbered elements of the array # and grepping for those that load successfully (some of the # modules depend on optional XML modules). my @ORDER = grep { my $module = "Bio::SeqIO::$_"; warn "trying to load $module\n" if DEBUG; eval "require $module; 1"; } grep { ! /gff/i } map { $FORMATS[2*$_] } (0..@FORMATS/2-1); # initialize %FORMATS and %LABELS from @FORMATS my %FORMATS = @FORMATS; my %LABELS = map { $_ => $FORMATS{$_}[0] } keys %FORMATS; $VERSION = '1.00'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Protein Sequence File" } sub description { p("The protein sequence dumper plugin dumps out translated protein sequences of genes found in the currently displayed genomic segment in the requested format.") . p("This plugin was originally written by Lincoln Stein and Jason Stajich, modified by Aaron Mackey."); } sub dump { my $self = shift; my $segment = shift; unless ($segment) { my $mime_type = $self->mime_type; print start_html($self->name) if $mime_type =~ /html/; print "No sequence specified.\n"; print end_html if $mime_type =~ /html/; CORE::exit 0; } my $config = $self->configuration; my $ct = Bio::Tools::CodonTable->new; $ct->id($config->{geneticcode}); my @filter = $self->selected_features; $segment->absolute(1); my @seqs; for my $f ($segment->features(-types => \@filter)) { my @cds = $self->_collect_cds($f); next unless @cds; my $cds = join("", map { $self->_get_dna($_) } @cds); if ( (my $phase = $cds[0]->phase) > 0) { # some genefinders will predict incomplete genes, wherein # initial exons may not be in phase 0; in which case, we have to # turn the first incomplete codon into NNN substr($cds, 0, $phase, "NNN"); } push @seqs, Bio::Seq->new(-display_id => $f->display_id, -descr => $f->location->to_FTstring, -seq => $ct->translate($cds) ); } unless (@seqs) { print "# no features with CDS parts found\n"; CORE::exit 0; } my $out = new Bio::SeqIO(-format => $config->{fileformat},-fh=>\*STDOUT); my $mime_type = $self->mime_type; if ($mime_type =~ /html/) { print start_html($segment->desc),h1($segment->desc), start_pre; $out->write_seq(@seqs); print end_pre(); print end_html; } else { $out->write_seq(@seqs); } undef $out; } sub mime_type { my $self = shift; my $config = $self->configuration; return 'text/plain' if $config->{format} eq 'text'; return 'text/xml' if $config->{format} eq 'html' && $FORMATS{$config->{fileformat}}[1]; # this flag indicates xml return 'text/html' if $config->{format} eq 'html'; return wantarray ? ('application/octet-stream','dumped_region') : 'application/octet-stream' if $config->{format} eq 'todisk'; return 'text/plain'; } sub config_defaults { my $self = shift; my $browser_config = $self->browser_config; # try to get the codon table to use # first priority is the geneticcode or codontabe setting in the plugin config section my $default_code = $browser_config->plugin_setting('geneticcode') || $browser_config->plugin_setting('codontable'); # second priority is the setting in any "translation" track. unless (defined $default_code) { # search config file for a translation track for my $label ($browser_config->labels) { next unless $browser_config->setting($label => 'glyph') eq 'translation'; $default_code ||= $browser_config->setting($label => 'geneticcode') || $browser_config->setting($label => 'codontable'); last if $default_code; } } # last try, set to 1 $default_code ||= 1; return { format => 'html', fileformat => 'fasta', geneticcode => $default_code, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; foreach my $param ( $self->config_param() ) { $current_config->{$param} = $self->config_param($param); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my @choices = TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Output", td(radio_group(-name => $self->config_name('format'), -values => [qw(text html todisk)], -default => $current_config->{'format'}, -labels => {html => 'html/xml', 'todisk' => 'Save to Disk', }, -override => 1, ) ) ) ); push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Sequence File Format", td(popup_menu('-name' => $self->config_name('fileformat'), '-values' => \@ORDER, '-labels' => \%LABELS, '-default'=> $current_config->{'fileformat'}, ) ) ) ); push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Genetic Code", td(popup_menu('-name' => $self->config_name('geneticcode'), '-values' => [ grep { $Bio::Tools::CodonTable::NAMES[$_-1] } 1..@Bio::Tools::CodonTable::NAMES ], '-labels' => { map { ( $_ => $Bio::Tools::CodonTable::NAMES[$_-1] ) } grep { $Bio::Tools::CodonTable::NAMES[$_-1] } 1..@Bio::Tools::CodonTable::NAMES }, '-default'=> $current_config->{'geneticcode'}, ) ) ) ); my $html= table(@choices); $html; } sub gff_dump { my $self = shift; my $segment = shift; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $date = localtime; my $mime_type = $self->mime_type; my $html = $mime_type =~ /html/; print start_html($segment) if $html; print h1($segment),start_pre() if $html; print "##gff-version 2\n"; print "##date $date\n"; print "##sequence-region ",join(' ',$segment->ref,$segment->start,$segment->end),"\n"; print "##source gbrowse SequenceDumper\n"; print "##See http://www.sanger.ac.uk/Software/formats/GFF/\n"; print "##NOTE: Selected features dumped.\n"; my @feature_types = $self->selected_features; $segment->absolute(0); my $iterator = $segment->get_seq_stream(-types => \@feature_types) or return; while (my $f = $iterator->next_seq) { print $f->gff_string,"\n"; for my $s ($f->sub_SeqFeature) { print $s->gff_string,"\n"; } } print end_pre() if $html; print end_html() if $html; } sub _collect_cds { my $self = shift; my $feature = shift; if ($feature->type =~ /^CDS/i) {return $feature}; my @sub = $feature->get_SeqFeatures; return unless @sub; return map {$self->_collect_cds($_)} @sub; } sub _get_dna { my $self = shift; my $f = shift; my $s = $f->seq; return $s unless ref $s; return $s->seq; } 1; GBrowse-2.56/conf/plugins/RandomGene.pm000444001750001750 644413036764442 20136 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::RandomGene; # $Id: RandomGene.pm,v 1.2 2005-12-09 22:19:09 mwz444 Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Feature; use CGI qw(:standard *table); use vars '$VERSION','@ISA'; $VERSION = '0.3'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Simulated Genes" } sub description { p("The simulated gene plugin generates random genes", "on the current view."). p("It was written to illustrate how annotation plugins work."); } sub type { 'annotator' } sub init { } sub config_defaults { my $self = shift; return { gene_size => 5_000, exon_size => 100, intron_size => 500, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; my $defaults = $self->config_defaults; for my $size ('exon_size','intron_size','gene_size') { my $new_size = $self->config_param($size); if ($new_size > 0 and $new_size < 1_000_000) { # sanity check $current_config->{$size} = $new_size; } else { # doesn't pass check, so go to defaults $current_config->{$size} = $defaults->{$size}; } } } sub configure_form { my $self = shift; my $current_config = $self->configuration; return "Average length of simulated gene: ".textfield(-name=>$self->config_name('gene_size'), -default=>$current_config->{gene_size} ) .br(). "Average length of simulated exon: ".textfield(-name=>$self->config_name('exon_size'), -default=>$current_config->{exon_size} ) .br(). "Average length of simulated intron: ".textfield(-name=>$self->config_name('intron_size'), -default=>$current_config->{intron_size} ); } sub annotate { my $self = shift; my $segment = shift; my $dna = $segment->seq; my $abs_start = $segment->start; my $end = $segment->end; my $length = $segment->length; my $exon_size = $self->configuration->{exon_size}; my $gene_size = $self->configuration->{gene_size}; my $intron_size = $self->configuration->{intron_size}; my $feature_list = Bio::Graphics::FeatureFile->new; $feature_list->add_type('gene' => {glyph => 'transcript2', key => 'simulated gene', bgcolor => 'blue', }); for (1..5) { my $gene_start = int(rand($length)); my $gene_end = $gene_start+int(rand($gene_size)); my $strand = rand > 0.5 ? +1 : -1; my $name = sprintf("GMOD%010d",rand(1E6)); my $gene = Bio::Graphics::Feature->new(-start=>$abs_start+$gene_start, -end =>$abs_start+$gene_end, -display_name => $name, -type=>'gene', -strand => $strand, -url => "http://www.google.com/search?q=$name", ); my $exon_start = $gene_start; my $exon_end; do { $exon_end = $exon_start + int(rand($exon_size)); $exon_end = $gene_end if $exon_end > $gene_end; my $exon_feature = Bio::Graphics::Feature->new(-start=>$abs_start+$exon_start, -end =>$abs_start+$exon_end, -type => 'exon', -strand => $strand, ); $gene->add_segment($exon_feature); $exon_start = $exon_end + int(rand($intron_size)); } until ($exon_end >= $gene_end); $feature_list->add_feature($gene,'gene'); } return $feature_list; } 1; GBrowse-2.56/conf/plugins/RestrictionAnnotator.pm000444001750001750 1135413036764442 22326 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::RestrictionAnnotator; # $Id: RestrictionAnnotator.pm,v 1.16 2009-01-02 20:57:37 lstein Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(:standard *table); use vars '$VERSION'; $VERSION = '0.25'; use base 'Bio::Graphics::Browser2::Plugin'; my %SITES; my @COLORS = qw(red green blue orange cyan black turquoise brown indigo wheat yellow emerald); sub name { "Restriction Sites" } sub description { p("The restriction site plugin generates a restriction map", "on the current view."). p("This plugin was written Elizabeth Nickerson & Lincoln Stein."); } sub type { 'annotator' } sub init {shift->configure_enzymes} sub config_defaults { my $self = shift; return { on => 1, EcoRI => 1, ClaI => 1, BamHI => 1, PvuII => 1, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; %$current_config = map {$_=>1} $self->config_param('enzyme'); $current_config->{on} = $self->config_param('on'); } sub configure_form { my $self = shift; my $current_config = $self->configuration; configure_enzymes() unless %SITES; my @buttons = checkbox_group(-name => $self->config_name('enzyme'), -values => [sort keys %SITES], -cols => 4, -defaults => [grep {$current_config->{$_}} keys %$current_config] ); return table(TR({-class=>'searchtitle'}, th("Select Restriction Sites To Annotate")), TR({-class=>'searchtitle'}, th({-align=>'LEFT'}, "Restriction Site Display ", radio_group(-name=>$self->config_name('on'), -values =>[0,1], -labels => {0=>'off',1=>'on'}, -default => $current_config->{on}, -override=>1, ))), TR({-class=>'searchbody'}, td(@buttons))); } sub annotate { my $self = shift; my $segment = shift; my $config = $self->configuration; configure_enzymes() unless %SITES; return unless %SITES; return unless %$config; return unless $config->{on}; my $ref = $segment->seq_id; my $abs_start = $segment->start; my $dna = $segment->seq; $dna = $dna->seq if ref $dna; # API changes -darn! my $feature_list = $self->new_feature_list; # find restriction sites my $i = 0; for my $type (keys %$config) { next if $type eq 'on'; next unless $SITES{$type}; my ($pattern,$offset) = @{$SITES{$type}}; $feature_list->add_type($type=>{glyph => 'generic', key => "$type restriction site", fgcolor => $COLORS[$i % @COLORS], bgcolor => $COLORS[$i % @COLORS], point => 0, orient => 'N', link => 'http://www.google.com/search?q=$name', }); $i++; while ($dna =~ /($pattern)/ig) { my $pos = $abs_start + pos($dna) - length($1) + $offset; my $feature = Bio::Graphics::Feature->new(-start=>$pos,-stop=>$pos, -ref=>$ref, -name=>$type, -type=>$type, -class=>'RestrictionSite', -source=>'RestrictionAnnotator.pm'); $feature_list->add_feature($feature,$type); } } return $feature_list; } sub configure_enzymes { my $self = shift; my $conf_dir = $self->config_path(); my $file = "$conf_dir/enzymes.txt"; open (ENZYMES, "$file") or die "Error: cannot open file $file: $!.\n"; while () { chomp; my @hold_enzyme = split(/\t/,$_); my $enzyme_name = shift(@hold_enzyme); $SITES{$enzyme_name} = \@hold_enzyme; next; } close(ENZYMES); } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::RestrictionAnnotator - Generate a restriction map track in GBrowse =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugins = RestrictionAnnotator =head1 DESCRIPTION The RestrictionAnnotator plugin generates a series of automatic tracks showing restriction enzyme cut sites. For it to work properly, the genomic DNA must be loaded. =head1 OPTIONS There are now config file options. The list of enzymes and their cut sites is contained in APACHE_CONFIG/gbrowse.conf/enzymes.txt, where APACHE_CONFIG is your Apache configuration directory. It is straightforward to add new enzymes. The format is: For example, the entry for EcoRI is EcoRI GAATTC 1 The "1" means that EcoRI will be cleaved at position 1, where positions are BETWEEN the bases starting with 0: 0 1 2 3 4 5 6 G A A T T C The recognition site can be a regular expression. =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elstein@cshl.orgE. Copyright (c) 2001 Cold Spring Harbor Laboratory. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/SequenceDumper.pm000444001750001750 1717413036764442 21066 0ustar00lsteinlstein000000000000# $Id: SequenceDumper.pm,v 1.18 2009-01-02 20:57:37 lstein Exp $ # # BioPerl module for Bio::Graphics::Browser2::Plugin::SequenceDumper # # Cared for by Jason Stajich # # Copyright Jason Stajich and Cold Spring Harbor Laboratories 2002 # # You may distribute this module under the same terms as perl itself # POD documentation - main docs before the code =head1 NAME Bio::Graphics::Browser2::Plugin::SequenceDumper - A plugin for dumping sequences in various formats =head1 SYNOPSIS Give standard usage here =head1 DESCRIPTION This is a plugin to the Generic Model Organism Database browse used by Bio::Graphics::Browser to dump out an annotated region in a requested flatfile format. Currently the feature formats are =head1 FEEDBACK See the GMOD website for information on bug submission http://www.gmod.org. =head1 AUTHOR - Jason Stajich Email jason@bioperl.org Describe contact details here =head1 CONTRIBUTORS Additional contributors names and emails here =head1 APPENDIX The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _ =cut # Let the code begin... package Bio::Graphics::Browser2::Plugin::SequenceDumper; # $Id: SequenceDumper.pm,v 1.18 2009-01-02 20:57:37 lstein Exp $ # Sequence Dumper plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::SeqFeature::Generic; use Bio::SeqIO; use Bio::Seq::RichSeq; use Bio::Graphics::Browser2::TrackDumper::RichSeqMaker; use CGI qw(:standard *pre); use POSIX qw(strftime); use vars qw($VERSION @ISA); use constant DEBUG => 0; # module label is xml? my @FORMATS = ( 'fasta' => ['Fasta', undef], 'genbank' => ['Genbank', undef], 'embl' => ['EMBL', undef], 'gcg' => ['GCG', undef], 'raw' => ['Raw sequence', undef], 'bsml' => ['BSML (XML)', 'xml'], 'featurefasta'=>['Feature Fasta', undef], 'gff' => ['GFF3', undef], ); # initialize @ORDER using the even-numbered elements of the array # and grepping for those that load successfully (some of the # modules depend on optional XML modules). my @ORDER = grep { my $module = "Bio::SeqIO::$_"; warn "trying to load $module\n" if DEBUG; eval "require $module; 1"; } grep { ! /gff/i } map { $FORMATS[2*$_] } (0..@FORMATS/2-1); unshift @ORDER,'featurefasta'; unshift @ORDER,'gff'; # initialize %FORMATS and %LABELS from @FORMATS my %FORMATS = @FORMATS; my %LABELS = map { $_ => $FORMATS{$_}[0] } keys %FORMATS; $VERSION = '0.14'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Sequence File" } sub description { p("The Sequence dumper plugin dumps out the currently displayed genomic segment", "in the requested format."). p("This plugin was written by Lincoln Stein and Jason Stajich."); } sub dump { my $self = shift; my $segment = shift; my $config = $self->configuration; my $wantsorted = $config->{'wantsorted'} || 0; my $browser = $self->browser_config(); my @markup; my %markuptype; # special case for GFF dumping if ($config->{'fileformat'} eq 'gff') { $self->gff_dump($segment); return; } # special case for feature fasta if ($config->{'fileformat'} eq 'featurefasta') { $self->feature_fasta_dump($segment); return; } my @filter = $self->selected_features; my $iterator = $segment->get_seq_stream(-types => \@filter); my $seq = Bio::Graphics::Browser2::TrackDumper::RichSeqMaker->stream_to_rich_seq($segment,$iterator); my $out = new Bio::SeqIO(-format => $config->{fileformat},-fh=>\*STDOUT); my $mime_type = $self->mime_type; if ($mime_type =~ /html/) { print start_html($segment->desc),h1($segment->desc), start_pre; $out->write_seq($seq); print end_pre(); print end_html; } else { $out->write_seq($seq); } undef $out; } sub mime_type { my $self = shift; my $config = $self->configuration; return 'text/plain' if $config->{format} eq 'text'; return 'text/xml' if $config->{format} eq 'html' && $FORMATS{$config->{fileformat}}[1]; # this flag indicates xml return 'text/html' if $config->{format} eq 'html'; return wantarray ? ('application/octet-stream','dumped_region') : 'application/octet-stream' if $config->{format} eq 'todisk'; return 'text/plain'; } sub config_defaults { my $self = shift; return { format => 'html', fileformat => 'fasta', wantsorted => 0, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; foreach my $param ( $self->config_param() ) { $current_config->{$param} = $self->config_param($param); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my @choices = TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Output", td(radio_group(-name => $self->config_name('format'), -values => [qw(text html todisk)], -default => $current_config->{'format'}, -labels => {html => 'html/xml', 'todisk' => 'Save to Disk', }, -override => 1)))); my $browser = $self->browser_config(); # this to be fixed as more general push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'},"Sequence File Format", td(popup_menu('-name' => $self->config_name('fileformat'), '-values' => \@ORDER, '-labels' => \%LABELS, '-default'=> $current_config->{'fileformat'} )))); push @choices, TR({-class => 'searchtitle'}, th({-align=>'RIGHT',-width=>'25%'}, "Sorted SubLocations (for VectorNTI input of GenBank)", td(popup_menu('-name' => $self->config_name('wantsorted'), '-values' => [qw(0 1)], '-labels' => { '0' => 'No', '1' => 'Yes'}, '-default'=> $current_config->{'wantsorted'} )))); my $html= table(@choices); $html; } sub gff_dump { my $self = shift; my $segment = shift; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $date = localtime; my $mime_type = $self->mime_type; my $html = $mime_type =~ /html/; print start_html($segment) if $html; print h1($segment),start_pre() if $html; print "##gff-version 3\n"; print "##date $date\n"; print "##sequence-region ",join(' ',$segment->ref,$segment->start,$segment->stop),"\n"; print "##source gbrowse SequenceDumper\n"; print "##See http://www.sanger.ac.uk/Software/formats/GFF/\n"; print "##NOTE: Selected features dumped.\n"; my @feature_types = $self->selected_features; $segment->absolute(0); my $iterator = $segment->get_seq_stream(-types => \@feature_types) or return; while (my $f = $iterator->next_seq) { eval{$f->version(3)}; my $s =$f->gff_string(1); chomp($s); print $s,"\n"; } print end_pre() if $html; print end_html() if $html; } sub feature_fasta_dump { my $self = shift; my $segment = shift; my $page_settings = $self->page_settings; my $conf = $self->browser_config; my $date = localtime; my $mime_type = $self->mime_type; my $html = $mime_type =~ /html/; print start_html($segment) if $html; print h1($segment),start_pre() if $html; print "##date $date\n"; print "##source gbrowse SequenceDumper\n"; print "##$segment\n"; print "##NOTE: Selected features dumped.\n"; my @feature_types = $self->selected_features; $segment->absolute(0); my $iterator = $segment->get_seq_stream(-types => \@feature_types) or return; while (my $f = $iterator->next_seq) { my $out = new Bio::SeqIO(-format =>'fasta',-fh=>\*STDOUT); $out->write_seq($f->seq); } print end_pre() if $html; print end_html() if $html; } 1; GBrowse-2.56/conf/plugins/SimpleTrackFinder.pm000444001750001750 524213036764442 21460 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::SimpleTrackFinder; # $Id: SimpleTrackFinder.pm,v 1.2 2009-05-20 21:29:40 lstein Exp $ use strict; use CGI qw(:standard *table); use base 'Bio::Graphics::Browser2::Plugin'; our $VERSION = '0.25'; sub name { "Simple Track Finder" } sub description { return p("The simple track finder filters the track table by the name of the track."); } sub type { 'trackfilter' } sub init { } sub config_defaults { my $self = shift; return { track_name => undef, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; $current_config->{track_name} = $self->config_param('track_name'); } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $name = $current_config->{track_name}; return b('Partial or full track name:'). textfield(-id => 'track_name_filter', -name => $self->config_name('track_name'), -default => $name, -override => 1, -onKeyDown=>'if (event.keyCode==13) doPluginUpdate()', ). button(-value => 'Clear', -onClick => "\$('track_name_filter').clear(); doPluginUpdate()"); } sub filter_tracks { my $self = shift; my $tracks = shift; my $source = shift; my $config = $self->configuration; my $name = $config->{track_name} or return @$tracks; my @filtered = grep { my $key = $source->setting($_=>'key') || $_; $key =~ m/$name/i } @$tracks; warn "name = $name, filtered = @filtered"; return @filtered; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::SimpleTrackFinder - Limit list of tracks to those that match a name pattern =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugin = SimpleTrackFinder =head1 DESCRIPTION This plugin activates a panel above the tracks table that allows the user to filter the tracks according to a name or part of a name. The user is shown a textfield in which he or she can type a search string. When the user presses the "Configure" button, the tracks table is filtered to show only tracks that match the search string. Note that this only affects the display of track names. Tracks that were previously turned on will stay on, but their entries will be invisible in the tracks table. The user can still turn them off by clicking on the individual track's configure or (-) buttons. =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elincoln.stein@gmail.comE. Copyright (c) 2009 Ontario Institute for Cancer Research This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/SinWave.pm000444001750001750 470113036764442 17465 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::SinWave; # $Id: SinWave.pm,v 1.2 2008-12-02 23:56:53 lstein Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Feature; use CGI qw(:standard *table); use vars '$VERSION','@ISA'; $VERSION = '0.1'; use constant RADIANS_PER_CYCLE => 2*3.14159265; # pi use constant BINS_PER_SEGMENT => 1000; # number of data points @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Sine Wave" } sub description { p("The sine wave plugin generates a sine wave ", "on the current view."). p("It was written to illustrate how to create quantitative features for the xyplot."); } sub type { 'annotator' } sub init { } sub config_defaults { my $self = shift; return { cycles => 10, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; my $defaults = $self->config_defaults; my $new_cycles = $self->config_param('cycles'); if ($new_cycles >= 1 and $new_cycles < 100) { # sanity check $current_config->{cycles} = $new_cycles; } else { # doesn't pass check, so go to defaults $current_config->{cycles} = $defaults->{cycles}; } } sub configure_form { my $self = shift; my $current_config = $self->configuration; return "Cycles per window: ".textfield(-name=>$self->config_name('cycles'), -default=>$current_config->{cycles} ); } sub annotate { my $self = shift; my $segment = shift; my $chr = $segment->seq_id; my $segstart = $segment->start; my $length = $segment->length; my $cycles = $self->configuration->{cycles}; my $radians_per_bin = RADIANS_PER_CYCLE * $cycles/BINS_PER_SEGMENT; my $bases_per_bin = $length/BINS_PER_SEGMENT; my $feature_list = Bio::Graphics::FeatureFile->new; $feature_list->add_type('wave' => {glyph => 'xyplot', key => "$cycles cycles", bgcolor => 'blue', height => 50, min_score => -1.0, max_score => +1.0, }); my $curve = Bio::Graphics::Feature->new(); for (0..BINS_PER_SEGMENT-1) { my $start = $segstart + int($_ * $bases_per_bin); my $end = int($start + $bases_per_bin); my $score = sin($_ * $radians_per_bin); $curve->add_SeqFeature(Bio::Graphics::Feature->new(-seq_id=>$chr, -start => $start, -end => $end, -score => $score)); } $feature_list->add_feature($curve,'wave'); return $feature_list; } 1; GBrowse-2.56/conf/plugins/SourceTrackFinder.pm000444001750001750 1046413036764442 21511 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::SourceTrackFinder; # $Id: SourceTrackFinder.pm,v 1.2 2009-05-20 21:29:40 lstein Exp $ use strict; use CGI qw(:standard *table); use base 'Bio::Graphics::Browser2::Plugin'; use Bio::Graphics::Browser2::Util 'shellwords'; our $VERSION = '0.25'; sub name { "Source Track Finder" } sub description { return p("The source track finder filters the track table by the data and config source the track."); } sub type { 'trackfilter' } sub init { } sub config_defaults { my $self = shift; # this line gets all the options defined in the "[SourceTrackFinder:plugin]" stanza my %fields = map {$_=>undef} $self->get_fields; return \%fields; } # this method gets all the options defined in the "[SourceTrackFinder:plugin]" stanza sub get_fields { my $self = shift; return $self->browser_config->plugin_setting; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; for my $f ($self->get_fields) { $current_config->{lc $f} = $self->config_param($f); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $source = $self->browser_config; my @fields = $self->get_fields; my @elements; for my $f (@fields) { my @options = ('',shellwords($source->plugin_setting($f))); push @elements,b(ucfirst $f.':'); push @elements, popup_menu( -id => "plugin_$f", -class => "SourceTrackFinderPopup", -name => $self->config_name($f), -values => \@options, -default => $current_config->{$f}, -override => 1, -onChange => 'doPluginUpdate()', ) } push @elements, button(-value => 'Clear', -onClick => q($$('.SourceTrackFinderPopup').each(function(m) {m.selectedIndex=0}); doPluginUpdate();) ); return join ' ',@elements; } sub filter_tracks { my $self = shift; my $track_labels = shift; my $source = shift; my $config = $self->configuration; my @fields = $self->get_fields; my %filters = map {lc $_ => $config->{lc $_}} @fields; my @result; LABEL: for my $l (@$track_labels) { do {push @result,$l; next LABEL} if $l =~ /^(plugin|file|http|das)/; for my $f (keys %filters) { my %values = map {lc $_=>1} shellwords $source->fallback_setting($l=>$f); next LABEL if length $filters{$f} && !$values{lc $filters{$f}}; } push @result,$l; } return @result; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::SourceTrackFinder - Limit list of tracks to those that contain arbitrary fields =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugin = SourceTrackFinder [SourceTrackFinder:plugin] tissue source = brain pancreas kidney gender = male female [track1] (usual config options) tissue source = brain gender = male [track2] (usual config options) tissue source = pancreas gender = female =head1 DESCRIPTION This plugin activates a panel above the tracks table that allows the user to filter the tracks according to combinations of fields that you define. The fields are defined in the [SourceTrackFinder:plugin] stanza of the configuration file and consist of one or more field names followed by their allowable values, separated by spaces using the usual GBrowse config rules. For filtering to work, each track must also have a similarly-named set of fields, each with one or more values. GBrowse will prompt the user to select field values using a series of popup menus located above the tracks table. When the user changes the popups, the tracks table will be filtered to show only the tracks that match the selected field values. The user can press the "clear" button to turn off filtering. Note that this only affects the display of track names. Tracks that were previously turned on will stay on, but their entries will be invisible in the tracks table. The user can still turn them off by clicking on the individual track's configure or (-) buttons. =head1 OPTIONS None =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elincoln.stein@gmail.comE. Copyright (c) 2009 Ontario Institute for Cancer Research This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/Spectrogram.pm000444001750001750 4355713036764442 20433 0ustar00lsteinlstein000000000000# $Id: Spectrogram.pm,v 1.9 2009-01-08 16:42:29 lstein Exp $ # bioperl module for Bio::Graphics::Browser2::Plugin::Spectrogram # cared for by Sheldon McKay mckays@cshl.edu # Copyright (c) 2006 Cold Spring Harbor Laboratory. =head1 NAME Bio::Graphics::Browser2::Plugin::Spectrogram =head1 SYNOPSIS This module is not used directly. It is an 'annotator' plugin for tehe Generic Genome Browser. =head1 DESCRIPTION The Spectrogram plugin builds up a spectrogram for digitized DNA sequence using the short-time fourier transform (STFT) method, adapted from classical digital signal processing methods. A sliding window of variable size and overlap is used to calculate each "column" of the spectrogram, where the column width is equal to the step, or overlap between windows. For each window, we: 1) digitize the DNA by creating four binary indicator sequences: G A T C C T C T G A T T C C A A G 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 A 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 T 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 0 C 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 0 2) take the discrete fourier transform (DFT) for each of the four indicator sequences and square the values to get the magnitude. 3) create a Bio::Graphics::Feature object that contains the spectrogram data as attributes. The features are passed back to gbrowse as parts of a Bio::Graphics::Featurefile object. The calculations for the real DFT are handled by the xs module Math::FFT. The actual algorithm used is the fast fourier transfrom (FFT), which is much faster than the original DFT algorithm but is limited in that only base2 numbers (128, 256, 512, etc) can be used for window sizes. This is necessary to make the spectrogram calculation fast enough for real-time use. It should be noted, however, that calculating spectrograms dynamically is computationally intensive and will increase latency when the spectrogram track is turned on in gbrowse. The graphical rendering of the spectrogram depends on the glyph module Bio::Graphics::Glyph::spectrogram. The plugin is discussed in more detail in the plugin's help links. =head1 FEEDBACK See the GMOD website for information on bug submission http://www.gmod.org. =head1 AUTHOR - Sheldon McKay Email Emckays@cshl.eduE =cut ; package Bio::Graphics::Browser2::Plugin::Spectrogram; use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::Util qw/error/; use CGI ':standard'; use CGI::Carp 'fatalsToBrowser'; use CGI::Toggle; use GD; use Math::FFT; use Statistics::Descriptive; use List::Util qw/shuffle max/; use Data::Dumper; use vars qw/@ISA $CONFIG $VERSION/; use constant IMAGE_DIR => '/gbrowse2/images/help'; use constant BUTTONS_DIR => '/gbrowse2/images/buttons'; $VERSION = 1.1; @ISA = qw/ Bio::Graphics::Browser2::Plugin /; sub init { my $self = shift; $CONFIG = $self->browser_config; } sub name { 'DNA spectrogram'; } sub type { 'annotator'; } sub verb { 'Draw'; } sub mime_type { 'text/html'; } sub config_defaults { { win => 512, inc => 256, binsize => 1, y_unit => 1, quantile => 99.99, filter_01 => 1, min => 2, max => 4, type => 'period'} } sub reconfigure { my $self = shift; my $conf = $self->configuration; $conf->{win} = $self->config_param('win'); $conf->{inc} = $self->config_param('inc'); $conf->{min} = $self->config_param('min') || 0; $conf->{max} = $self->config_param('max') || $conf->{win} - 1; $conf->{type} = $self->config_param('measure'); $conf->{filter_01} = $self->config_param('filter_01'); $conf->{quantile} = $self->config_param('quantile') || 99.99; $conf->{y_unit} = $self->config_param('y_unit') || 1; $self->configuration($conf); } sub annotate { my $self = shift; my $segment = shift or die "No segment"; my $conf = $self->configuration; my $win = $conf->{win}; my $inc = $conf->{inc}; my $ltype = $conf->{ltype}; # sanity check for window size if ($inc >= $win) { error("Spectrogram.pm error: window size must be greater than the overlap"); return; } # and for maximum period or frequency if ($conf->{max} && $conf->{max} > $win) { error("maximum $conf->{type} can not exceed ". " the window size: resetting to $win."); $conf->{max} = $win; } my $slide_offset = 0; my $db = $segment->factory; unless ($segment->start == 1) { my $original_start = $segment->start; ($segment) = $db->segment( $segment->ref, ($segment->start - $win), ($segment->end + $win) ); $slide_offset = $original_start - $segment->start - $inc; } else { ($segment) = $db->segment( $segment->ref, $segment->start, ($segment->end + $win) ); } my $seq_obj = $segment->seq; my $seq; if ($seq_obj && ref $seq_obj) { $seq = lc eval{$seq_obj->seq}; } elsif ($seq_obj) { $seq = lc $seq_obj; } $seq || die "No sequence found for $segment $@"; my $offset = $segment->start; my $end = $segment->length; my (@g,@a,@t,@c,@offsets,@meta_array,@coords); my ($min_f,$max_f); if ( $conf->{min} || $conf->{max} ) { my $max = $conf->{max} || $win; my $min = $conf->{min} || 0; my $type = $conf->{type}; if ($type eq 'period') { $min_f = $min && $max && $max > 1 ? int(2*$win/($max)) - 1 : $win - 1; $max_f = $min ? int(2*$win/($min)) - 1 : $win - 1; } else { unless (int $min == $min) { error("minimum frequency value should be an integer between", "0 and ".($win-2)); return; } unless (int $max == $max) { error("maximum frequency value should be an integer between", "1 and ".($win-1)); return; } $min_f = $min; $max_f = $max || $win-1; } } else { $min_f = 0; $max_f = $win-1; } $min_f-- unless $min_f == 0; $max_f++ unless $max_f == $win-1; my $key = join('; ',"window size $win", "overlap $inc", "saturation $conf->{quantile}th percentile"); if ($conf->{min}) { $key .= "; $conf->{type} range $conf->{min}-$conf->{max}"; } if ($conf->{filter_01}) { $key .="; 0-1 Hz filter ON"; } my $feature_list = $self->new_feature_list; my $link = sub { shift->url || 0 }; $feature_list->add_type( spectrogram => { glyph => 'spectrogram', bump => 0, # must be zero height => $conf->{y_unit} * ($max_f - $min_f + 1), key => $key, win => $win, link => $link } ); my $start = 0; my $skipped; until ( $start > ( $end - $win ) ) { my $sub_seq = substr $seq, $start, $win; # runs of N's will screw things up. $sub_seq =~ s/[^gatcGATC]/N/g; my $has_Ns = $sub_seq =~ tr/N/a/; unless ( $has_Ns > $win/10 ) { # Digitize the DNA my ($g,$a,$t,$c) = make_numeric($sub_seq); # take the magnitude of the DFT dft(\$_) for ($g,$a,$t,$c); # get rid of DC 'component' if ($conf->{filter_01} ) { for ($g,$a,$t,$c) { $_->[0] = 0; $_->[1] = 0; } } push @g, [@{$g}[$min_f..$max_f]]; push @a, [@{$a}[$min_f..$max_f]]; push @t, [@{$t}[$min_f..$max_f]]; push @c, [@{$c}[$min_f..$max_f]]; push @coords, [$start + $offset + 1, $start + $offset + $inc]; } else { $skipped++; } $start += $inc; } # warn if there are a lot of 'N's if ($skipped) { error("Spectrogram: blank areas correspond to ambiguous sequence regions with > 10% 'N's"); } # max out the intensity range at the nth # percentile to avoid saturation of color intensity my $stat = Statistics::Descriptive::Full->new; my @data = grep {defined $_} map {@$_} @g,@a,@t,@c; $stat->add_data(@data); my $max = $stat->percentile($conf->{quantile}); my @labels = $min_f .. $max_f; @labels = map {$_ ? 2*$win/$_ : $win} @labels if $conf->{type} eq 'period'; my $first = 1; for my $coords (@coords) { my ($start, $end) = @$coords; # make a link for zooming in (my $url = self_url) =~ s/\?.+//;; my $pad = int $segment->length/20; my $z_start = $start - $pad; my $z_stop = $end + $pad; my $name = $segment->ref .":$z_start..$z_stop"; $url .= "?name=$name"; my $G = shift @g; my $A = shift @a; my $T = shift @t; my $C = shift @c; my $atts = { g => $G, a => $A, t => $T, c => $C, max => $max }; # y-axis labels for first column if ($first) { $atts->{labels} = [$conf->{type},@labels]; $first = 0; } # create a column for the spectrogram. Offset the seuquence # coordinates so that features in the specrogam are directly below # the corresponding DNA my $sf = Bio::Graphics::Feature->new( -type => 'spectrogram', -source => 'calculated', -start => $start + $slide_offset, -end => $end + $slide_offset, -ref => $segment->ref, -url => $url, -attributes => $atts ); $feature_list->add_feature($sf); } return $feature_list; } sub configure_form { my $self = shift; my $conf = $self->configuration; my $segment = ($self->segments)[0]; my $state = { on => 0, override => 1 }; my $description = p( $self->_help_message($state, span({-class=>'searchtitle'}, 'What is a DNA spectrogram?'), $self->long_description) ); my $form = $description; my $msg = $self->_help_message( $state, 'Sliding window size', split "NL", <<'END;'); Window size is the number of bases to include in each calculation.NL Overlap is the increment by which the window slides (amount of overlap).NL Note: larger window sizes and/or smaller overlaps increase computation time. END; $form .= h4({-class => 'searchtitle'}, $msg) . p( 'Window: size ', popup_menu( -name => $self->config_name('win'), -values => [8,16,32,64,128,256,512,1024,2048,4096,8192], -default => $conf->{win} ), ' bp' . br. br . ' overlap ', textfield( -name => $self->config_name('inc'), -value => $conf->{inc}, -size => 4 ), 'bp' ); $msg = $self->_help_message( $state, 'Display options', split "NL", <<'END;'); The allowed range of periods or frequencies controls spectrogram height and calculation time.NL period = size (bp) of structure or repeat unit, calculated as 2*(window size)/frequency.NL row height = the height (pixels) of each frequency row in the spectrogram. END; $form .= br . h4({-class => 'searchtitle'}, $msg) . p( 'Restrict ', popup_menu( -name => $self->config_name('measure'), -values => [qw/period frequency/], -default => $conf->{type} ), ' to between ', textfield( -name => $self->config_name('min'), -value => $conf->{min}, -size => 4 ), ' and ', textfield( -name => $self->config_name('max'), -value => $conf->{max}, -size => 4 ), br . br . 'Row height', textfield( -name => $self->config_name('y_unit'), -value => $conf->{y_unit}, -size => 2 ), ' px ' ); $msg = $self->_help_message( $state, 'Image saturation', split "NL", <<'END;'); Lowering the saturation value will reduce the dominance of very bright colors on the spectrogram by setting an arbitrary maximum value (expressed as a percentile rank).NL Setting a lower saturation will reduce the effects of very high amplitude signals elsewhere in the spectrogram and help to emphasize less intense features.NL The higher the saturation value is set, the darker the "background" of the spectrogram.NL There is a very large amplitude signal at frequency 0 Hz (the very top of the spectrogram), with some bleed over to 1 Hz.NL Filtering out these frequencies will help make the fainter spots more visible by decreasing the overall range of signal magnitudes. END; $form .= br . h4({-class => 'searchtitle'}, $msg) . p( 'Saturate color intensity at the ', textfield( -name => $self->config_name('quantile'), -value => $conf->{quantile}, -size => 5 ), 'th percentile' ); my @checked = (checked => 'checked') if $conf->{filter_01}; $form .= p( checkbox( -name => $self->config_name('filter_01'), @checked, -label => 'Filter out 0-1 Hz' )); return $form; } sub _help_message { my $self = shift; my $state = shift; my $section = shift; my @items = map li($_).br, @_; my $details = table( {-width => 800}, Tr( td( {-class => 'databody'}, ul(@items)))); $self->toggle( $state, $section, $details ); } sub make_numeric { my $seq = lc shift; my @seq = split q{}, $seq; my @G = map { $_ eq 'g' ? 1 : 0 } @seq; my @A = map { $_ eq 'a' ? 1 : 0 } @seq; my @T = map { $_ eq 't' ? 1 : 0 } @seq; my @C = map { $_ eq 'c' ? 1 : 0 } @seq; return (\@G,\@A,\@T,\@C); } sub dft { # my $self = shift; # my $conf = $self->configuration; # my $remove_DC = $conf->{remove_DC}; my $array = shift; my $fft = Math::FFT->new($$array); # this is a call to the 'real' DFT (no imaginary numbers) # algorithm, which is actually implented via the FFT # algorithm my $dft = $fft->rdft; $dft = magnitude(@$dft); $$array = $dft; } sub magnitude { $_ = $_**2 for @_; return \@_; } sub _process_msg { my $msg = shift; $msg =~ s/\\n|\n\n/BREAK/gm; $msg =~ s/\n/ /gm; $msg =~ s/BREAK/\\n/g; $msg; } sub description { my $self = shift; return p(< 800}, Tr( td({-class => 'databody'}, p(< this article).

    Coding DNA examples

    This is an example of a spectrogram of a genic region of yeast chromosome I. Note the linear feature at period 3 (codon size).


    This is an example of a portion of C. elegans predicted gene Y38C1AB.4. Note the differences between exons and introns.

    Repeats

    Repeats cause a ladder-like series of horizontal lines. Short repeats, such as telomeric repeats, are most visible with small window sizes. Longer repeats, such as minisatellites, are best seen with larger window sizes.

    This is an example of telomeric repeats on C. elegans chromosome I.

    END p(<How is the DNA spectrogram calculated?

    A sliding window of variable size and overlap is used to calculate the spectrogram, which is displayed graphically as a track in the genome browser. Each window is a subsegment of DNA and corresponds to a 'column' in the graphical display of the spectrogram. The window slides along the sequence, from left to right, at a set increment, which corresponds to the column width.

    The spectrogram refers collectively to all of the rows and columns seen in the graphical display.

    The spectrogram has n rows, where n is the number of bases in the window. Each row corresponds to a discrete 'frequency' from 0 -> n-1.

    An arguably more intuitive way to relate this to DNA sequence to calculate the 'period' (n/frequency*2). If we see a feature in the spectrogram at period x, there is a non-random structure with a periodicity of x nucleotides. The chief example of this would be coding DNA at period 3.


    The DNA sequence is converted from analog to digital by creating four binary indicator sequences:
               G A T C C T C T G A T T C C A A
             G 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
             A 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1
             T 0 0 1 0 0 1 0 1 0 0 1 1 0 0 0 0
             C 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 0
    

    The magnitude of the discrete fourier transform (DFT) is calculated seperately for each of the four indicator sequences. The algorithm used is the fast fourier transfrom (FFT; via Math::FFT), which is much faster than the original DFT algorithm but is limited in that only base2 numbers (128, 256, 512, etc) can be used for window sizes. This is necessary to make the spectrogram calculation fast enough for real-time use.

    For graphical rendering, each transformed sequence is assigned a color (A=blue; T=red; C=green; G=yellow). The colors for each base are superimposed on the image. In a given spot on the spectrogram, the brightness corresponds to the magnitide (signal intensity) and the color corresponds to the dominant base at that frequency/period. If no single base predominates, an intermediate color is calculated based on the relative magnitudes.

    The spectrogram is visible as a track in the generic genome browser. Please note that the calculations and graphical rendering are computationally intensive, so the image will take a while to load, especially with larger sequence regions and/or small increments for the sliding window.

    After you have launched this plugin, the spectrogram will continue to be calculated in the main gbrowse display until you turn off the 'Spectrogram' track.

    END p("The plugin was written by Sheldon McKay (mckays\@cshl.edu)")))); } sub toggle { my $self = shift; my ($state,$section_head,@body) = @_; my $buttons_dir = $CONFIG->globals->button_url || BUTTONS_DIR; $state ||= {}; $state->{plus_img} = "$buttons_dir/query.png"; $state->{minus_img} = "$buttons_dir/minus12.png"; my ($label) = $self->language->tr($section_head) || $section_head; return toggle_section($state,$label,b($label),@body); } 1; GBrowse-2.56/conf/plugins/Submitter.pm000444001750001750 1306613036764442 20113 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::Submitter; # $Id: Submitter.pm,v 1.2 2008-10-19 02:37:59 lstein Exp $ # Submitter is an invisible plugin (Does not appear in the "Reports and Analysis" menu) # designed to support rubber-band select menu items that submit sequence data and # other parameters to external web sites such as NCBI blast. Check the GMOD wiki # for documentation. # This plugin: http://www.gmod.org/wiki/index.php/Submitter.pm # Rubber-band selection: http://www.gmod.org/wiki/index.php/GBrowse_Rubber_Band_Selection.pm use strict; use CGI qw/standard escape unescape/; use CGI 'html3'; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::Util; use Bio::Graphics::FeatureFile; use CGI qw(:standard *pre); use vars qw($VERSION @ISA); use Data::Dumper; $VERSION = 0.1; @ISA = qw(Bio::Graphics::Browser2::Plugin); # not visible in plugin menu sub hide {1} sub mime_type {'text/html'} # Gets the configuration for inidivual web site "targets" # in a config stanze that looks like this: #[Submitter:plugin] #submitter = [UCSC_BLAT] # confirm = 1 # url = http://genome.ucsc.edu/cgi-bin/hgBlat # seq_label = userSeq # output = hyperlink # type = DNA # org = Human # # [NCBI_BLAST] # confirm = 1 # url = http://www.ncbi.nlm.nih.gov/blast/Blast.cgi # seq_label = QUERY # PAGE = Nucleotides # PROGRAM = blastn # DATABASE = nr # CLIENT = web # CMD = put sub targets { my $self = shift; return $self->{targets} if $self->{targets}; my $submitter_cfg = $self->browser_config->plugin_setting('submitter'); my $text = _prepare_text($submitter_cfg); my %config_values = $text =~ /\[([^\]]+)\]([^\[]+)/gm; for my $target (keys %config_values) { my %config = $config_values{$target} =~ /(\w+)\s*=(.+)$/gm; next unless %config >= 2; for (keys %config) { $config{$_} =~ s/^\s+|\s+$//g; } $self->{targets}->{$target} = \%config; } $self->{targets} } # The text needs a bit of pre-processing to # make sure the sub-stanza key-value pairs are # respected and and embedded HTML is escaped # Bio::Graphics FeatureFile.pm is not used for parsing # because it does not respect case-sensitive keys sub _prepare_text { my $text = shift; my @html = $text =~ /(\<.+\>)\[?/; for my $html (@html) { $text =~ s/$html/escape($html)/em; } $text =~ s/\[/\n\[/g; $text =~ s/(\w+\s*=)/\n$1/g; $text; } sub dump { my $self = shift; my $segment = shift; my $targets = $self->targets; my $target = $self->config_param('target') || fatal_error(qq(Error: A target for the submitter must be included in the URL "Submitter.target=target")); my $config = $targets->{$target} || fatal_error(qq(Error: No configuration for target $target!)); my $seq = $segment->seq; $seq = $seq->seq if ref $seq; my $name = $segment->name; my $url = $config->{url} || fatal_error('Error: a url for the external website is required'); my $seq_label = $config->{seq_label} || fatal_error('Error: a label is required for the sequence submission'); my $region_label = $config->{region_label}; # Other form elements to include my $extra_html = unescape($config->{extra_html}); # Whether to print a confirmation page before external submission my $confirm = $config->{confirm}; # Format the display sequence as fasta my $fasta = $seq; $fasta =~ s/(\S{60})/$1\n/g; $fasta = ">$name\n$fasta\n"; unless ($url =~ /^http/i) { $url = "http://$url"; } # pass-thru arguments -- to be sent to the extertnal web-site my %args; for my $arg (keys %$config) { next if $arg =~ /^seq_label$|^region_label$|^confirm$|^url$|^fasta$|^extra_html$/; $args{$arg} = unescape($config->{$arg}); } # print a hidden form and a summary of the data. The "extra_html" # configuration key will trigger inclusion of other form input # elemants if required. print start_form(-name=>'f1', -method=>'POST', -action=>$url), "\n"; for my $arg (keys %args) { print hidden($arg => $args{$arg}), "\n"; } print hidden($seq_label => $seq); if (defined $region_label){ print hidden($region_label => $name); } if ($extra_html || $confirm) { my @rows = th({-colspan => 2, -style => "background:lightsteelblue"}, b("The following data will be submitted to $url"), p(submit(-name => 'Confirm'),'  ', button(-name => 'Cancel', -onclick => 'javascript:window.close()'))); for my $arg (keys %args) { next if $arg eq $seq_label; next if $arg eq $region_label; $arg =~ s/extra_html/Additional options/; push @rows, td({-width => 100, -style => 'background:lightyellow'}, [b("$arg:"), unescape($args{$arg})]); } if ($extra_html) { push @rows, td({-width => 100, -style => 'background:lightyellow'}, [b("Other options"), pre(unescape($extra_html))]); } push @rows, td({-width => 100, -style => 'background:lightyellow'}, [b($seq_label), pre($fasta)]); push @rows, td({-width => 100, -style => 'background:lightyellow'}, [b($region_label), pre($name)]) if defined $region_label; print table({-border=> 1}, Tr({-valign => 'top'}, \@rows)); } print end_form; unless ($confirm || $extra_html) { print qq(); } } sub description{'A plugin to submit the selected region to an external website'} sub config_defaults {{}} sub configure_form {''} 1; GBrowse-2.56/conf/plugins/TestAuthenticator.pm000444001750001750 70613036764442 21544 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::TestAuthenticator; # $Id$ use strict; use base 'Bio::Graphics::Browser2::Plugin::AuthPlugin'; sub authenticate { my $self = shift; my ($name,$password) = $self->credentials; if ($name eq 'lincoln' && $password eq 'foobar') { return ($name,'Lincoln Stein'); # username, fullname } elsif ($name eq 'jane' && $password eq 'foobar') { return ($name,'Jane Doe'); } return; } 1; __END__ GBrowse-2.56/conf/plugins/TestFinder.pm000444001750001750 107513036764442 20161 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::TestFinder; use strict; use warnings; use base 'Bio::Graphics::Browser2::Plugin'; sub name { 'Features by type'} sub type { 'finder' } # return all objects of type given in the search field sub find { my $self = shift; my $query = $self->page_settings->{name} or return; return $self->auto_find($query); } sub auto_find { my $self = shift; my $query = shift; my $search = $self->db_search; my $features = $search->search_features({-type=>$query}); return @$features ? $features : undef; } 1; GBrowse-2.56/conf/plugins/TrackDumper.pm000444001750001750 1537613036764442 20364 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::TrackDumper; # $Id: TrackDumper.pm,v 1.3 2009-01-30 22:06:19 lstein Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use Bio::Graphics::Browser2::TrackDumper; use CGI qw(:standard *sup); use vars '$VERSION','@ISA'; $VERSION = '1.00'; @ISA = qw/ Bio::Graphics::Browser2::Plugin /; sub name { "Track Data" } sub description { p("The Track dumper plugin dumps out the currently selected tracks and their configuration in", a({-href=>'http://www.sequenceontology.org/gff3.shtml'},'GFF Version 3 format.'), "The information can be edited and then uploaded to this, or another GBrowse instance to create new tracks.", "This plugin was written by Lincoln Stein & Sheldon McKay."); } sub config_defaults { my $self = shift; return { version => 3, mode => 'selected', disposition => 'save', coords => 'absolute', region => 'selected', embed => 0, print_config=> 1, }; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; my @keys = keys %{$self->config_defaults}; foreach my $p ( @keys ) { $current_config->{$p} = $self->config_param($p); } } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $html = p('Dump', popup_menu(-name => $self->config_name('mode'), -values => ['selected','all'], -default => $current_config->{mode}, -override => 1, ), '  features using GFF version', popup_menu(-name => $self->config_name('version'), -values => [2,2.5,3], -labels => { 2 => '2', 2.5 => '2.5*', 3 => '3'}, -default => $current_config->{version}, -override => 1), popup_menu(-name=>$self->config_name('region'), -default=>$current_config->{region}, -override=>1, -values => ['selected','all'], -labels=>{all => 'Across entire genome', selected => 'Across currently visible region'}) ); autoEscape(0); $html .= p( radio_group(-name=>$self->config_name('disposition'), -values => ['view','save','edit'], -labels => {view => 'View', save => 'Save to File', edit => 'Edit'.sup('**'), } )); $html .= p( checkbox(-name=>$self->config_name('embed'), -checked=>$current_config->{embed}, -override=>1, -label=>'Embed DNA sequence in the file') ); $html .= p( checkbox(-name=>$self->config_name('print_config'), -checked=>$current_config->{print_config}, -override=>1, -label=>'Include track configuration data') ); autoEscape(1); my $href = a( {-href => 'javascript:void(0)', -onclick => "alert('" . "\\'Target\\' syntax in the group field:\\n" . "GFF2: Target class:name start stop\\n" . "GFF2.5: Target class:name ; tstart start ; tstop stop\\n')"}, "similarity target" ); $html .= p(sup('*'), "GFF2.5 is GFF2 with a special syntax for $href" ) . p(sup('**'), "To edit, install a helper application for MIME type", cite('application/x-gff2'),'or', cite('application/x-gff3') ); $html; } sub mime_type { my $self = shift; my $config = $self->configuration; my $ps = $self->page_settings; my $base = join '_',@{$ps}{qw(ref start stop)}; my $gff = $config->{version} < 3 ? 'gff2' : 'gff3'; return $config->{disposition} eq 'view' ? 'text/plain' :$config->{disposition} eq 'save' ? ('application/octet-stream',"$base.$gff") :$config->{disposition} eq 'edit' ? "application/x-${gff}" :'text/plain'; } sub dump { my $self = shift; my ($segment, @more_feature_sets) = @_; my $conf = $self->browser_config; my $page_settings = $self->page_settings; my $config = $self->configuration; my $version = $config->{version} || 3; my $mode = $config->{mode} || 'selected'; my $entire_genome = $config->{region} && $config->{region} eq 'all'; my $db = $self->database; my $whole_segment = $db->segment(Accession => $segment->seq_id) || $db->segment($segment->seq_id); my $coords = $config->{coords}; my $embed = $config->{embed}; my $thing_to_dump = $entire_genome ? $segment->db : $segment; # safest thing to do is to use embedded logic if ($version == 3 && $config->{print_config}) { my $dumper = Bio::Graphics::Browser2::TrackDumper->new( -data_source => $conf, -id => $page_settings->{userid}, -segment => $segment->seq_id.':'.$segment->start.'..'.$segment->end, -labels => $mode eq 'selected' ? [$self->selected_tracks] : [] ) or return; $dumper->print_datafile(); } elsif ($config->{print_config}) { Bio::Graphics::Browser2::TrackDumper->print_configuration ($self->browser_config, $mode eq 'selected' ? [$self->selected_tracks] : () ); $self->print_gff($thing_to_dump,@more_feature_sets); } else { $self->print_gff($thing_to_dump,@more_feature_sets); } if ( $embed && !$entire_genome) { my $dna = $segment->dna; $dna =~ s/(\S{60})/$1\n/g; print ">$segment\n$dna\n" if $dna; } } sub print_gff { my $self = shift; my ($segment, @more_feature_sets) = @_; my $config = $self->configuration; my $version = $config->{version} || 3; my $mode = $config->{mode} || 'selected'; my $date = localtime; print "##gff-version $version\n"; print "##date $date\n"; eval {print "##sequence-region ",join(' ',$segment->ref,$segment->start,$segment->stop),"\n"}; print "##source gbrowse GFFDumper plugin\n"; print $mode eq 'selected' ? "##NOTE: Selected features dumped.\n" : "##NOTE: All features dumped.\n"; my @args; if ($mode eq 'selected') { my @feature_types = $self->selected_features; @args = (-types => \@feature_types); } my @feats = (); my $iterator = $segment->get_seq_stream(@args); while ( my $f = $iterator->next_seq ) { $self->print_feature($f,$version); } for my $set (@more_feature_sets) { if ( $set->can('get_seq_stream') ) { my @feats = (); my $iterator = $set->get_seq_stream; while ( my $f = $iterator->next_seq ) { $self->print_feature($f); } } } } sub print_feature { my $self = shift; my ($f,$version) = @_; $version ||= 3; eval{$f->version($version)}; my $s = $f->gff_string(1); # the flag is for GFF3 subfeature recursion chomp $s; print $s,"\n"; return if $version >= 3; # gff3 recurses automatically for my $ss ($f->sub_SeqFeature) { # next if $ss eq $f; my $s = $ss->gff_string; print $s,"\n"; } } 1; GBrowse-2.56/conf/plugins/TrackFinder.pm000444001750001750 1055513036764442 20331 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::TrackFinder; # $Id: SourceTrackFinder.pm,v 1.2 2009-05-20 21:29:40 lstein Exp $ use strict; use CGI qw(:standard *table); use base 'Bio::Graphics::Browser2::Plugin'; use Bio::Graphics::Browser2::Util 'shellwords'; our $VERSION = '0.25'; sub name { "Track Finder" } sub description { return p("The track finder filters the track table by the contents of its key, comments and select fields."); } sub type { 'trackfilter' } sub init { } sub config_defaults { my $self = shift; # this line gets all the options defined in the "[TrackFinder:plugin]" stanza my %fields = map {$_=>undef} $self->get_fields; return \%fields; } # this method gets all the options defined in the "[SourceTrackFinder:plugin]" stanza sub get_fields { my $self = shift; return $self->browser_config->plugin_setting; } sub reconfigure { my $self = shift; my $current_config = $self->configuration; $current_config->{keywords} = $self->config_param('keywords'); } sub configure_form { my $self = shift; my $current_config = $self->configuration; my $source = $self->browser_config; my $html = ''; $html .= div({-class=>'searchbody'}, b('Search: ').textfield(-id => 'plugin_TrackFinderKeywords', -name => $self->config_name('keywords'), -onKeyDown => "Controller.busy();if (typeof(timeOutID) != 'undefined') clearTimeout(timeOutID);timeOutID= setTimeout('Controller.idle();doPluginUpdate()',500)", -override => 1, -value => $current_config->{keywords}, -onBlur => 'clearTimeout(timeOutID)', ), input({-type => 'checkbox', -id => 'stickySearch', -value => 'Stick to top when scrolled' } ), label({-for => 'stickySearch'}, 'Stick to top when scrolled') ); $html .= button(-value => 'Clear', -onClick => "\$('plugin_TrackFinderKeywords').clear();doPluginUpdate()", ); return $html; } sub filter_tracks { my $self = shift; my $track_labels = shift; my $source = shift; my $config = $self->configuration; my @keywords = map {quotemeta($_)} shellwords $config->{keywords}; my @searches = get_fields($self); my @result; LABEL: for my $l (@$track_labels) { do {push @result,$l; next LABEL} if $l =~ /^(plugin|file|http|das)/; my @searched_fields = @searches ? @searches :(qw(key keywords select),"subtrack select labels"); my $aggregate_text = join ' ',map {$source->code_setting($l=>$_)} @searched_fields; $aggregate_text ||= $l; my $labels = $source->subtrack_scan_list($l); $aggregate_text .= " @$labels" if $labels && @$labels; for my $k (@keywords) { next LABEL unless $aggregate_text =~ /$k/i; } push @result,$l; } return @result; } sub hilite_terms { my $self = shift; my $config = $self->configuration; my @keywords = map {quotemeta($_)} shellwords $config->{keywords}; return @keywords; } # Scripts required by the plugin. sub scripts { return qw(scrollfix.js); } # Functions to run once the content has been loaded. sub onLoads { my %loads = (track_page => "scrollfix.setup();"); return %loads; } 1; __END__ =head1 NAME Bio::Graphics::Browser2::Plugin::TrackFinder - Limit list of tracks to those that mention keywords =head1 SYNOPSIS In the appropriate gbrowse configuration file: plugin = TrackFinder [TrackFinder:plugin] category = 1 citation = 1 keywords = 1 =head1 DESCRIPTION This plugin activates a panel above the tracks table that allows the user to filter the tracks according to typed keywords. The fields to search are hard-coded to "key", "citation", "keywords", "subtack select labels". Or they can be configured as shown above Note that this only affects the display of track names. Tracks that were previously turned on will stay on, but their entries will be invisible in the tracks table. The user can still turn them off by clicking on the individual track's configure or (-) buttons. =head1 OPTIONS None =head1 BUGS None known yet. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein Elincoln.stein@gmail.comE. Copyright (c) 2009 Ontario Institute for Cancer Research This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut GBrowse-2.56/conf/plugins/test.pm000444001750001750 114013036764442 17062 0ustar00lsteinlstein000000000000package Bio::Graphics::Browser2::Plugin::test; # $Id: test.pm,v 1.1 2002-03-25 05:31:45 lstein Exp $ # test plugin use strict; use Bio::Graphics::Browser2::Plugin; use CGI qw(param url header p); use vars '$VERSION','@ISA'; $VERSION = '0.10'; @ISA = qw(Bio::Graphics::Browser2::Plugin); sub name { "Test" } sub description { p("This is the Test plugin, used to test that the dump architecture is working properly."); } sub dump { my $self = shift; my $segment = shift; print header('text/plain'); my $dna = $segment->dna; $dna =~ s/(.{1,60})/$1\n/g; print ">$segment\n"; print $dna; } 1; GBrowse-2.56/conf/synteny000755001750001750 013036764442 15444 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/synteny/oryza.synconf.disabled.conf000444001750001750 257513036764442 23051 0ustar00lsteinlstein000000000000[GENERAL] description = BLASTZ alignments for Oryza sativa # The synteny database join = dbi:mysql:database=rice_synteny;host=localhost;user='www-data' # This option maps the relationship between the species data sources, names and descriptions # The value for "name" (the first column) is the symbolic name that gbrowse_syn users to identify each species. # This value is also used in two other places in the gbrowse_syn configuration: # the species name in the "examples" directive and the species name in the .aln file # The value for "conf. file" is the basename of the corresponding gbrowse .conf files. # This value is also used to identify the species configuration stanzas at the bottom of the configuration file. # name conf. file Description source_map = rice rice_synteny "Domesic Rice (O. sativa)" wild_rice wild_rice_synteny "Wild Rice" tmpimages = /gbrowse2/tmp/gbrowse_syn imagewidth = 800 stylesheet = /gbrowse2/css/gbrowse_transparent.css cache time = 1 config_extension = conf # example searches to display examples = rice 3:337601..383524 wild_rice 3:1..400000 zoom levels = 5000 10000 25000 50000 100000 200000 400000 1000000 # species-specific databases [rice_synteny] tracks = EG color = blue [wild_rice_synteny] tracks = EG color = red GBrowse-2.56/conf/synteny/rice_synteny.conf000444001750001750 76613036764442 21154 0ustar00lsteinlstein000000000000[GENERAL] description = Domestic rice chromosome 3 db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/gbrowse_syn/rice # Web site configuration info tmpimages = /gbrowse2/tmp/gbrowse_syn [EG] feature = gene:ensembl glyph = gene height = 10 bgcolor = peachpuff fgcolor = hotpink description = 0 label = 0 category = Transcripts key = ensembl gene balloon hover = Hello, my name is $name! GBrowse-2.56/conf/synteny/wild_rice_synteny.conf000444001750001750 125113036764442 22201 0ustar00lsteinlstein000000000000[GENERAL] description = Wild rice chromosome 3 db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dir $DATABASES/gbrowse_syn/wild_rice # Web site configuration info tmpimages = /gbrowse2/tmp/gbrowse_syn ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### [EG] feature = gene:ensembl glyph = gene height = 10 bgcolor = orange fgcolor = purple description = 0 label = 0 category = Transcripts key = ensembl gene balloon hover = Hello, my name is $name! GBrowse-2.56/conf/themes000755001750001750 013036764442 15220 5ustar00lsteinlstein000000000000GBrowse-2.56/conf/themes/solid_gray_colors000444001750001750 40113036764442 20770 0ustar00lsteinlstein000000000000stylesheet = css/gbrowse_solid.css hilite fill = #E0E6EE hilite outline = blue overview bgcolor = #F2F6FA region bgcolor = #F2F6FA detail bgcolor = #F2F6FA grid color = paleturquoise grid major color = skyblue GBrowse-2.56/conf/themes/transparent_colors000444001750001750 53213036764442 21202 0ustar00lsteinlstein000000000000stylesheet = css/gbrowse_transparent.css hilite fill = beige:0.8 hilite outline = red:0.8 overview bgcolor = white:0.5 region bgcolor = white:0.5 detail bgcolor = white:0.8 grid color = paleturquoise grid major color = skyblue overview grid = 0 region grid = 0 detail grid = 1 GBrowse-2.56/conf/themes/warm_colors000444001750001750 37313036764442 17612 0ustar00lsteinlstein000000000000stylesheet = css/gbrowse_warm.css hilite fill = wheat hilite outline = red overview bgcolor = lightgrey region bgcolor = ivory detail bgcolor = white grid color = paleturquoise grid major color = skyblue GBrowse-2.56/docs000755001750001750 013036764442 13736 5ustar00lsteinlstein000000000000GBrowse-2.56/docs/Gbrowse_Color_Palette.pdf000444001750001750 15373613036764442 21071 0ustar00lsteinlstein000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 2 0 obj << /Length 1 0 R /Filter /FlateDecode >> stream xÚµK“£8…÷ú,§M›7lç1»é‰Ž˜5e“™î$M–U‘óëGÝ‹%®.ÆøF/º:J}Ìgtt…¿¿߃¨ ŠMX¦yIdqFY›à¿Á!ˆ‚Ó¶o’Uéõ¯½ùû— ŽÃ8.2••UXIPÄY˜¥™n¥a^•V«`l5üÛj¥´n\¦úÊ2,¢<ˆ‹0-Ê2øþpÕÊ¢°Œ±M^êÿ?¯°º¶‰â(ÌŠ9¥(ۄѦµ6aœF•²[ÅQ¦›rF+Nª°¯]¹×5´J6Õ—×J’2Œ“DA«" «2JœVi¤¿®"âµTšê¯kS`+\L”ª$ì{×§4|§™îD}(…E9Ô_zXÉŒT¾ÑxóÅgúËÊ´ûl­<×€qìj9Ý“WúB²ñ+ͪ0*³Iïgé.ÖV¦•Œ±†&tÿ¡¯8´•Q\x\Å)¡©¸kBOqJÆRÐhÆQœjhÄú‰ý¶Œ ï&NÍd”x/±J`%£Ä:)‰Â\ÿ›µ’i3ã%V ÍZ¼›†VjfŒb¯ËøI9×x eZ‘ŽRè(V -eZÙžR¶§X%09®R¶«X)´h ¾R_ñZ`,Ó=¼³ô÷=ΦßÐFÍ8‹U2ÎRÐjÆYœ–Bg?Ry´”í,Ójf¬²µ|ƒ•iÅŽV¬8 „øñÊtÏŒ³@‹±߉è,Ð"œ…ÏU©¾¼L_ç,hÃ?WñJ0f¡û\Åk³L«™ç*^ ž« ï,V Ÿ« ç,Ÿ’õ\…B¬³x)pj±Yèhyµ¸1+Móp“ŠuÖÐf& y%thqc–‚V3Îâ®K¡³X-³ •ë,e;‹ÕBg™V\òJà,bÓ—Bg›†3Zà,ÓÕ¼³¢BpÌYC›™4ä• ¡Ÿ†¬¦!jñc–GËNCh53fÙZž4„Vì˜Å*³@ˆ³L÷Ì8 ´Ø4ä;Z\&zÂXåü*´áÓW‚1 µØ4äµÀY¦ÕLòZ†ÐŠw«…i­8gù”¬4D!ÖY¼8 µØ4t´¢‹,ºŸPy]ŠRa)C9Aø­Ù¿º„˜‰ú¹"ï§ä¢T¢ŸFX‰êï¯Ê&xûÓ÷‹'ŸÁ‡R·|ÑF°ÏD‚°­Û·fW·Ýaçö$$š‡T-xº)‹´ºQŽ©#©š†ã )¦¿?¾5‰a¤”ÍË<½é\¤ù~ì»¶9ßPª1ïuë„Q9©h&wª…^íSÑ%Tùvì~èX|ÆÍˆR`*r3ö±HÜŒ—cûõ³ëÜû£Œƒ¼ïù ¥,ÈLäù횊S£në]s&îFŒ³õw£‘rîÆ\än¼&#AùVÏÇær1•IFý¸¼S‘ñ¸éè¥ÀYHd”V®e·oݶӟà IŽò>Ë¢”M9<稵١)•“’·˜Ð›Ý±n}é8 ®šûRÊA¬–VÝ7w¤/m÷³9^ïME'å"Ó*vi±Æ2=}TR®Õ¬§}ûNÏïeTsóG›0!죒"Ô¢§Î›–O@)2‹K ò«>ø¢r=!JÙ„‰Ü ’@ÜÕÇw.+ׯ(ec¦"Ãë5,‰Á§Ç$zs ¸8ÌÊg¬®¦EFY ”™È«£2Ö·%ÁøÚµ»æpÔOxŠŽË+èšá”Ð\lNyKzcÚ×cýå Ì;!ÕìlÒ,ÄÖZ½MsðM*Êek­¥ÌƒOŸ”Ó¾¿Õï{:*Wß—ƒŽ!4+­q%¶Ôê!ü¨_›Ã¹vžÔLj[pS’ê d÷d² K_»VeÚ1ëHÔ = ä FjE—TE§¦§OõûáÕ“›ê¡.%§˜g,(רôrnßönž@pöGC7ýFðŠm-J‹0ÇÉt’HM2㬠¬{lvž)æÝŒóë°c*š4äéº ë‰M†S-\…u83±eØ[ÎÏžšš‰NµÌµäf§M*³ÉuÍNi¿6BL¨!÷UD€Ú˜…ØTÓgÜ“xäƒ],(e£–"ÁrÍPºGÏ—ã÷K·?9Ñ¢Æà{Ô¼j’¡6ê=Eê±™§§['û ·sÏ'ŒG(e¦‘ñhQ¢S›æósx§çž*M³¡ùñÁ#4ªÂMYf$3ez(ÈÓû1Ù·„“Ÿ{Úœ±XŒÞ‚‚m÷ÌÔónÈ;æž6¤\Ùí^Í:-=ùd8Õ²M—3¹7û%\û²?6ß´&¹PûŒ;Ó¤§˜‰Ü—}zRˆm¿µ0T3):;×ߘ(eƒæbóO³/ݱ9¹ÉçL‹R6h!(×S²D—^¶o§}í™z>Áµ›6e)âÛkl”¯õþpúÖ;ßÔ3ʇS>ë§žI¥¯RóN± $ŸlÉ¿¾u§3SËaÞkZ²13™§ klæ“íê~aÚ—™á3ö7ÂHlÓCH-½9·Ú¯ å`Æb[›”a‰I˜ ¹;ùæ¶5ºDl®IÒMãc ·õ€FÊA”«ò!~5mÛýôåäú!¤ÐL0'§wä[wh¾vÍO_P.º!Ù t0sÁ ¤0Ï×é%“ýëŠzÕgÄd‡}!†R¬ ¨?šã˜vØí냖¥\VäPÊ•Ýb#ækçÉIÃø”œ´åê€(ÆÝñš jš‘ËÌJ®W¢”…˜Ë•ÿnõohÞ 8’6ž\í×Ö?šÃ®9zrò ÷"JÙ”±È½8!™ø(¿µ—Ó”ê1¿Z‚Ii£&22œ#!X†GE.Å>!DPÊæL%O“LÛ|t‡íÛþå¥ó•%YV›xÕ.H%I˜ÂÎmžÉ”Uhï“}ÛvÿúF•@cÆ k¢NnÚ2%Ð×´ôPÚ•³ÊNL_Þ] R¦\!Ð-¦ºÅœ¯aÒq”Ë*lÊRîÔ¥§3qMÎO†UÙÇ:•X•µa+±EY/,1àbð-‚d×d-ÌB®$Èç\ùå™h>Á¹(eQFrçM|½Iìðaä­maÎjcÆrN|˜V‰r³3‰Â$Ê‘“d“†UЧjŪ²¸ ]ë© ÁõªÅê’¦"õ}‚Þ¢Z]j¶mírƒ1øéS«Ü¥lÒL¤Ü Q›T¤ž*’1þ¼¬Kw5Ö\lWÓÛ«ç¦i‰G@¢÷ª¢6g!–¢>Nó¤à‰ÑE˜|ŒÚ ¥XŽ’#ÒGã‹Ð{ çÏ¡8„•Ü9"5àb†rœË¢ØœåFî éÙCãznâ°ì_õ¾þŠþô0Õß´aŒ¤Ž¡dådßö¦Ö]Á90®yD)‡Q® èRä±óÒÞÍ8_ä0ÊQŒÍnù¸y•Š'4=´jñË \Z™G¡kh¶½Òúó!ßé0ÊÕyÉ‚þ1æ–p²‰éÊy½ûy9~¶Þäô“.ÝåtH«¼JÏWÆ Ê‡í«Üøt`K™¢ák|úúu,z§ƒ´ux\­ªG©´Ë*‡ËJfHÊ‚<É<û©ÇÞW·oÕM¤úhçúV‘jÑVr/ ºÅµºÖSý~ˆë»¤lX™d}¶zûv(·wµÕM´>¡gQʆ•+¢zv¿;x6$ ½œjÑ9O‡2y´ïÕêÒýá¼=6õ‡g[Ô@®:ÌjÞÑç`¦"O÷}²’˜§ó×±;ùÞ¬·Ì³ì›õÌLnBJ™¶ÛnëÓÞ7e1—ÍGÌ\n>Jtç¡þQÿÙQ¨8•L³°X³R4*EU˜$°z]R“Ò¼¬Ì/gÑz̼øè ©ÍWÊ¥g9ÙÙîÚ][o½©y'ãR›±›’ŒZÜ3 ]OˆJa´‘«ò!îŽõ7:'WCQ®zˆB¤ÎÍcH®'%‡QîÅA^Æi¹â˜l~Ìeûž.¦Ì#Ï’ÓaÕ,%x"ò ùŒ]O2•{ ùY·¯¸§‰Q¡ôU¶Qµ Kݳ›Im}édÃþŠÊl{²˜ËÊl]Ì\¬Îö–ó¦KgfšjY—ÒçrMhº¬2»d}jzXlj&}6å ö)—µ‹OÒ¿ŸõW­Ÿf?éü\oßAÈ…¬DêMú¥:´©·oŸ——_†”Ϙh:œóoŽ~x¦Ir/Î3û˜zܛРP1’›eR†õW ÝÍ8ÿw—1–+º¥Ûˇg¡6*Ë0/Ëg¼Â=Êã0Îsd«*ªÉæõg÷sG—ǰós.=Äér¦b§8oAá–¤6T0åÈgœOq!3±*äøØ®œ˜¼Û®óÇS\Â\.&§~=v§/òeçC¸­¿)Ã(÷Ö ’ñ«&ëŸLJ²”ËN©¸œ¥Ø1­§z·kª7áÊc®%©¸¤•Ü)õZ{JQYFÉQq(…^=ÄåÔ¸§ú°#ïÎ1é6a”%Ï8¡%š8‰Tæ÷2th–Ùdßš¯°U åÒ_s)å~ŒÆ<½5mëù]°e˜ì˜rÅB·˜àÚ}s8ÔžÅÙ»!çWg]ÈT,7IÈöÇôأɺՈFÈÌÄB“¤JÁorn=#H9”rÅA¥§|dL9†sÙò¬ËYÈ-ÏRc§ÞÖUŸ0Æbf: ‚ï ¢@“ð1â¢0Ч¬Ìn²0ªð—3c¹ ÛL¶£é2 kŽé]<Ç´A¹7Ý’B_z.àÜpQ‡òë²g$¶.Kpž‡Ä[#¤§™¡\ÝáÙs3ùMȸ;gÃÒÁ“{W…÷¶?[oX>¤JÁŸ #(»úÜù’r=$J9‚Õ>¥g3hŒ7tY¹ *XïCŒ:äwÇ€KÂMù”(EæÙøKS‰X±O•UÓšnê³§ÚÇ >£ÜÇE,VsRap­Ø:}tïÞÕX?èÒ·¹» •à¯jN:“|Ào« ï„w S™­®á§5=Î ~ÿ?NB endstream endobj 1 0 obj 4711 endobj 3 0 obj << /Type /Page /Parent 4 0 R /Resources 5 0 R /Contents 2 0 R /MediaBox [ 0 0 792 612 ] >> endobj 5 0 obj << /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /Font << /F1.0 6 0 R >> /XObject << /Im70 7 0 R /Im28 8 0 R /Im71 9 0 R /Im58 10 0 R /Im72 11 0 R /Im73 12 0 R /Im110 13 0 R /Im114 14 0 R /Im75 15 0 R /Im117 16 0 R /Im51 17 0 R /Im86 18 0 R /Im78 19 0 R /Im87 20 0 R /Im53 21 0 R /Im93 22 0 R /Im119 23 0 R /Im115 24 0 R /Im116 25 0 R /Im19 26 0 R /Im81 27 0 R /Im82 28 0 R /Im94 29 0 R /Im95 30 0 R /Im37 31 0 R /Im136 32 0 R /Im38 33 0 R /Im131 34 0 R /Im39 35 0 R /Im101 36 0 R /Im5 37 0 R /Im41 38 0 R /Im50 39 0 R /Im140 40 0 R /Im10 41 0 R /Im43 42 0 R /Im35 43 0 R /Im127 44 0 R /Im2 45 0 R /Im65 46 0 R /Im66 47 0 R /Im36 48 0 R /Im4 49 0 R /Im118 50 0 R /Im69 51 0 R /Im7 52 0 R /Im104 53 0 R /Im128 54 0 R /Im105 55 0 R /Im3 56 0 R /Im130 57 0 R /Im84 58 0 R /Im33 59 0 R /Im111 60 0 R /Im74 61 0 R /Im108 62 0 R /Im107 63 0 R /Im112 64 0 R /Im137 65 0 R /Im113 66 0 R /Im60 67 0 R /Im138 68 0 R /Im67 69 0 R /Im88 70 0 R /Im89 71 0 R /Im106 72 0 R /Im90 73 0 R /Im59 74 0 R /Im91 75 0 R /Im92 76 0 R /Im109 77 0 R /Im31 78 0 R /Im96 79 0 R /Im97 80 0 R /Im129 81 0 R /Im56 82 0 R /Im57 83 0 R /Im122 84 0 R /Im25 85 0 R /Im123 86 0 R /Im124 87 0 R /Im98 88 0 R /Im125 89 0 R /Im99 90 0 R /Im6 91 0 R /Im126 92 0 R /Im8 93 0 R /Im47 94 0 R /Im32 95 0 R /Im9 96 0 R /Im49 97 0 R /Im100 98 0 R /Im80 99 0 R /Im102 100 0 R /Im85 101 0 R /Im133 102 0 R /Im139 103 0 R /Im132 104 0 R /Im77 105 0 R /Im29 106 0 R /Im13 107 0 R /Im30 108 0 R /Im12 109 0 R /Im14 110 0 R /Im15 111 0 R /Im16 112 0 R /Im40 113 0 R /Im1 114 0 R /Im76 115 0 R /Im11 116 0 R /Im64 117 0 R /Im54 118 0 R /Im34 119 0 R /Im24 120 0 R /Im55 121 0 R /Im48 122 0 R /Im22 123 0 R /Im79 124 0 R /Im83 125 0 R /Im23 126 0 R /Im135 127 0 R /Im120 128 0 R /Im26 129 0 R /Im103 130 0 R /Im27 131 0 R /Im121 132 0 R /Im17 133 0 R /Im18 134 0 R /Im42 135 0 R /Im134 136 0 R /Im52 137 0 R /Im44 138 0 R /Im61 139 0 R /Im45 140 0 R /Im20 141 0 R /Im62 142 0 R /Im46 143 0 R /Im21 144 0 R /Im63 145 0 R /Im68 146 0 R >> >> endobj 7 0 obj << /Length 147 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 þÕ–Êß @ð„XR endstream endobj 147 0 obj 31 endobj 8 0 obj << /Length 149 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ™ÕدwÏ„5SUUUUUUõ?þÁ{± endstream endobj 149 0 obj 34 endobj 9 0 obj << /Length 150 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þM,`>÷^8–NUUUUUUÕÿ"w Ê endstream endobj 150 0 obj 35 endobj 10 0 obj << /Length 151 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  Éª«ùÿzׄÜGUUUUUUÕ]6n_7 endstream endobj 151 0 obj 34 endobj 11 0 obj << /Length 152 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ¸Æ1²{¯k¦ªªªªªªê² endstream endobj 152 0 obj 33 endobj 12 0 obj << /Length 153 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  uß·BwÏ„¬QUUUUUUõ?ß$ïA endstream endobj 153 0 obj 34 endobj 13 0 obj << /Length 154 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  D–³¢Åö^8ÖLUUUUUUÕÿJpÌ endstream endobj 154 0 obj 35 endobj 14 0 obj << /Length 155 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡~ÿkçx€£+UUUUUUU÷Qa endstream endobj 155 0 obj 33 endobj 15 0 obj << /Length 156 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ²V°ƒ±÷^8ÒEUUUUUUÕÿDx endstream endobj 156 0 obj 35 endobj 16 0 obj << /Length 157 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  H¦±¼iö^8ÒEUUUUUUÕÿ¡}Z¼ endstream endobj 157 0 obj 35 endobj 17 0 obj << /Length 158 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  V·˜‰ö^8ÖLUUUUUUÕÿd/uÿ endstream endobj 158 0 obj 35 endobj 18 0 obj << /Length 159 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ƒÚÚB{¯颪ªªªªªêC΢ endstream endobj 159 0 obj 33 endobj 19 0 obj << /Length 160 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡÷oºãŽ®TUUUUUUÝ_wºÄ endstream endobj 160 0 obj 32 endobj 20 0 obj << /Length 161 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  @f2ž=÷^8²FUUUUUUÕÿ3¶| endstream endobj 161 0 obj 35 endobj 21 0 obj << /Length 162 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡7\ÿkçx€£+UUUUUUU÷V°(± endstream endobj 162 0 obj 33 endobj 22 0 obj << /Length 163 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚí¡ °ÿïE¡˜Þmš5ªªªªªªªþထ endstream endobj 163 0 obj 34 endobj 23 0 obj << /Length 164 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  §uPÿé·{ ¬™ªªªªªªªÿ’°? endstream endobj 164 0 obj 35 endobj 24 0 obj << /Length 165 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  û—ÖÛ0šTUUUUUUÕ?IºÄ endstream endobj 165 0 obj 31 endobj 25 0 obj << /Length 166 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  äf²¢·`4©ªªªªªªªÉJ7U endstream endobj 166 0 obj 32 endobj 26 0 obj << /Length 167 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Šv2­-ö^8ÒEUUUUUUÕÿÿEðá endstream endobj 167 0 obj 35 endobj 27 0 obj << /Length 168 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡ú7ý㎮TUUUUUUÝ¡¢u– endstream endobj 168 0 obj 32 endobj 28 0 obj << /Length 169 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  Ûÿõ¶Œ&UUUUUUUõ`(± endstream endobj 169 0 obj 32 endobj 29 0 obj << /Length 170 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿ{ÔJwÏ„5SUUUUUUõ?ô„£ endstream endobj 170 0 obj 34 endobj 30 0 obj << /Length 171 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þIle÷^8ÖLUUUUUUÕÿÉ£’y endstream endobj 171 0 obj 35 endobj 31 0 obj << /Length 172 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  *±.o;ÀHUUUUUUUÿ²¶Ì¬ endstream endobj 172 0 obj 34 endobj 32 0 obj << /Length 173 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !Éõý*:Ç]©ªªªªªªº¼’— endstream endobj 173 0 obj 33 endobj 33 0 obj << /Length 174 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 °ú×U¨­ÝótQUUUUUUõ?2HN endstream endobj 174 0 obj 34 endobj 34 0 obj << /Length 175 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Þ²‹­ö^8ÖLUUUUUUÕÿ{¶¨s endstream endobj 175 0 obj 35 endobj 35 0 obj << /Length 176 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  e7ÞRù¶¹ªªªªªªª»Žªå endstream endobj 176 0 obj 33 endobj 36 0 obj << /Length 177 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  úÿ«·»çš©ªªªªªªúr!j2 endstream endobj 177 0 obj 33 endobj 37 0 obj << /Length 178 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  û—ÖÛ0ÒFUUUUUUÕ?æÐu– endstream endobj 178 0 obj 31 endobj 38 0 obj << /Length 179 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ûDZ {¯颪ªªªªªêøù…u endstream endobj 179 0 obj 33 endobj 39 0 obj << /Length 180 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  û—3’{¯k¦ªªªªªªêk ¸ endstream endobj 180 0 obj 33 endobj 40 0 obj << /Length 181 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  .kk®óm8òUUUUUUUw»©öü endstream endobj 181 0 obj 35 endobj 41 0 obj << /Length 182 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ¹ c ÷^8ÖLUUUUUUÕÿ‡‡ûÜ endstream endobj 182 0 obj 35 endobj 42 0 obj << /Length 183 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ¶º{¯颪ªªªªªê(9^ endstream endobj 183 0 obj 33 endobj 43 0 obj << /Length 184 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !審;Ç]©ªªªªªªºàä7U endstream endobj 184 0 obj 33 endobj 44 0 obj << /Length 185 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ¢V°‚Ù÷^8ÒEUUUUUUÕÿ}az endstream endobj 185 0 obj 35 endobj 45 0 obj << /Length 186 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 õOío xL endstream endobj 186 0 obj 30 endobj 46 0 obj << /Length 187 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ%Ìd£ì½p¤‹ªªªªªªªÿYäƒ endstream endobj 187 0 obj 36 endobj 47 0 obj << /Length 188 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÄF·ƒ·`4©ªªªªªªªÚ\\ endstream endobj 188 0 obj 32 endobj 48 0 obj << /Length 189 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  C»ëmî{ׄÜGUUUUUUÕ][% endstream endobj 189 0 obj 34 endobj 49 0 obj << /Length 190 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿê*£úížk¦ªªªªªªêuá6ƒ endstream endobj 190 0 obj 35 endobj 50 0 obj << /Length 191 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ¿vª®îwÏ„5SUUUUUUõ?Sñ³ endstream endobj 191 0 obj 34 endobj 51 0 obj << /Length 192 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ç/¸*:Ç]©ªªªªªªº(ü‹' endstream endobj 192 0 obj 33 endobj 52 0 obj << /Length 193 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  þaÍ ·`¤ªªªªªªªY€‘ endstream endobj 193 0 obj 32 endobj 53 0 obj << /Length 194 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿ*¯_Uìžk¦ªªªªªªêž€ú endstream endobj 194 0 obj 35 endobj 54 0 obj << /Length 195 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  þ‘½ô¶Œ&UUUUUUUõâ») endstream endobj 195 0 obj 32 endobj 55 0 obj << /Length 196 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ùï¹Sçx€£+UUUUUUU÷©?×> endstream endobj 196 0 obj 33 endobj 56 0 obj << /Length 197 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚí¡ °ÿÅb™Þmš.ªªªªªªªþl?(­ endstream endobj 197 0 obj 34 endobj 57 0 obj << /Length 198 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Rö²•9÷^8ÒEUUUUUUÕÿ¤ª™ endstream endobj 198 0 obj 35 endobj 58 0 obj << /Length 199 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡÷o«Æ:Çu©ªªªªªªºÁp¶ endstream endobj 199 0 obj 33 endobj 59 0 obj << /Length 200 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  kÛÞÛ0šTUUUUUUÕ?0òá endstream endobj 200 0 obj 31 endobj 60 0 obj << /Length 201 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ} `3÷^8–NUUUUUUÕÿVìf endstream endobj 201 0 obj 35 endobj 61 0 obj << /Length 202 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  Ó•XSývÏ„tQUUUUUUõ?ÎïgÀ endstream endobj 202 0 obj 34 endobj 62 0 obj << /Length 203 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þÝlb÷^8ÖLUUUUUUÕÿ†Qzß endstream endobj 203 0 obj 35 endobj 63 0 obj << /Length 204 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ƒÚÚB{¯k¦ªªªªªªê]Ö¢ endstream endobj 204 0 obj 33 endobj 64 0 obj << /Length 205 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿSݽžÎñGWªªªªªªªîé«Éh endstream endobj 205 0 obj 34 endobj 65 0 obj << /Length 206 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þAÌd ì½p¬™ªªªªªªªÿ>fÅV endstream endobj 206 0 obj 36 endobj 66 0 obj << /Length 207 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿ2*«_¥ìž颪ªªªªªê³ƒø3 endstream endobj 207 0 obj 35 endobj 67 0 obj << /Length 208 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Þ¦µ€ö^8ÖLUUUUUUÕÿ‰U>§ endstream endobj 208 0 obj 35 endobj 68 0 obj << /Length 209 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 þyWÀß @ð.Ôк endstream endobj 209 0 obj 31 endobj 69 0 obj << /Length 210 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  þM£·`¤ªªªªªªª†è½2 endstream endobj 210 0 obj 32 endobj 70 0 obj << /Length 211 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ’ aö¥ðm8rUUUUUUUwœ endstream endobj 211 0 obj 35 endobj 71 0 obj << /Length 212 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  Ú¯ä~»çBÖ¨ªªªªªªú¢œº[ endstream endobj 212 0 obj 33 endobj 72 0 obj << /Length 213 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  þ-Ìg o;ÀHUUUUUUUÿõsö* endstream endobj 213 0 obj 34 endobj 73 0 obj << /Length 214 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  WõŸ>µµ{ dªªªªªªªÿÍY< endstream endobj 214 0 obj 35 endobj 74 0 obj << /Length 215 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿb«á;Çu©ªªªªªªº¹ €‘ endstream endobj 215 0 obj 33 endobj 75 0 obj << /Length 216 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ¦5Ÿáö^8–NUUUUUUÕÿEŸû endstream endobj 216 0 obj 35 endobj 76 0 obj << /Length 217 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !¯°þutŽ8êRUUUUUUu?~Ô endstream endobj 217 0 obj 34 endobj 77 0 obj << /Length 218 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ]Lc!÷^8ÖLUUUUUUÕÿàCN endstream endobj 218 0 obj 35 endobj 78 0 obj << /Length 219 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  s[޽׎5SUUUUUUõ?ª[bw endstream endobj 219 0 obj 32 endobj 79 0 obj << /Length 220 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ%¬e÷^8ÖLUUUUUUÕÿ{Èö* endstream endobj 220 0 obj 35 endobj 80 0 obj << /Length 221 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡7\ÿkçx€£.UUUUUUU÷.(± endstream endobj 221 0 obj 33 endobj 81 0 obj << /Length 222 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1   ®ÿ·»çBÖ¨ªªªªªªú_”Ù° endstream endobj 222 0 obj 33 endobj 82 0 obj << /Length 223 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ”V´¦{¯K§ªªªªªªê‡N† endstream endobj 223 0 obj 33 endobj 83 0 obj << /Length 224 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  zö¶˜·`4©ªªªªªªª·BïA endstream endobj 224 0 obj 32 endobj 84 0 obj << /Length 225 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿVûV@wÏ„5SUUUUUUõ?Kî endstream endobj 225 0 obj 34 endobj 85 0 obj << /Length 226 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  «Šëª*wÏ„5SUUUUUUõ?EÒ® endstream endobj 226 0 obj 34 endobj 86 0 obj << /Length 227 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  &V1¢•÷^8ÖLUUUUUUÕÿºX8 endstream endobj 227 0 obj 35 endobj 87 0 obj << /Length 228 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 þ}Ðß @ð¸yš endstream endobj 228 0 obj 31 endobj 88 0 obj << /Length 229 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 0ÿ.ë¡wa÷<$dÍTUUUUUUý\ÕxÖ endstream endobj 229 0 obj 35 endobj 89 0 obj << /Length 230 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ÒF´‹5ö^8ÒEUUUUUUÕÿ¤B·é endstream endobj 230 0 obj 35 endobj 90 0 obj << /Length 231 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡~ÿkçx€£.UUUUUUU÷¸ÄQa endstream endobj 231 0 obj 33 endobj 91 0 obj << /Length 232 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Â65”{¯Y£ªªªªªªêÅ옔 endstream endobj 232 0 obj 33 endobj 92 0 obj << /Length 233 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  v‹`áóm8rUUUUUUUw}d€ endstream endobj 233 0 obj 35 endobj 93 0 obj << /Length 234 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿ«ä tŽ8êRUUUUUUu?=«³ endstream endobj 234 0 obj 34 endobj 94 0 obj << /Length 235 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡ú7ý㎮TUUUUUUÝ¡¢u– endstream endobj 235 0 obj 32 endobj 95 0 obj << /Length 236 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  .Kk®%óm8rUUUUUUUwbUãt endstream endobj 236 0 obj 35 endobj 96 0 obj << /Length 237 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þLc÷^8ÖLUUUUUUÕÿã¹8Œ endstream endobj 237 0 obj 35 endobj 97 0 obj << /Length 238 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿ†mçx€£.UUUUUUU÷±e€‘ endstream endobj 238 0 obj 33 endobj 98 0 obj << /Length 239 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  «f™…÷m8òUUUUUUUw–iãÝ endstream endobj 239 0 obj 35 endobj 99 0 obj << /Length 240 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿ.k úížk¦ªªªªªªê.(. endstream endobj 240 0 obj 35 endobj 100 0 obj << /Length 241 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ;Ù?›{¯k¦ªªªªªªêZµ¬î endstream endobj 241 0 obj 33 endobj 101 0 obj << /Length 242 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  nëk‘¥òm8rUUUUUUUwkoÓ• endstream endobj 242 0 obj 35 endobj 102 0 obj << /Length 243 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿvªä%uŽ8ºRUUUUUUu?Hª endstream endobj 243 0 obj 34 endobj 103 0 obj << /Length 244 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡ú7ý㎺TUUUUUUÝ\tu– endstream endobj 244 0 obj 32 endobj 104 0 obj << /Length 245 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  Ûÿõ¶Œ´QUUUUUUõgdQa endstream endobj 245 0 obj 32 endobj 105 0 obj << /Length 246 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿ«æ;Çu©ªªªªªªºmE½2 endstream endobj 246 0 obj 33 endobj 106 0 obj << /Length 247 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡Ú~÷㎮TUUUUUUÝÉ;Ð endstream endobj 247 0 obj 32 endobj 107 0 obj << /Length 248 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  "Ö¶¯·`4©ªªªªªªª×FÒ^ endstream endobj 248 0 obj 32 endobj 108 0 obj << /Length 249 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  *Ëb‰õoâÛpä/ªªªªªªªîvC endstream endobj 249 0 obj 36 endobj 109 0 obj << /Length 250 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  "ëiÙ…ñm8rUUUUUUUw kÏ endstream endobj 250 0 obj 35 endobj 110 0 obj << /Length 251 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Ò¦²uö^8ÖLUUUUUUÕÿ{h² endstream endobj 251 0 obj 35 endobj 111 0 obj << /Length 252 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÕÖÔòîy€.ªªªªªªªþ|ײ  endstream endobj 252 0 obj 34 endobj 112 0 obj << /Length 253 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1   ®ÿw½ëBþ¢ªªªªªªê.lÙ° endstream endobj 253 0 obj 33 endobj 113 0 obj << /Length 254 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  þõ¯·»çš©ªªªªªªú> stream xÚíÁ1 þ©ço xãÍ0h endstream endobj 255 0 obj 30 endobj 115 0 obj << /Length 256 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  þ1laëì½p¤‹ªªªªªªªÿ¸=]ü endstream endobj 256 0 obj 36 endobj 116 0 obj << /Length 257 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡÷oºãŽºTUUUUUUݤ¥ºÄ endstream endobj 257 0 obj 32 endobj 117 0 obj << /Length 258 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿºªªWwÏ„5SUUUUUUõ?b «³ endstream endobj 258 0 obj 34 endobj 118 0 obj << /Length 259 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  *KnÕù¶ù‹ªªªªªªª»¾áú¥ endstream endobj 259 0 obj 33 endobj 119 0 obj << /Length 260 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ¸1ªAö^8ÖLUUUUUUÕÿ¡ª| endstream endobj 260 0 obj 35 endobj 120 0 obj << /Length 261 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  kÛÞÛ0ÒFUUUUUUÕ?jÚ;Ð endstream endobj 261 0 obj 31 endobj 121 0 obj << /Length 262 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿb_C;Ç]©ªªªªªªº.Ôк endstream endobj 262 0 obj 33 endobj 122 0 obj << /Length 263 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 þ×Çß @ðê@a¥ endstream endobj 263 0 obj 31 endobj 123 0 obj << /Length 264 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  û—ÖÛ0ÒFUUUUUUÕ?æÐu– endstream endobj 264 0 obj 31 endobj 124 0 obj << /Length 265 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !/ïßEuŽ8ºRUUUUUUu?2^ó endstream endobj 265 0 obj 34 endobj 125 0 obj << /Length 266 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ŽÖ3ŽÅö^8²FUUUUUUÕÿÐ_{± endstream endobj 266 0 obj 35 endobj 126 0 obj << /Length 267 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡·]÷㎺TUUUUUUÝõá endstream endobj 267 0 obj 32 endobj 127 0 obj << /Length 268 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  FöO`Ûì½pdªªªªªªªÿÉ2–ô endstream endobj 268 0 obj 36 endobj 128 0 obj << /Length 269 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  ‚Ƴ¨ ö^8ÖLUUUUUUÕÿK¾ endstream endobj 269 0 obj 35 endobj 129 0 obj << /Length 270 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 þÖÖß @ða6ƒl endstream endobj 270 0 obj 31 endobj 130 0 obj << /Length 271 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  £µÜ§ŠvÏ„¥SUUUUUUõ?ƒeXJ endstream endobj 271 0 obj 34 endobj 131 0 obj << /Length 272 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 ¡—Xÿj:Ç]©ªªªªªªºZ4 n endstream endobj 272 0 obj 33 endobj 132 0 obj << /Length 273 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  (–±”í÷^8²FUUUUUUÕÿ[gdé endstream endobj 273 0 obj 35 endobj 133 0 obj << /Length 274 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  v3´­ö^8ÖLUUUUUUÕÿf²™f endstream endobj 274 0 obj 35 endobj 134 0 obj << /Length 275 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  euTÿowÏ„5SUUUUUUõ?-‰-‘ endstream endobj 275 0 obj 34 endobj 135 0 obj << /Length 276 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ1 ”ë_Åß @ð_wºÄ endstream endobj 276 0 obj 31 endobj 136 0 obj << /Length 277 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  Tæ°÷^8ÖLUUUUUUÕÿ¬FÄ endstream endobj 277 0 obj 35 endobj 137 0 obj << /Length 278 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÁ!àÄëoïŸ(ÞÉxz endstream endobj 278 0 obj 31 endobj 138 0 obj << /Length 279 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ö êmMªªªªªªªêȈÜ" endstream endobj 279 0 obj 33 endobj 139 0 obj << /Length 280 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿ.ßF·ÎñG]ªªªªªªªîï˜+ endstream endobj 280 0 obj 34 endobj 140 0 obj << /Length 281 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿb+ WwÏ„5SUUUUUUõ?þEù endstream endobj 281 0 obj 34 endobj 141 0 obj << /Length 282 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿk¥owÏ„5SUUUUUUõ?=§>> endstream endobj 282 0 obj 34 endobj 142 0 obj << /Length 283 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1  ÿb{U@wÏ„¥SUUUUUUõ?B5 a endstream endobj 283 0 obj 34 endobj 143 0 obj << /Length 284 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !/¶î;Ç]©ªªªªªªºæ-8' endstream endobj 284 0 obj 33 endobj 144 0 obj << /Length 285 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂA  F±ûì½p,ªªªªªªªÿ[0 endstream endobj 285 0 obj 36 endobj 145 0 obj << /Length 286 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚí¡ °½ËÿrÍmš¿¨ªªªªªªº Ç”•T endstream endobj 286 0 obj 34 endobj 146 0 obj << /Length 287 0 R /Type /XObject /Subtype /Image /Width 50 /Height 50 /ColorSpace 148 0 R /BitsPerComponent 8 /Filter /FlateDecode >> stream xÚíÂ1 !ÿÒ*é·ÎñG]ªªªªªªªîìÌ«³ endstream endobj 287 0 obj 34 endobj 289 0 obj << /Length 288 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xÚ}’OHQÇ¿³%B¬e&RðN¶Wí`ŒÝõoʶ¬k¦²Î¾ÙÞÌn%Bˆ.AÖ1ºXÑI:†‚b]"è(‚—í73»îˆÚƒ7ï3¿ÿ¿ß{@](mšz€yÃÉþ(»;>Áê7P‡A+­Xf$‘v™lqdí}…䜛áãõÿ] ‚U€Æ¬ÇמöxÀáû¶iO:¬äÒb“¸M¤’1âWÄg³>žöq†[ ñ2ñMÅ'"()Y'æ±ld4ƒä—‰»2–’'&ßÀSg^™öÐ}8õ¹&›°€åwÀ¥Öš,Ô \V:k²Ý¤;©iÝR;;\‘Œu?ÊåÝV þ°ÿ¼\þûº\ÞC9¾u¥(J•IÒÀëÃ]ýÜàBS˜s_ QP5ûFz¼Úë׋Gõ%«t{3qW°D÷0vz ¼ü \}\ø$€Ôu¡ºmþÀÍ+˜…–ÍÙ¬C–;XØ9:Y„^g±BÞ,Ú\°ACioci]g®©Å·¸(ñL;òz±Úï9ÚAnŒŽÐIó ¨Üê­°4“I÷ÐÝ x#Ã{zwA¼¨j}ƒÎ…Ðþ¤Š¾Q¥óš=˜ò8Ðmèñá Ã(Äo{1±cÚÑd5¾Ué­ÊgÒ·t¶üÆlaȱi"ßÐ\.5æ±”šËÅâ^Å8tph0èk€!‰~D† TÒhd¡‘”»6‚ØÂì±–:>f¤ß&Ÿm×çŠäíxÝA4Ž…¶ƒLþ&ÿ–·ä%ù­ük±¥ªiÄ”¦¬?ûCqÌÕ¸m¥&/¾By#¤Õ‘%iþ 'ËW©¯:ÕXl©Errð'ñ=_—Ü—)Œi7Ò¬›©äê,úF|ÙNšٮͯ6×rm^™Ü ®ÍšUáHWü «Ãÿ5;¿?ÿͰh endstream endobj 288 0 obj 706 endobj 148 0 obj [ /ICCBased 289 0 R ] endobj 290 0 obj << /Length 291 0 R /Length1 12280 /Filter /FlateDecode >> stream xÚ­zy|TÕÝ÷9÷Þ™;ûÜÙ'“;sïÌd¶Ìdf’É6É$¹I&! ;a !,²(B£PA´U´R,.hZ‹[-!" ®Ôæq©Ø¢Ukµ¶h}Õ<íÓ‚­…̼¿s' öõý|Þ?Þ9¹g¿gùžßzrFéÐVD#iéšþuèyÜ5ÇáéZ:¸A¼¯©Éˆv"ĸ._·bÍÿØ{!E%BÔèŠ+7^îžÚw+Bì¿~¶ryÿ²¿A(ô¼_½*t+™—¡| Ê%+×l¸®]ŽPŠhå•k—ö_•YÞ啤ÿšþëÖ©¦P?ò>(‹Wõ¯YÞ~ßm@ùyÝÚõèÝLʧ¡E]èq< í@SQ­Á ¨¿‰ªQz=olDk¡o;úòÂ[Oç_„ºjô8A_ÂÚݨ̓QnC÷æGÑ>ô):›ßŸÿ ¥ÐÍÐãíüŸPNó6س `ÌÕh.£6ä·SaeO£°=ß»­D”E+ÐJ´]…¾mÏ¡·Ñï1»)CI˜§ÍE;Ñèn4„^Âþþ£Î¯Ì¯Fs`«á½Ý°›è/è° ¿€_ÎóùÃù<ÌíGµ¨En¿ýíG?&;A/C8Æð,<—öÓ•y}¾"ú5 u£…ðÆt=ìäô_è5¬a\gãux+Þ_¦Zh Ã*¦æo‚UªïÓ`ýëa¥»ÐÀðô„_¡ßòjì§š©­ÔÚDKÌ Å`þ†üÁüóù߉(àüÓ0k7œÊtÚŽn…õîFGЋè]8«¿¡qÌb;` ‡ñûøs Q&*£ýš^Kï 2ˆ¹Ÿy_Ѩؖ;;_‘ß“-ÿ/Ø=t€“¯P s4¡hêEËë+dú¸D‡ÐQÀîmt½ÆQ{`Ÿ5¸ÏÇ›ðOð(>ŽÿIQG 0g„ÚF=áuœz›vÑn:L—Ó—ÑwÑÒ0w*–)?TR~ÎnÏ-Í-Ë æ®Ï=›ïÎßÿYþ¬Æ «!gÚ:a·3Pœàåh“ŒõBK°ž'ÑSŽÀªžAÏ‚8>Bg€æÎj' ‘ÄiœÁ°ÎVœÅ¸OÃ=p>sñ<ÜWãÍx þ¾Âð~ØÇaGñ3ø5|ÿÂiü„R Š¥œ”Ÿ RÕ a.„~j)µ’ZE­¡n‡p€:H¦FhD7Òít?„!úý6ý{úCú+ÆÅl`¾Ãü’9ΜdN3g¾TpФb¶bŽÒ©L+•)Ÿd¯`Ÿ`O¢aÀøçètéo)ÚHÝEým¡&Ÿ½Òì×TœÄfü$~ú)Ðm%„S$å4n ‘ Jü>¯(xÜ|±«Èé°Û¬³‰3ô:­F­b• †¦0еùÛ‹CÁÅCLÐßÑQFÊþ~¨è¿¤bñUíßì3$.–»‰ßì)AÏËÿ£§Tè)]ì‰91ƒ2e1±Í/½žõ‹#xþŒy¿=ëï‡Æäü9¿KÎë!ïõ b›seV‹Ŷ¡öÁ•;Úga¸£¦)‹aZ2ðjíß¼Ò éÑ6äògÛ†ŠüY¹´õ/š>c^[¶Øëí-‹ áÖ¥þ%CÈß2dŒN¼NÞ¡ëÌy0wYlY?Ú©[æ_¶sDBK“\ÿÂyCtﵘÌaŠ9üÙ!Ǧ_/äÚn»¤qˆ ´÷/ßÑÐìì(“RÿmPêž%°Ôͽó†ðͽ…EÈk/ìb¹¿Ô,^-©ý-þ•;V/ÌÑÌyÃ.ÉÕæïÏö¡é󆋤"¹P;êÜRïPŽ–5—5“´ÞëÜRHÿòÝBý›Ç´r¿Ñ?BÚ=ó".˜Ìäï„e‰KåIü°ÖZ-¯E;–ÖB7øõbØåª!uëâ\¼5¤p~qÇYåûâ›5ý5Êw‘,9΋íyQ^Ðbwƒ£A>´¦p§B9‚çHÓN=“™2ž™Ê}™™ÂgPSf<è<™2yM!x¼ŠÁ‘sÿVtÿû©ú½ó uçÿ‡¾•> zWBÍX']þYð\bCíJJç߫ٛ~Tó¨öý³ê_«_K¼–<¥>•¬d•6«Ãžª¨®*©©TU†‚~©©Â*ý¾`UeuªdŒ©Ð«Æ¦”«C…¤ SÝë»weBÉ–9ôƒ…Øbõ]‘ŠÇ5›»,ùÄÃ/¶TúˆÃµuÙzrõ‚™s¶àÍTi0Þ;° Êw¥¯èϬ˜}y¸ÕUœÐ¥Uµv}}Iû½[Ú¾—[[gŠ+CEÁy -bõÆ>jŒHOÐoù1ú9°‘œ çn—JÏê°R‡÷ê±_…OÚ¦#ïò+¬ß[¬´iiämÔ²ÅKMZOÖ0BQ’&)Öc6lÁùC¡ œH_†œÈ’Ï€¿>:;vŸ•ÀÉ‹:NÔy‚˜ç ôÞ v‹ÁŒF1T†ÓRÕˆS€Uu €"‘©2èG2Âñ)m&öê#,åª\xÝ'r?µö±«wTÞ¶mËí“¶3ÿò¹$¥rüÁd´û_/½•{s^ŒñÖ•Ÿë/{sÏžñ¹­9ª€A0è¦"X;J;©FMï˜ÞqþÉô‰‡­Ò¶içhW«WkVÙVÙ7©7j6Ù6Ùµa•ÃÉj8‡“r8-¬F¯Ð§à°ï´`K3¯õS-~Á =ಡÖ@ ¡VîKsšéX°Ûq S0â^•±)v{5f„Ín.ˆ ^ˆ4&%ˆŒ¢>HÈs2Áá>Ô‡B6  ÉXX—šêÇ5U¢”ŸÚôT<é¯Òéô¢·úê=qçÊñ:>Ý´ñÁûÿ†•¯Äèƒ7Nñ¦“ñd•ÝöòOïþ[64Ût]û-_þî·¸´€M9`3¦MZ‡Þ“ÖÜ~4üZøÕØŸcgbJ´&~}|gü¾øãÑŸÅŸŽ>=z<þRí©è{ñ·k ttr„ò«´'™é^»ËäÓݼg··¢<™`Œ/T‘ð;hEec.3áÊT[× yµ>&aIì¦?’©É>PŠK „™zB^€aßY^q)Ìb’ N¦²‰¤@lUép¬*VDé0DÕÑÊ ®Ô]Bl„ÚÃî0É4ÅVÕ4b‚#kÀ6Ú:Á¨Fª’¥ª*Í)suU¡3Š7„Å)Y˜Y6ßÇ”¦(±Mk×*wþˆ­t.~ìwã¿X¿xgË–Ûöü>$Ú¸±!NÑ^›Î¥S¨UéõçÛ\‰)/•¬W§ÁU†Ù'þ€kÎ?²0‚Ÿ¸éвÿ<ÈÞpþS°†ïáRß*ÕjÝZó•¶ï°U›t›M7˜7[7Ûξ4êg«.W-62/›ßb>QÿɨjP©5'­ÖPj ­t¤9Ó“h%Ï/u[ØÝÊ+)e³^ëvæ¨7÷[ Öêè÷8½à)PoŸ9}fl‚~Ç&äëø‡¿ ".5#…-à ZͲD-FN.r* tÙM<ä1DŒQ)ŸÃy*³>¡l¯Ü<8`Ïz ¡×PKÞ¿YóüM«v5ø#ýäÙ×ÿû…ŸeD> -.__F?ö«'?}ëªåºÞÅüÑWqIçòê™ËÊçu‚÷Î*Í-ѵRM«ÔEš€¤›ü ÄÛÄ>ðÓ^EÐbwšö8SZ,(Ò7«TÚ#†qx„b$µÁíM° ð(ΣP‚ȼÌñ³}i¨²)“RÓØ˜© û`{NnÔYž$< ”UeòW¥*'dZ㘨 7NÙü&«Ýaó†W·>þxtæ{óv&}îR·ÉôM.6žûªáÆñÏyEÛZê¦ÖÖ¼Ñ^ï­ôÇ\6ww¸y¬u|Ë@“šx| ªÎµÐ/‚<³€—0<¿RgKGëΖ[[+V(Šu««5ݺš¾²ö€õ€SÝláⱨ‹±}ÅTp2×\¡†2™£žQQ¡æ¤:„È´È :2iZj®K,b©Æ´aîÜ }òŒ]Á}A*H´®W‘ª{ã m!»e¿)2Gge9{Ҿ˾ÏÎØ‰Žè—8>Þ7ÄÇßš"„Dhªé8 7xªoPTb|B…[~ÒD…Í  †â˜ü%k.hWÒRm~»£oÈWÐÉ")3ÜD!A L^Ð#²ŽNѯ>·éÀ‰žÊfúìKœºD2´üéÇ:‡fØf[tO˜5¦çö5»µÇk1^xwîÁÃKu·èâŽpÛÀÙ@¦`IÀ2x™*÷i}O«]Oað Š&©š í]|Í›môŒR¡®òêÔKѨq'î{àÙ›;KÚ²õ:³Iz—Y=Ékýw_yǦ©n W3ÐëÇ ›“èˆdo³ã¯Xíp9(—ŠKIÊßÄ #øœTï#ô›K\M¼GôG›ø„è¿ v#þh4âw™he(Ép6# 5ÚØdBðhJü‰"±\(š`hr:åÀç²ÏÈ"6“ùZÄ~­Ä‰ÕÇ ³:ÚA{‰;œGȃeãhBªÊä>!Tqv”¹l:¯ºØ>Qaž™r×jmúØE‹©¦òy—ÿ¸^,Ÿœ›6·¢yþÔÝ•³s“xmýUô±Ú*š*ÑTv|o‡/³½ãšÜÊÕ’†çuuWá=ý×­3å,ëju|A‡ßSÀQ 6NŸôëŒM:> –øEÑ)rÓ¼s7/ œ‘áª=âÙ@‰&$[œ¢v"$ˆïsFÂéÁ±n?!|Þ4E¶2 ª†; ¬^`4FI§¯þ¹¥3¶"ðjw¶Yà ¼Æo²)Uç—=Ñ?œ©ð¦€Wà•¼bÕ¢7¥Áö’yâ íÛÛg%ÿ.a1(½Õb·×Ú›\!®NÞkÓx}¾´ÙêóÛ¬~Ÿä›eö–[måI[ÒZ^žôû¼`±=2"«DÕ:È×Ö„4¶rh§Ýþ$ªp/m  Ñ¡º‹Zky¢VÔž<Ê0T]šØ,§Oƒo½Õ7*›*ŽtC"á$Ü5îÈ4®83vÞT¨…zVŹ¢..©LRÕFå%”8›PY UymlÄ`@`¨šB%&”™Å É2 oš¿¢#Æ*ilóØÊêðþuÛYôû»fäZý&^£Îý:åéÌyy¶býÙ¤ EñÎb§Q¡>ÿ‹3ŢΡ£yží>Tý·‘¬‹§°Î µèð=¹ï·zöö™¿®GÔ%‰6D·"Þ!–ØE³î$S§åu»Ì&†f ³Ã®)"4h2'h†p”³@ƒ„€)—²RÍ¥ìS]SqyJûZ´Öƒ·hÛó,¹,Çóêô,ú–¢R¥Ò[’ÑYÏ͘›byrƒ ~±²’~MEÿ–øê¢J‘2‰¨i‘iŠ«ç¦S馚²V>ò<>Æ¿Þ2pŠ“}Lâ§Š%%u|Xô×4ñõ¢¿³ŽŸ"úu¢b:li·±µ³¸Fêìh•jªËJŠ­ F×6Õb¬hktT4 ‚ÃÈN’©„5Ó‰ Ñ×Åï(;QFu”àI’¾]ª®I4ß!¨ j~ÑÎXB …ŒÊ´„,ƒÏ ö9‰W~!ó‰,‘3ÄĘÂv5_Ìæ <[ðIMqÜ×Wž$ÆÔr!ÐŽ“äÛ¤qÁgeÿ³êBwª+*³Ù ¡a…‚ZºkòŠÑÖU³héþj¡if®an-pe³¨N/ÌU-ª´z¯h,«êÍ¥]¬Å=—RtÅ…ß©Ïj Ûæ·µ›»K¿Ûµ/×?)¥rñªêYø`|f´¨&‡fôÐ.—.{3vî­[ÒZ=þþä:ìB…ûúÏôÏQ U¢_H½E®).ê.Ã(FÁËU©„·É«4ñ^ÑGˆ1%–ðu¼(úÁ÷© GX Jc¼,À[šM™‘FGÈȦ*¼¢¦’­ •L1'÷‹js(ž i†0suÑŽœ¬Éu¹m Çq§é‚& ð+ú˜‚r …®°3¯+TùZ9ö |“¼›09•ÿ‹r¼x80)­³Ô«-†È½—±ôÂÊ©=ÙÚ+ë²¹ÙuÒœú_µÔ–ëÆ§xuÕB bp²_W!hÔwÎËC“•+ë0Ïk.ÇÏ;ªÆOt”S< I£ÊüG`3>ú„ü×d·{Iý±šº‹»×¾{Ü~V£°#+ãpÌÖôpŠ:•3UD±æ”J[dËià*)6fZ¬%ÞB±kÂQ3§eg|Žrè:l "m b“rrä b;§1‘U ‘ld4 ±%ú\@²Èf¥ü>T…ˆÁf–m@Ê_S9þòK˜9ÿʱܗ¸·nÙþ;ÖmÜ»;@Ý-¹óワ;‰]oã*|8œ;þ›‡ŸÀBCjÙF>„t@E£RoµºÚ{WѽÇ?  ©4E¨+@(Ám%اâZõ|êdI¼•¯øÀïM²ÑP¬ÓjhEœ‹GRe‚I§QPžbU£Ÿ-f©¥mªÂ Èåk’*‘é‡9BFU•—^“ddÝ+ÐEk÷"/<Ø’0ÍÒaE³%1!*ˆ”UO8°Ä{è+¹ôVSa\$.» ØÍÕ¿¢ýÊ{\Õµ)÷âe©@Jk1/RŒ*-óíxù¯OÕF¤ê–µ9Ó†Öß9² –S?®ÌvÒÇ&GÁ{pV­ÜÖ"Ö~~ü•ÜÓ[mîèò¸Ê?qoø~ >ÖëÒlMÔ­‰Ò{bÆÆÇÿ@}ÿ2ÆN‰áZU •÷~à+–”VôN‡•.V:’ÅRoЪ¢®È©I%Y'Ë5–j½¢A $\R1.–W}öÁ2\FÈN6^åûÀöÿÖ”Â<Š \ÃÑk1ƨ>ˆ´ ˆÔ&¥[¬†Dº¸·h<„ ñÄuß„a[R} ÿßÁ Ò€ö`ۄ敹÷ë› Íð'­Î²Íßßvë–•þIkÕ =-îY9¾wn{ªgÕæ¿~gq…kði±éŸß}è$µèÂ- fí9©ÊRñ^\· onó”ÿå¿Á ¢ãÔö!À9‚¶K“G=¸Æ‡…&R/ê«•¨/­È4³›ó :ZRâe±º-âV7ÝI7åÞãæB”ÕVvE-¡’‚;pø XiâxŸ¬ŽFû¦SNè3gÌñÄŠ/hœoXýä'+ž‚q8aîר¼ê…™@¹ÆkN_稨biéZ)%•‚Sìþ˧÷å,^Uùtü«¥³Œ×Zª¶85ÜC½Ëâ‘ÚöL®aN+å-ÐÚÊüõ*ðr9ªÀ´äµ ¶S}Z¿R·J¿Q»Q·]§‰¨’|ù þàüƒ'!šØ+}¥N¾è ©˜÷ºØ=iƒ¢´E½f=Ò¨`Åz £RfV‘*ÕV]ø¯®¼‹rµ«š+P2„C•¾ü‰C¡uÆ}ÆcFÚØŽ*qe  |ËÙwz l?…ƒ£}Î húZo7¸¾pºÎ|܇!7¹1¹Êå<ó1æ\ c)ˆO>½!ªˆÊƒE“σذƒ¼œ _Mã wÑ–”Ý1! ÈåÂE¿¸&eñ_¸+ð×§Áúñj¯#Ô¾­{nEÓºïlØ·±ê•™S:YÁêk¼¦}úŽï½}èŽÌ=YáÂ\uúY-¥SRË- Öí k´¹ÿÕ_½lNÝÂŽIöÞ6éè£@›Ep.õÌ~0­æJ¥j.öQV*íñ)%­W3‰m4j%W["y¼ÈG%¬ÅNɳ‚[zü”ëש†Q'7>z²Ü;¡¦ñÁ·\ÎW\MÇÇ3òe>b³ù鉻tr]GD[•É/o™\â£ÔÇ)½³½¤Êç²Wn¨,u¬Q(Ô憽‚ÞÛ1~lr¨Í°{ÚëV¥—S—ÑJ…FkMOº‡ÑIhËœ£ß½E1ôˆ4µ›íæ³ó…5ìa#{{Ÿ ô‚r«4u¼Aôëø¨è·‚Wiá­»Šø¢ ›Ó¨QR‚žlôjc,Ò$Œ±X€3r ÀžŠ#œ‰^ˆ—ÉÎw¬ rÂ!FdX&Cî>¾¡̾Š¡ƒŒìo å*(ˆ¨ÂÕ0.üƒXÏ${2·0¾`–¥Š\ Tpƒ%°4ÛfæãÖòi5• ®y *[;{ÑÜ)S}öüWúñ­ÙÈä²¢U2%©ðŽKÙÍVµO­Ü?#”ilØE±Ó‹M,¯#2)˜ ÷#?ú©tYH²ÕhklóTs¹¹¦¹Ž^w¯g¥j·Â´Â±Ò}­úZûužmêmöíž{ѽءbUjuÚ ¬rØYv–Ùãq{Xµ]¥(òù8 y2 bÕj;eÁçLrxX?å†ìS“vù1˜Ú/õ žw:Lé÷DzȉXjàmyÅ*À±Re&â`aÀ„¸£˜¨MâS±˜øRARƒG*£jí‰ÃzGÀÄ|y4’ûP¥Qk ªÜo¥EIz¿ ´ú87?~ÿÚÛa ™Ô´ 0éãI‹Áa¢NõŠf¥€ä/[Jó_(¾øÔa•tK &Ó¶tqÚ[çSªY•AeTYÕI§/â»ÖºÍªQà\25T ]Ã(+ª\ÉdÚ\–,æ‹ù*—ÕGªRKrÊYæŠâ*èQV6Ëìóy}eɪŠbè`õò6½Ó×"ƒÂÄ×…8¥àÔf¬*ÊÆ%9Œd»d\ÒO²)á&íJʂԈiœò¾2ÊôBÍS“Ä Ö'^€ ˜ïsä¾n <ßWȽS¸½ð ËŽF¹Q– > Î-8¸$øнôîÔ…†èB‚¬p.ä::ÖTÊ·U^z$S§×ÖññX®HtçŽ1J¥ŽúSî+ŠUè¨ÜÛåb_/8W¦¢Vk*Ž÷Ó7±®­Ì“ àa~#àRºÝŠà¤óŸ«UJ†JŒÿNÁBúÑÆ( ‡Xq4÷åNã›tÖ5Ñ2?#ôŸ“è×@6$ÀÆù±tÕü"ÌjÎpi$Ö¥ÎwÅæ¯Œm×lÝ;û}ÌÐá¨&ªÑjÓf'˜5jõ,s,©µÎ"hS%”ÙF'x RúYÞd“Ú’j+ÚjÅÖ a+±uÞéå^ê#Gd|´é?'ô­Ø'0¶xmò(/œÀ—ú5a–/ÚT8ãýgÏÒú^À–HĘû¯™w­¯]R_æZa¯½^ÉäŽùRø}·€Uú ÁíÿŠÒªj5.'E ‚"9ÿü»/Ö6„S`¸ÆÔ. u¸+Á& øU‚7ð#ßm=,-tP/Q”v–S˜šeÖh´‹Ùv¨³“¥0§Õ`¬5iÓ&¥FC©©´Zcf)¨4cIÉ{U!‰=ÈRl§U×$y¯)ÄõM:¨ÒÓЫ… 5xÆy4¬Ëù7øheYÛŽ&ä /ÀÒ†„óBZøÆ`¢ü‹ƒ pdömC{«°—¨ÎšÝ0þ6.¾sjÐÏŸÿŠòçÎ\Ù¢÷3x.}·óü±îÝlîsÝÚuÅß-hâ›6½êòEÆÌYŒUrùÙŸdn¸’›=e¥âz(ª/ô'©åä¥rå~Æ>s±åÂÏ¥xyéÛQ7ƒ iÒrHÃÔc( ùjxÌTÊéüÈ3(ÓÈ yòT£&ï@5íF+¡½ˆ¼OÆ.…”‡ñ*É÷}؃÷Qqê ýCFÅ|¡Ø¥ø·ò&VboS]a¯¦K“ÓnÕMÖý\ß¡×ð¬q¡ñ -‚\‡X8}Bû)> uXîažØ—’Ü}·÷´OÚíYµfùú²™k×ô_…¨ÂfóËÑrôm?„$£ú·=ØØƒ›NDðƒ=XjÖãs°”¤‹rÌÉ1"w|¤j‹w)ñßš§Q Tÿ•¢!>F‘¯‡p AîJ~õAÈ„…¤ÈCr7À6n HªBw@þÈo¥ª™µP³jÖBÍZ¨aÐ"(M‡É#Nƒ™uš\JB© JI¹”€ÙPJÈ%R ƒŠyŒ§à™O… ³¸OAK€Ë‡o™&< éñr|“dõˆú“¢þQƒ¨ïàôøJ9Æ’aºþÝéúÖéú¦éúºéúgp= C-YÃúçÂú‘°þá°þú°~0¬/ ÃÛ‡àôøa9þ¡$véÿÙ¥¥KO—þæ.ý¦.ýå]zo—~ òE_ÌëGð–#ÆÝÆ]F¤†ìá]úÝ» îì“å ¡,ì§RB4V-Œà[‡{b|w¸çq¡Ù†oDÃŽ¶¢EÒëQVN7⤜^‡“rûµÃ‰¼¶~¸ñH†OW ¸Ü¸z8ujk‡{.šÕ851fʪHZ6Üx'4—Ç^šM8„â8Õ%(%7ûQJîî›H•Ã=Aè®8 ÍGF0rÛÁK="œK̾Œ0Ps6>¢‚ä£Èõø°ð~É!¼—¸LøCc—0 #üªç´ðBâJáé˜ü£ÙgÉèèœÄ{%­ðÓÄÂC‰[…7ÊÍûRòxwõÈÉžTn…aÖÇGðœaáê™A+\#®Žu K¡z¯dâ±aVâaFâjaZa¦Î¬œt$ž–·óIßìšn¡¡ñu¡> ;Òäõa¡²0yE\Þ^yãd! ÛcŽ¥=傦ÄR™0{»ˆÍÖ°Ul’ ²ÖúY«Ê¬âÀâÑ©4*•J©bT@·*ëHþR”ˆ«’#‰’!1#ç9 ÉßËò„Â* H Œç›‡ðíöÁ&g“¹Ñ”nÏ~K´x"Ž~ÛÏ=tW÷¬yC¹{‡*H&ïîíª"˜ÅÁ·eâOHÒ e/þKÛL¹Þ›ííuvMž>oÒ¶jVõI¤ñ¨’ú¡C÷ÐyªìQÔC‡ªF2lµÜíÖB·Œݲ$!ÝN£„Ü-A–»½NºÚiËŠDä.Š8Ú.wÙ®ˆ“.xaåIx5{(‘{i†pR^wR3$ä–J¥ KcŠt9T‘‚‡RrsâëæX¡yf¡y¦Ü¼àëæx¡y_¡y4Gÿ?ý–·ü¿õ{rÁ}7ÞO¾ø[ìo[Ï⡃+C[—ˆâ¡ï›ø0¸xÉÒ•$í_>tŸyvèFV<´àþoi¾Ÿ4/ðg¡ûÛzæº_Zž^ -?|ò–ÛÚ¾1×­ç¸ý[» 6@溥í[šÛHó-d®62W™ëéy.²·¶U³ZÖËoÃ5×\¶~ýeè¬.<» endstream endobj 291 0 obj 9214 endobj 292 0 obj << /Type /FontDescriptor /Ascent 750 /CapHeight 0 /Descent -250 /Flags 32 /FontBBox [ -167 -414 967 969 ] /FontName /FTFNNI+Times-Roman /ItalicAngle 0 /StemV 0 /MaxWidth 1000 /FontFile2 290 0 R >> endobj 293 0 obj [ 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 722 500 444 ] endobj 6 0 obj << /Type /Font /Subtype /TrueType /BaseFont /FTFNNI+Times-Roman /FontDescriptor 292 0 R /Widths 293 0 R /FirstChar 97 /LastChar 122 /Encoding /MacRomanEncoding >> endobj 4 0 obj << /Type /Pages /Count 1 /Kids [ 3 0 R ] >> endobj 294 0 obj << /Type /Catalog /Pages 4 0 R >> endobj 295 0 obj << /CreationDate (D:20040414150743-04'00') /Creator (Safari) /ModDate (D:20040414150743-04'00') /Producer (Mac OS X 10.3.3 Quartz PDFContext) >> endobj 296 0 obj [ <42c2b158778ef872046f79cebf360eac> <42c2b158778ef872046f79cebf360eac> ] endobj xref 0 297 0000000000 65535 f 0000004807 00000 n 0000000022 00000 n 0000004827 00000 n 0000048862 00000 n 0000004933 00000 n 0000048684 00000 n 0000006937 00000 n 0000007156 00000 n 0000007378 00000 n 0000007601 00000 n 0000007824 00000 n 0000008046 00000 n 0000008269 00000 n 0000008493 00000 n 0000008715 00000 n 0000008939 00000 n 0000009163 00000 n 0000009387 00000 n 0000009609 00000 n 0000009830 00000 n 0000010054 00000 n 0000010276 00000 n 0000010499 00000 n 0000010723 00000 n 0000010943 00000 n 0000011164 00000 n 0000011388 00000 n 0000011609 00000 n 0000011830 00000 n 0000012053 00000 n 0000012277 00000 n 0000012500 00000 n 0000012722 00000 n 0000012945 00000 n 0000013169 00000 n 0000013391 00000 n 0000013613 00000 n 0000013833 00000 n 0000014055 00000 n 0000014277 00000 n 0000014501 00000 n 0000014725 00000 n 0000014947 00000 n 0000015169 00000 n 0000015393 00000 n 0000015612 00000 n 0000015837 00000 n 0000016058 00000 n 0000016281 00000 n 0000016505 00000 n 0000016728 00000 n 0000016950 00000 n 0000017171 00000 n 0000017395 00000 n 0000017616 00000 n 0000017838 00000 n 0000018061 00000 n 0000018285 00000 n 0000018507 00000 n 0000018727 00000 n 0000018951 00000 n 0000019174 00000 n 0000019398 00000 n 0000019620 00000 n 0000019843 00000 n 0000020068 00000 n 0000020292 00000 n 0000020516 00000 n 0000020736 00000 n 0000020957 00000 n 0000021181 00000 n 0000021403 00000 n 0000021626 00000 n 0000021850 00000 n 0000022072 00000 n 0000022296 00000 n 0000022519 00000 n 0000022743 00000 n 0000022964 00000 n 0000023188 00000 n 0000023410 00000 n 0000023632 00000 n 0000023854 00000 n 0000024075 00000 n 0000024298 00000 n 0000024521 00000 n 0000024745 00000 n 0000024965 00000 n 0000025189 00000 n 0000025413 00000 n 0000025635 00000 n 0000025857 00000 n 0000026081 00000 n 0000026304 00000 n 0000026525 00000 n 0000026749 00000 n 0000026973 00000 n 0000027195 00000 n 0000027419 00000 n 0000027643 00000 n 0000027866 00000 n 0000028091 00000 n 0000028315 00000 n 0000028537 00000 n 0000028759 00000 n 0000028982 00000 n 0000029204 00000 n 0000029426 00000 n 0000029652 00000 n 0000029877 00000 n 0000030102 00000 n 0000030326 00000 n 0000030549 00000 n 0000030772 00000 n 0000030992 00000 n 0000031218 00000 n 0000031440 00000 n 0000031664 00000 n 0000031887 00000 n 0000032112 00000 n 0000032333 00000 n 0000032556 00000 n 0000032777 00000 n 0000032998 00000 n 0000033222 00000 n 0000033447 00000 n 0000033669 00000 n 0000033895 00000 n 0000034120 00000 n 0000034341 00000 n 0000034565 00000 n 0000034788 00000 n 0000035013 00000 n 0000035238 00000 n 0000035462 00000 n 0000035683 00000 n 0000035908 00000 n 0000036129 00000 n 0000036352 00000 n 0000036576 00000 n 0000036800 00000 n 0000037024 00000 n 0000037248 00000 n 0000037471 00000 n 0000037697 00000 n 0000037921 00000 n 0000007136 00000 n 0000038977 00000 n 0000007358 00000 n 0000007581 00000 n 0000007804 00000 n 0000008026 00000 n 0000008249 00000 n 0000008473 00000 n 0000008695 00000 n 0000008919 00000 n 0000009143 00000 n 0000009367 00000 n 0000009589 00000 n 0000009810 00000 n 0000010034 00000 n 0000010256 00000 n 0000010479 00000 n 0000010703 00000 n 0000010923 00000 n 0000011144 00000 n 0000011368 00000 n 0000011589 00000 n 0000011810 00000 n 0000012033 00000 n 0000012257 00000 n 0000012480 00000 n 0000012702 00000 n 0000012925 00000 n 0000013149 00000 n 0000013371 00000 n 0000013593 00000 n 0000013813 00000 n 0000014035 00000 n 0000014257 00000 n 0000014481 00000 n 0000014705 00000 n 0000014927 00000 n 0000015149 00000 n 0000015373 00000 n 0000015592 00000 n 0000015817 00000 n 0000016038 00000 n 0000016261 00000 n 0000016485 00000 n 0000016708 00000 n 0000016930 00000 n 0000017151 00000 n 0000017375 00000 n 0000017596 00000 n 0000017818 00000 n 0000018041 00000 n 0000018265 00000 n 0000018487 00000 n 0000018707 00000 n 0000018931 00000 n 0000019154 00000 n 0000019378 00000 n 0000019600 00000 n 0000019823 00000 n 0000020048 00000 n 0000020272 00000 n 0000020496 00000 n 0000020716 00000 n 0000020937 00000 n 0000021161 00000 n 0000021383 00000 n 0000021606 00000 n 0000021830 00000 n 0000022052 00000 n 0000022276 00000 n 0000022499 00000 n 0000022723 00000 n 0000022944 00000 n 0000023168 00000 n 0000023390 00000 n 0000023612 00000 n 0000023834 00000 n 0000024055 00000 n 0000024278 00000 n 0000024501 00000 n 0000024725 00000 n 0000024945 00000 n 0000025169 00000 n 0000025393 00000 n 0000025615 00000 n 0000025837 00000 n 0000026061 00000 n 0000026284 00000 n 0000026505 00000 n 0000026729 00000 n 0000026953 00000 n 0000027175 00000 n 0000027399 00000 n 0000027623 00000 n 0000027846 00000 n 0000028071 00000 n 0000028295 00000 n 0000028517 00000 n 0000028739 00000 n 0000028962 00000 n 0000029184 00000 n 0000029406 00000 n 0000029632 00000 n 0000029857 00000 n 0000030082 00000 n 0000030306 00000 n 0000030529 00000 n 0000030752 00000 n 0000030972 00000 n 0000031198 00000 n 0000031420 00000 n 0000031644 00000 n 0000031867 00000 n 0000032092 00000 n 0000032313 00000 n 0000032536 00000 n 0000032757 00000 n 0000032978 00000 n 0000033202 00000 n 0000033427 00000 n 0000033649 00000 n 0000033875 00000 n 0000034100 00000 n 0000034321 00000 n 0000034545 00000 n 0000034768 00000 n 0000034993 00000 n 0000035218 00000 n 0000035442 00000 n 0000035663 00000 n 0000035888 00000 n 0000036109 00000 n 0000036332 00000 n 0000036556 00000 n 0000036780 00000 n 0000037004 00000 n 0000037228 00000 n 0000037451 00000 n 0000037677 00000 n 0000037901 00000 n 0000038125 00000 n 0000038956 00000 n 0000038145 00000 n 0000039016 00000 n 0000048323 00000 n 0000048345 00000 n 0000048559 00000 n 0000048921 00000 n 0000048972 00000 n 0000049134 00000 n trailer << /Size 297 /Root 294 0 R /Info 295 0 R /ID 296 0 R >> startxref 49225 %%EOF GBrowse-2.56/docs/README.AWS000444001750001750 1312013036764442 15421 0ustar00lsteinlstein000000000000GBrowse Amazon EC2 Image -- Early documentation The development version of GBrowse is located on the private AMI ami-2e48b347, named "GBrowse 2.40 Master". To launch it: 1. Find the image in the AWS Console. 2. Right click and select "Launch Instance" - Launch 1 instance. - Select either the "micro" or "small" instance size. - Select termination protection (good idea) - Select your public/private keypair - Select the WebServer security group (ports 80 and 22 open) 3. Wait for the instance to boot up, as indicated by "running" state in the console instance browser. To access the web server: 1. Identify the public DNS name for the running instance, as indicated in the console. 2. Point your web browse to this DNS name, using: http://XXXX.amazonaws.com/gb2/gbrowse/elegans/ or http://XXXX.amazonaws.com/gb2/gbrowse/yeast To log in: 1. Identify the public DNS name for the running instance 2. ssh to the instance using your keypair file and the user name "gbrowse": ssh -i keypair_file.pem gbrowse@XXXX.amazonaws.com 3. This should give you a command shell on the remote machine. To launch slave processes: 1. While logged in to the running instance, create a .eucarc file in your home directory. It should contain the following: EC2_ACCESS_KEY= EC2_SECRET_KEY= 2. Run the following command: ~/GBrowse/bin/gbrowse_attach_slaves.pl Count is the number of rendering slaves you wish to launch. This will launch the indicated number of GBrowse slave instances and attach them to the running GBrowse process. HOW THE SYSTEM WORKS Filesystem Structure -------------------- All GBrowse-related infrastructure, including libraries and configuration files is mounted on /srv/gbrowse. For example, the master GBrowse.conf script can be found at /srv/gbrowse/etc/GBrowse.conf. Species-specific datasets are mounted at /srv/gbrowse/species/XXXXX, where XXXXX is the name of the species. Within each species directory, you will find the following: species.conf -- Contains the data source definition for this species. tracks.conf -- Contains detailed track configuration for this data source. dbs/ -- SQLite databases for this data source. Source/ -- Source files used to construct the SQLite databases Source/README-- Description of how to get the source and regenerate the SQLite databases (this may be incomplete) bin/ -- Scripts possibly used during the collection and processing of source data. /srv/gbrowse and each of the species mounts all occupy distinct EBS volumes and have a corresponding snapshot. The idea is that by mounting and unmounting the volumes, you can control what data sources are available to GBrowse (and avoid paying for storage for species you don't care about). Here is the current mapping between EBS volumes and snapshots: /srv/gbrowse snap-c43e21aa /srv/gbrowse/species/s_cerevisiae snap-c23e21ac /srv/gbrowse/species/c_elegans snap-c03e21ae After mounting or unmounting a species-specific volume, you should restart GBrowse using /etc/init.d/apache2 restart. The gbrowse_attach_slaves.pl Script ----------------------------------- This script uses the euca2ools command-line tools, which in turn uses Amazon's REST API. The REST API is a lot faster than the SOAP API, so I prefer it. 1. Look up which species volumes are mounted on the currently-running master machine. This is done by inspecting the filesystem mount tables. 2. Find out what EBS snapshots correspond to the mounted volumes.This is done via a series of euca2ools calls. 3. Look up the AMI image for the current GBrowse Slave AMI. This is currently done by inspecting the file /srv/gbrowse/etc/ami_map.txt. 4. Create a new security group for the slave instances that allows network connections between the currently running master instance and the slaves. 5. Launch the desired number of GBrowse slave instances using the AMI identified in step (3), the security group created in step (4), and the EBS snapshots identified in step (2). 6. As soon as the instances are running, update the configuration file /srv/gbrowse/etc/renderfarm.conf so that the running GBrowse process is aware of the slaves. 7. Restart gbrowse. To Do ----- 1. The gbrowse_attach_slaves.pl script should record the instanceIds of the launched instances so that they can be shut down when no longer needed. Ideally this could be done by attaching a tag to the instance -- something like SlaveOf=i-12345, where i-12345 is the ID of the currently running master intance. The challenge is that euca2ools doesn't currently support the tagging API. I have started work on a Perl interface that supports just enough of the tagging API to get this done. 2. There should be a gbrowse_detach_slaves.pl script that will use this recorded slave instance information to terminate one or more of the slaves (or all of them) and deregister them from renderfarm.conf. 3. Using /srv/gbrowse/etc/ami_map.txt to find the slave AMI is a bit awkward. It means that every time we update the slave image we have to fix ami_map.txt and create a new snapshot of the /srv/gbrowse image. It would be better to use the tagging system to mark the latest slave. 4. Web-based interface for mounting and unmounting species data volumes, and controlling the number of atached slaves. GBrowse-2.56/docs/README.tutorial000444001750001750 17313036764442 16576 0ustar00lsteinlstein000000000000After installation, the tutorial will be installed on your system's web site under http://your.site/gbrowse2/tutorial.html GBrowse-2.56/docs/login.sql000444001750001750 417413036764442 15732 0ustar00lsteinlstein000000000000DROP DATABASE IF EXISTS gbrowse_login; CREATE DATABASE gbrowse_login; GRANT ALL PRIVILEGES ON gbrowse_login.* TO 'gbrowse'@'localhost' identified by "gbrowse" WITH GRANT OPTION; use gbrowse_login; DROP TABLE IF EXISTS users; CREATE TABLE users ( userid integer not null PRIMARY KEY auto_increment, gecos varchar(64) not null, email varchar(64) not null UNIQUE, pass varchar(32) not null, remember boolean not null, openid_only boolean not null, confirmed boolean not null, cnfrm_code varchar(32) not null, last_login timestamp not null, created datetime not null ) ENGINE=InnoDB; DROP TABLE IF EXISTS openid_users; CREATE TABLE openid_users ( userid integer not null UNIQUE, openid_url varchar(128) PRIMARY KEY ) ENGINE=InnoDB; DROP TABLE IF EXISTS session; CREATE TABLE session ( userid integer not null PRIMARY KEY auto_increment, username varchar(32) not null, sessionid char(32) not null UNIQUE, uploadsid char(32) not null UNIQUE ) ENGINE=InnoDB; DROP TABLE IF EXISTS favorites; CREATE TABLE favorites ( userid integer not null PRIMARY KEY auto_increment, username varchar(32) not null, favorite varchar(32) not null )ENGINE=InnoDB; DROP TABLE IF EXISTS uploads; CREATE TABLE uploads ( trackid varchar(32) not null PRIMARY key, userid integer not null, path text, title text, description text, imported boolean not null, creation_date datetime not null, modification_date datetime, sharing_policy ENUM('private', 'public', 'group', 'casual') not null, public_count int, data_source text ) ENGINE=InnoDB; DROP TABLE IF EXISTS sharing; CREATE TABLE sharing ( trackid varchar(32) not null, userid integer not null, public boolean ) ENGINE=InnoDB; DROP TABLE IF EXISTS dbinfo; CREATE TABLE dbinfo ( schema_version int(10) not null UNIQUE ) ENGINE=InnoDB; GBrowse-2.56/docs/developer_notes000755001750001750 013036764442 17133 5ustar00lsteinlstein000000000000GBrowse-2.56/docs/developer_notes/README.rearchitecture000444001750001750 2147413036764442 23210 0ustar00lsteinlstein000000000000This document describes the desired architecture for GBrowse version 2.0. 1) CGI Scripts: gbrowse -- interactive search and browsing of genomic regions gbrowse_img -- static images of genomic regions gbrowse_details -- default details page gbrowse_karyotype -- karyotype view for displaying multiple hits, genome-wide trends, etc Typical flow for CGI scripts use Bio::Graphics::Browser; # globals and utilities use Bio::Graphics::Browser::Render::HTML; # UI driver my $globals = Bio::Graphics::Browser->new('/path/to/globals.txt'); # new globals object my $session = $globals->new_session; my $dsn = $globals->update_data_source($session); my $data_source = $globals->create_data_source($dsn); my $render = Bio::Graphics::Browser::Render::HTML->new($data_source,$session); $render->run; exit 0; There is also a shortcut that lets Render do the session management my $globals = Bio::Graphics::Browser->new('/path/to/globals.txt'); # new globals object my $render = Bio::Graphics::Browser::Render::HTML->new($globals); $render->run; ================================================================= 2) Bio::Graphics::Browser This object is used to obtain all global settings. It is also responsible for creating/restore the user session and selecting the data source name. Create a new globals object: $globals = Bio::Graphics::Browser->new('/path/to/globals.txt'); Get the IDs of all valid data sources: @data_sources = $globals->data_sources; Create or retrieve the persistent settings (optionally forcing the ID): $session = $globals->session ([$id]); Create the data source-specific configuration, a Bio::Graphics::Browser::DataSource object: $data_source = $globals->create_data_source($dsn); Get the value of an option in a section name ('general' by default): $setting = $globals->setting('section name' => 'value'); Examples of using setting(): $label = $globals->setting($data_sources[0] => 'description'); $path = $globals->setting($data_sources[0] => 'path'); Find the new data source based on CGI path information and/our the 'source' parameter. This will return the current source if the requested new source is invalid. $dsn = $globals->update_data_source($session); The globals file lists all the data sources as well as browser-wide globals. Some of the globals, such as the stylesheet path, can be overridden by specific data sources. Others can't. This needs to be determined on a case-by-case basis and the logic for this should be embedded in Bio::Graphics::Browser::Render. To simplify organization, there will be two top-level paths, one for config files, and one for htdocs files. If any path configs are given as relative paths, then these top-level paths are used to make them absolute. Note that for efficiency's sake, the Bio::Graphics::Browser object may be cached and reused, provided that its config file hasn't been updated. [GENERAL] # path globals config base = /etc/gbrowse htdocs base = /var/www/htdocs/gbrowse stylesheet = /absolute/path or ./relative/to/docs_base icons = /absolute/path or ./relative/to/docs_base plugins = /absolute/path or ./relative/to/config_base languages = /absolute/path or ./relative/to/config_base # the default DSN default source = HUM77 # session globals session settings = settings # other globals max_segment = 5000000 global1 = setting1 global2 = setting2 # subsequent stanzas are data sources [HUM77] description = Human Build 77 path = /etc/gbrowse/hum77.conf [MouseV3] description = Mouse Test database path = /var/htdocs/gbrowse/conf/mouse_test.conf hide = 1 # hide from popup menu restrict = ## additional authentication options? ================================================================= 3) Bio::Graphics::Browser::Session This object is responsible for persistent per-user settings. It is created by the Bio::Graphics::Browser object based on the session configuration globals. It has the following methods, all of which are in the current Bio::Graphics::Browser::PageSettings object: Create new session from provided arguments: $session = Bio::Graphics::Browser::Session->new(@args); Flush to disk or database: $session->flush; Return per-session ID: $id = $session->id; Retrieve a hash of persistent page settings: $session->page_settings; Get or set the data source DSN: $dsn = $session->source([$new_dsn]); ================================================================= 4) Bio::Graphics::Browser::DataSource This is the data-source specific configuration. It is identical to the Bio::Graphics::BrowserConfig package that is currently defined inside Bio/Graphics/Browser.pm. It supports the methods: labels() overview_tracks() regionview_tracks() karyotype_tracks() authorized() label2type() type2label() style() semantic_setting() semantic_label() etc. Note that for efficiency's sake, the Bio::Graphics::Browser::DataSource objects may be cached and reused, provided that their corresponding config files have not been updated. ADDED 5/4/07 -- I think that the DataSource should be able to manage a cache of database objects. The syntax is: my $biodas_style_handle = $datasource->database('track_label') If track_label is null or not found, the default database is opened. ================================================================= 5) Bio::Graphics::Browser::Render This is the base class for driving the browser. It contains all methods common to the template, HTML and Ajax versions. $render = Bio::Graphics::Browser::Render->new($data_source,$session) The global configuration, the data source configuration, and the session are passed in as separate objects and stored as instance variables. ================================================================= 6) Bio::Graphics::Browser::RenderTracks This class provides methods for generating the images and imagemaps themselves (the core of the application!). $view = Bio::Graphics::Browser::RenderTracks->new($datasource,$page_settings); Create a new view object using information from the provided data source and settings. @requests = $view->request_panels({labels=>[list,of,labels], featurefiles => [list,of,3d party features], deferred => 1 }); This returns a series of CachedTrack objects, which can be interrogated for the GD object, the imagemap, the width and height of the object. If "deferred" is true, then the CachedTrack objects will not contain the data until some time has passed (processing is occurring in the background). Check the CachedTrack's status() method to find out whether the data is ready. Each CachedTrack has a unique request ID associated with it, which you can get by calling its key() method. If a CachedTrack is pending, you can later use this key to generate an equivalent CachedTrack: my $cache = Bio::Graphics::Browser::CachedTrack->new(-base => $directory, -key => $key); if ($cache->status eq 'AVAILABLE') { my $gd = $cache->gd; } The -base is a directory where the cached track stores its state. The server knows how to find the base. THE CLIENT SIDE The client should maintain a series of
    sections corresponding to each of the tracks in the overview, region and detail panels. These sections dynamically open and close, and use the Scriptaculous system of drag-and-drop to reorder themselves. TRANSACTION NOTES Step 1: The client-side controller for the page detects when user actions have changed the current view, and sends a request to the server informing it of this fact. *Note* need to figure out the format of this request -- the information on coordinates is contained in the slider table form and probably easist just to pack this up in serialized form (using prototype's form.serialize()) and send it in. Step 2: The server updates its state and calls RenderPanels->request_panels() to create a series of CachedTrack requests. It sends back to the controller a response that associates the requested track labels with a series of CachedTrack keys. Step 3: The controller now tells various page elements that their data has changed and they need to update themselves. In particular, it should tell each of the track
    s to update themselves using the corresponding CachedTrack key. The track
    s should use an asynchronous request to poll the server until the image and map data are ready. HOW ASYNCHRONOUS CALLS ARE MADE Asynchronous calls need to be consolidated in the server. Currently they are handled in an ad-hoc manner. I suggest that asynchronous calls standardize on a URL like this: /gbrowse/source/async, and that the POSTed requests and responses use JSON format. This provides support for nested hashes, lists of lists, etc, and has nice Perl and Prototype support. GBrowse-2.56/docs/developer_notes/README.sharing_tracks000444001750001750 2502413036764442 23174 0ustar00lsteinlstein00000000000014 June 2009 Notes on what needs to be done at the user interface level to share tracks properly. 1. GBROWSE ACCOUNTS 1a. Use case 1 -- Signing into GBrowse Motivation: Currently when a user logs into gbrowse, he gets an anonymous cookie that provides access to his stored preferences and uploaded files. This means that he loses the information when moving to a different machine or after "cleaning" his cookies. This needs to be supplemented with a sign-in mechanism that identifies the user via a username and password. - When bringing up gbrowse, a "log in/create account" link appears in the upper right corner of the screen. - User clicks on link -- a username/password box appears in dropdown fashion. - User enters username/password and optionally clicks on a "remember me on this computer" checkbox. - User presses "submit" link. - To CANCEL at any point, user presses "cancel" link. - Dropdown box disappears and is replaced by a "Logged in as " message, and a "log out" link. - Screen is refreshed to show users custom settings and tracks. 1b. Use case 2 -- Signing out of GBrowse Motivation: On public computers, people will want to erase their tracks. - User presses "log out" link. - Screen refreshes to show anonymous page. 1c. Use case 3 -- Signing up for new GBrowse account Motivation: Users need a way to create new accounts for themselves. - User presses "log in/create account" link. - Username/password dropdown box appears. There is a "create new account" link inside it. - User presses "create new account". - Box expands to show user "first name (optional)", "last name (optional)", "email address (required)", "password (required)" and "confirm password (required)" links. - User fills out information and submits. - Confirmation appears telling user that an email message has been sent with confirmation code. - Within a few minutes, confirmation email appears in user's inbox. It contains a confirmation code link. - User clicks on link, which takes him to GBrowse, confirms account activation, and logs him in for the first time. 1d. Use case 4 -- User has forgotten his password Motivation: Users are human. - User presses "log in/create account" link. - Dropdown box appears. There is a "forgotten username/password" link inside it. - User clicks this link. Box expands to prompt user for his email address. - User fills in email address and presses submit. An email message with username and a newly-generated password appears. 1e. Use case 4 -- User wants to change his password Motivation: Good idea - User presses "log in/create account" link. - Dropdown box appears. There is a "change password" link inside it. - User clicks this link. Box expands to prompt user for old password, new password and confirm password. - User submits. IMPLEMENTATION NOTES: - Users should be identified in a MySQL database. - Passwords should not be stored in the database in the clear, but instead be hashed using a salt plus a one-way hash algorithm. - When users log in, the db should keep track of when the most recent login, so that admin can clear out old unused accounts. 2. UPLOADING TRACKS INTRO: Logged-in users have access to long-term track storage and configuration. Their tracks are stored as a series of configuration files and databases. The databases are indexed file or mysql-based databases, and not in-memory databases. 2a. Use case 5 -- User creates a new track Motivation: Users want to add their own custom tracks to the genome. - User presses "Manage custom tracks" button. - A new section called "My tracks" drops down. This section lists all previously-created custom tracks, along with track management controls, and has a link marked "New track". - User presses "New track" button. - Section expands to show two controls: a file upload field marked "Upload data file", and a text box marked "View a shared track." - User presses the "Upload data file" field. - The upload data field is replaced by a spinning disk icon, and user is given the message that "Your data is being processed. You will receive an email notification when it is ready for configuration." - When data processing is completed, a new entry for the uploaded data file appears in the section's track management listing. 2b. Use case 5 -- User configures a (new) track Motivation: After uploading a new file, GBrowse guesses at the track configuration using a generic configuration. The user will want to customize this. - User presses the "Manage custom tracks" button. The track management section appears. - Each uploaded file appears as a line in the custom tracks listing, accompanied by icons to manage the following functions "configure", "share" and "delete." - User presses the "configure" icon. This expands the box to show a series of controls to adjust the track configuration. The details of the track configuration need to be worked out, but should build on the work of WebGBrowse (http://webgbrowse.cgb.indiana.edu/webgbrowse/cgi-bin/uploadData) and Sheldon McKay's track config templates (mckays@cshl.edu). - There are three commit controls: "cancel", "preview" and "save". The preview button updates the main gbrowse screen to show the effect of a change, but doesn't save the changes. - User presses "cancel" to leave the previous configuration intact, and "save" to permanently save the changes. 2c. Use case 6 -- User deletes a track Motivation: User wants to permanently remove an uploaded track. - User presses the "Manage custom tracks" button. The track management section appears. - Each uploaded file appears as a line in the custom tracks listing, accompanied by icons to manage the following functions "configure", "share" and "delete." - User presses the "delete" icon. The track disappears in the main gbrowse screen is updated to reflect this fact. 2d. Use case 7 -- User shares a track Motivation: User wants to share a track with friends or with the public. - User presses the "Manage custom tracks" button. The track management section appears. - Each uploaded file appears as a line in the custom tracks listing, accompanied by icons to manage the following functions "configure", "share" and "delete." - User presses the "share" icon. The section expands to show the following two controls: - a checkbox saying "make this track public". - a textbox prompting user to enter email address of someone to share the track with. - If user presses the checkbox, then the track becomes public. Other users can then search for it using the interface described later. - If user presses the "share this track with individuals" link, a textbox appears that prompts him to enter the email address of an individual to share the link with. User types an email address and presses a save3 button (or types ). - The email address converts to plain text, and a new text field appears to prompt for additional email addresses. - The system will send an email message to the designated user containing a link that allows him access to the track. 2e. Use case 8 -- User unshares a track Motivation: User wants to share a track with friends or with the public. - User presses the "Manage custom tracks" button. The track management section appears. - Each uploaded file appears as a line in the custom tracks listing, accompanied by icons to manage the following functions "configure", "share" and "delete." - User presses the "share" icon. - User sees the list of people with whom the track is shared. Each email addresses has a "delete" icon next to it. User presses "delete" button. - To unshare a public track, user unselects the "make this track public" checkbox. 2f. Use case 9 -- Finding a public shared track Motivation: User wants to access a track that was uploaded by a different user. Anyone can access tracks marked public. - User presses the "Manage custom tracks" button. - The track management section appears (see use case 5). User presses the "New track" button. - Section expands to show the "Upload data file" and "Add a shared track" fields. - Next to the latter field is a "Search for public tracks" link. User presses it. - A text field appears. User types in search terms. User can search for following fields: 1) name or email address of the track owner; 2) track title (contents of its "key" configure option); 3) track description (contents of its "citation" configure option). - User presses "search" button or presses . A checkbox list of suggested matches appears. User checks the track(s) that he desires. - User presses the "submit" button to close the section and view shared tracks. 2g. Use case 10 -- Entering a public or private track by its URL Motivation: User enters the known URL of a public or private track. He will get the URL of a private track from the email that is generated when the track owner shares the track with him. A user can only get access to a private track if he is logged in under an authorized email address/account. - User presses the "Manage custom tracks" button. - The track management section appears (see use case 5). User presses the "New track" button. - Section expands to show the "Upload data file" and "Add a shared track" fields. - User pastes URL of a private track into the "Add a shared track" field. - User presses the "submit" button to close the section and view the shared track. Alternative scenarios - If user is not authorized to see this track, he is given an error message. - Instead of pasting the track URL into the field, user can simply click on the link in the email that is sent him when the owner shares the track. 2h. Use case 11 -- Managing shared tracks Motivation: As shared tracks are added, a list of those tracks appears. User can delete them. - In the "Manage custom tracks" section, there is a "Other tracks" section in addition to the "My tracks" section. The "Other tracks" section lists each shared track that is being viewed, along with a "delete" icon. - User presses "delete" icon to remove shared track. - Shared track disappears from gbrowse main section. GBrowse-2.56/docs/example_remote_configs000755001750001750 013036764442 20454 5ustar00lsteinlstein000000000000GBrowse-2.56/docs/example_remote_configs/volvox_local.conf000444001750001750 1647513036764442 24224 0ustar00lsteinlstein000000000000[GENERAL] database = volvox1 aggregators = match BAC{left_end_read,right_end_read/BAC} processed_transcript coding tprofile{tlevel} qtl{signal/peak} chromosome{chromosome_band,centromere/contig} plugins = Aligner RestrictionAnnotator ProteinDumper TestFinder initial landmark = ctgA:1..10000 # the extra left padding makes it easier to see the mRNA labels, # which are printed on the left by the new "gene" glyph pad_left = 60 pad_right = 30 # list of tracks to turn on by default default features = ExampleFeatures Motifs:overview TransChip:region Transcripts Transcripts:overview reference class = Contig # examples to show in the introduction examples = ctgA # "automatic" classes to try when an unqualified identifier is given automatic classes = My_feature Motif show track categories = 0 ### HTML TO INSERT AT VARIOUS STRATEGIC LOCATIONS ### html2 = This is overridden # max and default segment sizes for detailed view max segment = 100000 default segment = 5000 # size of the "region panel" region segment = 20000 # zoom levels zoom levels = 100 200 1000 2000 5000 10000 20000 40000 50000 75000 100000 # colors of the overview, detailed map and key overview bgcolor = lightgrey detailed bgcolor = lightgoldenrodyellow key bgcolor = beige default varying = 1 # DAS reference server das mapmaster = SELF ######################### # Database configuration ######################### [volvox1:database] db_adaptor = Bio::DB::GFF db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox search options = name search, keyword search [volvox2:database] db_adaptor = Bio::DB::GFF db_args = -adaptor memory -gff $ENV{GBROWSE_DOCS}/databases/volvox2 search options = name search [volvox3:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -gff $ENV{GBROWSE_DOCS}/databases/volvox3 search options = name search [volvox4:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox4 search options = none ######################## # Plugin configuration ######################## [Aligner:plugin] alignable_tracks = EST upcase_tracks = CDS Motifs upcase_default = CDS ######################## # Default glyph settings ######################## [TRACK DEFAULTS] glyph = generic height = 10 bgcolor = lightgrey fgcolor = black font2color = blue label density = 25 bump density = 100 # where to link to when user clicks in detailed view link = AUTO ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### [ExampleFeatures] feature = my_feature glyph = generic stranded = 1 bgcolor = blue height = 10 category = Genes balloon hover = sub { my $f = shift; "feature name=".$f->display_name." database=".$f->gbrowse_dbid } das category = example citation = These are undifferentiated features that are displayed using the generic glyph with a bgcolor of blue. key = Example features [Motifs] feature = motif glyph = span height = 5 description = sub { warn shift->attributes('note') } das category = example category = Proteins key = Example motifs [Alignments] database = volvox2 feature = match glyph = segments category = Alignments das category = example key = Example alignments [Alignments:30000] glyph = box [Alignments:45000] glyph = box label = 0 bump = 0 [Clones] feature = BAC glyph = segments_new bgcolor = yellow strand_arrow = 1 description = 1 das category = example category = Alignments key = Fingerprinted BACs [Transcripts] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff category = Genes key = Protein-coding genes [Transcripts:overview] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff height = 12 category = Genes key = Protein-coding genes [CDS] feature = coding glyph = cds category = Genes phase_style = 012 translation = 3frame key = Frame usage [Variation] feature = variation glyph = triangle point = 1 orient = N description = 1 restrict = Order deny,allow deny from all allow from .cshl.edu .ebi.ed.uk require valid-user key = Variations [EST:200] label_position = top [EST] database = volvox4 feature = EST_match:est glyph = segments height = 8 draw_target = 1 true_target = 0 label_position = left # draw_dna = 1 show_mismatch = 1 realign = 1 canonical_strand = 1 bgcolor = sub { my $feature = shift; my $name = $feature->display_name; if ($name =~ /\.5$/) { return 'red'; } else { return 'orange'; } } box_subparts = 0 group_pattern = /\.[53]$/ category = Alignments key = ESTs [TransChip] feature = tprofile database = volvox2 glyph = xyplot graph_type = boxes height = 50 min_score = 0 max_score = 1000 scale = right category = Genes key = Transcriptional Profile [TransChip:region] feature = tprofile database = volvox2 glyph = xyplot graph_type = boxes height = 50 min_score = 0 max_score = 1000 bgcolor = blue scale = right key = Profile [DNA] glyph = dna global feature = 1 height = 40 do_gc = 1 fgcolor = red axis_color = blue strand = both category = Genes link = '' key = DNA/GC Content [Translation] glyph = translation global feature = 1 height = 40 fgcolor = purple start_codons = 0 stop_codons = 1 codontable = 2 category = Proteins translation = 6frame key = 6-frame translation [Translation:30000] hide = 1 [Motifs:overview] feature = motif glyph = span height = 5 description = 0 label = 1 key = Motifs [motif:details] translation = sub { my $value = shift; $value =~ s/(\S{1,60})/$1\n/g; "
    $value
    "; } Note = $value [ProteinDumper:plugin] geneticcode=12 [Linkage] feature = qtl glyph = xyplot graph_type = points bgcolor = black point_symbol = disc height = 50 min_score = 0 max_score = 1 scale = right key = Linkage [Linkage2] feature = qtl color_subparts = 1 glyph = redgreen_box key = Linkage2 [BindingSites] database = volvox2 feature = binding_site key = Binding Sites [CleavageSites] database = volvox3 feature = cleavage_site key = Cleavage Sites [builtin:karyotype] chromosome = chromosome chrom_height = 120 chrom_width = 16 fgcolor = black bgcolor = gneg:white gpos25:silver gpos50:gray gpos:gray gpos75:darkgray gpos100:black gvar:var stalk:#666666 arcradius = 7 key = You should never see this GBrowse-2.56/docs/example_remote_configs/volvox_remote.conf000444001750001750 1611513036764442 24414 0ustar00lsteinlstein000000000000[GENERAL] description = Volvox Example Database db_adaptor = Bio::DB::GFF db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox/ aggregators = match BAC{left_end_read,right_end_read/BAC} processed_transcript coding tprofile{tlevel} qtl{signal/peak} chromosome{chromosome_band,centromere/contig} plugins = Aligner RestrictionAnnotator ProteinDumper TestFinder initial landmark = ctgA:1..10000 renderfarm = 1 # the extra left padding makes it easier to see the mRNA labels, # which are printed on the left by the new "gene" glyph pad_left = 60 pad_right = 30 # list of tracks to turn on by default default features = ExampleFeatures Motifs:overview TransChip:region Transcripts Transcripts:overview reference class = Contig # examples to show in the introduction examples = ctgA # "automatic" classes to try when an unqualified identifier is given automatic classes = My_feature Motif show track categories = 0 ### HTML TO INSERT AT VARIOUS STRATEGIC LOCATIONS ### html2 = This is overridden # max and default segment sizes for detailed view max segment = 100000 default segment = 5000 # size of the "region panel" region segment = 20000 # zoom levels zoom levels = 100 200 1000 2000 5000 10000 20000 40000 50000 75000 100000 # colors of the overview, detailed map and key overview bgcolor = lightgrey detailed bgcolor = lightgoldenrodyellow key bgcolor = beige default varying = 1 # DAS reference server das mapmaster = SELF ######################## # Plugin configuration ######################## [Aligner:plugin] alignable_tracks = EST upcase_tracks = CDS Motifs upcase_default = CDS ######################## # Default glyph settings ######################## [TRACK DEFAULTS] glyph = generic height = 10 bgcolor = lightgrey fgcolor = black font2color = blue label density = 25 bump density = 100 # where to link to when user clicks in detailed view link = AUTO ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### [ExampleFeatures] remote renderer = http://blackmamba:8101 feature = my_feature glyph = generic stranded = 1 bgcolor = blue height = 10 category = Genes das category = example citation = These are undifferentiated features that are displayed using the generic glyph with a bgcolor of blue. key = Example features [Motifs] remote renderer = http://blackmamba:8101 feature = motif glyph = span height = 5 description = 1 das category = example category = Proteins key = Example motifs [Alignments] remote renderer = http://tunno:8101 db_adaptor = Bio::DB::GFF db_args = -adaptor memory -gff $ENV{GBROWSE_DOCS}/databases/volvox2/ feature = match glyph = segments category = Alignments das category = example key = Example alignments [Alignments:30000] glyph = box [Alignments:45000] glyph = box label = 0 bump = 0 [Clones] feature = BAC glyph = segments_new bgcolor = yellow strand_arrow = 1 description = 1 das category = example category = Alignments key = Fingerprinted BACs [Transcripts] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff category = Genes key = Protein-coding genes [Transcripts:overview] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff height = 12 category = Genes key = Protein-coding genes [CDS] feature = coding glyph = cds category = Genes phase_style = 012 translation = 3frame key = Frame usage [Variation] feature = variation glyph = triangle point = 1 orient = N description = 1 restrict = Order deny,allow deny from all allow from .cshl.edu .ebi.ed.uk require valid-user key = Variations [EST:200] label_position = top [EST] remote renderer = http://tunno:8101 db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox4 feature = EST_match glyph = segments height = 8 draw_target = 1 true_target = 0 label_position = left # draw_dna = 1 show_mismatch = 1 realign = 1 canonical_strand = 1 bgcolor = sub { my $feature = shift; my $name = $feature->display_name; if ($name =~ /\.5$/) { return 'red'; } else { return 'orange'; } } box_subparts = 0 group_pattern = /\.[53]$/ category = Alignments key = ESTs [TransChip] feature = tprofile glyph = xyplot graph_type = boxes height = 50 min_score = 0 max_score = 1000 scale = right category = Genes key = Transcriptional Profile [TransChip:region] feature = tprofile glyph = xyplot graph_type = boxes height = 50 min_score = 0 max_score = 1000 bgcolor = blue scale = right key = Profile [DNA] glyph = dna global feature = 1 height = 40 do_gc = 1 fgcolor = red axis_color = blue strand = both category = Genes link = '' key = DNA/GC Content [Translation] glyph = translation global feature = 1 height = 40 fgcolor = purple start_codons = 0 stop_codons = 1 codontable = 2 category = Proteins translation = 6frame key = 6-frame translation [Translation:30000] hide = 1 [Motifs:overview] feature = motif glyph = span height = 5 description = 0 label = 1 key = Motifs [motif:details] translation = sub { my $value = shift; $value =~ s/(\S{1,60})/$1\n/g; "
    $value
    "; } Note = $value [ProteinDumper:plugin] geneticcode=12 [Linkage] feature = qtl glyph = xyplot graph_type = points bgcolor = black point_symbol = disc height = 50 min_score = 0 max_score = 1 scale = right key = Linkage [Linkage2] feature = qtl color_subparts = 1 glyph = redgreen_box key = Linkage2 [BindingSites] db_adaptor = Bio::DB::GFF db_args = -adaptor memory -gff $ENV{GBROWSE_DOCS}/databases/volvox2 feature = binding_site key = Binding Sites [CleavageSites] remote renderer = http://blackmamba:8101 db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox3 feature = cleavage_site key = Cleavage Sites [builtin:karyotype] chromosome = chromosome chrom_height = 120 chrom_width = 16 fgcolor = black bgcolor = gneg:white gpos25:silver gpos50:gray gpos:gray gpos75:darkgray gpos100:black gvar:var stalk:#666666 arcradius = 7 key = You should never see this GBrowse-2.56/docs/example_remote_configs/volvox_slave.conf000444001750001750 1613313036764442 24233 0ustar00lsteinlstein000000000000# note: for this configuration to work, you will need to launch gbrowse slave # servers on ports 8100 & 8101 on localhost. [GENERAL] description = Volvox Example Database database = volvox1 aggregators = match BAC{left_end_read,right_end_read/BAC} processed_transcript coding tprofile{tlevel} qtl{signal/peak} chromosome{chromosome_band,centromere/contig} plugins = Aligner RestrictionAnnotator ProteinDumper TestFinder initial landmark = ctgA:1..10000 # the extra left padding makes it easier to see the mRNA labels, # which are printed on the left by the new "gene" glyph pad_left = 60 pad_right = 30 # list of tracks to turn on by default default features = ExampleFeatures Motifs:overview TransChip:region Transcripts Transcripts:overview reference class = Contig # examples to show in the introduction examples = ctgA # "automatic" classes to try when an unqualified identifier is given automatic classes = My_feature Motif Binding_site Match show track categories = 0 ### HTML TO INSERT AT VARIOUS STRATEGIC LOCATIONS ### html2 = This is overridden # max and default segment sizes for detailed view max segment = 100000 default segment = 5000 # size of the "region panel" region segment = 20000 # zoom levels zoom levels = 100 200 1000 2000 5000 10000 20000 40000 50000 75000 100000 # colors of the overview, detailed map and key overview bgcolor = lightgrey detailed bgcolor = lightgoldenrodyellow key bgcolor = beige default varying = 1 # DAS reference server das mapmaster = SELF ######################## # Named databases ######################## [volvox1:database] db_adaptor = Bio::DB::GFF db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox/ [volvox2:database] db_adaptor = Bio::DB::GFF db_args = -adaptor memory -gff $ENV{GBROWSE_DOCS}/databases/volvox2 [volvox3:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox3 [volvox4:database] db_adaptor = Bio::DB::SeqFeature::Store db_args = -adaptor memory -dsn $ENV{GBROWSE_DOCS}/databases/volvox4 ######################## # Plugin configuration ######################## [Aligner:plugin] alignable_tracks = EST upcase_tracks = CDS Motifs upcase_default = CDS ######################## # Default glyph settings ######################## [TRACK DEFAULTS] glyph = generic height = 10 bgcolor = lightgrey fgcolor = black font2color = blue label density = 25 bump density = 100 # where to link to when user clicks in detailed view link = AUTO ################## TRACK CONFIGURATION #################### # the remainder of the sections configure individual tracks ########################################################### [ExampleFeatures] feature = my_feature glyph = generic stranded = 1 bgcolor = blue height = 10 category = Genes das category = example citation = These are undifferentiated features that are displayed using the generic glyph with a bgcolor of blue. key = Example features [Motifs] feature = motif glyph = span height = 5 description = 1 das category = example category = Proteins key = Example motifs [Clones] feature = BAC glyph = segments_new bgcolor = yellow strand_arrow = 1 description = 1 das category = example category = Alignments key = Fingerprinted BACs [Transcripts] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff category = Genes key = Protein-coding genes [Transcripts:overview] feature = processed_transcript gene glyph = processed_transcript bgcolor = peachpuff height = 12 category = Genes key = Protein-coding genes [CDS] feature = coding glyph = cds category = Genes phase_style = 012 translation = 3frame key = Frame usage [Variation] feature = variation glyph = triangle point = 1 orient = N description = 1 restrict = Order deny,allow deny from all allow from .cshl.edu .ebi.ed.uk require valid-user key = Variations [DNA] glyph = dna global feature = 1 height = 40 do_gc = 1 fgcolor = red axis_color = blue strand = both category = Genes link = '' key = DNA/GC Content [Translation] glyph = translation global feature = 1 height = 40 fgcolor = purple start_codons = 0 stop_codons = 1 codontable = 2 category = Proteins translation = 6frame key = 6-frame translation [Translation:30000] hide = 1 [Motifs:overview] feature = motif glyph = span height = 5 description = 0 label = 1 key = Motifs [motif:details] translation = sub { my $value = shift; $value =~ s/(\S{1,60})/$1\n/g; "
    $value
    "; } Note = $value [ProteinDumper:plugin] geneticcode=12 [BindingSites] database = volvox2 feature = binding_site key = Binding Sites [builtin:karyotype] chromosome = chromosome chrom_height = 120 chrom_width = 16 fgcolor = black bgcolor = gneg:white gpos25:silver gpos50:gray gpos:gray gpos75:darkgray gpos100:black gvar:var stalk:#666666 arcradius = 7 key = You should never see this [CleavageSites] database = volvox3 feature = cleavage_site key = Cleavage Sites [Alignments] database = volvox2 remote renderer = http://localhost:8100 feature = match glyph = segments category = Alignments das category = example key = Example alignments [Alignments:30000] glyph = box [Alignments:45000] glyph = box label = 0 bump = 0 [EST] database = volvox4 remote renderer = http://localhost:8101 feature = EST_match glyph = segments height = 8 draw_target = 1 true_target = 0 label_position = left # draw_dna = 1 show_mismatch = 1 realign = 1 canonical_strand = 1 bgcolor = sub { my $feature = shift; my $name = $feature->display_name; if ($name =~ /\.5$/) { return 'red'; } else { return 'orange'; } } box_subparts = 0 group_pattern = /\.[53]$/ category = Alignments key = ESTs [EST:200] label_position = top # this one uses a slave renderer [TransChip] database = volvox2 feature = tprofile remote renderer = http://localhost:8100 glyph = xyplot graph_type = boxes height = 50 bgcolor = orange min_score = 0 max_score = 1000 scale = right category = Genes key = Transcriptional Profile # this one uses the main renderer [TransChip:region] database = volvox2 feature = tprofile glyph = xyplot graph_type = boxes height = 50 min_score = 0 max_score = 1000 bgcolor = blue scale = right key = Profile GBrowse-2.56/docs/pod000755001750001750 013036764442 14520 5ustar00lsteinlstein000000000000GBrowse-2.56/docs/pod/BIOSQL_ADAPTER_HOWTO.pod000444001750001750 440213036764442 20472 0ustar00lsteinlstein000000000000=head1 CONFIGURATION OF Bio::DB::Das::BioSQL, THE ADAPTER CODE TO BIOPERL-DB BioSQL is a Bioperl-based system for storing record-oriented biological objects, including GenBank/EMBL sequences and PubMed records, in a relational database. GBrowse provides support for viewing sequence annotation data stored in BioSQL. The support is functional, but not heavily tested, so it may still contain bugs. =head2 1. PREREQUISITES =over 4 =item A) GBrowse -- L Make sure that Gbrowse is correctly installed. =item B) Bioperl-db -- L Make sure that you have the latest version of Bioperl-db. =item C) Biosql-schema -- L Make sure that you have the latest version of Bioperl-schema. =item D) Database You need to have a database (MySQL, Postgresql, Oracle) that is supported by the Perl DBI interface. =back =head2 2. CONFIGURING YOUR SYSTEM =over 4 =item A) Create a bioperl database If you plan to use MySQL, run create_mysql_db.pl (it is included in the bioperl-schema distribution). Other databases would use similar SQL commands. =item B) Load data into your bioperl database Take a Genbank file and call the script load_seqdatabase.pl from the bioperl distribution to load the data. For example, load_seqdatabase.pl --host somewhere.edu --dbname biosql \ --namespace bioperl --format genbank \ your_genbank_file The value of "namespace" is arbitrary. =item C) Configure gbrowse to use bioperl-db Point a gbrowse configuration file to this database. See include 06.biosql.conf for an example. The only nontrivial parameters in it are "namespace" and "version". For namespace, use the same value that you specified when you uploaded data. The version number is contained in the Genbank file. =item D) Install the Bio::DB::BioSQL files. Until these files are uploaded into the bioperl CVS, put the attached files on your system in a directory accessible to Perl, for example, into /usr/lib/perl5/site_perl/5.8.1/ =back =head2 3. SUPPORT AND BUG REPORTS Please send requests for help to simonf@cshl.edu Vsevolod (Simon) Ilyushchenko simonf@cshl.edu GBrowse-2.56/docs/pod/CONFIGURE_HOWTO.pod000444001750001750 35062013036764442 17730 0ustar00lsteinlstein000000000000head1 CONFIGURE-HOWTO This document provides information on configuring the Generic Genome Browser (GBrowse), part of the Generic Model Organism Systems Database Project (L). =head2 CONTENTS =over 4 =item A. CREATING NEW DATABASES FROM SCRATCH =item B. ADDING A NEW DATABASE TO THE BROWSER =item C. GENERATING HISTOGRAMS =item D. INTERNATIONALIZATION =item E. AUTHENTICATION AND AUTHORIZATION =item F. DISPLAYING GENETIC AND RH MAPS =item G. CHANGING THE LOCATION OF THE CONFIGURATION FILES =item H. USING DAS (DISTRIBUTED ANNOTATION SYSTEM) DATABASES =item I. THE BioMOBY BROWSER =item J. BIOMOBY SERVICES =item K. FILTERING SEARCH RESULTS =item L. INVOKING GBROWSE URLs =item M. FURTHER INFORMATION =back =head1 A. CREATING NEW DATABASES FROM SCRATCH This section describes how to create new annotation databases from scratch. =head2 A1. The GFF file format GBrowse is based around the GFF file format, which stands for "Gene Finding Format" and was invented at the Sanger Centre. The GFF format is a flat tab-delimited file, each line of which corresponds to an annotation, or feature. Each line has nine columns and looks like this: Chr1 curated CDS 365647 365963 . + 1 Transcript "R119.7" The 9 columns are as follows: =over =item 1 reference sequence This is the ID of the sequence that is used to establish the coordinate system of the annotation. In the example above, the reference sequence is "Chr1". =item 2 source The source of the annotation. This field describes how the annotation was derived. In the example above, the source is "curated" to indicate that the feature is the result of human curation. The names and versions of software programs are often used for the source field, as in "tRNAScan-SE/1.2". =item 3 method The annotation method. This field describes the type of the annotation, such as "CDS". Together the method and source describe the annotation type. =item 4 start position The start of the annotation relative to the reference sequence. =item 5 stop position The stop of the annotation relative to the reference sequence. Start is always less than or equal to stop. =item 6 score For annotations that are associated with a numeric score (for example, a sequence similarity), this field describes the score. The score units are completely unspecified, but for sequence similarities, it is typically percent identity. Annotations that don't have a score can use "." =item 7 strand For those annotations which are strand-specific, this field is the strand on which the annotation resides. It is "+" for the forward strand, "-" for the reverse strand, or "." for annotations that are not stranded. =item 8 phase For annotations that are linked to proteins, this field describes the phase of the annotation on the codons. It is a number from 0 to 2, or "." for features that have no phase. =item 9 group GFF provides a simple way of generating annotation hierarchies ("is composed of" relationships) by providing a group field. The group field contains the class and ID of an annotation which is the logical parent of the current one. In the example given above, the group is the Transcript named "R119.7". The group field is also used to store information about the target of sequence similarity hits, and miscellaneous notes. See the next section for a description of how to describe similarity targets. =back The sequences used to establish the coordinate system for annotations can correspond to sequenced clones, clone fragments, contigs or super-contigs. In addition to a group ID, the GFF format allows annotations to have a group class. This makes sure that all groups are unique even if they happen to share the same name. For example, you can have a GenBank accession named AP001234 and a clone named AP001234 and distinguish between them by giving the first one a class of Accession and the second a class of Clone. You should use double-quotes around the group name or class if it contains white space. =head2 A2. Creating a GFF table The first 8 fields of the GFF format are easy to understand. The group field is a challenge. It is used in three distinct ways: =over =item 1 to group together a single sequence feature that spans a discontinuous range, such as a gapped alignment. =item 2 to name a feature, allowing it to be retrieved by name. =item 3 to add one or more notes to the annotation. =back 1. Using the Group field for simple features For a simple feature that spans a single continuous range, choose a name and class for the object and give it a line in the GFF file that refers to its start and stop positions. Chr3 giemsa heterochromatin 4500000 6000000 . . . Band 3q12.1 2. Using the Group field to group features that belong together For a group of features that belong together, such as the exons in a transcript, choose a name and class for the object. Give each segment a separate line in the GFF file but use the same name for each line. For example: IV curated exon 5506900 5506996 . + . Transcript B0273.1 IV curated exon 5506026 5506382 . + . Transcript B0273.1 IV curated exon 5506558 5506660 . + . Transcript B0273.1 IV curated exon 5506738 5506852 . + . Transcript B0273.1 These four lines refer to a biological object of class "Transcript" and name B0273.1. Each of its parts uses the method "exon", source "curated". Once loaded, the user will be able to search the genome for this object by asking the browser to retrieve "Transcript:B0273.1". The browser can also be configured to allow the Transcript: prefix to be omitted. You can extend the idiom for objects that have heterogeneous parts, such as a transcript that has 5' and 3' UTRs IV curated mRNA 5506800 5508917 . + . Transcript B0273.1; Note "Zn-Finger" IV curated 5'UTR 5506800 5508999 . + . Transcript B0273.1 IV curated exon 5506900 5506996 . + . Transcript B0273.1 IV curated exon 5506026 5506382 . + . Transcript B0273.1 IV curated exon 5506558 5506660 . + . Transcript B0273.1 IV curated exon 5506738 5506852 . + . Transcript B0273.1 IV curated 3'UTR 5506852 5508917 . + . Transcript B0273.1 In this example, there is a single feature with method "mRNA" that spans the entire range. It is grouped with subparts of type 5'UTR, 3'UTR and exon. They are all grouped together into a Transcript named B0273.1. Furthermore the mRNA feature has a note attached to it. *NOTE* The subparts of a feature are in absolute (chromosomal or contig) coordinates. It is not currently possible to define a feature in absolute coordinates and then to load its subparts using coordinates that are relative to the start of the feature. Some annotations do not need to be individually named. For example, it is probably not useful to assign a unique name to each ALU repeat in a vertebrate genome. For these, just leave the Group field empty. 3. Using the Group field to add a note The group field can be used to add one or more notes to an annotation. To do this, place a semicolon after the group name and add a Note field: Chr3 giemsa heterochromatin 4500000 6000000 . . . Band 3q12.1 ; Note "Marfan's syndrome" You can add multiple Notes. Just separate them by semicolons: Band 3q12.1 ; Note "Marfan's syndrome" ; Note "dystrophic dysplasia" The Note should come AFTER the group type and name. 3. Using the Group field to add an alternative name If you want the feature to be quickly searchable by an alternative name, you can add one or more Alias tags. A feature can have multiple aliases, and multiple features can share the same alias: Chr3 giemsa heterochromatin 4500000 6000000 . . . Band 3q12.1 ; Alias MFX Searches for aliases will be both faster and more reliable than searches for keywords in notes, since the latter relies on whole-text search methods that vary somewhat from DBMS to DBMS. =head2 A3. Identifying the reference sequence Each reference sequence in the GFF table must itself have an entry. This is necessary so that the length of the reference sequence is known. For example, if "Chr1" is used as a reference sequence, then the GFF file should have an entry for it similar to this one: Chr1 assembly chromosome 1 14972282 . + . Sequence Chr1 This indicates that the reference sequence named "Chr1" has length 14972282 bp, method "chromosome" and source "assembly". In addition, as indicated by the group field, Chr1 has class "Sequence" and name "Chr". It is suggested that you use "Sequence" as the class name for all reference sequences, since this is the default class used by the Bio::DB::GFF module when no more specific class is requested. If you use a different class name, then be sure to indicate that fact with the "reference class" option (see below). =head2 A4. Sequence alignments There are several cases in which an annotation indicates the relationship between two sequences. One common one is a similarity hit, where the annotation indicates an alignment. A second common case is a map assembly, in which the annotation indicates that a portion of a larger sequence is built up from one or more smaller ones. Both cases are indicated by using the Target tag in the group field. For example, a typical similarity hit will look like this: Chr1 BLASTX similarity 76953 77108 132 + 0 Target Protein:SW:ABL_DROME 493 544 Here, the group field contains the Target tag, followed by an identifier for the biological object. The GFF format uses the notation Class:Name for the biological object, and even though this is stylistically inconsistent, that's the way it's done. The object identifier is followed by two integers indicating the start and stop of the alignment on the target sequence. Unlike the main start and stop columns, it is possible for the target start to be greater than the target end. The previous example indicates that the the section of Chr1 from 76,953 to 77,108 aligns to the protein SW:ABL_DROME starting at position 493 and extending to position 544. A similar notation is used for sequence assembly information as shown in this example: Chr1 assembly Link 10922906 11177731 . . . Target Sequence:LINK_H06O01 1 254826 LINK_H06O01 assembly Cosmid 32386 64122 . . . Target Sequence:F49B2 6 31742 This indicates that the region between bases 10922906 and 11177731 of Chr1 are composed of LINK_H06O01 from bp 1 to bp 254826. The region of LINK_H0601 between 32386 and 64122 is, in turn, composed of the bases 5 to 31742 of cosmid F49B2. =head2 A6. Loading the GFF file into the database Use the BioPerl script utilities bulk_load_gff.pl, load_gff.pl or (if you are brave) fast_load_gff.pl to load the GFF file into the database. For example, if your database is a MySQL database on the local host named "dicty", you can load it into an empty database using bulk_load_gff.pl like this: bulk_load_gff.pl -c -d dicty my_data.gff To update existing databases, use either load_gff.pl or fast_load_gff.pl. The latter is somewhat experimental, so use with care. =head2 A5. Aggregators The Bio::DB::GFF module has a feature known as "aggregators". These are small software packages that recognize certain common feature types and convert them into complex biological objects. These aggregators make it possible to develop intelligent graphical representations of annotations, such as a gene that draws confirmed exons differently from predicted ones. An aggregator typically creates a new composite feature with a different method than any of its components. For example, the standard "alignment" aggregator takes multiple alignments of method "similarity", groups them by their name, and returns a single feature of method "alignment". The various aggregators are described in detail in the Bio::DB::GFF manual page. It is easy to write new aggregators, and also possible to define aggregators on the fly in the gbrowse configuration file. It is suggested that you use the sample GFF files from the yeast, drosophila and C. elegans projects to see what methods to use to achieve the desired results. In addition to the standard aggregators that are distributed with BioPerl, GBrowse distributes several experimental and/or special-purpose aggregators: =over 4 =item match_gap This aggregator is used for GFF3 style gapped alignments, in which there is a single feature of method 'match' with a 'Gap' attribute. This aggregator was contributed by Dmitri Bichko. =item orf This aggregator aggregates raw "ORF" features into "coding" features. It is basically identical to the "coding" aggregator, except that it looks for features of type "ORF" rather than "cds". =item reftranscript This aggregator was written to make the compound feature, "reftranscript" for use with Gbrowse editing software developed outside of the GMOD development group. It can be used to aggregate "reftranscripts" from "refexons", loaded as second copy features. These features, in contrast to "transcripts", are usually implemented as features which cannot be edited and serve as starting point references for annotations added using Gbrowse for feature visualization. Adding features to the compound feature, "reftranscript", can be done by adding to the "part_names" call (i.e. "refCDS"). =item waba_alignment This aggregator handles the type of alignments produced by Jim Kent's WABA program, and was written to be compatible with the C elegans GFF files. It aggregates the following feature types into an aggregate type of "waba_alignment": nucleotide_match:waba_weak nucleotide_match:waba_strong nucleotide_match:waba_coding =item wormbase_gene This aggregator was written to be compatible with the C elegans GFF2 files distributed by the Sanger Institute. It aggregates raw "CDS", "5'UTR", "3'UTR", "polyA" and "TSS" features into "transcript" features. For compatibility with the idiosyncrasies of the Sanger GFF format, it expects that the full range of the transcript is contained in a main feature of type "Sequence". It is strongly recommended that for mirroring C. elegans annotations, you use the "processed_transcript" aggregator in conjunction with the GFF3 files found at: ftp://ftp.wormbase.org/pub/wormbase/genomes/elegans/genome_feature_tables/GFF3 =back IT IS NOT NECESSARY TO USE AGGREGATORS WITH THE CHADO, BIOSQL OR BIO::DB::SEQFEATURE::STORE (GFF3) DATABASES. =head1 B. ADDING A NEW DATABASE TO THE BROWSER Each data source has a corresponding configuration file in the directory gbrowse.conf. Once you've created and loaded a new database, you should make a copy of one of the existing configuration files and modify it to meet your needs. The name of the new configuration file must follow the form: sourcename.conf where "sourcename" is a short word that describes the data source. You can use this name to select the data source when linking to the browser. Just construct a URL that uses "sourcename" as a virtual directory under cgi-bin/gbrowse: http://your.site.org/cgi-bin/gbrowse/sourcename/ (Note: If you don't add the slash at the end, gbrowse will automatically do it for you, since the terminal slash is needed to work around an apparent bug in MSIE's cookie handling.) It is suggested that you use the same name as the database, although this isn't a requirement. (If no "source=" argument is given, gbrowse picks the first configuration file that occurs alphabetically; you can control this by placing numbers in front of the configuration file, as in "01.yeast.conf".) The configuration file is divided into a number of sections, each one introduced by a [SECTION TITLE]. The [GENERAL] section contains settings that are applicable to the entire application. Other sections define tracks to display. I suggest that you begin with one of the example configuration files provided with the distribution and modify it to suit your needs. =head2 B1. The [GENERAL] Section The [GENERAL] section consists of a series of name=value options. For example, the beginning of the yeast.conf sample configuration file looks like this: [GENERAL] description = S. cerevisiae (via SGD Nov 2001) db_adaptor = Bio::DB::GFF db_args = -adaptor dbi::mysql -dsn dbi:mysql:database=yeast;host=localhost aggregators = transcript alignment user = passwd = Each option is a single word or phrase, usually in lower case. This is followed by an equals sign and the value of the option. You can add whitespace around the equals sign in order to increase readability. If a value is very long, you can continue it on additional lines provided that you put a tab or other whitespace on the continuation lines. For example: description = S. cerevisiae annotations via SGD Nov 2001, and converted using the process_sgd.pl script Any lines that begin with a pound sign (#) are considered comments and ignored. During this discussion, you might want to follow along with one of the example configuration files. The following [GENERAL] options are recognized: =over =item * description The description of the database. This will appear in the popup menu that allows users to select the data source and in the header of the page. Don't make it as long as the previous example! (You will want to change this.) =item * db_adaptor Tells GBrowse what database adaptor to use. By using different adaptors you can attach gbrowse to a variety of different databases. Currently the only stable adaptor you can use is Bio::DB::GFF, which is a standard set of adaptors contained in Bioperl. =item * db_args Arguments to pass to the adaptor for it to use when making a database connection. The exact format will depend on the adaptor you're using. For Bio::DB::GFF running on top of a MySQL database use a db_args like the following: db_args = -adaptor dbi::mysql -dsn dbi:mysql:database=;host= replacing and with the database and database host of your choice. For MySQL databases running on the localhost, you can shorten this to just "db_name". If the database requires you to log in with a user name and password, use the following db_adaptor: db_args = -adaptor dbi::mysql -dsn dbi:mysql:database=;host= -user -pass replacing and with the appropriate values. In the example configuration files, we use a username of "nobody" and an empty password. This is appropriate if the database is configured to allow "nobody" to log in from the local machine without using a password. To use the Oracle version of Bio::DB::GFF, use these arguments: db_args = -adaptor dbi::oracle -dsn dbi:oracle:database=db_service Where db_description should be replaced with the name of the desired database service definition. See the documentation for the Perl dbd::Oracle database driver for more information about the -dsn format. To use the in-memory version of Bio::DB::GFF, use these arguments: db_args = -adaptor memory -dir /path/to/directory The indicated directory should contain one or more GFF and FASTA files, distinguished by the filename extensions .gff and .fa respectively. =item * aggregators This option is only valid when used with Bio::DB::GFF adaptors, and lists one or more aggregators to use for complex features. It is possible to declare your own aggregator here using a special syntax described in "B7. Declaring New Aggregators." To disable the default aggregators, leave this setting blank, as in: aggregators= To activate the default aggregators of "transcript," "clone," and "alignment," comment this setting out entirely: # aggregators = =item * user The user name for the gbrowse script to log in under if you are not using "nobody". This is exactly the same as providing the -user option to db_args, and is deprecated. =item * pass The password to use if the database is password protected. This is the same as providing the -pass option to db_args, and is deprecated. =item * stylesheet Location of the stylesheet used to create the GBrowse look and feel. (You probably will not need to change this.) =item * plugins This is a list of plugins that you want to be available from gbrowse. Plugins are a way for third-party developers to add functionality to gbrowse without changing its core source code. Plugins are stored on the gbrowse configuration directory under a subdirectory named "plugins." A good standard list of plugins is: plugins = SequenceDumper FastaDumper RestrictionAnnotator See the contents of conf/plugins and contrib/plugins for more plugins that you can install. =item * quicklink plugins This is a list of plugins that you want to appear as links in the link bar (which includes the [Bookmark this] and [Link to Image] links). Selecting one of these links is equivalent to choosing the plugin from the popup menu and pressing the "Go" button. The popup will continue to appear in the popup menu. =item * plugin_path By default gbrowse searches for plugins in its standard location of conf/plugins. You can store plugins in a non-standard location by providing this option with a space-delimited list of additional directories to search in. =item * buttons URL in which the various graphical buttons used by GBrowse are located. (You will probably not need to change this.) =item * js URL in which the gbrowse javascript helper function files are located. (You will probably not need to change this). =item * tmpimages URL of a writable directory in which GBrowse can write its temporary images. The format is: tmpimages = Where is the directory as it appears as a URL and is the physical path to the directory as it appears to the filesystem. Usually the physical path is just the URL with the DocumentRoot configuration variable prepended to it, in which case only the URL is needed. However, if the URL is defined using an Alias directive, then the path argument is mandatory. The tmpimages option is mandatory. NOTE: The path argument is ignored if gbrowse is running under modperl, because modperl allows the URL to be translated into a physical directory programatically. =item * cachedir This is a writable directory that can be used for caching gbrowse_img-generated images. Defining it will speed up some operations. If not defined gbrowse_img will still work, but will regenerate images from scratch even if they've been used before. It is OK to use the same path as the tmpimages directory. =item * image widths The image widths option controls the set of image sizes to offer the user. Its value is a space-delimited list of pixel widths. The default is probably fine. Note that the height of the image depends on the number of tracks and features, and cannot be controlled. =item * default width The default width is the image width to start off with when the user invokes the browser for the first time. The default is 800. =item * default features The default features option is a space-delimited list of tracks to turn on by default. You will probably need to change this. For example: default features = Genes ORFs tRNAs Centromeres:overview The syntax for annotation plugins is slightly different. To activate an annotation plugin track by default, preface the plugin's name with "plugin:" default features = Genes ORFs Centromeres:overview plugin:RestrictionAnnotator =item * reference class gbrowse needs to know the class of the reference sequences that other features are placed on. The default is Sequence. If you want to use another class, such as Contig, please indicate the class here (if you don't, certain features such as the keyword search will fail): reference class = contig =item * initial landmark This option controls what feature to show when the user first visits a gbrowse database and has not yet performed a search. If not present, gbrowse displays a page with the search area and options, but no overview or panel. Example: initial landmark = Chr1 =item * autocomplete This turns on the autocomplete functionality, which is very rudimentary at the moment. The argument to this option is the relative path of a "nameserver" script that is expected to respond to queries of the type: http://your.server/cgi-bin/nameserver?query=NNNN where "NNNN" is the partial name that the user has typed into the search box. The nameserver should return a line-delimited list of completed names to suggest to the user. Included in this distribution are two example nameserver scripts, gbrowse_gff_autocomplete and gbrowse_seqfeature_autocomplete, which work with the mysql versions of the Bio::DB::GFF and Bio::DB::SeqFeature::Store adaptors, respectively. To have them invoked properly, add the name of the database to the end of the path. For example, if you are using the Bio::DB::GFF adaptor with a database named "dbi:mysql:volvox", then this is what you should put into the configuration file: autocomplete = /cgi-bin/gbrowse_gff_autocomplete/volvox Change this if as appropriate if gbrowse_gff_autocomplete is not installed in /cgi-bin. For javascript security reasons, the nameserver script MUST be running on the same machine as gbrowse. You can work around this using a proxy, if need be. Also note that the scripts do not (currently) allow you to pass a username or password, and do not check that the user is authorized to connect to the database. Please check and change the source code if this is of concern to you (the scripts are *VERY* simple). These scripts will be made more sophisticated in the future. =item * truecolor If this option is present and true, then GBrowse will create 24-bit (truecolor) images. This is mainly useful when using the "image" glyph, which allows you to paste arbitrary images onto the genome map. Do not use this option unless you need it, because it slows down drawing and makes the images much larger. =item * units, unit_divider The units option allows GBrowse to display units on an alternate scale (for example, (centi)Morgans), and the unit_divider provides the converstion factor between base pair units (which is what must be specified in the GFF file) and the specified units. For example if it is known that 5010 base pairs is equal to one Morgan, 5010 would be specified for the unit_divider. Note that if unit_divider is specified, max segment, default segment and and zoom levels will all be interpreted in terms of the specified units. =item * max segment, min segment These options control the size of segments that will be shown in the detailed view. The max segment option sets an upper bound on the maximum size segment that will be displayed on the detailed view. Its value is in the selected units. Above this limit, the user will be prompted to select a smaller region on the birds-eye view. The default is 1,000,000 base pairs. If the user tries to view a segment smaller than the min segment option, then the segment will be resized to be this size. The default is 20 bp. =item * default segment The default segment option sets the width of the segment (bp) that will be displayed when the user clicks on the birds-eye view without previously having set a desired magnification. You may want to adjust this value. =item * zoom levels GBrowse allows unlimited zoom levels. This option selects the width of each level, in bp. For example: zoom levels = 1000 2000 5000 10000 20000 40000 100000 200000 =item * region segment If this configuration option is set, a new "region panel" will appear that is intermediate in size between the overview and the detail panel. The value of this option becomes the initial size of the region panel in base pairs. region segment = 10000 =item * region sizes This contains a space-delimited list of region panel sizes to present to the user in a popup menu: region sizes = 5000 10000 20000 =item * show sources A 0 (false) or 1 (true) value which controls whether or not to show the popup menu displaying the defined data sources. Set this to 0 if you wish for the names of the data sources to be hidden. If not present, this option defaults to 1 (true). Note that all data sources will need to have this option defined in order for it to take effect across all databases. =item * default varying The track selection table will be sorted alphabetically, by default; setting this variable to true will cause the tracks to appear in the same order as they appear in the configuration file. =item * keyword search max By default, gbrowse will limit the number of keyword search results to 1,000. The order in which the 1,000 hits are returned depends on how the database was loaded, and so you may see odd patterns, such as only hits on a particular chromosome being displayed. To raise the limit on keyword search results, set "keyword search max" to the desired maximum value. =item * overview units This option controls the units that will be used on the scale for the birds-eye view display. Possible values are "bp" (base pairs), "k" (kilobases), "M" (megabases), and "G" (gigabases). If this option is omitted, the browser will guess the most appropriate unit. =item * overview bgcolor This is the color for the background of the birds-eye view. =item * selection rectangle color This is the color of the rectangle in the overview and region panels that shows where on the overview the detail panel represents. The default is red. =item * cache_overview This option will cause the overview images to be cached on disk for a period of time. This may improve performance if you are placing many complex tracks into the overview. The value is the number of hours to keep the cached copy of the overview image before refreshing it (default = don't cache). You can freshen the cache and force cached copies to be ignored by touching the configuration file or by calling gbrowse with the CGI option nocache=1. =item * detailed bgcolor This is the color for the background of the detailed view. =item * request timeout This is the timeout value for requests. If a user requests a large region and the request takes more than the indicated number of seconds, then the request will timeout and the user will be advised to choose a smaller region. The default is 60 seconds (one minute). You can make the timeout longer or shorter than this. =item * head This is content to insert into the HTML section. It is the appropriate place to stick JavaScript code, etc. It can be a code reference if you wish. =item * header_template This give the name of a Template Toolkit template file to print at the top of the browser page. This file should contain any valid Template Toolkit syntax (including regular HTML). The header template file needs to be placed in the gbrowse template folder (ex: /usr/local/apache/conf/gbrowse.conf/templates/default/) It is also possible to place an anonymous Perl subroutine here. The code will be invoked during preparation of the page and must return a string value of the header template file name. See COMPUTED OPTIONS for details. Example: header = header.tt2 =item * header (deprecated) The header option has been replaced by header_template. It will still work for the time being but it is encouraged that you check out Template Toolkit and look at using that instead. This is a header to print at the top of the browser page. It is any valid HTML, and can span multiple lines provided that the continuation lines begin with white space. It is also possible to place an anonymous Perl subroutine here. The code will be invoked during preparation of the page and must return a string value to use as the header. See COMPUTED OPTIONS for details. Example: header =

    Welcome to the Volvox Sequence Page

    =item * footer_template This give the name of a Template Toolkit template file to print at the top of the browser page. This file should contain any valid Template Toolkit syntax (including regular HTML). The footer template file needs to be placed in the gbrowse template folder (ex: /usr/local/apache/conf/gbrowse.conf/templates/default/) It is also possible to place an anonymous Perl subroutine here. The code will be invoked during preparation of the page and must return a string value of the footer template file name. See COMPUTED OPTIONS for details. Example: footer = footer.tt2 =item * footer (deprecated) The footer option has been replaced by footer_template. It will still work for the time being but it is encouraged that you check out Template Toolkit and look at using that instead. This is a footer to print at the top of the browser page. It is any valid HTML, and can span multiple lines provided that the continuation lines begin with white space. It is also possible to place an anonymous Perl subroutine here. The code will be invoked during preparation of the page and must return a string value to use as the header. See COMPUTED OPTIONS for details. Example: footer =
    For the source code for this browser, see the Generic Model Organism Database Project. For other questions, send mail to lstein@cshl.org.
    =item * examples You can provide GBrowse with some canned examples of "interesting regions" for the user to click on. The examples option, if present, provides a space-delimited list of interesting regions. For example: examples = II NPY1 NAB2 Orf:YGL123W =item * automatic classes When the user types in a search string that is not qualified by a class (as in EST:yk1234.5), GBrowse will automatically search for a matching feature of class "Sequence". You can have it search for the name in other classes as well by defining the "automatic classes" option. Example: automatic classes = Symbol Gene Clone When the user types in "hb3", the browser will search first for a Sequence feature of class hb3, followed in turn by matching features in Symbol, Gene and Clone. The search stops when the first match is found. Otherwise, the browser will proceed to a full text search of all the comment fields. =item * search attributes (Bio::DB::SeqFeature::Store adaptor only) When the browser has searched the name and alias of features without success, it will do a whole database keyword search by calling the database's search_notes() method. By default this will search the text of all attributes, including such things as protein sequence. The Bio::DB::SeqFeature::Store database is a bit smarter about searching, and will only, by default, search attributes named "Note". You can expand the search by giving a list of attribute names to the "search attributes" option. =item * remote sources This option allows you to add remote annotation sources to the menu of such sources at the bottom of the main window. The format is: remote sources = "Menu Label 1" http://url1.host.com/etc/etc "Menu Label 2" http://url2.host.com/etc/etc =item * instructions, search_instructions, navigation_instructions You may override the default instructions (as defined in the language-specific configuration files in conf/lang) by setting these options. For example: instructions = "Type in the name of a contig or clone." =item * no search If you don't want the "Landmark or Region" textbox to appear, set this to true. The user will still be able to search the database by appending q= to the URL. no search = 1 =item * no autosearch If this option is set to a true value, then the user's previous search will not be automatically re-executed the next time he visits gbrowse. Instead, the previous search will be pasted into the "Landmark or Region" box and the user will have to press "Search" to reexecute it. =item * instructions section =item * search section =item * overview section =item * region section =item * details section =item * tracks section =item * display_settings section =item * upload_tracks section These options control which sections are displayed and whether they are initially open or collapsed. Their values are one of: open Show the section initially open closed Show the section initially collapsed off Do not show the section at all For example "instructions section = closed" will initially show the instructions section in collapsed form when the user visits gbrowse for the first time. "upload_tracks section = off" will disable the uploads section entirely. Note that turning off the details section will effectively disable gbrowse, but you might want to do this if you want to show the overview section only. Turning off the search section will also disable the navigation buttons. If you want to disable searching selectively, you should use the "no search" option instead. =item * html1, html2, html3, html4, html5, html6 These options allow you to insert HTML into the GBrowse page at strategic places. Eventually this will be replaced with an HTML template system, but for now, this is the best we have.
    OptionWhere it goes
    headerbetween the top and the instructions
    html1 between the instructions and the navigation bar
    html2 between the navigation bar and the overview
    html3 between the overview and the detail view
    html4 between the detail view and the data source panel
    html5 between the data source panel and the track list
    html6 between the track list and the annotation upload
    footerbetween the annotation upload and the bottom
    These can be code references. One useful thing to do is to use the language translator to insert language-specific HTML. Here's an example provided by Marc Logghe: html2 = sub { my $go = $main::CONFIG->tr('Go'); return qq(
    Dump:
    ); } If you use a coderef for the html options, the subroutine is passed two arguments. The first argument is a Bio::Das::SegmentI object (see the manual page for Bio::DB::GFF::RelSegment for details). The second argument is a hashref containing the user's settings for the current page. =item * keystyle, empty_tracks These two general options control the appearance of the keys printed on the detailed view. keystyle takes one of two values "between" or "beneath". keystyle = between Print the track labels between the tracks themselves. keystyle = beneath Print the track labels at the bottom of the detailed view. The "empty_tracks" option controls what to do when a track has no features in it. Possible values are: empty_tracks = key Print just the key (the track label). empty_tracks = suppress Suppress the track completely. empty_tracks = line Draw a solid line across the track. empty_tracks = dashed Draw a dashed line across the track. The default value is "key." =item * background, postgrid These two options can be used to place custom background images in the details panel and are useful for advanced operations such as colorizing the panel to show gaps in the assembly. Either option accepts either the path to a graphics file to be tiled onto the background, or a callback subroutine. In the case of the latter the callback will passed a two argument list consisting of the GD::Image object and the Bio::Graphics::Panel object. This gives the callback a chance to draw on top of the background using GD library calls. The only difference between the two options is the time that they are applied relative to the grid that shows base pair coordinates. The background option is invoked before the grid is drawn so that the grid appears on top of it. The postgrid option is invoked after the grid is drawn, so that anything the option draws appears on top of the grid. See http://sourceforge.net/mailarchive/message.php?msg_id=12116755 for an example of using this feature to show assembly gaps as vertical gray regions. =item * show track categories If this option is set to a true value, then tracks that have been assigned to categories (using the "category" option described later), will have their categories included in their labels. For example, a track of key "Protein matches" and category "vertebrate" will be displayed in a track labeled "Protein match (vertebrate)". The default is false. =item * das mapmaster This option, which should appear somewhere in the [GENERAL] section, indicates that the database should be made available as a DAS source. The value of the option corresponds to the URL of the DAS reference server for this data source, or "SELF" if this database is its own reference server. (See http://www.biodas.org/ for an explanation of what reference servers are.) Please see L for more information on using DAS with GBrowse. =item * proxy, http proxy, ftp proxy If your web server is behind a firewall and needs to use a proxy in order to access remote HTTP or FTP sites, then one or more of these options needs to be specified in order for the "add remote annotations" feature to work (both for file-based and DAS-based remote annotations). "http proxy" will set the proxy to use for outgoing HTTP connections, "ftp proxy" will set the proxy to use for outgoing FTP connections, and "proxy" will set both. The value is the URL of the proxy: proxy = http://myproxy.myorg.com:9000 =item * session driver =item * session args These options fine-tune how gbrowse manages its state-maintaining sessions. GBrowse uses CGI::Session to store session data on the server. By default (if neither of these options is present), it uses CGI::Session's "file" driver and "default" serializer. The session files are stored in the "sessions" directory underneath the directory specified by the "tmpimages" option (e.g. /usr/local/apache/htdocs/gbrowse/tmpimages/sessions). The "session driver" option will be passed to CGI::Session->new() as the first argument. It specifies the driver, serializer and ID generator according to the syntax described in the CGI::Session manual page. The "session args" option will be passed to CGI::Session->new() as the third argument. It specifies additional parameters to be passed to the selected driver. For example, here is how to create session data that is stored in the MySQL "test" database under a table named "gbrowse_sessions." The session data will be stored in binary form by the Storable module: session driver = driver:mysql;serializer:storable session args = DataSource test TableName gbrowse_sessions See the CGI::Session documentation for information about setting up the MySQL table and appropriate permissions. You might also want to read about CGI::Session::ID::salted_md5 for an ID generation algorithm that should be more secure (but slightly slower) than the default one. You will not ordinarily need to use these settings, as the defaults seem to work well. =item remember settings time The length of time to remember page-specific settings in the format "+NNNu", where NNN is a number and "u" is a unit ("w" = weeks, "d" = days, "M" = months). For example: remember settings time = +3M # remember settings for 3 months The users' settings, which includes uploaded files, track options and plugin configuration, will be reset to the default if he or she fails to visit the site within the time specified. The default value is 1 month. See the CGI module's manual page for more information on the time format. =item remember source time Like "remember settings time" but applies to remembering the user's preferred data source. "remember source time" should be greater or equal to "remember settings time" because the settings will expire when the source expires. If you have multiple sources, this option should be the same for each one. The default value is 3 months. =item msie hack GBrowse uses HTTP POST to transfer the current page settings to the web server. Because of the way that Microsoft Internet Explorer caches pages, when users of this browser press the "Back" button, MSIE will display an annoying alert that prompts the user to reload the page. When you set "msie hack" to a true value, Gbrowse will use the GET request when it detects MSIE in use. This will fix the "Back" button issue, but will put very long URLs in the Location box. It is your choice which of these is more annoying to your users. =back =head2 B2. The [TRACK DEFAULTS] section The track defaults section specifies default values for each track. The following common options are recognized: glyph height bgcolor fgcolor fontcolor font2color strand_arrow These options control the default graphical settings for any annotation types that are not explicitly specified. See the section below on controlling the settings. Any of the options allowed in the [track] sections described below are allowed here. =over =item * label density When there are too many annotations on the screen GBrowse automatically disables the printing of identifying labels next to the feature. "label density" controls where the cutoff occurs. The value in the example files is 25, meaning that labels will be turned off when there are more than 25 annotations of a particular type on display at once. =item * bump density When there are too many annotations on the screen GBrowse automatically disables collision control. The "bump density" option controls where the cutoff occurs. The value in the example files is 100, meaning that when there more than 100 annotations of the same type on the display, the browser will stop shifting them verticially to prevent them from colliding, but will instead allow them to overlap. =item * link The link option creates a default rule for creating outgoing links from the GBrowse display. When the user clicks on a feature of interest, he will be taken to the corresponding URL. The link option's value should be a URL containing one or more variables. Variables begin with a dollar sign ($), and are replaced at run time with the information relating to the selected annotation. Recognized variables include: $name The feature's name (group name) $id The feature's id (eg, PK from a database) $class The feature's class (group class) $method The feature's method $source The feature's source $ref The name of the sequence segment (chromosome, contig) on which this feature is located $description The feature's description (notes) $start The start position of this feature, relative to $ref $end The end position of this feature, relative to $ref $segstart The left end of $ref displayed in the detailed view $segend The right end of $ref displayed in the detailed view For example, the wormbase.conf file uses this link rule: link = http://www.wormbase.org/db/get?name=$name;class=$class At run time, if the user clicks on an EST named yk1234.5, this will generate the URL http://www.wormbase.org/db/get?name=yk1234.5;class=EST It is possible to override the global link rule on a feature-by-feature basis. See the next section for details on this. It is also possible to declare a subroutine to compute the proper URL dynamically. See COMPUTED OPTIONS for details. A special link type of AUTO will cause the feature to link to the gbrowse_details script, which summarizes information about the feature. The default is not to link at all. =item * link_target By default links will replace the contents of the current window. If you wish, you can specify a new window to pop up when the user clicks on a feature, or designate a named window or frame to receive the contents of the link. To do this, add the "link_target" option to the [TRACK DEFAULTS] section or to a track stanza. The format is this: link_target = _blank The value uses the HTML targetting rules to name/create the window to receive the value of the link. The first time the link is accessed, a window with the specified name is created. The next time the user clicks on a link with the same target, that window will receive the content of the link if it is still present, or it will be created again if it has been closed. A target named "_blank" is special and will always create a new window. The "link_target" option can also be computed dynamically. See COMPUTED OPTIONS for details. =item * title The title option controls the "tooltips" text that pops up when the mouse hovers over a glyph in certain browsers. The rules for generating titles are the same as the "link" option discussed above. The "title" option can also be computed dynamically. See COMPUTED OPTIONS for details. Note HTML characters such as "<", ">" and "&" are not automatically escaped from the title. This lets you do neat stuff, such as create popup menus, but also means that you need to be careful. The function CGI::escapeHTML() is available to properly escape HTML characters in dynamically-generated titles. The special value "AUTO" causes a default description to appear describing the name, type and position of the feature. This is also assumed if the title option is missing or blank. =item * landmark_padding = 1000 The landmark_padding option will add the indicated number of base pairs to the right and left of all landmarks that are searched for by name. =item * image_padding = 25 =item * pad_left = 50 =item * pad_right = 30 The image_padding option will add the indicated amount of whitespace (in pixels) to the right and left of the detail panel. The default is 25 pixels. You may need to adjust this if you are using the xyplot glyph and finding that the scale (which is printed outside the graph area) is being cut off. You can individually adjust the left and right padding using pad_left and pad_right, which, if present, will supersede image_padding. =back =head2 B3. Track Sections Any other [Section] in the configuration file is treated as a declaration of a track. The order of track sections will become the default order of tracks on the display (the user can change this later). Here is a typical track declaration from yeast.conf: [Genes] feature = gene:sgd glyph = generic bgcolor = yellow forwardcolor = yellow reversecolor = turquoise strand_arrow = 1 height = 6 description = 1 key = Named gene This track is named "Genes". You may use a short mnemonic if you prefer; this will make the URL shorter when the user bookmarks a view he or she likes. Track names can contain almost any character, including whitespace, but cannot contain the "-" or "+" signs because these are used to separate track names in the URL when bookmarking. [My Genes] is OK, but [My-Genes] is not. As in the general configuration section, the track declaration contains multiple name=value option pairs. Valid options are as follows: =over =item 1 feature This relates the track to one or more feature types as they appear in the database. Recall that each feature has a method and source. This is represented in the form method:source. So, for example, a feature of type "gene:sgd" has the method "gene" and the source "sgd". It is possible to omit the source. A feature of type "gene" will include all features whose methods are "gene", regardless of the source field. It is not possible to omit the method. It is possible to have several feature types displayed on a single track. Simply provide the feature option with a space-delimited list of the features you want to include. For example: feature = gene:sgd stRNA:sgd This will include features of type "gene:sgd" and "stRNA:sgd" in the same track and display them in a similar fashion. =item 2 remote feature This relates the track to a remote feature track somewhere on the Internet. The value is a http: or ftp: URL, and may correspond to a static file of features in GFF format, gbrowse upload format, a CGI script, or a DAS source. When this option is active, the "feature" option and most of the glyph control options described below are ignored, but the "citation" and "key" options are honored. Example: remote feature = http://www.wormbase.org/cgi-bin/das/wormbase?type=mRNA =item 3 glyph This controls the glyph (graphical icon) that is used to represent the feature. The list of glyphs and glyph-specific options are listed in the section GLYPHS AND GLYPH OPTIONS. The "generic" glyph is the default. =item 4 bgcolor This controls the background color of the glyph. The format of colors is explained in GLYPHS AND GLYPH OPTIONS. =item 5 fgcolor This controls the foreground color (outline color) of the glyph. The format of colors is explained in GLYPHS AND GLYPH OPTIONS. =item 6 fontcolor This controls the color of the primary font of text drawn in the glyph. This is the font used for the features labels drawn at the top of the glyph. =item 7 font2color This controls the color of the secondary font of text drawn in the glyph. This is the font used for the longish feature descriptions drawn at the bottom of the glyphs. =item 8 height This option sets the height of the glyph. It is expressed in pixels. =item 9 strand_arrow This is a true or false value, where true is 1 and false is 0. If this option is set to true, then the glyph will indicate the strandedness of the feature, usually by drawing an arrow of some sort. Some glyphs are inherently stranded, or inherently non-stranded and simply ignore this option. =item 10 label This is a true or false value, where true is 1 and false is 0. If the option is set to true, then the name of the feature (i.e. its group name) is printed above the feature, space allowing. =item 11 description This is a true or false value, where true is 1 and false is 0. If the option is set to true, then the description of the feature (any Note fields) is printed below the feature, space allowing. =item 12 key This option controls the descriptive key that is drawn in the key area at the bottom of the image. It also appears in the checkboxes that the end user uses to switch tracks on and off. If not specified, it defaults to the track name. =item 13 citation If present, this option creates a human-readable descriptive paragraph describing the feature and how it was derived. This is the text information that is displayed when the user clicks on the track name in the checkbox group. The value can either be a URL, in which case clicking on the track name invokes the corresponding URL, or a text paragraph, in which case clicking on the track name generates a page containing the text description. Long paragraphs can be continued across multiple lines, provided that continuation lines begin with whitespace. =item 14 link, title, link_target These options are identical to the similarly-named options in the [GENERAL] section, but change the rules on a track-by-track basis. They can be used to override the global rules. To force a track not to contain any links, use a blank value. =item 15 box_subparts If this option is greater than zero, then gbrowse will generate imagemap rectangles for each of the subparts of a feature (e.g. the exons within a transcript), allowing you to link each subpart separately. The numeric value will control the number of levels of subfeatures that the boxes will descend into. For example, if using the "gene" glyph, set -box_subparts to 2 to create boxes for the whole gene (level 0), the mRNAs (level 1) and the exons (level 2). =item 16 feature_low If this option is present, GBrowse will use the list of feature types listed here at resolution views. (This is one of the ways that semantic zooming is implemented.) This allows you, for example, to switch off detailed exon, UTR, promoters and other within-the-gene features, and just show the start and stop of the transcription unit. =item 17 global feature If this option is present and set to a true value (e.g. "1"), GBrowse will automatically generate a pseudo-feature that starts at the beginning of the currently displayed region and extends to the end. This is often used in conjunction with the "translation" and "dna" glyphs in order to display global characteristics of the sequence. If this option is set, then you do not need to specify a "feature" option. =item 18 group_pattern This option lets you connect related features by dotted lines based on a pattern match in the features' names. A typical example is connecting the 5' and 3' read pairs from ESTs or plasmids. See GROUPING FEATURES for details. =item 19 group_on For Bio::DB::SeqFeature::Store databases I, the group_on field allows you to group features together by display_name, target or any other method. This is mostly useful for XY-plot data, where you may want to dynamically group related data points together so that they share the same vertical scaling. Example: group_on = display_name (this feature is under refinement and may change in the future) =item 20 restrict This option allows you to restrict who is allowed to view the current track by host name, IP address or username/password. See AUTHENTICATION AND AUTHORIZATION for details. =item 21 category This option allows you to group tracks into different groups on the GBrowse display in addition to the default group called 'General'. For example, if you wanted several tracks to be in a separate group called "Genes", you would add this to each of the track defintions: category = Genes Note that it is not possible to make subcategories. If all tracks are categorized, then the "General" category will not be displayed. =item 22 das category, das landmark, das subparts, das superparts All these options pertain to exporting the GBrowse database as a DAS data source. Please see L for more information. =back A large number of glyph-specific options are also recognized. These are described in the next section. =head2 B4. Glyphs and Glyph Options A large variety of glyphs are available, and more are being added as the Bio::Graphics module grows. A list of the common glyphs and their options is provided by the GBrowse itself. Click on the "[Help]" link in the section labeled "Upload your own annotations". This page also lists the valid foreground and background colors. Most of the glyphs are found in the BioPerl distribution, but a few are distributed directly with GBrowse. The most popular glyph types are: Glyph Description ----- ----------- generic a rectangle allele_tower allele found at a SNP position arrow an arrow anchored_arrow a span with vertical bases |---------|. If one or the other end of the feature is off-screen, the base will be replaced by an arrow. box another rectangle; doesn't show subparts of features cds shows the reading frame of spliced transcripts; used in conjunction with the "coding" aggregator. diamond a point-like feature represented as a triangle dna DNA and GC content heterogeneous_segments a multi-segmented feature in which each segment can have a distinctive color. For Jim Kent's WABA features, this works with the waba_alignment aggregator. idiogram this takes specially-formatted feature data and turns it into an idiogram of a Giemsa-stained metaphase chromosome image this embeds photographic images and/or diagrams on features processed_transcript multi-purpose representation of a spliced mRNA, including positions of UTRs segments a multi-segmented feature such as an alignment span like anchored_arrow, except that the ends are truncated at the edge of the panel, not turned into an arrow trace reads an SCF trace file and draws a graphic representation triangle a point-like feature represented as a diamond transcript a gene model transcript2 a slightly different representation of a gene model translation 1-, 3- and 6-frame translations wormbase_transcript yet another gene model that can show UTR segments (for features that conform to the WormBase gene schema). Used in conjunction with the "wormbase_gene" aggregator. xyplot histograms and line plots A more definitive list of glyph options can be found in the Bio::Graphics manual pages. Consult the manual pages for the following modules: Glyph Manual Page ----- ----------- (common options for all) Bio::Graphics::Glyph allele_tower Bio::Graphics::Glyph::allele_tower anchored_arrow Bio::Graphics::Glyph::anchored_arrow arrow Bio::Graphics::Glyph::arrow box Bio::Graphics::Glyph::box cds Bio::Graphics::Glyph::cds crossbox Bio::Graphics::Glyph::crossbox diamond Bio::Graphics::Glyph::diamond dna Bio::Graphics::Glyph::dna dot Bio::Graphics::Glyph::dot ellipse Bio::Graphics::Glyph::ellipse extending_arrow Bio::Graphics::Glyph::extending_arrow generic Bio::Graphics::Glyph::generic graded_segments Bio::Graphics::Glyph::graded_segments heterogeneous_segments Bio::Graphics::Glyph::heterogeneous_segments idiogram Bio::Graphics::Glyph::idiogram image Bio::Graphics::Glyph::image line Bio::Graphics::Glyph::line primers Bio::Graphics::Glyph::primers processed_transcript Bio::Graphics::Glyph::processed_transcript rndrect Bio::Graphics::Glyph::rndrect ruler_arrow Bio::Graphics::Glyph::ruler_arrow segments Bio::Graphics::Glyph::segments span Bio::Graphics::Glyph::span toomany Bio::Graphics::Glyph::toomany trace Bio::Graphics::Glyph::trace transcript Bio::Graphics::Glyph::transcript transcript2 Bio::Graphics::Glyph::transcript2 translation Bio::Graphics::Glyph::translation triangle Bio::Graphics::Glyph::triangle wormbase_transcript Bio::Graphics::Glyph::wormbase_transcript xyplot Bio::Graphics::Glyph::xyplot The "perldoc" command is handy for reading the documentation from the Unix command line. For example: perldoc Bio::Graphics::Glyph::primers This will provide you with a summary of the options that apply to the "primers" glyph. In the manual pages, the glyph options are presented the way they are called from Perl. For example, the documentation will tell you to use the -connect_color option to set the color to use when drawing the line that connects the two inward pointing arrows in the primer pair glyph. This translates to the configuration file as an option named "connect_color". For example: [PCR Products] glyph = primer connect_color = blue When referring to colors, you can use a variety of color names such as "blue" and "green". To get the full list, cut and paste the following magic incantation into the command line: perl -MBio::Graphics::Panel -e 'print join "\n",Bio::Graphics::Panel->color_names' or see this URL: http://www.wormbase.org/db/seq/gbrowse?help=annotation Alternatively, you can use the #RRGGBB notation to specify the red, green and blue components of the color. Refer to any book on HTML for the details on using the notation. =head2 B5. Adding features to the overview You can make any set of tracks appear in the overview by creating a stanza with a title of the format [