Skip to content

Commit

Permalink
Merge pull request #19 from jakobnissen/automa1
Browse files Browse the repository at this point in the history
Migrate to Automa v1
  • Loading branch information
jakobnissen authored Jul 30, 2024
2 parents 2e082b1 + 796f609 commit 9fca84a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 97 deletions.
35 changes: 22 additions & 13 deletions .github/workflows/UnitTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,49 @@ on:

jobs:
test:
name: Julia ${{ matrix.julia-version }} - ${{ matrix.os }} - ${{ matrix.julia-arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
julia-version:
- '1.0' # LTS
- '1'
julia-arch: [x64, x86]
os: [ubuntu-latest, windows-latest, macOS-latest]
exclude:
- os: macOS-latest
julia-arch: x86
os: [ubuntu-latest, macOS-latest, windows-latest]
experimental: [false]
include:
# Include nightly, but experimental, so it's allowed to fail without
# failing CI.
- julia-version: nightly
julia-arch: x64
os: ubuntu-latest
experimental: true
fail_ci_if_error: false
# Windows is extremely slow on 1.6, so we skip this combination,
# since it increases CI time by 5x
- julia-version: '1.7'
os: windows-latest
experimental: false
# Oldest supported version
- julia-version: '1.6'
os: ubuntu-latest
experimental: false
# MacOS Aarch64 reached Tier1 support of Julia in version 1.9
- julia-version: '1.9'
os: macOS-latest
experimental: false

steps:
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup Julia
uses: julia-actions/setup-julia@v1
uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
- name: Run Tests
uses: julia-actions/julia-runtest@v1
uses: julia-actions/julia-runtest@latest
- name: Create CodeCov
uses: julia-actions/julia-processcoverage@v1
uses: julia-actions/julia-processcoverage@latest
- name: Upload CodeCov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v4
with:
file: ./lcov.info
flags: unittests
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ Indexes = "4ffb77ac-cb80-11e8-1b35-4b78cc642f6d"
TranscodingStreams = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"

[compat]
Automa = "0.7, 0.8"
Automa = "1"
BGZFStreams = "0.3"
BioGenerics = "0.1"
ColorTypes = "0.7, 0.8, 0.9, 0.10, 0.11"
FixedPointNumbers = "0.5, 0.6, 0.7, 0.8"
GenomicFeatures = "2"
Indexes = "0.1"
TranscodingStreams = "0.9.5"
julia = "1"
TranscodingStreams = "0.9.5, 0.10, 0.11"
julia = "1.6"

[extras]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Expand Down
4 changes: 2 additions & 2 deletions src/BED.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module BED

import Automa
import Automa.RegExp: @re_str
using Automa: Automa, @re_str, @mark, @markpos, @relpos, @abspos
using Automa: onenter!, onexit!
import BGZFStreams
import BioGenerics
import ColorTypes
Expand Down
107 changes: 28 additions & 79 deletions src/reader.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
# BED Reader
# ==========
import Automa
import Automa.RegExp: @re_str
import Automa.Stream: @mark, @markpos, @relpos, @abspos

function appendfrom!(dst, dpos, src, spos, n)
if length(dst) < dpos + n - 1
resize!(dst, dpos + n - 1)
Expand Down Expand Up @@ -84,72 +80,34 @@ function GenomicFeatures.eachoverlap(reader::Reader, interval::GenomicFeatures.I
return Indexes.TabixOverlapIterator(reader, interval)
end

const record_machine, file_machine = (function ()
const record_machine, file_machine = let
alt = Automa.RegExp.alt
cat = Automa.RegExp.cat
rep = Automa.RegExp.rep
opt = Automa.RegExp.opt

record = let
chrom = re"[ -~]*"
chrom.actions[:enter] = [:pos]
chrom.actions[:exit] = [:record_chrom]

chromstart = re"[0-9]+"
chromstart.actions[:enter] = [:pos]
chromstart.actions[:exit] = [:record_chromstart]

chromend = re"[0-9]+"
chromend.actions[:enter] = [:pos]
chromend.actions[:exit] = [:record_chromend]

name = re"[ -~]*"
name.actions[:enter] = [:pos]
name.actions[:exit] = [:record_name]

score = re"[0-9]+"
score.actions[:enter] = [:pos]
score.actions[:exit] = [:record_score]

strand = re"[+\-.?]"
strand.actions[:enter] = [:record_strand] #Note: single byte.

thickstart = re"[0-9]+"
thickstart.actions[:enter] = [:pos]
thickstart.actions[:exit] = [:record_thickstart]

thickend = re"[0-9]+"
thickend.actions[:enter] = [:pos]
thickend.actions[:exit] = [:record_thickend]

# Note: The name cannot end with a #, nor whitespace, because if so,
# it is undistinguishable from whitespace and comments
chrom = onexit!(onenter!(re"" | re"[^# \t\v\r\n\f][ -~]*", :pos), :record_chrom)
chromstart = onexit!(onenter!(re"[0-9]+", :pos), :record_chromstart)
chromend = onexit!(onenter!(re"[0-9]+", :pos), :record_chromend)
name = onexit!(onenter!(re"[ -~]*", :pos), :record_name)
score = onexit!(onenter!(re"[0-9]+", :pos), :record_score)
strand = onenter!(re"[+\-.?]", :record_strand) #Note: single byte.
thickstart = onexit!(onenter!(re"[0-9]+", :pos), :record_thickstart)
thickend = onexit!(onenter!(re"[0-9]+", :pos), :record_thickend)
itemrgb = cat(re"[0-9]+", opt(cat(',', re"[0-9]+", ',', re"[0-9]+")))
itemrgb.actions[:enter] = [:pos]
itemrgb.actions[:exit] = [:record_itemrgb]

blockcount = re"[0-9]+"
blockcount.actions[:enter] = [:pos]
blockcount.actions[:exit] = [:record_blockcount]
onexit!(onenter!(itemrgb, :pos), :record_itemrgb)
blockcount = onexit!(onenter!(re"[0-9]+", :pos), :record_blockcount)

# comma-separated values
csv(x) = cat(rep(cat(x, ',')), opt(x))

blocksizes = let
blocksize = re"[0-9]+"
blocksize.actions[:enter] = [:pos]
blocksize.actions[:exit] = [:record_blocksizes_blocksize]

csv(blocksize)
end
blocksizes.actions[:exit] = [:record_blocksizes]

blockstarts = let
blockstart = re"[0-9]+"
blockstart.actions[:enter] = [:pos]
blockstart.actions[:exit] = [:record_blockstarts_blockstart]

csv(blockstart)
end
blockstarts.actions[:exit] = [:record_blockstarts]
blocksizes = csv(onexit!(onenter!(re"[0-9]+", :pos), :record_blocksizes_blocksize))
onexit!(blocksizes, :record_blocksizes)
blockstarts = csv(onexit!(onenter!(re"[0-9]+", :pos), :record_blockstarts_blockstart))
onexit!(blockstarts, :record_blockstarts)

cat(
chrom, '\t',
Expand All @@ -165,19 +123,16 @@ const record_machine, file_machine = (function ()
opt(cat('\t', blocksizes,
opt(cat('\t', blockstarts)))))))))))))))))))
end
record.actions[:enter] = [:mark]
record.actions[:exit] = [:record]
onexit!(onenter!(record, :mark), :record)
hspace = re"[ \t\v\f]"

