Skip to content

Add write gtf feature - Issue #21 - #46

Closed
Benoitdw wants to merge 2 commits into
openvax:masterfrom
Benoitdw:write_gtf-feature
Closed

Add write gtf feature - Issue #21#46
Benoitdw wants to merge 2 commits into
openvax:masterfrom
Benoitdw:write_gtf-feature

Conversation

@Benoitdw

@Benoitdw Benoitdw commented Apr 8, 2024

Copy link
Copy Markdown

Fixe #21

Comment thread tests/test_write_gtf.py Outdated
def test_write_gtf(tmp_path):
gtf_dict = read_gtf(REFSEQ_GTF_PATH)
write_gtf(gtf_dict, tmp_path/"dummy_gtf.gtf")
assert isinstance(read_gtf(str(tmp_path/"dummy_gtf.gtf")), DataFrame)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for equality of this gtf and the original one too ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better now ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup 👍

@gamazeps

Copy link
Copy Markdown

Looks good to me at least :)

@iskandr all good with you too ?

@iskandr

iskandr commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Thanks @Benoitdw — sorry this sat so long! I've adopted your write_gtf and carried it forward in #72, which is now open against current master. Your authorship is preserved there via a Co-authored-by trailer.

I made a few fixes on top of your version so it could land:

  • Python 3.9 compat — the str | Path union syntax needs 3.10+, but the project targets >=3.9, so I switched to typing.Union/Optional.
  • No silent data loss — the and (row[field]) filter dropped attributes whose value was falsy (0, "", False); attributes are now omitted only when the value is None, so those survive a round trip.
  • Missing fixed-column values now serialize as ., the attribute field ends with a trailing ; (canonical GTF), and expand_attribute_column=False DataFrames round-trip too.
  • Added round-trip tests for RefSeq + Ensembl (expanded and unexpanded), pandas input, and the edge cases above.

Closing this in favor of #72 — really appreciate the original contribution, which is what got the feature moving. 🙏

@iskandr iskandr closed this Jul 8, 2026
iskandr added a commit that referenced this pull request Jul 8, 2026
…tions

Addresses the review findings on the first draft:

- Faithful missing-value handling. read_gtf represents an absent attribute
  as null (numeric *_version columns) or the empty string (string columns)
  and cannot tell absent from present-but-empty. The writer now omits both
  null and "" so that read -> write -> read reproduces the parsed frame
  exactly, including column order, on multi-feature GTFs (GENCODE). A
  non-empty falsy value such as "0" is still written (the original #46 bug).

- Vectorized. The attribute field and full line are built with polars
  expressions (concat_str/format) instead of per-row Python; ~200k rows x
  6 attributes now writes in ~0.1s.

- gzip output. A path ending in .gz is gzip-compressed, mirroring read_gtf
  which transparently reads gzipped GTFs.

- Dropped the redundant fixed-column filter; fixed columns are always
  written in canonical order (the missing-column guard runs first).

- Documented that "\"" and ";" in attribute values cannot round-trip
  (a limitation shared with read_gtf, which strips quotes and splits on ";").

Tests now cover both directions across RefSeq/Ensembl/GENCODE/StringTie
fixtures: write(read(...)) recovers the parsed frame and is byte-idempotent
(a fixed point); read(write(...)) recovers a DataFrame's values. Plus gzip,
pandas input, the "0"-vs-empty-vs-null semantics, "." for missing fixed
values, header lines, the structural-character limitation, and the
missing-column error.

Co-authored-by: Benoitdw <[email protected]>
Claude-Session: https://claude.ai/code/session_014fNxSBm5zvdsDNwN3nhmpS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants