diff --git a/CHANGELOG.md b/CHANGELOG.md index a0cb796a..e38c17c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] -## [1.0.3] +## [1.0.4] - 2020-01-15 +### Changed +- General housekeeping (code). + +## [1.0.3] - 2020-01-07 ### Changed - Add ColorTypes "0.9" to compat. - Add FixedPointNumbers "0.7" to compat. @@ -14,29 +18,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - CompatHelper configuration. -## [1.0.2] +## [1.0.2] - 2020-01-07 ### Fixed - Corrected typo in Strand constructor. -## [1.0.1] +## [1.0.1] - 2020-01-04 (yanked) +### Changed - General housekeeping. -## [1.0.0] -- Version 1.0 updates ([#15](https://github.com/BioJulia/GenomicFeatures.jl/pull/15)) +## [1.0.0] - 2018-09-10 +### Added +- Issue and PR templates. +- Code of Conduct and Contributing files. +- Support for julia v0.7 and v1.0. + +### Removed +- :exclamation: Support for julia prior to v0.7. -## [0.2.1] +## [0.2.1] - 2017-06-27 ### Added -- Read and write methods for Strand ([#4](https://github.com/BioJulia/GenomicFeatures.jl/pull/4)). +- Read and write methods for Strand type ([#4](https://github.com/BioJulia/GenomicFeatures.jl/pull/4)). -## [0.2.0] +## [0.2.0] - 2017-06-25 ### Added - Optional filter functions to `eachoverlap`, and a `findfirst` function ([#3](https://github.com/BioJulia/GenomicFeatures.jl/pull/3)). -## [0.1.0] -- Move code from Bio.jl. -- Add support for GFF3 and BigWig. +## [0.1.0] - 2017-06-17 +### Added +- Code from Bio.jl. +- Support for GFF3 and BigWig. -[Unreleased]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.3...HEAD +[Unreleased]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.4...HEAD +[1.0.4]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.3...v1.0.4 [1.0.3]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.2...v1.0.3 [1.0.2]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/BioJulia/GenomicFeatures.jl/compare/v1.0.0...v1.0.1 diff --git a/Project.toml b/Project.toml index ab9f4b61..e05e8eb6 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GenomicFeatures" uuid = "899a7d2d-5c61-547b-bef9-6698a8d05446" authors = ["Kenta Sato ", "Ben J. Ward ", "Ciarán O’Mara "] -version = "1.0.3" +version = "1.0.4" [deps] Automa = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b" diff --git a/src/bbi/bbi.jl b/src/bbi/bbi.jl index c3306e1a..ca11ae7e 100644 --- a/src/bbi/bbi.jl +++ b/src/bbi/bbi.jl @@ -1,8 +1,7 @@ # BBI - Shared Parts of bigWig and bigBed # ======================================= # -# Detailed description of bigWig and bigBed file formats are found in the paper -# and its supplement: +# Detailed description of bigWig and bigBed file formats are found in the paper and its supplement: # https://doi.org/10.1093/bioinformatics/btq351 # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2922891/bin/supp_btq351_bbiSuppFINAL.doc # diff --git a/src/bbi/btree.jl b/src/bbi/btree.jl index 4bfc4fea..6712e5c5 100644 --- a/src/bbi/btree.jl +++ b/src/bbi/btree.jl @@ -86,8 +86,7 @@ function chromlist(tree::BTree) end function write_btree(stream::IO, chromlist::Vector{Tuple{String,UInt32,UInt32}}) - # This function stores all chromosomes in the root node as a leaf because it - # is simple to implement. + # This function stores all chromosomes in the root node as a leaf because it is simple to implement. blksize = length(chromlist) keysize = Base.maximum(sizeof(name) for (name, _) in chromlist) valsize = 8 diff --git a/src/bigwig/stats.jl b/src/bigwig/stats.jl index 6c70e67a..7d943163 100644 --- a/src/bigwig/stats.jl +++ b/src/bigwig/stats.jl @@ -6,8 +6,8 @@ Compute the coverage of values in `[chromstart, chromend]` of `chrom`. -If `usezoom` is `true`, this function tries to use precomputed statistics (zoom) -in the file. This is often faster but not exact in most cases. +If `usezoom` is `true`, this function tries to use precomputed statistics (zoom) in the file. +This is often faster but not exact in most cases. """ function coverage(reader::Reader, chrom::AbstractString, chromstart::Integer, chromend::Integer; usezoom=false)::Int chromid = reader.chroms[chrom][1] @@ -34,8 +34,8 @@ end Compute the mean of values in `[chromstart, chromend]` of `chrom`. -This function returns `NaN32` if there are no data in that range. See `coverage` -for the `usezoom` keyword argument. +This function returns `NaN32` if there are no data in that range. +See `coverage` for the `usezoom` keyword argument. """ function mean(reader::Reader, chrom::AbstractString, chromstart::Integer, chromend::Integer; usezoom=false)::Float32 chromid = reader.chroms[chrom][1] @@ -66,8 +66,8 @@ end Compute the minimum of values in `[chromstart, chromend]` of `chrom`. -This function returns `NaN32` if there are no data in that range. See `coverage` -for the `usezoom` keyword argument. +This function returns `NaN32` if there are no data in that range. +See `coverage` for the `usezoom` keyword argument. """ function minimum(reader::Reader, chrom::AbstractString, chromstart::Integer, chromend::Integer; usezoom=false)::Float32 chromid = reader.chroms[chrom][1] @@ -86,8 +86,8 @@ end Compute the maximum of values in `[chromstart, chromend]` of `chrom`. -This function returns `NaN32` if there are no data in that range. See `coverage` -for the `usezoom` keyword argument. +This function returns `NaN32` if there are no data in that range. +See `coverage` for the `usezoom` keyword argument. """ function maximum(reader::Reader, chrom::AbstractString, chromstart::Integer, chromend::Integer; usezoom=false)::Float32 chromid = reader.chroms[chrom][1] diff --git a/src/coverage.jl b/src/coverage.jl index a7ff9c24..820a2fc0 100644 --- a/src/coverage.jl +++ b/src/coverage.jl @@ -9,16 +9,14 @@ """ coverage(intervals) -Compute the coverage of a collection of intervals and return an -`IntervalCollection` that contains run-length encoded coverage data. +Compute the coverage of a collection of intervals and return an `IntervalCollection` that contains run-length encoded coverage data. For example, given intervals like: [------] [------------] [---------------] -This function would return a new set of disjoint intervals with annotated -coverage like: +This function would return a new set of disjoint intervals with annotated coverage like: [1][-2-][-1-][--2--][--1--] """ @@ -40,8 +38,7 @@ function coverage(stream, seqname_isless::Function=isless) while true if interval.seqname != coverage_seqname - coverage_process_lasts_heap!(cov, current_coverage, coverage_seqname, - coverage_first, lasts) + coverage_process_lasts_heap!(cov, current_coverage, coverage_seqname, coverage_first, lasts) if !(isempty(coverage_seqname) || seqname_isless(coverage_seqname, interval.seqname)) error("Intervals must be sorted to compute coverage.") end @@ -70,8 +67,7 @@ function coverage(stream, seqname_isless::Function=isless) current_coverage -= 1 else @assert pos >= coverage_first - push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, - pos, STRAND_BOTH, current_coverage)) + push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, pos, STRAND_BOTH, current_coverage)) current_coverage -= 1 coverage_first = pos + 1 end @@ -83,9 +79,7 @@ function coverage(stream, seqname_isless::Function=isless) current_coverage += 1 else if current_coverage > 0 - push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, - first(interval) - 1, STRAND_BOTH, - current_coverage)) + push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, first(interval) - 1, STRAND_BOTH, current_coverage)) end current_coverage += 1 coverage_first = first(interval) @@ -101,8 +95,7 @@ function coverage(stream, seqname_isless::Function=isless) end end - coverage_process_lasts_heap!(cov, current_coverage, coverage_seqname, - coverage_first, lasts) + coverage_process_lasts_heap!(cov, current_coverage, coverage_seqname, coverage_first, lasts) return cov end @@ -113,17 +106,14 @@ end # Helper function for coverage. Process remaining interval end points after # all intervals have been read. -function coverage_process_lasts_heap!(cov::IntervalCollection{UInt32}, - current_coverage, coverage_seqname, - coverage_first, lasts) +function coverage_process_lasts_heap!(cov::IntervalCollection{UInt32}, current_coverage, coverage_seqname, coverage_first, lasts) while !isempty(lasts) pos = DataStructures.heappop!(lasts) if pos == coverage_first - 1 current_coverage -= 1 else @assert pos >= coverage_first - push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, - pos, STRAND_BOTH, current_coverage)) + push!(cov, Interval{UInt32}(coverage_seqname, coverage_first, pos, STRAND_BOTH, current_coverage)) current_coverage -= 1 coverage_first = pos + 1 end diff --git a/src/gff3/reader.jl b/src/gff3/reader.jl index 35d5a2ea..622136ae 100644 --- a/src/gff3/reader.jl +++ b/src/gff3/reader.jl @@ -49,10 +49,9 @@ end Create a reader for data in GFF3 format. -The first argument specifies the data source. When it is a filepath that ends -with *.bgz*, it is considered to be block compression file format (BGZF) and the -function will try to find a tabix index file (.tbi) and read it if -any. See for bgzip and tabix tools. +The first argument specifies the data source. +When it is a filepath that ends with *.bgz*, it is considered to be block compression file format (BGZF) and the function will try to find a tabix index file (.tbi) and read it if any. +See for bgzip and tabix tools. Arguments --------- @@ -129,11 +128,9 @@ end """ -Return all directives that preceded the last GFF entry parsed as an array of -strings. +Return all directives that preceded the last GFF entry parsed as an array of strings. -Directives at the end of the file can be accessed by calling `close(reader)` -and then `directives(reader)`. +Directives at the end of the file can be accessed by calling `close(reader)` and then `directives(reader)`. """ function directives(reader::Reader) ret = String[] @@ -157,8 +154,7 @@ end """ Return a BioSequences.FASTA.Reader initialized to parse trailing FASTA data. -Throws an exception if there is no trailing FASTA, which can be checked using -`hasfasta`. +Throws an exception if there is no trailing FASTA, which can be checked using `hasfasta`. """ function getfasta(reader::Reader) if !hasfasta(reader) diff --git a/src/gff3/record.jl b/src/gff3/record.jl index 72ca6bbb..293fdb9f 100644 --- a/src/gff3/record.jl +++ b/src/gff3/record.jl @@ -458,7 +458,8 @@ end """ content(record::Record)::String -Get the content of `record`. Leading '#' letters are removed. +Get the content of `record`. +Leading '#' letters are removed. """ function content(record::Record) checkfilled(record) diff --git a/src/indexes/bgzfindex.jl b/src/indexes/bgzfindex.jl index 43247840..bce71028 100644 --- a/src/indexes/bgzfindex.jl +++ b/src/indexes/bgzfindex.jl @@ -3,8 +3,7 @@ # # An index type for BGZFStream. # -# The details of the internal is specified in -# https://samtools.github.io/hts-specs/SAMv1.pdf. +# The details of the internal is specified in https://samtools.github.io/hts-specs/SAMv1.pdf. # # This file is a part of BioJulia. # License is MIT: https://github.com/BioJulia/Bio.jl/blob/master/LICENSE.md diff --git a/src/indexes/overlap.jl b/src/indexes/overlap.jl index eb5e9272..c421a307 100644 --- a/src/indexes/overlap.jl +++ b/src/indexes/overlap.jl @@ -47,10 +47,8 @@ function done(iter::TabixOverlapIterator, state) end while state.chunkid ≤ lastindex(state.chunks) chunk = state.chunks[state.chunkid] - # The `virtualoffset(source)` is not synchronized with the current - # reading position because data are buffered in `buffer` for parsing - # text. So we need to check not only `virtualoffset` but also - # `nb_available`, which returns the current buffered data size. + # The `virtualoffset(source)` is not synchronized with the current reading position because data are buffered in `buffer` for parsing text. + # So we need to check not only `virtualoffset` but also `nb_available`, which returns the current buffered data size. while bytesavailable(buffer) > 0 || BGZFStreams.virtualoffset(source) < chunk.stop read!(iter.reader, state.record) c = icmp(state.record, iter.interval) diff --git a/src/indexes/tabix.jl b/src/indexes/tabix.jl index 7c315b84..4fe18a73 100644 --- a/src/indexes/tabix.jl +++ b/src/indexes/tabix.jl @@ -75,8 +75,7 @@ end Return chunks possibly overlapping with the range specified by `interval`. -Note that records within the returned chunks are not guaranteed to actually -overlap the query interval. +Note that records within the returned chunks are not guaranteed to actually overlap the query interval. """ function overlapchunks(tabix::Tabix, interval::Interval) seqid = findfirst(isequal(interval.seqname), tabix.names) diff --git a/src/interval.jl b/src/interval.jl index 449b36e5..e3f5c7db 100644 --- a/src/interval.jl +++ b/src/interval.jl @@ -16,13 +16,11 @@ struct Interval{T} <: IntervalTrees.AbstractInterval{Int64} metadata::T end -function Interval(seqname::AbstractString, first::Integer, last::Integer, - strand::Union{Strand,Char}=STRAND_BOTH, metadata=nothing) +function Interval(seqname::AbstractString, first::Integer, last::Integer, strand::Union{Strand,Char}=STRAND_BOTH, metadata=nothing) return Interval{typeof(metadata)}(seqname, first, last, strand, metadata) end -function Interval(seqname::AbstractString, range::UnitRange{T}, - strand::Union{Strand,Char}=STRAND_BOTH, metadata=nothing) where T<:Integer +function Interval(seqname::AbstractString, range::UnitRange{T}, strand::Union{Strand,Char}=STRAND_BOTH, metadata=nothing) where T<:Integer return Interval{typeof(metadata)}(seqname, first(range), last(range), strand, metadata) end @@ -59,45 +57,48 @@ end IntervalTrees.first(i::Interval) = i.first IntervalTrees.last(i::Interval) = i.last -function Base.isless(a::Interval{T}, b::Interval{T}, - seqname_isless::Function=isless) where T +function Base.isless(a::Interval{T}, b::Interval{T}, seqname_isless::Function=isless) where T if a.seqname != b.seqname return seqname_isless(a.seqname, b.seqname)::Bool - elseif a.first != b.first + end + + if a.first != b.first return a.first < b.first - elseif a.last != b.last + end + + if a.last != b.last return a.last < b.last - elseif a.strand != b.strand + end + + if a.strand != b.strand return a.strand < b.strand - else - return false end + + return false end """ Check if two intervals are well ordered. -Intervals are considered well ordered if a.seqname <= b.seqnamend and -a.first <= b.first. +Intervals are considered well ordered if a.seqname <= b.seqnamend and a.first <= b.first. """ -function isordered(a::Interval{T}, b::Interval{T}, - seqname_isless::Function=isless) where T +function isordered(a::Interval{T}, b::Interval{T}, seqname_isless::Function=isless) where T if a.seqname != b.seqname return seqname_isless(a.seqname, b.seqname)::Bool - elseif a.first != b.first + end + + if a.first != b.first return a.first < b.first - else - return true end + + return true end """ Return true if interval `a` entirely precedes `b`. """ -function precedes(a::Interval{T}, b::Interval{T}, - seqname_isless::Function=isless) where T - return (a.last < b.first && a.seqname == b.seqname) || - seqname_isless(a.seqname, b.seqname)::Bool +function precedes(a::Interval{T}, b::Interval{T}, seqname_isless::Function=isless) where T + return (a.last < b.first && a.seqname == b.seqname) || seqname_isless(a.seqname, b.seqname)::Bool end function Base.:(==)(a::Interval{T}, b::Interval{T}) where T @@ -115,8 +116,7 @@ end function Base.show(io::IO, i::Interval) if get(io, :compact, false) - print(io, i.seqname, ":", i.first, "-", i.last, " ", i.strand, - " ", i.metadata === nothing ? "nothing" : i.metadata) + print(io, i.seqname, ":", i.first, "-", i.last, " ", i.strand, " ", i.metadata === nothing ? "nothing" : i.metadata) else println(io, summary(i), ':') println(io, " sequence name: ", i.seqname) diff --git a/src/intervalcollection.jl b/src/intervalcollection.jl index 2a415f68..9491fe74 100644 --- a/src/intervalcollection.jl +++ b/src/intervalcollection.jl @@ -1,5 +1,5 @@ -# An IntervalCollection is an efficiently stored and indexed set of annotated -# genomic intervals. It looks something like this. +# An IntervalCollection is an efficiently stored and indexed set of annotated genomic intervals. +# It looks something like this. # # ┌─────┐ # │trees│ @@ -40,16 +40,14 @@ const ICTreeIntersectionIterator{F,S,T} = IntervalTrees.IntersectionIterat const ICTreeIntervalIntersectionIterator{F,T} = IntervalTrees.IntervalIntersectionIterator{F, Int64,Interval{T},64} mutable struct IntervalCollection{T} - # Sequence name mapped to IntervalTree, which in turn maps intervals to - # a list of metadata. + # Sequence name mapped to IntervalTree, which in turn maps intervals to a list of metadata. trees::Dict{String,ICTree{T}} # Keep track of the number of stored intervals length::Int # A vector of values(trees) sorted on sequence name. - # This is used to iterate intervals as efficiently as possible, but is only - # updated as needed, indicated by the ordered_trees_outdated flag. + # This is used to iterate intervals as efficiently as possible, but is only updated as needed, indicated by the ordered_trees_outdated flag. ordered_trees::Vector{ICTree{T}} ordered_trees_outdated::Bool @@ -58,7 +56,7 @@ mutable struct IntervalCollection{T} end # bulk insertion - function IntervalCollection{T}(intervals::AbstractVector{Interval{T}}, sort=false) where T + function IntervalCollection{T}(intervals::AbstractVector{Interval{T}}, sort::Bool=false) where T if sort sort!(intervals) else @@ -82,7 +80,7 @@ mutable struct IntervalCollection{T} end end -function IntervalCollection(intervals::AbstractVector{Interval{T}}, sort=false) where T +function IntervalCollection(intervals::AbstractVector{Interval{T}}, sort::Bool=false) where T return IntervalCollection{T}(intervals, sort) end @@ -275,9 +273,9 @@ function Base.findfirst(a::IntervalCollection{T}, b::Interval{S}; filter=true_cmp) where {T,S} if !haskey(a.trees, b.seqname) return nothing - else - return findfirst(a.trees[b.seqname], b, filter) end + + return findfirst(a.trees[b.seqname], b, filter) end @@ -287,9 +285,9 @@ end function eachoverlap(a::IntervalCollection{T}, b::Interval; filter::F = true_cmp) where {F,T} if haskey(a.trees, b.seqname) return intersect(a.trees[b.seqname], b) - else - return ICTreeIntervalIntersectionIterator{F,T}() end + + return ICTreeIntervalIntersectionIterator{F,T}() end function eachoverlap(a::IntervalCollection, b::IntervalCollection; filter = true_cmp) @@ -457,14 +455,13 @@ end =# # New julia 0.7 / 1.0 iteration protocol for collection stream iterator. -# State is a tuple: +# State is a tuple: # (current_query, stream_state, intersection_object) function Base.iterate(it::IntervalCollectionStreamIterator{F,S,T}, state = ()) where {F,S,T} # If first iteration, make empty intersection, otherwise get it from the state. - intersection = (state !== () ? state[3] : ICTreeIntersection{T}()) - - # If this is not the first iteration, and there is an available intersection - # for the current query, return it and search for the next intersection. + intersection = (state !== () ? state[3] : ICTreeIntersection{T}()) + + # If this is not the first iteration, and there is an available intersection for the current query, return it and search for the next intersection. if state !== () && intersection.index != 0 entry = intersection.node.entries[intersection.index] return_value = (state[1], entry) @@ -472,8 +469,7 @@ function Base.iterate(it::IntervalCollectionStreamIterator{F,S,T}, state = ()) w return return_value, (state[1], state[2], intersection) end - # If code reaches this point, there is no valid intersection to return for - # the current query, so we get the next query and start looking for intersections. + # If code reaches this point, there is no valid intersection to return for the current query, so we get the next query and start looking for intersections. while intersection.index == 0 # Get a new query from the stream, and its first intersection in the collection. stream_it = (state === () ? iterate(it.stream) : iterate(it.stream, state[2])) diff --git a/src/overlap.jl b/src/overlap.jl index dfbd1e71..3a12ca3d 100644 --- a/src/overlap.jl +++ b/src/overlap.jl @@ -21,13 +21,11 @@ end Create an iterator of overlapping intervals between `intervals_a` and `intervals_b`. -This function assumes elements of `intervals_a` and `intervals_b` are sorted by -its sequence name and left position. If the element type is not a subtype of -`GenomicFeatures.Interval`, elements are converted to `Interval` objects. +This function assumes elements of `intervals_a` and `intervals_b` are sorted by its sequence name and left position. +If the element type is not a subtype of `GenomicFeatures.Interval`, elements are converted to `Interval` objects. -The third optional argument is a function that defines the order of sequence -names. The default function is `Base.isless`, which is the lexicographical -order. +The third optional argument is a function that defines the order of sequence names. +The default function is `Base.isless`, which is the lexicographical order. """ function eachoverlap(intervals_a, intervals_b, seqname_isless=Base.isless; filter=true_cmp) return OverlapIterator(intervals_a, intervals_b, seqname_isless, filter) @@ -40,8 +38,7 @@ struct OverlapIteratorState{Sa,Sb,Ta,Tb} queue_index::Int end -function OverlapIteratorState( - Ta::Type, Tb::Type, next_a::Sa, next_b::Sb, queue::Queue, queue_index::Int) where {Sa, Sb} +function OverlapIteratorState( Ta::Type, Tb::Type, next_a::Sa, next_b::Sb, queue::Queue, queue_index::Int) where {Sa, Sb} return OverlapIteratorState{Sa,Sb,Ta,Tb}(next_a, next_b, queue, queue_index) end @@ -129,8 +126,7 @@ function Base.iterate(iter::OverlapIterator, state::OverlapIteratorState{Sa,Sb,T queue_index = firstindex(state.queue) elseif c == 0 if iter.filter(interval_a, interval_b) - return ((interval_a, interval_b), - OverlapIteratorState(Ta, Tb, next_a, next_b, queue, queue_index)) + return ((interval_a, interval_b), OverlapIteratorState(Ta, Tb, next_a, next_b, queue, queue_index)) end else if queue_index == firstindex(queue) + 1 @@ -150,33 +146,41 @@ end # 0 when `i1` overlaps with `i2`, and # +1 when `i1` follows `i2`. function compare_overlap(i1::Interval, i2::Interval, isless::Function) - if isless(i1.seqname, i2.seqname)::Bool + if isless(i1.seqname, i2.seqname) return -1 - elseif isless(i2.seqname, i1.seqname)::Bool + end + + if isless(i2.seqname, i1.seqname) return +1 - else # i1.seqname == i2.seqname - if i1.last < i2.first - return -1 - elseif i1.first > i2.last - return +1 - else - return 0 - end end + + # i1.seqname == i2.seqname + if i1.last < i2.first + return -1 + end + + if i1.first > i2.last + return +1 + end + + return 0 end -# Faster comparison for `Base.isless`. Note that `Base.isless` must be -# consistent wtih `Base.cmp` to work correctly. +# Faster comparison for `Base.isless`. Note that `Base.isless` must be consistent wtih `Base.cmp` to work correctly. function compare_overlap(i1::Interval, i2::Interval, ::typeof(Base.isless)) c = cmp(i1.seqname, i2.seqname) + if c != 0 return c end + if i1.last < i2.first return -1 - elseif i1.first > i2.last + end + + if i1.first > i2.last return +1 - else - return 0 end + + return 0 end diff --git a/src/queue.jl b/src/queue.jl index 98efffe0..c1f380c7 100644 --- a/src/queue.jl +++ b/src/queue.jl @@ -66,9 +66,9 @@ end function Base.iterate(queue::Queue, i) if !(queue.first <= i <= queue.last) return nothing - else - queue.data[dataindex(queue, i)], i + 1 end + + return queue.data[dataindex(queue, i)], i + 1 end function dataindex(queue::Queue, i::Integer) @@ -90,5 +90,3 @@ function Base.getindex(queue::Queue, i::Integer) return queue.data[dataindex(queue, i)] end - - diff --git a/src/strand.jl b/src/strand.jl index 5a314af8..a3b63523 100644 --- a/src/strand.jl +++ b/src/strand.jl @@ -29,30 +29,42 @@ const STRAND_BOTH = convert(Strand, 0b011) function Base.convert(::Type{Strand}, strand::Char) if strand == '+' return STRAND_POS - elseif strand == '-' + end + + if strand == '-' return STRAND_NEG - elseif strand == '.' + end + + if strand == '.' return STRAND_BOTH - elseif strand == '?' + end + + if strand == '?' return STRAND_NA - else - error("'$(strand)' is not a valid strand") end + + error("'$(strand)' is not a valid strand") end Strand(strand::Char) = convert(Strand, strand) function Base.convert(::Type{Char}, strand::Strand) if strand == STRAND_NA return '?' - elseif strand == STRAND_POS + end + + if strand == STRAND_POS return '+' - elseif strand == STRAND_NEG + end + + if strand == STRAND_NEG return '-' - elseif strand == STRAND_BOTH + end + + if strand == STRAND_BOTH return '.' - else - error("'$(strand)' is not a valid strand") end + + error("'$(strand)' is not a valid strand") end function Base.show(io::IO, strand::Strand)