Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/build-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Build check

on:
pull_request:
branches:
- master
paths:
- 'src/**'
- 'pyproject.toml'
- 'setup.cfg'
- 'VERSION.txt'
- 'MANIFEST.in'
- '.github/workflows/build-check.yml'

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'

- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build twine

- name: Build sdist and wheel
run: python -m build

- name: Check package metadata
run: python -m twine check dist/*
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
4 changes: 2 additions & 2 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4
uses: actions/dependency-review-action@v5.0.0
# Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options.
with:
comment-summary-in-pr: always
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: '3.12'

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
steps:
# Step 1: Checkout the repository
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0 # Fetch the full history to allow branch checkout

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
python-version: ['3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
* planned new feature: during import of long reads, (optionally) correct for short exon alignment issues.
* separate new read import and classification of isoforms.

## [2.1.2]

* fixed: gff3 import silently dropped genes when the file's chromosome/seqid naming didn't match the genome (e.g. RefSeq-style accessions like `NC_000001.11` vs a plain `1`/`chr1` genome FASTA); chromosome name aliasing via `region` feature lines is now resolved again, restoring behavior lost when the tabix-based reader was replaced to fix #28 (#36)

## [2.1.1]

* fixed: `Transcriptome[...]` gene lookup by name silently returned an arbitrary gene when the name was shared by multiple genes (common for duplicated gene symbols); now warns clearly, separately from the existing gene id ambiguity check (which itself had a bug: it checked against the combined id+name index instead of ids alone) (#27)
Expand Down
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.1
2.1.2
43 changes: 32 additions & 11 deletions src/isotools/_transcriptome_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,12 @@ def _read_gff_file(file_name, chromosomes, infer_genes=False, progress_bar=True)

is_gz = file_name.endswith(".gz")
openfun = gziplib.open if is_gz else open
# seqid -> chromosome name, learned from "region" feature lines that
# carry a "chromosome" attribute (common in RefSeq-style GFF3, where
# seqid is an accession like NC_000001.11 and "chromosome" gives the
# plain name, e.g. "1") -- restores the chromosome aliasing that the
# old TabixFile-based reader did via get_gff_chrom_dict
chrom_alias = {}

with (
openfun(file_name, "rt") as gff,
Expand All @@ -1808,20 +1814,35 @@ def _read_gff_file(file_name, chromosomes, infer_genes=False, progress_bar=True)
logger.warning("GFF line has fewer than 9 fields, skipping:\n%s", line)
continue

chrom = ls[0]
raw_chrom = ls[0]
chrom = chrom_alias.get(raw_chrom, raw_chrom)
region_info = None
if ls[2] == "region":
try:
region_info = dict(
[pair.split("=", 1) for pair in ls[8].rstrip(";").split(";")]
)
except ValueError:
region_info = {}
if "chromosome" in region_info:
chrom = chrom_alias[raw_chrom] = region_info["chromosome"]

if chromosomes is not None and chrom not in chromosomes:
logger.debug("skipping line from chr " + chrom)
continue
try:
info = dict(
[pair.split("=", 1) for pair in ls[8].rstrip(";").split(";")]
) # some gff lines end with ';' in gencode 36
except ValueError:
logger.warning(
"GFF format error in infos (should be ; separated key=value pairs). Skipping line:\n%s",
line,
)
continue
if region_info is not None:
info = region_info
else:
try:
info = dict(
[pair.split("=", 1) for pair in ls[8].rstrip(";").split(";")]
) # some gff lines end with ';' in gencode 36
except ValueError:
logger.warning(
"GFF format error in infos (should be ; separated key=value pairs). Skipping line:\n%s",
line,
)
continue

start, end = [int(i) for i in ls[3:5]]
start -= 1 # to make 0 based
Expand Down
5 changes: 5 additions & 0 deletions tests/data/refseq_style_chrom_alias.gff3
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
##gff-version 3
NC_000001.11 RefSeq region 1 248956422 . + . ID=NC_000001.11:1..248956422;chromosome=1;gbkey=Src
NC_000001.11 BestRefSeq gene 100 500 . + . ID=GENE1
NC_000001.11 BestRefSeq transcript 100 500 . + . ID=GENE1.1;Parent=GENE1
NC_000001.11 BestRefSeq exon 100 500 . + . Parent=GENE1.1
16 changes: 16 additions & 0 deletions tests/data_import_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ def test_import_gff():
assert True


def test_import_gff_chromosome_alias():
# regression test for #36: RefSeq-style GFF3 files use an accession as
# seqid (e.g. NC_000001.11) with the plain chromosome name (e.g. "1")
# given via a "chromosome" attribute on a "region" feature line. Genes
# were previously silently dropped when filtering against the plain
# name, since the tabix-based alias resolution was lost when the
# reader was rewritten to fix #28.
transcriptome = Transcriptome.from_reference(
"tests/data/refseq_style_chrom_alias.gff3", chromosomes={"1"}
)
assert len(transcriptome) == 1, "gene should be found via chromosome alias"
gene = next(iter(transcriptome))
assert gene.id == "GENE1"
assert gene.chrom == "1", "gene should be indexed under the aliased chromosome name"


def test_add_sample_from_csv_missing_gene_info():
# regression test for #25: a coverage csv row referencing a transcript_id
# not found in the transcripts file previously broke gene_id/chr column
Expand Down