[Bio] / Sprout / ScenarioSaplingLoader.pm Repository:
ViewVC logotype

View of /Sprout/ScenarioSaplingLoader.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (download) (as text) (annotate)
Thu Apr 2 01:44:30 2009 UTC (10 years, 5 months ago) by parrello
Branch: MAIN
CVS Tags: rast_rel_2009_05_18
Changes since 1.1: +3 -1 lines
Fixed to clean subsystem objects.

#!/usr/bin/perl -w

#
# Copyright (c) 2003-2006 University of Chicago and Fellowship
# for Interpretations of Genomes. All Rights Reserved.
#
# This file is part of the SEED Toolkit.
#
# The SEED Toolkit is free software. You can redistribute
# it and/or modify it under the terms of the SEED Toolkit
# Public License.
#
# You should have received a copy of the SEED Toolkit Public License
# along with this program; if not write to the University of Chicago
# at info@ci.uchicago.edu or the Fellowship for Interpretation of
# Genomes at veronika@thefig.info or download a copy from
# http://www.theseed.org/LICENSE.TXT.
#

package ScenarioSaplingLoader;

    use strict;
    use Tracer;
    use ERDB;
    require Image::Magick;
    use Rectangle;
    use GD;
    use base 'BaseSaplingLoader';

=head1 Sapling Scenario Load Group Class

=head2 Introduction

The Scenario Load Group includes all of the major scenario-related data tables.

=head3 new

    my $sl = ScenarioSaplingLoader->new($erdb, $options, @tables);

Construct a new ScenarioSaplingLoader object.

=over 4

=item erdb

[[SaplingPm]] object for the database being loaded.

=item options

Reference to a hash of command-line options.

=item tables

List of tables in this load group.

=back

=cut

sub new {
    # Get the parameters.
    my ($class, $erdb, $options) = @_;
    # Create the table list.
    my @tables = sort qw(Scenario IsTerminusFor IsSubInstanceOf IsRelevantFor
                         HasParticipant Shows Displays Diagram Overlaps);
    # Create the BaseSaplingLoader object.
    my $retVal = BaseSaplingLoader::new($class, $erdb, $options, @tables);
    # Return it.
    return $retVal;
}

=head2 Public Methods

=head3 Generate

    $sl->Generate();

Generate the data for the scenario-related data files.

=cut

sub Generate {
    # Get the parameters.
    my ($self) = @_;
    # Get the database object.
    my $erdb = $self->db();
    # Get the source object.
    my $fig = $self->source();
    # Is this the global section?
    if ($self->global()) {
        # Yes. Load the scenarios.
        $self->LoadScenarios($fig);
        # Load the diagrams.
        $self->LoadDiagrams($fig);
    }
}

=head3 LoadScenarios

    $sl->LoadScenarios($fig);

Create the load files for the scenario data.

=over 4

=item fig

FIG-like object used to access the scenario data.

=back

=cut

