Commit 8a6ed0d9 authored by Andreas Tille's avatar Andreas Tille
Browse files

New upstream version 2019.7.0

parent e11900b3
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@ requirements:
    - scikit-bio >=0.5.4
    - numpy
    - blas=*=openblas
    # AVX 512 extensions are broken in 0.3.5 and 0.3.6
    - openblas 0.3.3
    - pandas
    - biom-format >=2.1.5,<2.2.0
    - ijson
+3 −3
Original line number Diff line number Diff line
@@ -23,9 +23,9 @@ def get_keywords():
    # setup.py/versioneer.py will grep for the variable names, so they must
    # each be defined on a line of their own. _version.py will just call
    # get_keywords().
    git_refnames = " (tag: 2019.4.1)"
    git_full = "39051b2475fccf77526778589b67efcbf00314cf"
    git_date = "2019-05-08 16:49:19 -0700"
    git_refnames = " (tag: 2019.7.0)"
    git_full = "9f31de0c81510fbe6be8b16f95e23b4c974ca002"
    git_date = "2019-07-30 18:15:54 +0000"
    keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
    return keywords

+6 −4
Original line number Diff line number Diff line
@@ -13,9 +13,11 @@ from ._format import (
    HeaderlessTSVTaxonomyDirectoryFormat, TSVTaxonomyFormat,
    TSVTaxonomyDirectoryFormat, DNAFASTAFormat, DNASequencesDirectoryFormat,
    PairedDNASequencesDirectoryFormat, AlignedDNAFASTAFormat,
    AlignedDNASequencesDirectoryFormat)
    AlignedDNASequencesDirectoryFormat, DifferentialFormat,
    DifferentialDirectoryFormat)
from ._type import (
    FeatureData, Taxonomy, Sequence, PairedEndSequence, AlignedSequence)
    FeatureData, Taxonomy, Sequence, PairedEndSequence, AlignedSequence,
    Differential)

# TODO remove these imports when tests are rewritten. Remove from __all__ too
from ._transformer import DNAIterator, PairedDNAIterator, AlignedDNAIterator
@@ -23,11 +25,11 @@ from ._transformer import DNAIterator, PairedDNAIterator, AlignedDNAIterator
__all__ = [
    'TaxonomyFormat', 'TaxonomyDirectoryFormat', 'HeaderlessTSVTaxonomyFormat',
    'HeaderlessTSVTaxonomyDirectoryFormat', 'TSVTaxonomyFormat',
    'TSVTaxonomyDirectoryFormat', 'DNAFASTAFormat',
    'TSVTaxonomyDirectoryFormat', 'DNAFASTAFormat', 'DifferentialFormat',
    'DNASequencesDirectoryFormat', 'PairedDNASequencesDirectoryFormat',
    'AlignedDNAFASTAFormat', 'AlignedDNASequencesDirectoryFormat',
    'FeatureData', 'Taxonomy', 'Sequence', 'PairedEndSequence',
    'AlignedSequence', 'DNAIterator', 'PairedDNAIterator',
    'AlignedDNAIterator']
    'AlignedDNAIterator', 'Differential', 'DifferentialDirectoryFormat']

importlib.import_module('q2_types.feature_data._transformer')
+65 −17
Original line number Diff line number Diff line
@@ -6,8 +6,12 @@
# The full license is in the file LICENSE, distributed with this software.
# ----------------------------------------------------------------------------

import re
import skbio.io

import qiime2.plugin.model as model
from qiime2.plugin import ValidationError
import qiime2

from ..plugin_setup import plugin

