aboutsummaryrefslogtreecommitdiff
path: root/julia/CrystFEL/src/crystal.jl
blob: f05f651f1cced5eecdcdcfa1f4e63109023b9373 (plain)
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
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