Skip to content

Commit

Permalink
Allowing reading for BD Accuri C6 and Attune files (#13)
Browse files Browse the repository at this point in the history
* fix BD Accuri skiiping offsets for analysis segment

* first try of support for floats

* Added tests for floating point files and Accuri files

* Replaced file for FCS2.0 and fix test so it recognizes the exception
[fixing tests for rebase]

* respond comments at #13 (review)

* remove extra files and dependencies
  • Loading branch information
vogu66 authored Oct 3, 2022
1 parent afc3f71 commit 222be70
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
30 changes: 25 additions & 5 deletions src/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,24 @@ function parse_header(io)
seek(io, 10)
# start, end positions of TEXT, DATA, and ANALYSIS sections
offsets = Array{Int64}(undef, 6)

for i in 1:6
# offsets are encoded as ASCII strings
raw_str = Array{UInt8}(undef, 8)
read!(io, raw_str)
offsets_str = String(raw_str)

# the last two numbers are for the analysis segment
# the analysis segment is facultative, although the bytes should
# always be there
# (FCS 3.1 ref at https://isac-net.org/page/Data-Standards)
# some cytometers (BD Accuri) do not put the last two bytes
# putting "0" bytes in their files is what other cytometers do
# see github discussion:
# https://github.com/tlnagy/FCSFiles.jl/pull/13#discussion_r985251676
if isempty(lstrip(offsets_str)) && i>4
offsets_str="0"
end
offsets[i] = parse(Int, strip(join(offsets_str)))
end

Expand All @@ -23,7 +36,7 @@ function parse_header(io)
offsets[3] = parse(Int64, text_mappings["\$BEGINDATA"])
offsets[4] = parse(Int64, text_mappings["\$ENDDATA"])
end
offsets
return offsets
end


Expand Down Expand Up @@ -58,10 +71,17 @@ function parse_data(io,
end_data::Int,
text_mappings::Dict{String, String})
seek(io, start_data)
# Add support for data types other than float
(text_mappings["\$DATATYPE"] != "F") && error("Non float32 support not implemented yet. Please see github issues for this project.")

flat_data = Array{Float32}(undef, (end_data - start_data + 1) ÷ 4)
# data type in FCS3.1 can be I (integer), F (float32), A (Ascii)
if text_mappings["\$DATATYPE"] == "I"
dtype = Int32
elseif text_mappings["\$DATATYPE"] == "F"
dtype = Float32
else
error("Only float and integer data types are implemented for now, the required .fcs file is using another number encoding.")
end

flat_data = Array{dtype}(undef, (end_data - start_data + 1) ÷ 4)
read!(io, flat_data)
endian_func = get_endian_func(text_mappings)
map!(endian_func, flat_data, flat_data)
Expand All @@ -71,7 +91,7 @@ function parse_data(io,
# data should be in multiples of `n_params` for list mode
(mod(length(flat_data), n_params) != 0) && error("FCS file is corrupt. DATA and TEXT sections don't match.")

data = Dict{String, Vector{Float32}}()
data = Dict{String, Vector{dtype}}()

for i in 1:n_params
data[text_mappings["\$P$(i)N"]] = flat_data[i:n_params:end]
Expand Down
1 change: 0 additions & 1 deletion test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[deps]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
16 changes: 15 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using FCSFiles
using FileIO
using Test, HTTP
using Test

project_root = isfile("runtests.jl") ? abspath("..") : abspath(".")
testdata_dir = joinpath(project_root, "test", "fcsexamples")
Expand All @@ -27,4 +27,18 @@ end
@test length(flowrun.data) == 50
@test length(flowrun.params) == 268
end

@testset "Loading float-encoded file" begin
flowrun = load(joinpath(testdata_dir, "Applied Biosystems - Attune.fcs"))

@test length(flowrun["SSC-A"]) == 22188
@test flowrun["FSC-A"][2] == 244982.11f0
end

@testset "Loading Accuri file" begin
flowrun = load(joinpath(testdata_dir, "Accuri - C6.fcs"))
@test length(flowrun["SSC-A"]) == 63273
@test flowrun["SSC-A"][2] == 370971

end
end

2 comments on commit 222be70

@tlnagy
Copy link
Owner

@tlnagy tlnagy commented on 222be70 Oct 3, 2022

Choose a reason for hiding this comment

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

@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/69449

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.1.6 -m "<description of version>" 222be7023e489be2dc69cc1f7e46606e50ffdee0
git push origin v0.1.6

Also, note the warning: Version 0.1.6 skips over 0.1.5
This can be safely ignored. However, if you want to fix this you can do so. Call register() again after making the fix. This will update the Pull request.

Please sign in to comment.