sub LoadScenarios {
    # Get the parameters.
    my ($self, $fig) = @_;
    # Get the Sapling object.
    my $erdb = $self->db();
    # We run through the subsystems and roles, generating the scenarios.
    # We'll need some hashes to prevent duplicates.
    my %roles = ();
    my %scenarios = ();
    my @subsystems = sort keys %{$erdb->SubsystemHash()};
    for my $subName (@subsystems) {
        Trace("Processing $subName.") if T(3);
        my $sub = $fig->get_subsystem($subName);
        # Get the subsystem's reactions. This is a bit complicated, since
        # the subsystem object only gives us a role-to-reaction map.
        my %roleMap = $sub->get_hope_reactions();
        my @reactions;
        for my $reactionList (values %roleMap) {
            push @reactions, @$reactionList;
        }
        # Connect the subsystem to its diagrams.
        my @maps = $sub->get_diagrams();
        for my $mapData (@maps) {
            $self->PutR(IsRelevantFor => $mapData->[0], $subName);
        }
        # Get the subsystem's scenarios. Note we ignore un-named scenarios.
        # None of them have any data, so we don't need to keep them.
        my @scenarioNames = grep { $_ } $sub->get_hope_scenario_names();
        # Loop through the scenarios, creating scenario data.
        for my $scenarioName (@scenarioNames) {
            $self->Track(Scenarios => $scenarioName, 100);
            # Link this scenario to this subsystem.
            $self->PutR(IsSubInstanceOf => $subName, $scenarioName);
            # If this scenario is new, we need to create it.
            if (! $scenarios{$scenarioName}) {
                Trace("Creating scenario $scenarioName.") if T(3);
                $scenarios{$scenarioName} = 1;
                # Create the scenario itself.
                $self->PutE(Scenario => $scenarioName);
                # Attach the input compounds.
                for my $input ($sub->get_hope_input_compounds($scenarioName)) {
                    $self->PutR(IsTerminusFor => $input, $scenarioName,
                                group_number => 0);
                }
                # Now we need to set up the output compounds. They come in two
                # groups, which we mark 1 and 2.
                my $outputGroupID = 1;
                # Set up the output compounds.
                for my $outputGroup ($sub->get_hope_output_compounds($scenarioName)) {
                    # Attach the compounds.
                    for my $compound (@$outputGroup) {
                        $self->PutR(IsTerminusFor => $compound, $scenarioName,
                                    group_number => $outputGroupID);
                    }
                    # # Increment the group number.
                    $outputGroupID++;
                }
                # Now we create the reaction lists. First we have the reactions that
                # are not in the subsystem but are part of the scenario.
                my @addReactions = $sub->get_hope_additional_reactions($scenarioName);
                for my $reaction (@addReactions) {
                    $self->PutR(HasParticipant => $scenarioName, $reaction, type => 1);
                }
                # Next is the list of reactions not in the scenario. We get the list
                # of these, and then we use it to modify the full reaction list. If
                # the reaction is in the not-list, the type is 2. If it isn't in the
                # not-list, the type is 0.
                my %notReactions = map { $_ => 2 } $sub->get_hope_ignore_reactions($scenarioName);
                for my $reaction (@reactions) {
                    $self->PutR(HasParticipant => $scenarioName, $reaction,
                                type => ($notReactions{$reaction} || 0));
                }
                # Link the maps.
                my @maps = $sub->get_hope_map_ids($scenarioName);
                for my $map (@maps) {
                    $self->PutR(Overlaps => $scenarioName, "map$map");
                }
            }
        }
        # Clear the subsystem cache to save space.
        $fig->clear_subsystem_cache();
    }
}


=head3 LoadDiagrams

    $sl->LoadDiagrams($fig);

Create the load files for the diagram data.

=over 4

=item fig

FIG-like object used to access the data.

=back

=cut

sub LoadDiagrams {
    # Get the parameters.
    my ($self, $fig) = @_;
    # Get an Image::Magick object. This enables us to convert GIFs to PNGs.
    my $p = Image::Magick->new();
    # Create a temporary file name for the PNGs.
    my $pngFileName = "$FIG_Config::temp/map$$.png";
    # Loop through the maps.
    my @maps = $fig->all_maps();
    for my $map (sort @maps) {
        $self->Track(Diagrams => $map, 20);
        # Get the map's descriptive name.
        my $name = $fig->map_name($map);
        # Compute its title. The properties of the map are read from files
        # having this title and different extensions.
        my $mapTitle = "$FIG_Config::kegg/pathway/map/$map";
        # Now we need the map itself. We use Image::Magick to convert it to a PNG.
        $p->Read("$mapTitle.gif");
        $p->Write($pngFileName);
        # Read it back in as a GD::Image.
        my $diagram = GD::Image->new($pngFileName);
        # Write the diagram record.
        $self->PutE(Diagram => $map, name => $name, content => $diagram);
        # Now we connect it to the compounds.
        $self->Connect($map, $mapTitle . "_cpd.coord", 'Shows');
        # Finally, the reactions.
        $self->Connect($map, $mapTitle . "_rn.coord", 'Displays');
    }
}

=head3 Connect

    $sl->Connect($mapID, $fileName, $relName);

Create the relationship records connecting the specified map to the
objects in the specified file. The file is tab-delimited, with the first
column being IDs of reactions or compounds, and the second through fifth
columns containing the rectangle coordinates of the compound or reaction
in the diagram.

=over 4

=item mapID

ID of the relevant map.

=item fileName

Name of the file containing the coordinate data.

=item relName

Name of the relationship to be filled from the data.

=back

=cut

sub Connect {
    # Get the parameters.
    my ($self, $mapID, $fileName, $relName) = @_;
    # Check the file.
    if (! -s $fileName) {
        Trace("File \"$fileName\" not found for map $mapID.") if T(1);
        $self->Add('file-missing' => 1);
    } else {
        # Open the file.
        my $ih = Open(undef, "<$fileName");
        # Loop through the records.
        while (! eof $ih) {
            # Get the ID and the coordinates.
            my ($id, @coords) = Tracer::GetLine($ih);
            # Connect the ID to the diagram.
            $self->PutR($relName => $mapID, $id, location => Rectangle->new(@coords));
        }
    }
}


1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3