Skip to content

Commit

Permalink
Add CI
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobnissen committed Jun 23, 2024
1 parent 4e38ab4 commit aad28c8
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 61 deletions.
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Thank you for making an issue.
If you are submitting a bug report, it will help us if you include the following information:

- Your version of Julia and all packages in your activated Julia environment
- A small example that demonstrates the bug. If possible, please make the code copy-pastable into a fresh REPL.
7 changes: 7 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Thank you for your contribution!
If you have any questions about your PR, or need help completing it, you can ping the maintainers of this repository, who will be happy to help if they can find time.

You can optionally use the following checklist when you work on your PR:
- [ ] I have updated any relevant documentation and docstrings.
- [ ] I have added unit tests, and the CodeCov bot shows tests cover my new code.
- [ ] I have mentioned my changes in the CHANGELOG.md file.
28 changes: 28 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
coverage:
status:
project:
default:
# basic
target: auto
threshold: 10%
base: auto
flags:
- unittest
paths:
- "src"
# advanced settings
if_ci_failed: ignore
informational: true
patch:
default:
# basic
target: auto
threshold: 10%
base: auto
flags:
- unittest
paths:
- "src"
# advanced settings
if_ci_failed: ignore
informational: true
29 changes: 29 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Documentation

on:
push:
branches:
- master # update to match your development branch (master, main, dev, trunk, ...)
tags: '*'
pull_request:

jobs:
build:
permissions:
contents: write
pull-requests: read
statuses: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: 'nightly'
- uses: julia-actions/cache@v1
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key
run: julia --project=docs/ docs/make.jl
45 changes: 45 additions & 0 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version:
- 'nightly'
os: [ ubuntu-latest, windows-latest ]
arch: [ x64 ]
include:
- julia-version: nightly
julia-arch: x86
os: ubuntu-latest
experimental: true
# - julia-version: 1
# os: macOS-latest
# experimental: false
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Setup Julia
uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.julia-version }}
- name: Run Tests
uses: julia-actions/julia-runtest@latest
- name: Create CodeCov
uses: julia-actions/julia-processcoverage@v1
- name: Upload CodeCov
uses: codecov/codecov-action@v1
with:
file: ./lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ XAMAuxData = "e99d641e-1821-45d7-9150-ecb7bf333fe1"
[compat]
Aqua = "0.8.7"
FormatSpecimens = "1.3"
MemViews = "0.1"
MemViews = "0.2"
PrecompileTools = "1.2.1"
StringViews = "1.3.3"
Test = "1.11"
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

