aboutsummaryrefslogtreecommitdiff
path: root/julia/CrystFEL/src/detgeom.jl
blob: d394ee7bcdb770154375c44dae7d085416ca69ef (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
122
123
module DetGeoms
export Panel, DetGeom

guardian = []

function protect(guardian, obj)
    push!(guardian, obj)
    obj
end

function unprotect(guardian, obj)
    let pos = findfirst(==(obj), guardian)
        if pos !== nothing
            deleteat!(guardian, pos)
        end
    end
end


mutable struct Panel
    name::Cstring
    cx::Cdouble
    cy::Cdouble
    cz::Cdouble
    pixel_pitch::Cdouble
    adu_per_photon::Cdouble
    max_adu::Cdouble
    fsx::Cdouble
    fsy::Cdouble
    fsz::Cdouble
    ssx::Cdouble
    ssy::Cdouble
    ssz::Cdouble
    w::Cint
    h::Cint
    group::Ptr{Cvoid}
end


mutable struct DetGeom
    panels::Ptr{Panel}
    n_panels::Cint
    top_group::Ptr{Cvoid}
end


"""
    Panel(name, width, height, (cnx, cny), clen, (fsx,fsy,fsz), (ssx,ssy,ssz), pixelsize, aduperphoton)

Create a panel for a CrystFEL `DetGeom`.

* `cnx` and `cny`: Corner position in pixel units
* `clen`: Corner z-position in meters
* `(fsx,fsy,fsz)`: Fast scan vector in pixel units
* `(ssx,ssy,ssz)`: Slow scan vector in pixel units
* `pixelsize`: Conversion factor from pixels to meters
* `aduperphoton`: Detector units per quantum, for error estimation

Additional keyword arguments:

* `max_adu`=Inf: Saturation value
* `group`: Panel group (for hierarchy)
"""
function Panel(name, width, height, corner::Tuple{Real, Real}, clen,
               fs::Tuple{Real,Real,Real}, ss::Tuple{Real,Real,Real},
               pixel_pitch, adu_per_photon,
               max_adu=Inf, group=C_NULL)

    myname = protect(guardian, deepcopy(name))

    p = Panel(pointer(myname),
              corner[1], corner[2], clen/pixel_pitch,
              pixel_pitch, adu_per_photon, max_adu,
              fs[1], fs[2], fs[3],
              ss[1], ss[2], ss[3],
              width, height, group)

    finalizer(p) do x
        unprotect(guardian, myname)
    end

end


function Base.show(io::IO, p::Panel)
    write(io, "Panel(")
    write(io, "name=\"")
    write(io, unsafe_string(p.name))
    write(io, "\", center=(")
    show(io, p.cx); write(io, ", "); show(io, p.cy); write(io, ", "); show(io, p.cz)
    write(io, "), fs=(")
    show(io, p.fsx); write(io, ", "); show(io, p.fsy); write(io, ", "); show(io, p.fsz)
    write(io, "), ss=(")
    show(io, p.ssx); write(io, ", "); show(io, p.ssy); write(io, ", "); show(io, p.ssz)
    write(io, "), size=(")
    show(io, p.w); write(io, ", "); show(io, p.h)
    write(io, "))")
end


"""
    DetGeom(panels; topgroup=g)

Create a CrystFEL `DetGeom` from a vector of `Panel`s.  Optionally set the
panel group which should be the top of the hierarchy.
"""
function DetGeom(panels; topgroup=C_NULL)

    pmem = Base.Libc.malloc(sizeof(panels[1])*length(panels))

    for (i,panel) in enumerate(panels)
        Base.unsafe_copyto!(pmem, pointer(panel), 1)
    end

    dg = DetGeom(pmem, length(panels), topgroup)

    finalize(dg) do x
        Base.Libc.free(dg.panels)
    end

end

end  # of module