1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
module Streams
import ..CrystFEL: libcrystfel
import ..CrystFEL.DataTemplates: DataTemplate, InternalDataTemplate
import ..CrystFEL.Images: Image, InternalImage
export Stream, chunkwrite, chunkread
# Represents the real C-side (opaque) structure.
mutable struct InternalStream end
# The Julia-side structure, needed to house the pointer to the C structure
mutable struct Stream
internalptr::Ptr{InternalStream}
end
"""
Stream(filename, "w", dtempl)
Opens a CrystFEL stream for writing. Note that you must provide a `DataTemplate`,
which is needed to translate "panel coordinates" to "file coordinates".
Corresponds to CrystFEL C API routine `stream_open_for_write`.
"""
function Stream(filename, mode::AbstractString, dtempl::DataTemplate)
if mode == "w"
out = @ccall libcrystfel.stream_open_for_write(filename::Cstring,
dtempl.internalptr::Ptr{InternalDataTemplate})::Ptr{InternalStream}
if out == C_NULL
throw(ErrorException("Failed to open stream for reading"))
end
@ccall libcrystfel.stream_write_data_template(out::Ptr{InternalStream},
dtempl.internalptr::Ptr{InternalDataTemplate})::Cvoid
finalizer(close, Stream(out))
elseif mode =="r"
throw(ArgumentError("To open a stream for reading, don't provide the DataTemplate"))
else
throw(ArgumentError("Unrecognised CrystFEL stream mode"*mode))
end
end
"""
Stream(filename, "r")
Opens a CrystFEL stream for reading.
Close the stream with `close` when you've finished (this will happen
automatically when the `Stream` object is finalized).
Corresponds to CrystFEL C API routine `stream_open_for_read`.
"""
function Stream(filename, mode::AbstractString)
if mode == "r"
out = @ccall libcrystfel.stream_open_for_read(filename::Cstring)::Ptr{InternalStream}
if out == C_NULL
throw(ErrorException("Failed to open stream for reading"))
end
finalizer(close, Stream(out))
elseif mode == "w"
throw(ArgumentError("To open a stream for writing, you must provide "
*"a DataTemplate: use Stream(filename, \"w\", dtempl)"))
else
throw(ArgumentError("Unrecognised CrystFEL stream mode"*mode))
end
end
function Base.close(st::Stream)
if st.internalptr != C_NULL
@ccall libcrystfel.stream_close(st.internalptr::Ptr{InternalStream})::Cvoid
st.internalptr = C_NULL
end
end
function streamflags(peaks, reflections, imagedata)
flags = 0
if reflections
flags |= 2
end
if peaks
flags |= 4
end
if imagedata
flags |= 8
end
return flags
end
function chunkwrite(st::Stream, image::Image; peaks=true, reflections=true)
st.internalptr == C_NULL && throw(ErrorException("Stream is closed"))
flags = streamflags(peaks, reflections, false)
@ccall libcrystfel.stream_write_chunk(st.internalptr::Ptr{InternalStream},
image.internalptr::Ptr{InternalImage},
flags::Cint)::Cvoid
end
function chunkread(st::Stream; peaks=true, reflections=true)
st.internalptr == C_NULL && throw(ErrorException("Stream is closed"))
flags = streamflags(peaks, reflections, true)
out = @ccall libcrystfel.stream_read_chunk(st.internalptr::Ptr{InternalStream},
flags::Cint)::Ptr{InternalImage}
out == C_NULL && return nothing
finalizer(Image(out, nothing, [], [])) do x
ccall((:image_free, libcrystfel), Cvoid, (Ptr{InternalImage},), x.internalptr)
end
end
end # of module
|