hspace = re"[ \t\v]"

blankline = rep(hspace)

comment = re"#.*"
# Note: We cannot start with a tab, because then it is indistinguishable
# from an empty chrom field
blankline = opt(re"[ \v\f]" * rep(hspace))
comment = re"#[^\n]*"

newline = let
lf = re"\n"
lf.actions[:enter] = [:countline]

lf = onenter!(re"\n", :countline)
cat(opt('\r'), lf)
end

Expand All @@ -187,18 +142,12 @@ const record_machine, file_machine = (function ()
cat(comment, newline),
))

return map(Automa.compile, (record, file))
end)()

#=
write("bed.dot", Automa.machine2dot(file_machine))
run(`dot -Tsvg -o bed.svg bed.dot`)
=#
map(Automa.compile, (record, file))
end

const record_actions = Dict(
:mark => :(@mark),
:pos => :(pos = @relpos(p)),
:countline => :(),
:record_chrom => :(record.chrom = (pos:@relpos(p-1)); record.ncols += 1),
:record_chromstart => :(record.chromstart = (pos:@relpos(p-1)); record.ncols += 1),
:record_chromend => :(record.chromend = (pos:@relpos(p-1)); record.ncols += 1),
Expand All @@ -216,7 +165,7 @@ const record_actions = Dict(
:record => :(record.filled = 1:@relpos(p-1))
)

Automa.Stream.generate_reader(
Automa.generate_reader(
:index!,
record_machine,
arguments = (:(record::Record),),
Expand All @@ -242,7 +191,7 @@ const loopcode = quote
end
end

Automa.Stream.generate_reader(
Automa.generate_reader(
:readrecord!,
file_machine,
arguments = (:(record::Record), :(state::Tuple{Int,Int})),
Expand Down

0 comments on commit 9fca84a

Please sign in to comment.