-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgtf_reader.jl
More file actions
49 lines (41 loc) · 1.67 KB
/
Copy pathgtf_reader.jl
File metadata and controls
49 lines (41 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module GTF
using CSV, DataFrames
"""
read(filename) -> DataFrame
Reads Ensembl GTF files.
### See Also
[GTF format description](https://www.ensembl.org/info/website/upload/gff.html).
"""
read(filename::AbstractString) =
CSV.read(filename, delim='\t', limit=10000000,# missingstrings = ".",
comment = "#!", #allowmissing=:auto,
header=[:seqname, :src_db, :feature, :start, :end, :score, :strand, :frame, :attribute])
"""
parse_attributes(gtf_df::AbstractDataFrame) -> DataFrame
Parses the attribute string of each GTF entry and returns the results as a data frame.
### See Also
[GTF format description](https://www.ensembl.org/info/website/upload/gff.html).
"""
function parse_attributes(attrs::AbstractVector{String})
taggedvals = Dict{Symbol, Vector{Tuple{Int, String}}}()
for (row_ix, attr_line) in enumerate(attrs)
attr_line !== missing || continue
chunks = split(attr_line, ';', keepempty=false)
for chunk in chunks
cm = match(r"^\s*(?<tag>.+)\s\"(?<val>.+)\"\s*$", chunk)
if cm === nothing
@warn "Tag value parsing failed: $chunk"
else
vals = get!(() -> sizehint!(valtype(taggedvals)(), length(attrs)), taggedvals, Symbol(cm[:tag]::SubString{String}))
push!(vals, (row_ix, string(cm[:val]::SubString{String})))
end
end
end
df = DataFrame(Vector{Union{String, Missing}}[begin
x = Vector{Union{String, Missing}}(missing, length(attrs))
setindex!(x, last.(vals), first.(vals))
x end for (tag, vals) in taggedvals], collect(keys(taggedvals)))
df.row_ix = eachindex(attrs)
return df
end
end