Skip to content

Commit

Permalink
Merge pull request #49 from Tokazama/house_keeping
Browse files Browse the repository at this point in the history
Some basic house keeping
  • Loading branch information
Tokazama authored Feb 12, 2021
2 parents e72842f + 095759a commit 8c27ae2
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 63 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: CI
on:
- push
- pull_request
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- '1'
- 'nightly'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
with:
file: lcov.info
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1'
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: |
julia --project=docs -e '
using Documenter: doctest
using NIfTI
doctest(NIfTI)'
- run: julia --project=docs docs/make.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
15 changes: 0 additions & 15 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "NIfTI"
uuid = "a3a9e032-41b5-5fc4-967a-a6b7a19844d3"
version = "0.5.0"
version = "0.5.1"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Expand Down
59 changes: 12 additions & 47 deletions src/NIfTI.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ using CodecZlib, Mmap, MappedArrays, TranscodingStreams
import Base.getindex, Base.size, Base.ndims, Base.length, Base.write, Base64
export NIVolume, niread, niwrite, voxel_size, time_step, vox, getaffine, setaffine

include("parsers.jl")

function define_packed(ty::DataType)
packed_offsets = cumsum([sizeof(x) for x in ty.types])
sz = pop!(packed_offsets)
Expand Down Expand Up @@ -103,48 +105,22 @@ function byteswap(hdr::NIfTI1Header)
hdr
end

const SIZEOF_HDR = Int32(348)

const NIfTI_DT_BITSTYPES = Dict{Int16,Type}([
(Int16(1), Bool),
(Int16(2), UInt8),
(Int16(4), Int16),
(Int16(8), Int32),
(Int16(16), Float32),
(Int16(32), ComplexF32),
(Int16(64), Float64),
(Int16(256), Int8),
(Int16(512), UInt16),
(Int16(768), UInt32),
(Int16(1024), Int64),
(Int16(1280), UInt64),
(Int16(1792), ComplexF64)
])
const NIfTI_DT_BITSTYPES_REVERSE = Dict{Type,Int16}()
for (k, v) in NIfTI_DT_BITSTYPES
NIfTI_DT_BITSTYPES_REVERSE[v] = k
end

const NP1_MAGIC = (0x6e,0x2b,0x31,0x00)
const NI1_MAGIC = (0x6e,0x69,0x31,0x00)

function string_tuple(x::String, n::Int)
a = codeunits(x)
padding = zeros(UInt8, n-length(a))
(a..., padding...)
end
string_tuple(x::AbstractString) = string_tuple(bytestring(x))

mutable struct NIfTI1Extension
struct NIfTI1Extension
ecode::Int32
edata::Vector{UInt8}
end

mutable struct NIVolume{T<:Number,N,R} <: AbstractArray{T,N}
struct NIVolume{T<:Number,N,R} <: AbstractArray{T,N}
header::NIfTI1Header
extensions::Vector{NIfTI1Extension}
raw::R

end
NIVolume(header::NIfTI1Header, extensions::Vector{NIfTI1Extension}, raw::R) where {R}=
niupdate(new(header, extensions, raw))
Expand Down Expand Up @@ -208,15 +184,6 @@ function nidim(x::AbstractArray)
(dim...,)
end

# Gets datatype to be used in header
function nidatatype(t::Type)
t = get(NIfTI_DT_BITSTYPES_REVERSE, t, nothing)
if t == nothing
error("Unsupported data type $t")
end
t
end

# Gets the size of a type in bits
nibitpix(t::Type) = Int16(sizeof(t)*8)
nibitpix(::Type{Bool}) = Int16(1)
Expand Down Expand Up @@ -363,9 +330,9 @@ function NIVolume(
slice_end = size(raw, dim_info[3]) - 1
end

NIVolume(NIfTI1Header(SIZEOF_HDR, string_tuple(data_type, 10), string_tuple(db_name, 18), extents, session_error,
NIVolume(NIfTI1Header(SIZEOF_HDR1, string_tuple(data_type, 10), string_tuple(db_name, 18), extents, session_error,
regular, to_dim_info(dim_info), nidim(raw), intent_p1, intent_p2,
intent_p3, intent_code, nidatatype(t), nibitpix(t),
intent_p3, intent_code, eltype_to_int16(t), nibitpix(t),
slice_start, (qfac, voxel_size..., time_step, 0, 0, 0), 352,
scl_slope, scl_inter, slice_end, slice_code,
xyzt_units, cal_max, cal_min, slice_duration,
Expand All @@ -380,12 +347,12 @@ esize(ex::NIfTI1Extension) = 8 + ceil(Int, length(ex.edata)/16)*16

# Validates the header of a volume and updates it to match the volume's contents
function niupdate(vol::NIVolume{T}) where {T}
vol.header.sizeof_hdr = SIZEOF_HDR
vol.header.sizeof_hdr = SIZEOF_HDR1
vol.header.dim = nidim(vol.raw)
vol.header.datatype = nidatatype(T)
vol.header.datatype = eltype_to_int16(T)
vol.header.bitpix = nibitpix(T)
vol.header.vox_offset = isempty(vol.extensions) ? Int32(352) :
Int32(mapreduce(esize, +, vol.extensions) + SIZEOF_HDR)
Int32(mapreduce(esize, +, vol.extensions) + SIZEOF_HDR1)
vol
end

Expand Down Expand Up @@ -431,7 +398,7 @@ end
# Read header from a NIfTI file
function read_header(io::IO)
header, swapped = read(io, NIfTI1Header)
if header.sizeof_hdr != SIZEOF_HDR
if header.sizeof_hdr != SIZEOF_HDR1
error("This is not a NIfTI-1 file")
end
header, swapped
Expand Down Expand Up @@ -484,10 +451,7 @@ function niread(file::AbstractString; mmap::Bool=false, mode::AbstractString="r"
extensions = read_extensions(header_io, header)
dims = convert(Tuple{Vararg{Int}}, header.dim[2:header.dim[1]+1])

if !haskey(NIfTI_DT_BITSTYPES, header.datatype)
error("data type $(header.datatype) not yet supported")
end
dtype = NIfTI_DT_BITSTYPES[header.datatype]
dtype = to_eltype(header.datatype)

ArrayType = if dtype == Bool
BitArray{length(dims)}
Expand Down Expand Up @@ -569,3 +533,4 @@ length(f::NIVolume) = length(f.raw)
lastindex(f::NIVolume) = lastindex(f.raw)

end

Loading

2 comments on commit 8c27ae2

@Tokazama
Copy link
Member Author

Choose a reason for hiding this comment

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

@JuliaRegistrator register

Release notes:

  • Use dedicated parsing functions instead of dictionary look up
  • NIVolume and NIfTI1Extension aren't mutable now b/c that property was never being used

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/29942

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.1 -m "<description of version>" 8c27ae255d7e1f8256fef5eb75d5faa9c0703286
git push origin v0.5.1

Please sign in to comment.