@@ -131,23 +135,47 @@ TSVTaxonomyDirectoryFormat = model.SingleFileDirectoryFormat(


class DNAFASTAFormat(model.TextFileFormat):
    def sniff(self):
        filepath = str(self)
        sniffer = skbio.io.io_registry.get_sniffer('fasta')
        if sniffer(filepath)[0]:
            generator = skbio.io.read(filepath, constructor=skbio.DNA,
                                      format='fasta', verify=False)
    def _validate_lines(self, max_lines):
        FASTADNAValidator = re.compile(r'[ACGTURYKMSWBDHVN]+\r?\n?')
        last_line_was_ID = False

        with open(str(self), 'rb') as fh:
            try:
                for seq, _ in zip(generator, range(5)):
                    pass
                return True
            # ValueError raised by skbio if there are invalid DNA chars.
            except ValueError:
                pass
                first = fh.read(6)
                if first[:3] == b'\xEF\xBB\xBF':
                    first = first[3:]
                # Empty files should validate
                if first.strip() == b'':
                    return
                if first[0] != ord(b'>'):
                    raise ValidationError("First line of file is not a valid "
                                          "FASTA ID. FASTA IDs must start "
                                          "with '>'")
                fh.seek(0)
                for line_number, line in enumerate(fh, 1):
                    if line_number >= max_lines:
                        return
                    line = line.decode('utf-8-sig')
                    if line.startswith('>'):
                        if last_line_was_ID:
                            raise ValidationError('Multiple consecutive IDs '
                                                  'starting on line '
                                                  f'{line_number-1!r}')
                        last_line_was_ID = True
                    elif re.fullmatch(FASTADNAValidator, line):
                        last_line_was_ID = False
                    else:
                        raise ValidationError('Invalid characters on line '
                                              f'{line_number} (does not match '
                                              'IUPAC characters for a DNA '
                                              'sequence).')
            except UnicodeDecodeError as e:
                raise ValidationError(f'utf-8 cannot decode byte on line '
                                      f'{line_number}') from e

        # Empty files are ok also
        empty_sniffer = skbio.io.io_registry.get_sniffer('<emptyfile>')
        return empty_sniffer(filepath)[0]
    def _validate_(self, max_lines):
        level_map = {'min': 100, 'max': float('inf')}
        self._validate_lines(level_map[max_lines])


DNASequencesDirectoryFormat = model.SingleFileDirectoryFormat(
@@ -185,10 +213,30 @@ AlignedDNASequencesDirectoryFormat = model.SingleFileDirectoryFormat(
    AlignedDNAFASTAFormat)


class DifferentialFormat(model.TextFileFormat):
    def validate(self, *args):
        try:
            md = qiime2.Metadata.load(str(self))
        except qiime2.metadata.MetadataFileError as md_exc:
            raise ValidationError(md_exc) from md_exc

        if md.column_count == 0:
            raise ValidationError('Format must contain at least 1 column')

        filtered_md = md.filter_columns(column_type='numeric')
        if filtered_md.column_count != md.column_count:
            raise ValidationError('Must only contain numeric values.')


DifferentialDirectoryFormat = model.SingleFileDirectoryFormat(
    'DifferentialDirectoryFormat', 'differentials.tsv', DifferentialFormat)


plugin.register_formats(
    TSVTaxonomyFormat, TSVTaxonomyDirectoryFormat,
    HeaderlessTSVTaxonomyFormat, HeaderlessTSVTaxonomyDirectoryFormat,
    TaxonomyFormat, TaxonomyDirectoryFormat, DNAFASTAFormat,
    DNASequencesDirectoryFormat, PairedDNASequencesDirectoryFormat,
    AlignedDNAFASTAFormat, AlignedDNASequencesDirectoryFormat
    AlignedDNAFASTAFormat, AlignedDNASequencesDirectoryFormat,
    DifferentialFormat, DifferentialDirectoryFormat
)
+19 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ from ..plugin_setup import plugin
from ..feature_table import BIOMV210Format
from . import (TaxonomyFormat, HeaderlessTSVTaxonomyFormat, TSVTaxonomyFormat,
               DNAFASTAFormat, PairedDNASequencesDirectoryFormat,
               AlignedDNAFASTAFormat)
               AlignedDNAFASTAFormat, DifferentialFormat)


# Taxonomy format transformers
@@ -359,3 +359,21 @@ def _19(data: AlignedDNAIterator) -> AlignedDNAFASTAFormat:
@plugin.register_transformer
def _33(ff: AlignedDNAFASTAFormat) -> qiime2.Metadata:
    return _dnafastaformats_to_metadata(ff)


# differential types
@plugin.register_transformer
def _222(ff: DifferentialFormat) -> pd.DataFrame:
    return qiime2.Metadata.load(str(ff)).to_dataframe()


@plugin.register_transformer
def _223(ff: DifferentialFormat) -> qiime2.Metadata:
    return qiime2.Metadata.load(str(ff))


@plugin.register_transformer
def _224(data: pd.DataFrame) -> DifferentialFormat:
    ff = DifferentialFormat()
    qiime2.Metadata(data).save(str(ff))
    return ff
Loading