aboutsummaryrefslogtreecommitdiff
path: root/julia/CrystFEL/src/reflists.jl
diff options
context:
space:
mode:
Diffstat (limited to 'julia/CrystFEL/src/reflists.jl')
-rw-r--r--julia/CrystFEL/src/reflists.jl411
1 files changed, 411 insertions, 0 deletions
diff --git a/julia/CrystFEL/src/reflists.jl b/julia/CrystFEL/src/reflists.jl
new file mode 100644
index 00000000..ba7311da
--- /dev/null
+++ b/julia/CrystFEL/src/reflists.jl
@@ -0,0 +1,411 @@
+module RefLists
+
+using Printf
+import ..CrystFEL: libcrystfel
+import ..CrystFEL.Symmetry: SymOpList, InternalSymOpList, symmetry_name
+export RefList, loadreflist, savereflist!
+export Reflection, UnmergedReflection, MergedReflection
+export InternalRefList
+
+
+# The internal libcrystfel structures, not exposed directly
+# We only ever have e.g. a Ptr{InternalRefList}, never a real InternalRefList
+mutable struct InternalRefList end
+mutable struct InternalReflection end
+mutable struct InternalRefListIterator end
+
+# The Julian exposed types
+abstract type Reflection end
+
+mutable struct RefList{T<:Reflection}
+ internalptr::Ptr{InternalRefList}
+ symmetry::SymOpList
+end
+
+mutable struct RefListIterator
+ lastrefl::Ptr{InternalReflection}
+ internalptr::Ptr{InternalRefListIterator}
+end
+
+mutable struct MergedReflection <: Reflection
+ internalptr::Ptr{InternalReflection}
+end
+
+mutable struct UnmergedReflection <: Reflection
+ internalptr::Ptr{InternalReflection}
+end
+
+
+function RefList{MergedReflection}(sym::SymOpList)
+ out = @ccall libcrystfel.reflist_new()::Ptr{InternalRefList}
+ if out == C_NULL
+ throw(ErrorException("Failed to create RefList"))
+ end
+ finalizer(RefList{MergedReflection}(out, sym)) do x
+ @ccall libcrystfel.reflist_free(x.internalptr::Ptr{InternalRefList})::Cvoid
+ end
+end
+
+
+function Base.iterate(reflist::RefList{T}) where T
+
+ rli = Ref{Ptr{InternalRefListIterator}}(C_NULL)
+ refl = ccall((:first_refl, libcrystfel),
+ Ptr{InternalReflection}, (Ptr{InternalRefList},Ref{Ptr{InternalRefListIterator}}),
+ reflist.internalptr, rli)
+
+ if refl == C_NULL
+ return nothing # no reflections!
+ end
+
+ iter = RefListIterator(refl,rli[])
+ finalizer(iter) do x
+ ccall((:free_reflistiterator, libcrystfel),
+ Cvoid, (Ptr{InternalRefListIterator},), x.internalptr)
+ end
+
+ return T(refl),iter
+
+end
+
+
+function Base.iterate(::RefList{T}, iter) where T
+
+ refl = ccall((:next_refl, libcrystfel),
+ Ptr{InternalReflection}, (Ptr{InternalReflection},Ptr{InternalRefListIterator}),
+ iter.lastrefl, iter.internalptr)
+
+ if refl == C_NULL
+ iter.internalptr = C_NULL # libcrystfel already freed it
+ return nothing
+ end
+
+ iter.lastrefl = refl
+
+ return T(refl),iter
+
+end
+
+
+Base.IteratorEltype(::RefList{T}) where T = T
+Base.isdone(iter::RefListIterator) = ((iter.internalptr == C_NULL) && (iter.lastrefl != C_NULL))
+Base.length(reflist::RefList) = ccall((:num_reflections, libcrystfel),
+ Cint, (Ptr{InternalRefList},), reflist.internalptr)
+
+
+function Base.getindex(reflist::RefList{T}, indices) where T
+
+ refl = @ccall libcrystfel.find_refl(reflist.internalptr::Ptr{InternalRefList},
+ indices[1]::Cint,
+ indices[2]::Cint,
+ indices[3]::Cint)::Ptr{InternalReflection}
+
+ if refl == C_NULL
+ return nothing
+ else
+ return T(refl)
+ end
+end
+
+
+function Base.get!(reflist::RefList{T}, indices) where T
+
+ refl = @ccall libcrystfel.find_refl(reflist.internalptr::Ptr{InternalRefList},
+ indices[1]::Cint,
+ indices[2]::Cint,
+ indices[3]::Cint)::Ptr{InternalReflection}
+
+ if refl == C_NULL
+ return push!(reflist, indices)
+ else
+ return T(refl)
+ end
+end
+
+
+function Base.push!(reflist::RefList{T}, indices) where T
+
+ refl = @ccall libcrystfel.add_refl(reflist.internalptr::Ptr{InternalRefList},
+ indices[1]::Cint,
+ indices[2]::Cint,
+ indices[3]::Cint)::Ptr{InternalReflection}
+
+ if refl == C_NULL
+ return nothing
+ else
+ return T(refl)
+ end
+end
+
+
+function loadreflist(filename::AbstractString)
+
+ psym = Ref{Cstring}()
+ out = ccall((:read_reflections_2, libcrystfel),
+ Ptr{InternalRefList}, (Cstring,Ref{Cstring}),
+ filename, psym)
+ if out == C_NULL
+ throw(ArgumentError("Failed to load reflection list"))
+ end
+
+ symmetryname = unsafe_string(psym[])
+ return RefList{MergedReflection}(out, SymOpList(symmetryname))
+
+end
+
+
+function savereflist!(reflist::RefList{MergedReflection}, filename::AbstractString)
+
+ r = @ccall libcrystfel.write_reflist_2(filename::Cstring,
+ reflist.internalptr::Ptr{InternalRefList},
+ reflist.symmetry.internalptr::Ptr{InternalSymOpList})::Cint
+
+ if r != 0
+ throw(ErrorException("Failed to save reflection list"))
+ end
+
+end
+
+
+function Base.show(io::IO, ::MIME"text/plain", reflist::RefList{MergedReflection})
+ println(io, "Merged reflection list in point group ", symmetry_name(reflist.symmetry))
+ print(io, " h k l intensity σ(intens) nmeas")
+ let n = 0
+ for refl in Iterators.take(reflist, 11)
+ if n == 10
+ # We have printed 10 already, and are here again. Truncate...
+ print(io, "\n ⋮ ⋮ ⋮ ⋮ ⋮ ⋮")
+ break
+ end
+ let ind = refl.indices
+ write(io, "\n")
+ @printf(io, "%4i %4i %4i %10.2f %10.2f %5i", ind[1], ind[2], ind[3],
+ refl.intensity, refl.sigintensity, refl.nmeasurements)
+ n += 1
+ end
+ end
+ end
+end
+
+
+function Base.show(io::IO, ::MIME"text/plain", reflist::RefList{UnmergedReflection})
+ println(io, "Unmerged reflection list in point group ", symmetry_name(reflist.symmetry))
+ print(io, " h k l intensity σ(intens) fs ss panel")
+ let n = 0
+ for refl in Iterators.take(reflist, 11)
+ if n == 10
+ # We have printed 10 already, and are here again. Truncate...
+ print(io, "\n ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮")
+ break
+ end
+ let ind = refl.indices,
+ pos = refl.detectorposition
+ write(io, "\n")
+ @printf(io, "%4i %4i %4i %10.2f %10.2f %7.2f %7.2f %6i",
+ ind[1], ind[2], ind[3], refl.intensity, refl.sigintensity,
+ pos.fs, pos.ss, pos.panelnumber)
+ n += 1
+ end
+ end
+ end
+end
+
+
+function detectorpos(refl::Reflection)
+ pfs = Ref{Cdouble}(0)
+ pss = Ref{Cdouble}(0)
+ pn = ccall((:get_panel_number, libcrystfel),
+ Cint, (Ptr{InternalReflection},), refl.internalptr)
+ ccall((:get_detector_pos, libcrystfel),
+ Cint, (Ptr{InternalReflection},Ref{Cdouble},Ref{Cdouble}),
+ refl.internalptr, pfs, pss)
+ (fs=pfs[], ss=pss[], panelnumber=pn)
+end
+
+
+function indices(refl::Reflection)
+ h = Ref{Cint}(0)
+ k = Ref{Cint}(0)
+ l = Ref{Cint}(0)
+ ccall((:get_indices, libcrystfel),
+ Cint, (Ptr{InternalReflection},Ref{Cint},Ref{Cint},Ref{Cint}),
+ refl.internalptr, h, k, l)
+ [h[], k[], l[]]
+end
+
+
+function symmetricindices(refl::Reflection)
+ h = Ref{Cint}(0)
+ k = Ref{Cint}(0)
+ l = Ref{Cint}(0)
+ ccall((:get_symmetric_indices, libcrystfel),
+ Cint, (Ptr{InternalReflection},Ref{Cint},Ref{Cint},Ref{Cint}),
+ refl.internalptr, h, k, l)
+ [h[], k[], l[]]
+end
+
+
+function Base.getproperty(refl::Reflection, name::Symbol)
+ if name === :intensity
+ ccall((:get_intensity, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :sigintensity
+ ccall((:get_esd_intensity, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :partiality
+ ccall((:get_partiality, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :khalf
+ ccall((:get_khalf, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :kpred
+ ccall((:get_kpred, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :excitationerror
+ ccall((:get_exerr, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :lorentzfactor
+ ccall((:get_lorentz, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :phase
+ ccall((:get_phase, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :peak
+ ccall((:get_peak, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :meanbackground
+ ccall((:get_mean_bg, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :temp1
+ ccall((:get_temp1, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :temp2
+ ccall((:get_temp2, libcrystfel),
+ Cdouble, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :nmeasurements
+ ccall((:get_redundancy, libcrystfel),
+ Cint, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :flag
+ ccall((:get_flag, libcrystfel),
+ Cint, (Ptr{InternalReflection},), refl.internalptr)
+ elseif name === :detectorposition
+ detectorpos(refl)
+ elseif name === :indices
+ indices(refl)
+ elseif name === :symmetricindices
+ symmetricindices(refl)
+ else
+ getfield(refl, name)
+ end
+end
+
+
+function Base.setproperty!(refl::Reflection, name::Symbol, val)
+ if name === :intensity
+ @ccall libcrystfel.set_intensity(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :sigintensity
+ @ccall libcrystfel.set_esd_intensity(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :partiality
+ @ccall libcrystfel.set_partiality(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :khalf
+ @ccall libcrystfel.set_khalf(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :kpred
+ @ccall libcrystfel.set_kpred(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :excitationerror
+ @ccall libcrystfel.set_exerr(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :lorentzfactor
+ @ccall libcrystfel.set_lorentz(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :phase
+ @ccall libcrystfel.set_phase(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :peak
+ @ccall libcrystfel.set_peak(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :meanbackground
+ @ccall libcrystfel.set_mean_bg(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :temp1
+ @ccall libcrystfel.set_temp1(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :temp2
+ @ccall libcrystfel.set_temp2(refl.internalptr::Ptr{InternalReflection},
+ val::Cdouble)::Cvoid
+ elseif name === :nmeasurements
+ @ccall libcrystfel.set_redundancy(refl.internalptr::Ptr{InternalReflection},
+ val::Cint)::Cvoid
+ elseif name === :flag
+ @ccall libcrystfel.set_flag(refl.internalptr::Ptr{InternalReflection},
+ val::Cint)::Cvoid
+ elseif name === :detectorposition
+ @ccall libcrystfel.set_detector_pos(refl.internalptr::Ptr{InternalReflection},
+ val.fs::Cdouble, val.ss::Cdouble)::Cvoid
+ @ccall libcrystfel.set_panel_number(refl.internalptr::Ptr{InternalReflection},
+ val.panelnumber::Cint)::Cvoid
+ elseif name === :indices
+ throw(ErrorException("Cannot set the indices of a Reflection"))
+ elseif name === :symmetricindices
+ @ccall libcrystfel.set_symmetric_indices(refl.internalptr::Ptr{InternalReflection},
+ val[1]::Cint, val[2]::Cint, val[3]::Cint)::Cvoid
+ else
+ setfield!(refl, name, val)
+ end
+end
+
+
+function Base.propertynames(::UnmergedReflection; private=false)
+ names = (:intensity,:sigintensity,:partiality,:khalf,:kpred,:lorentzfactor,
+ :excitationerror,:phase,:peak,:meanbackground,:temp1,:temp2,
+ :nmeasurements,:flag,:detectorposition,:indices,:symmetricindices)
+ if private
+ tuple(names..., :internalptr)
+ else
+ names
+ end
+end
+
+
+function Base.propertynames(::MergedReflection; private=false)
+ names = (:intensity,:sigintensity,:phase,:temp1,:temp2,
+ :nmeasurements,:flag,:indices,:symmetricindices)
+ if private
+ tuple(names..., :internalptr)
+ else
+ names
+ end
+end
+
+
+function Base.show(io::IO, refl::MergedReflection)
+ write(io, "MergedReflection(")
+ show(io, refl.indices)
+ write(io, ", intensity=")
+ show(io, refl.intensity)
+ write(io, ", σ(intensity)=")
+ show(io, refl.sigintensity)
+ write(io, ", nmeasurements=")
+ show(io, refl.nmeasurements)
+ write(io, ")")
+end
+
+
+function Base.show(io::IO, refl::UnmergedReflection)
+ write(io, "UnmergedReflection(")
+ show(io, refl.indices)
+ write(io, " at ");
+ show(io, refl.detectorposition)
+ write(io, ", intensity=")
+ show(io, refl.intensity)
+ write(io, ", σ(intensity)=")
+ show(io, refl.sigintensity)
+ write(io, ")")
+end
+
+
+end # of module