aboutsummaryrefslogtreecommitdiff
path: root/julia/CrystFEL/src/crystal.jl
diff options
context:
space:
mode:
Diffstat (limited to 'julia/CrystFEL/src/crystal.jl')
-rw-r--r--julia/CrystFEL/src/crystal.jl121
1 files changed, 121 insertions, 0 deletions
diff --git a/julia/CrystFEL/src/crystal.jl b/julia/CrystFEL/src/crystal.jl
new file mode 100644
index 00000000..f05f651f
--- /dev/null
+++ b/julia/CrystFEL/src/crystal.jl
@@ -0,0 +1,121 @@
+module Crystals
+
+using Printf
+
+import ..CrystFEL: libcrystfel
+import ..CrystFEL.RefLists: RefList, InternalRefList, UnmergedReflection
+import ..CrystFEL.UnitCells: UnitCell, InternalUnitCell
+export Crystal, InternalCrystal
+
+# Represents the real C-side (opaque) structure.
+mutable struct InternalCrystal end
+
+mutable struct Crystal
+ internalptr::Ptr{InternalCrystal}
+ cell
+end
+
+
+function Crystal(cell::UnitCell; profileradius=2e6, mosaicity=0)
+
+ out = ccall((:crystal_new, libcrystfel),
+ Ptr{InternalCrystal}, ())
+
+ if out == C_NULL
+ throw(ArgumentError("Failed to create crystal"))
+ end
+
+ # We make a copy of the cell, to avoid memory model shenanigans
+ uccopy = ccall((:cell_new_from_cell, libcrystfel),
+ Ptr{InternalUnitCell}, (Ptr{InternalUnitCell},),
+ cell.internalptr)
+
+ ccall((:crystal_set_cell, libcrystfel),
+ Cvoid, (Ptr{InternalCrystal},Ptr{InternalUnitCell}),
+ out, uccopy)
+
+ ccall((:crystal_set_profile_radius, libcrystfel),
+ Cvoid, (Ptr{InternalCrystal},Cdouble),
+ out, profileradius)
+
+ ccall((:crystal_set_mosaicity, libcrystfel),
+ Cvoid, (Ptr{InternalCrystal},Cdouble),
+ out, mosaicity)
+
+ cr = Crystal(out, nothing)
+
+ finalizer(cr) do x
+ ccall((:crystal_free, libcrystfel), Cvoid, (Ptr{InternalCrystal},),
+ x.internalptr)
+ end
+
+ return cr
+end
+
+
+function Base.setproperty!(cr::Crystal, name::Symbol, val)
+ if name === :internalptr
+ setfield!(cr, :internalptr, val)
+ end
+end
+
+
+function getcell(cr)
+ out = @ccall libcrystfel.crystal_relinquish_cell(cr.internalptr::Ptr{InternalCrystal})::Ptr{InternalUnitCell}
+ if getfield(cr, :cell) === nothing || getfield(cr, :cell).internalptr != out
+ if out != C_NULL
+ setfield!(cr, :cell, UnitCell(out))
+ else
+ setfield!(cr, :cell, nothing)
+ end
+ end
+ return getfield(cr, :cell)
+end
+
+
+function Base.getproperty(cr::Crystal, name::Symbol)
+ if name === :internalptr
+ getfield(cr, :internalptr)
+ elseif name === :cell
+ return getcell(cr)
+ elseif name === :Bfac
+ return @ccall libcrystfel.crystal_get_Bfac(cr.internalptr::Ptr{InternalCrystal})::Cdouble
+ elseif name === :osf
+ return @ccall libcrystfel.crystal_get_osf(cr.internalptr::Ptr{InternalCrystal})::Cdouble
+ elseif name === :mos
+ return @ccall libcrystfel.crystal_get_mosaicity(cr.internalptr::Ptr{InternalCrystal})::Cdouble
+ elseif name === :r
+ return @ccall libcrystfel.crystal_get_profile_radius(cr.internalptr::Ptr{InternalCrystal})::Cdouble
+ elseif name === :resolution
+ return @ccall libcrystfel.crystal_get_resolution_limit(cr.internalptr::Ptr{InternalCrystal})::Cdouble
+ elseif name === :flag
+ return @ccall libcrystfel.crystal_get_user_flag(cr.internalptr::Ptr{InternalCrystal})::Cint
+ else
+ throw(ErrorException("Type Crystal has no field "*String(name)))
+ end
+end
+
+
+function Base.show(io::IO, mime::MIME"text/plain", cr::Crystal)
+ @printf(io, "CrystFEL.Crystal(%p):\n\n", cr.internalptr)
+ if cr.cell !== nothing
+ show(io, cr.cell)
+ write(io, "\n\n")
+ else
+ write(io, "Unit cell parameters not set\n\n")
+ end
+ println(io, " Linear scale factor: ", cr.osf)
+ println(io, " Debye-Walle factor: ", cr.Bfac)
+ println(io, " Mosaicity: ", cr.mos)
+ println(io, " Profile radius: ", cr.r/1e9, " nm⁻¹")
+ println(io, " Resolution limit: ", cr.resolution)
+ println(io, " Flag: ", cr.flag)
+end
+
+
+function Base.show(io::IO, cr::Crystal)
+ @printf(io, "CrystFEL.Crystal(%p)", cr.internalptr)
+end
+
+
+end # of module