Source code for trackhub.assembly

from __future__ import absolute_import

import os
from collections import OrderedDict
from .validate import ValidationError
from .base import HubComponent, deprecation_handler
from .genome import Genome
from .genomes_file import GenomesFile
from .groups import GroupsFile
from .trackdb import TrackDb
from . import constants
from .track import HTMLDoc, ParameterError


class TwoBitFile(HubComponent):
    def __init__(self, source, filename=None, assembly_obj=None, **kwargs):
        source, filename = deprecation_handler(source, filename, kwargs)
        HubComponent.__init__(self)
        self.source = source
        self._filename = filename
        self.assembly_obj = assembly_obj

    @property
    def assembly(self):
        obj, level = self.root(cls=Assembly)
        if level is None:
            return None
        if level != -1:
            raise ValueError("Assembly is level %s, not -1" % level)
        return obj

    @property
    def source(self):
        if self._source is not None:
            return self._source
        return None

    @source.setter
    def source(self, fn):
        self._source = fn

    @property
    def filename(self):
        if self._filename is not None:
            return self._filename

        # If filename hasn't been assigned then make one automatically based
        # on the assembly's parent genomes_file and the assembly's genome.
        if not self.assembly:
            return None
        if not self.assembly.genomes_file:
            return None
        return os.path.join(
            os.path.dirname(self.assembly.genomes_file.filename),
            self.assembly.genome,
            self.assembly.genome + ".2bit",
        )

    def validate(self):
        if not os.path.exists(self.source):
            raise ValueError("Local filename {0} does not exist".format(self.source))

    @filename.setter
    def filename(self, fn):
        self._filename = fn

    def _render(self, staging="staging"):
        pass


[docs] class Assembly(Genome):
[docs] def __init__( self, genome, twobit_file=None, groups=None, trackdb=None, genome_file_obj=None, html_string=None, html_string_format="rst", **kwargs ): """ Represents a genome stanza within a "genomes.txt" file for a non-UCSC genome. The file itself is represented by a :class:`GenomesFile` object. Parameters ---------- genome : str The genome assembly name to use for this assembly twobit_file : str Local path to 2bit file. """ Genome.__init__(self, genome, trackdb=trackdb, genome_file_obj=genome_file_obj) if twobit_file is not None: self.add_twobit(TwoBitFile(twobit_file)) self.html_string = html_string self.html_string_format = html_string_format if groups is not None: self.add_groups(groups) else: self.groups = None self._orig_kwargs = kwargs self.track_field_order = [] self.track_field_order.extend(constants.track_fields["assembly"]) self.track_field_order.extend(constants.track_fields["all"]) self.add_params(**kwargs)
def add_twobit(self, twobit): self.children = [x for x in self.children if not isinstance(x, TwoBitFile)] self.add_child(twobit) self.twobit = twobit def add_trackdb(self, trackdb): self.children = [x for x in self.children if not isinstance(x, TrackDb)] self.add_child(trackdb) self.trackdb = trackdb def add_groups(self, groups): self.children = [x for x in self.children if not isinstance(x, GroupsFile)] self.add_child(groups) self.groups = groups @property def genomes_file(self): obj, level = self.root(cls=GenomesFile) if level is None: return None if level != -1: raise ValueError("GenomesFile is level %s, not -1" % level) return obj
[docs] def add_params(self, **kw): """ Add [possibly many] parameters to the Assembly. Parameters will be checked against known UCSC parameters and their supported formats. """ for k, v in kw.items(): if k not in self.track_field_order: raise ParameterError( '"{0}" is not a valid parameter for {1}'.format( k, self.__class__.__name__ ) ) constants.param_dict[k].validate(v) self._orig_kwargs.update(kw) self.kwargs = self._orig_kwargs.copy()
[docs] def remove_params(self, *args): """ Remove [possibly many] parameters from the Assembly. E.g., remove_params('color', 'visibility') """ for a in args: self._orig_kwargs.pop(a) self.kwargs = self._orig_kwargs.copy()
@property def _html(self): if not self.html_string: return None _html = AssemblyHTMLDoc(self.html_string, self.html_string_format) _html.add_parent(self) return _html def __str__(self): try: self.validate() except ValidationError: return "Unconfigured <Assembly> object" s = [] s.append("genome %s" % self.genome) s.append("trackDb %s" % self.trackdb.filename) s.append("twoBitPath %s" % self.twobit.filename) if self.groups is not None: s.append("groups %s" % self.groups.filename) for name in self.track_field_order: value = self.kwargs.pop(name, None) if value is not None: if constants.param_dict[name].validate(value): s.append("%s %s" % (name, value)) if self._html is not None: s.append("htmlDocumentation %s" % self._html.filename) self.kwargs = self._orig_kwargs.copy() return "\n".join(s) + "\n"
[docs] def validate(self): Genome.validate(self)
# check for necessary params? class AssemblyHTMLDoc(HTMLDoc): # overload track-specific methods in HTMLDoc @property def filename(self): if (self.genomes_file is None) or (self.genome is None): return None return os.path.join( os.path.dirname(self.genomes_file.filename), self.genome.genome, "%s_info.html" % self.genome.genome, ) @property def genomes_file(self): obj, level = self.root(cls=GenomesFile) if level is None: return None if level != -2: raise ValueError("GenomesFile is level %s, not -2" % level) return obj @property def genome(self): obj, level = self.root(cls=Assembly) if level is None: return None if level != -1: raise ValueError("Assembly is level %s, not -1" % level) return obj def validate(self): if not self.genome: raise ValueError( "HTMLDoc object must be connected to an" "Assembly subclass instance" ) return True