[![Latest Release](https://img.shields.io/github/release/BioJulia/PairwiseMappingFormat.jl.svg)](https://github.com/BioJulia/PairwiseMappingFormat.jl/releases/latest)
[![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/BioJulia/PairwiseMappingFormat.jl/blob/master/LICENSE)
[![Documentation](https://img.shields.io/badge/docs-stable-blue.svg)](https://biojulia.github.io/PairwiseMappingFormat.jl/stable)
[![Documentation](https://img.shields.io/badge/docs-dev-blue.svg)](https://biojulia.github.io/PairwiseMappingFormat.jl/dev)
[![](https://codecov.io/gh/BioJulia/PairwiseMappingFormat.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/BioJulia/PairwiseMappingFormat.jl)

PairwiseMappingFormat.jl provide a parser for Pairwise Mapping Format (PAF) files.
PAF is a simple, tab-delimited format created by programs such as minimap2.

To learn how to use the package, [read the documentation](https://biojulia.github.io/PairwiseMappingFormat.jl/stable/)
To learn how to use the package, [read the documentation](https://biojulia.github.io/PairwiseMappingFormat.jl/dev/)

## Example
```julia
Expand All @@ -29,4 +30,4 @@ add PairwiseMappingFormat
```

## Contributing
Get in touch with the BioJulia community over at the [Julia Slack](https://julialang.org/slack/) or Zulip servers.
Make an issue or PR on this repository, or get in touch with the BioJulia community over at the [Julia Slack](https://julialang.org/slack/) or Zulip servers.
30 changes: 14 additions & 16 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@ meta = quote
using PairwiseMappingFormat: try_parse
end

DocMeta.setdocmeta!(
PairwiseMappingFormat,
:DocTestSetup,
meta,
recursive=true
)
DocMeta.setdocmeta!(PairwiseMappingFormat, :DocTestSetup, meta; recursive=true)

makedocs(
sitename = "PairwiseMappingFormat.jl",
modules = [PairwiseMappingFormat],
pages = [
"Home" => "index.md",
],
authors = "Jakob Nybo Nissen",
checkdocs = :public,
remotes=nothing, # TODO: Remove
makedocs(;
sitename="PairwiseMappingFormat.jl",
modules=[PairwiseMappingFormat],
pages=["Home" => "index.md"],
authors="Jakob Nybo Nissen",
checkdocs=:public,
remotes=nothing,
)

# TODO: Call deploydocs
deploydocs(;
repo="github.com/BioJulia/PairwiseMappingFormat.jl.git",
push_preview=true,
deps=nothing,
make=nothing,
)
18 changes: 6 additions & 12 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ NaN
## Low-level interface
Iterating `PAFReader`s, and the `parse` function will throw a `PairwiseMappingFormat.ParserException` if the data is invalid:
```jldoctest
parse(PAFRecord, "not a PAF line")
# output
julia> parse(PAFRecord, "not a PAF line")
ERROR: Error when parsing PAF record on line 1, near byte number 14 in line: Not enough tab-separated fields. Each line must have at least 12 fields
[...]
```
Expand All @@ -186,13 +184,10 @@ It either returns a valid `PAFRecord`, or else returns the [`ParserException`](@
but does not throw the exception:

```jldoctest public
const PAF = PairwiseMappingFormat
julia> const PAF = PairwiseMappingFormat;
println(PAF.try_parse("not a PAF line"))
# output
julia> println(PAF.try_parse("not a PAF line"))
PairwiseMappingFormat.ParserException(PairwiseMappingFormat.Errors.TooFewFields, 14, 1)
```

Similarly, the next record of a `PAFReader` may be obtained with the unexported [`try_next!`](@ref)
Expand Down Expand Up @@ -234,11 +229,10 @@ The [`ParserException`](@ref) type contains the error type as an `Enum`, and the
the exception occurred. These can be obtained with the `.kind` and `.line` properties.

```jldoctest public
println(err.line)
println(err.kind)
# output
julia> err.line
1
julia> err.kind
TooFewFields
```

Expand Down
47 changes: 21 additions & 26 deletions src/PairwiseMappingFormat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ function Base.show(io::IO, ::MIME"text/plain", record::PAFRecord)
buf = IOBuffer()
is_mapped(record) || print(buf, "Unmapped ")
println(buf, "PAFRecord:")
println(buf, " Query: ", qname(record))
println(buf, " Query: \"", qname(record), '"')
if is_mapped(record)
println(buf, " Target: ", tname(record))
println(buf, " Target: \"", tname(record), '"')
println(buf, " Q cov: ", round(query_coverage(record); digits=4))
println(buf, " T cov: ", round(target_coverage(record); digits=4))
println(buf, " Identity: ", round(aln_identity(record); digits=4))
Expand All @@ -165,7 +165,7 @@ function Base.show(io::IO, ::MIME"text/plain", record::PAFRecord)
end

# Print the AUX fields indented
function repr_aux(record::PAFRecord)
function repr_aux(record::PAFRecord)::Vector{UInt8}
buf = IOBuffer()
out = IOBuffer()
show(buf, MIME"text/plain"(), aux_data(record))
Expand Down Expand Up @@ -220,10 +220,7 @@ end
"""
query_coverage(rec::Record) -> Float64
Compute the approximate fraction of the query covered by the alignment.
This is computed as the alignment length divided by the query length,
and thus may be inaccurate if there are deletions in the alignment.
The result is guaranteed to be non-negative.
Compute the fraction of the query covered by the alignment.
# Examples
```jldoctest
Expand All @@ -240,10 +237,7 @@ end
"""
target_coverage(rec::Record) -> Float64
Compute the approximate fraction of the target covered by the alignment.
This is computed as the alignment length divided by the target length,
and thus may be inaccurate if there are deletions in the alignment.
The result is guaranteed to be non-negative.
Compute the fraction of the target covered by the alignment.
# Examples
```jldoctest
Expand Down Expand Up @@ -450,9 +444,9 @@ function parse_line!(
strand = if b == UInt8('*')
return finish_unmapped!(record, mem, qname, qlen, i + 2)
elseif b == UInt8('-')
0x01
elseif b == UInt8('+')
0x02
elseif b == UInt8('+')
0x01
else
return ParserException(i % Int32, Errors.InvalidStrand)
end
Expand Down Expand Up @@ -484,11 +478,11 @@ function parse_line!(
length(data) == filled || resize!(data, filled)
doff = 1
dataview = MemView(data)
unsafe_copyto!(dataview, doff, mem, first(qname), length(qname))
unsafe_copyto!(dataview, mem[qname])
doff += length(qname)
unsafe_copyto!(dataview, doff, mem, first(tname), length(tname))
unsafe_copyto!(dataview[doff:end], mem[tname])
doff += length(tname)
iszero(auxlen) || unsafe_copyto!(dataview, doff, mem, i, auxlen)
iszero(auxlen) || unsafe_copyto!(dataview[doff:end], mem[i:end])


# Fill in fields of the struct
Expand Down Expand Up @@ -529,7 +523,7 @@ function finish_unmapped!(
i + 1
end
end
i = findnext(==(0x00), mem, i)
i = findnext(==(UInt8('\t')), mem, i)
aux_end = lastindex(mem)
aux_start = isnothing(i) ? aux_end + 1 : i + 1
aux = aux_start:aux_end
Expand All @@ -539,8 +533,8 @@ function finish_unmapped!(
data = getfield(record, :data)
dataview = MemView(data)
length(data) == filled || resize!(data, filled)
unsafe_copyto!(dataview, 1, mem, first(qname), length(qname))
unsafe_copyto!(dataview, length(qname) + 1, mem, aux_start, length(aux))
unsafe_copyto!(dataview, mem[qname])
unsafe_copyto!(dataview[length(qname)+1:end], mem[aux])

# Fill in fields
record.qname_len = length(qname) % Int32
Expand Down Expand Up @@ -594,13 +588,15 @@ function parse_int(
n < 0 && return ParserException(i % Int32, Errors.IntegerOverflow)
n = Int32(10) * n + (b - Int32(48))
end
# Note: It is not possible to get an InvalidZero error here, because
# the last field (mapq) does allow zero, and for any other fields,
# if they do not end with a \t and thus reach this line, a TooFewFields
# error will be returned.
# at_end is if this is the mapq field, which does not need to end with a tab
if !at_end
ParserException(lastindex(v) % Int32, Errors.TooFewFields)
elseif from > lastindex(v)
ParserException(i % Int32, Errors.EmptyInteger)
elseif !allow_zero & iszero(n)
ParserException(i % Int32, Errors.InvalidZero)
else
(n, i + 1)
end
Expand Down Expand Up @@ -660,9 +656,8 @@ mutable struct PAFReader{I <: IO}
copy::Bool
end

function PAFReader(io::IO; copy::Bool=true)
# 2^16 and 512 are reasonable buffer sizes, they are arbitrary
mem = Memory{UInt8}(undef, 2^16)
function PAFReader(io::IO; buf_size::Int=2^16, copy::Bool=true)
mem = Memory{UInt8}(undef, max(buf_size, 16))
rec = PAFRecord(512)
PAFReader{typeof(io)}(io, rec, mem, 1, 0, 1, copy)
end
Expand All @@ -671,8 +666,8 @@ Base.IteratorSize(::Type{<:PAFReader}) = Base.SizeUnknown()
Base.eltype(::Type{<:PAFReader}) = PAFRecord
Base.close(reader::PAFReader) = close(reader.io) # TODO: Docstring

function PAFReader(f::Function, io::IO; copy::Bool=true)
reader = PAFReader(io; copy)
function PAFReader(f::Function, io::IO; kwargs...)
reader = PAFReader(io; kwargs...)
try
f(reader)
finally
Expand Down
Loading

0 comments on commit aad28c8

Please sign in to comment.