aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml83
-rw-r--r--doc/articles/tutorial-images/detector-shift-2.pngbin48161 -> 0 bytes
-rw-r--r--doc/articles/tutorial-images/detector-shift.pngbin70526 -> 0 bytes
-rw-r--r--doc/articles/tutorial.rst99
-rw-r--r--doc/man/indexamajig.1.md3
-rw-r--r--julia/CrystFEL/src/CrystFEL.jl2
-rw-r--r--julia/CrystFEL/src/detgeom.jl140
-rw-r--r--julia/CrystFEL/src/image.jl7
-rw-r--r--julia/CrystFEL/src/indexing.jl3
-rw-r--r--julia/plot-geom.jl162
-rw-r--r--libcrystfel/src/cell-utils.c4
-rw-r--r--libcrystfel/src/detgeom.c1
-rw-r--r--libcrystfel/src/index.c7
-rw-r--r--libcrystfel/src/indexers/pinkindexer.c1
-rw-r--r--libcrystfel/src/integration.c5
-rw-r--r--libcrystfel/src/predict-refine.c19
-rw-r--r--libcrystfel/src/utils.c20
-rw-r--r--libcrystfel/src/utils.h1
-rw-r--r--src/im-asapo.c20
-rw-r--r--src/im-asapo.h1
-rw-r--r--src/indexamajig.c6
21 files changed, 398 insertions, 186 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7f9e8160..92a33525 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,22 +3,6 @@ stages:
- deploy
- build_container
-.build-and-test:
- image: fedora:32
- script:
- - dnf group install -y 'Development Tools'
- - dnf install -y hdf5-devel gsl-devel flex bison gcc-c++
- - dnf install -y gtk3-devel cairo-devel pango-devel gdk-pixbuf2-devel fftw-devel libpng-devel diffutils
- - dnf install -y meson pandoc
- - meson setup build && ninja -C build
- - ninja -C build test
- artifacts:
- when: always
- paths:
- - build/meson-logs/testlog.junit.xml
- reports:
- junit: build/meson-logs/testlog.junit.xml
-
build-and-test:
image: gitlab.desy.de:5555/thomas.white/crystfel/fedora32/dev_env
script:
@@ -31,22 +15,6 @@ build-and-test:
reports:
junit: build/meson-logs/testlog.junit.xml
-.build-and-test-minimal:
- image: fedora:37
- script:
- - dnf group install -y 'Development Tools'
- - dnf install -y gsl-devel flex bison
- - dnf install -y gtk3-devel cairo-devel pango-devel gdk-pixbuf2-devel fftw-devel libpng-devel diffutils
- - dnf install -y meson
- - meson setup build -Dhdf5=disabled && ninja -C build
- - ninja -C build test
- artifacts:
- when: always
- paths:
- - build/meson-logs/testlog.junit.xml
- reports:
- junit: build/meson-logs/testlog.junit.xml
-
build-and-test-minimal:
image: gitlab.desy.de:5555/thomas.white/crystfel/fedora37/dev_env
script:
@@ -120,28 +88,6 @@ build_container_image_tag:
- if: $CI_COMMIT_TAG
when: manual
-.build-native-macos:
- tags:
- - macOS
- variables:
- GIT_STRATEGY: clone
- script:
- - brew update
- - brew upgrade -f
- - brew install gsl hdf5 flex bison argp-standalone pkg-config doxygen gtk+3 cairo pango gdk-pixbuf fftw meson ninja
- - export PATH="$(brew --prefix)/opt/bison/bin:$(brew --prefix)/opt/flex/bin:$PATH"
- - export LDFLAGS="-L$(brew --prefix)/opt/bison/lib -L$(brew --prefix)/opt/flex/lib -L$(brew --prefix)/opt/argp-standalone/lib -largp $LDFLAGS"
- - export CFLAGS="-I$(brew --prefix)/opt/flex/include -I$(brew --prefix)/opt/argp-standalone/include/ $CFLAGS"
- - meson setup build
- - ninja -C build
- - ninja -C build test
- artifacts:
- when: always
- paths:
- - build/meson-logs/testlog.junit.xml
- reports:
- junit: build/meson-logs/testlog.junit.xml
-
build-brew-macos:
dependencies: []
tags:
@@ -155,31 +101,8 @@ build-brew-macos:
- brew install -v -s ./crystfel.rb --HEAD
- brew test crystfel
- brew uninstall -v -f crystfel
-
-.build-centos7:
- image: centos:centos7
- #image:centos:latest
- #image: centos:centos7.9.2009
- variables:
- SECURE_FILES_DOWNLOAD_PATH: './downloads'
- script:
- - yum update -y
- - yum group install -y "Development Tools"
- - yum install -y wget lz4 lz4-devel bzip2-libs bzip2-devel python3 gtk3-devel curl which libcurl-devel pandoc
- - curl --silent "https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer" | bash
- - python3 -m pip install meson ninja
- - wget https://gitlab.desy.de/thomas.white/install-crystfel/-/raw/main/run-me-desy-maxwell-centos7
- - chmod 755 ./run-me-desy-maxwell-centos7
- - ./run-me-desy-maxwell-centos7 --yes-really
- - cp -Rp /software $CI_PROJECT_DIR
- artifacts:
- paths:
- - software/
- - temp/crystfel/build/meson-logs/testlog.junit.xml
- when: on_success
- expire_in: 1 day
- reports:
- junit: temp/crystfel/build/meson-logs/testlog.junit.xml
+ rules:
+ - if: $CI_COMMIT_BRANCH == "master"
build-centos7:
image: gitlab.desy.de:5555/thomas.white/crystfel/centos7/dev_env
@@ -203,7 +126,7 @@ build-centos7:
reports:
junit: temp/crystfel/build/meson-logs/testlog.junit.xml
rules:
- - if: $CI_PIPELINE_SOURCE != 'merge_request_event'
+ - if: $CI_COMMIT_BRANCH == "master"
build-deploy-local-maxwell:
tags:
diff --git a/doc/articles/tutorial-images/detector-shift-2.png b/doc/articles/tutorial-images/detector-shift-2.png
deleted file mode 100644
index 3c17148f..00000000
--- a/doc/articles/tutorial-images/detector-shift-2.png
+++ /dev/null
Binary files differ
diff --git a/doc/articles/tutorial-images/detector-shift.png b/doc/articles/tutorial-images/detector-shift.png
deleted file mode 100644
index 1bd50738..00000000
--- a/doc/articles/tutorial-images/detector-shift.png
+++ /dev/null
Binary files differ
diff --git a/doc/articles/tutorial.rst b/doc/articles/tutorial.rst
index 15c23ae0..9e02b2f3 100644
--- a/doc/articles/tutorial.rst
+++ b/doc/articles/tutorial.rst
@@ -760,69 +760,44 @@ parameteters for just one frame, before launching the big processing job!
Advanced: Check and optimise the detector geometry
--------------------------------------------------
-This step is marked as *Advanced* because it needs some work outside the
-CrystFEL GUI, but it's a very good idea to do this check.
-
Even if the geometry file is supposedly correct for the experiment, it's best
-to check that, for example, the beam position hasn't drifted. Fortunately,
-CrystFEL has already done most of the work for you. After indexing each
-pattern, CrystFEL runs a short optimisation procedure, adjusting the unit cell
-parameters, orientation and beam centre position to get the best possible
-agreement between the observed and predicted peak locations at the same time as
-making sure that the observed peaks correspond to Bragg positions as closely as
-possible. The required beam shift (equivalently considered as a shift of the
-detector) is recorded in the stream for each pattern (see the *Advanced* part
-of section 8)::
-
- $ grep "predict_refine/det_shift" index-all-cell-1/crystfel.stream | head -n 5
- predict_refine/det_shift x = 0.020 y = 0.010 mm
- predict_refine/det_shift x = -0.028 y = -0.017 mm
- predict_refine/det_shift x = 0.028 y = 0.048 mm
- predict_refine/det_shift x = 0.022 y = -0.014 mm
- predict_refine/det_shift x = -0.016 y = -0.002 mm
- $
-
-A program provided with CrystFEL called detector-shift will plot these values.
-Simply run it on the stream::
-
- $ detector-shift index-all-cell-1/crystfel.stream
- Mean shifts: dx = 0.0062 mm, dy = -0.0097 mm
-
-You can also run ``detector-shift`` conveniently from within the CrystFEL GUI:
-Simply choose **Check detector shift** from the **Tools** menu. This will run
-``detector-shift`` on whichever indexing result is currently selected (see the
-start of section 7).
-
-A window should open, which shows the detector shifts as a scatter plot:
-
-.. image:: tutorial-images/detector-shift.png
-
-The cyan point marks the origin (0,0), and the pink point marks the mean of all
-the offsets. The pixel size of the `Jungfrau detector
-<https://www.psi.ch/en/lxn/jungfrau>`_, which was used for this experiment, is
-75 µm, so almost all of the offsets are less than 1 pixel, and the average
-offset is very much less than 1 pixel. Therefore, no further refinement is
-required.
-
-Just for reference, here is how the graph might look if the offset were larger:
-
-.. image:: tutorial-images/detector-shift-2.png
-
-Notice that the cluster of points is significantly displaced from the origin.
-This offset has already been taken into account by CrystFEL when calculating
-the position of Bragg peaks, but the results will be better overall if the
-geometry is correct from the start of the process. In this case, it would be a
-good idea to update the geometry file. The detector-shift program can fix the
-geometry file for you::
-
- $ detector-shift index-all-cell-1/crystfel.stream jf-swissfel-16M.geom
- Mean shifts: dx = -0.14 mm, dy = -0.25 mm
- Applying corrections to jf-swissfel-16M.geom, output filename jf-swissfel-16M-predrefine.geom
- default res 9097.525473
-
-The updated geometry file is called ``jf-swissfel-16M-predrefine.geom``, as the
-script tells you. If you process this dataset again, use this new geometry
-file.
+to check that, for example, the beam position hasn't drifted. CrystFEL
+includes a tool for refining the detector geometry. This tool looks for small
+alterations to the geometry which improve the average fit between observed and
+calculated peak locations, for all patterns, while taking into account that
+changing the detector position will also change the orientation reported by the
+indexing procedure. The topic of detector geometry refinement is deep and
+complex, but only a basic application is needed here.
+
+Click **Refine detector geometry** in the bar at the left of the CrystFEL GUI.
+You will be presented with a dialogue box to choose the filename for the new,
+refined geometry file. Choose any suitable new filename, then look at the
+bottom of the window. There is a drop-down menu where you should select the
+name of the indexing job from earlier in this step (using prior unit cell
+parameters). The geometry refinement calculations will be based on the results
+of that indexing job. Leave **Heirarchy level** at zero and **Include
+out-of-plane positions and tilts** unselected, to keep the refinement simple.
+This will only refine the overall beam center position on the detector. Higher
+refinement levels will do a more fine-grained refinement where the subunits
+comprising the detector are refined individually, but this usually needs more
+data than have been included in this tutorial.
+
+Once you click **Save**, the updated geometry file should appear after a moment
+of calculation. The corrections applied to the detector position are reported
+in the terminal::
+
+ Millepede succeeded.
+
+ Group all:
+ x-translation +0.019464 mm
+ y-translation +0.001548 mm
+
+If you process this dataset again, use this new geometry file and you should
+find that the indexing results are slightly better.
+
+The command-line tool for detector geometry refinement is called
+``align_detector``, and you can read more about how it works in its
+`manual page <../man/align_detector.1.md>`_.
diff --git a/doc/man/indexamajig.1.md b/doc/man/indexamajig.1.md
index 1955ef76..42d555e7 100644
--- a/doc/man/indexamajig.1.md
+++ b/doc/man/indexamajig.1.md
@@ -359,6 +359,9 @@ BASIC OPTIONS
: Set the timeout used for "get next" calls from ASAP::O, in ms. The default
: is 500 ms.
+**--asapo-acks*
+: Use ASAP::O acknowledgements for more reliable message delivery.
+
**--data-format=format**
: Specify the data format for data received over ZeroMQ or ASAP::O. Possible
: values in this version are msgpack, hdf5 and seedee.
diff --git a/julia/CrystFEL/src/CrystFEL.jl b/julia/CrystFEL/src/CrystFEL.jl
index 9ab5d15f..bb1f1534 100644
--- a/julia/CrystFEL/src/CrystFEL.jl
+++ b/julia/CrystFEL/src/CrystFEL.jl
@@ -38,7 +38,7 @@ export rotatecell, compare_reindexed_cell_parameters
include("detgeom.jl")
using .DetGeoms
-export Panel, DetGeom
+export Panel, DetGeom, DetGeomPanel, DetGeomGroup, findgroup
include("symmetry.jl")
using .Symmetry
diff --git a/julia/CrystFEL/src/detgeom.jl b/julia/CrystFEL/src/detgeom.jl
index ba943d98..d8dc5972 100644
--- a/julia/CrystFEL/src/detgeom.jl
+++ b/julia/CrystFEL/src/detgeom.jl
@@ -1,7 +1,8 @@
module DetGeoms
-export Panel
+export DetGeom, DetGeomPanel, DetGeomGroup, InternalDetGeom, copydetgeom
+export findgroup
-mutable struct Panel
+mutable struct InternalPanel
name::Cstring
cx::Cdouble
cy::Cdouble
@@ -21,27 +22,144 @@ mutable struct Panel
end
-mutable struct DetGeom
- panels::Ptr{Panel}
+mutable struct InternalDetGeomPanelGroup
+ name::Cstring
+ n_children::Cint
+ parent::Ptr{InternalDetGeomPanelGroup}
+ serial::Cint
+ cx::Cdouble
+ cy::Cdouble
+ cz::Cdouble
+ children::Ptr{Ptr{InternalDetGeomPanelGroup}}
+ panel::Ptr{InternalPanel}
+end
+
+
+mutable struct InternalDetGeom
+ panels::Ptr{InternalPanel}
n_panels::Cint
- top_group::Ptr{Cvoid}
+ top_group::Ptr{InternalDetGeomPanelGroup}
end
-function Base.show(io::IO, p::Panel)
+mutable struct DetGeomPanel
+ name
+ corner
+ fsvec
+ ssvec
+ pixel_pitch
+ adu_per_photon
+ max_adu
+ w
+ h
+end
+
+struct DetGeomGroup
+ serial
+ name
+ children
+ center # For rotation
+end
+
+
+mutable struct DetGeom
+ panels::Vector{DetGeomPanel}
+ topgroup::DetGeomGroup
+end
+
+
+function copy_dg_panel(p::InternalPanel)
+ DetGeomPanel(unsafe_string(p.name),
+ [p.cx, p.cy, p.cz],
+ [p.fsx, p.fsy, p.fsz],
+ [p.ssx, p.ssy, p.ssz],
+ p.pixel_pitch, p.adu_per_photon, p.max_adu,
+ p.w, p.h)
+end
+
+
+function copydggroup(panels, grp)
+ grpdata = unsafe_load(grp, 1)
+ name = unsafe_string(grpdata.name)
+ children = DetGeomGroup[]
+ if grpdata.n_children > 1
+ for i in 1:grpdata.n_children
+ cdata = unsafe_load(grpdata.children, i)
+ push!(children, copydggroup(panels, cdata))
+ end
+ DetGeomGroup(grpdata.serial, name, children,
+ [grpdata.cx, grpdata.cy, grpdata.cz])
+ else
+ name = unsafe_string(grpdata.name)
+ pn = findfirst(x->x.name==name, panels)
+ DetGeomGroup(grpdata.serial, name, [panels[pn]],
+ [grpdata.cx, grpdata.cy, grpdata.cz])
+ end
+end
+
+
+function copydetgeom(dg::Ptr{InternalDetGeom})
+ dgdata = unsafe_load(dg, 1)
+ panels = DetGeomPanel[]
+ for i in 1:dgdata.n_panels
+ paneldata = unsafe_load(dgdata.panels, i)
+ push!(panels, copy_dg_panel(paneldata))
+ end
+ topgroup = copydggroup(panels, dgdata.top_group)
+ DetGeom(panels, topgroup)
+end
+
+
+function seq100(ser, head)
+ if ser == 0
+ ()
+ elseif ser < 100
+ (head...,ser % 100)
+ else
+ seq100(ser ÷ 100, (head..., ser % 100))
+ end
+end
+
+findgroup(dg::DetGeom, ser) = findgroup(dg.topgroup, ser, seq100(ser÷100, ()))
+
+function findgroup(group::DetGeomGroup, ser, path)
+ if length(path) == 0
+ @assert(group.serial == ser)
+ return group
+ end
+ findgroup(group.children[path[1]], ser, path[2:end])
+end
+
+
+function Base.show(io::IO, p::DetGeomPanel)
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, p.name)
+ write(io, "\", corner=")
+ show(io, p.corner)
write(io, "), fs=(")
- show(io, p.fsx); write(io, ", "); show(io, p.fsy); write(io, ", "); show(io, p.fsz)
+ show(io, p.fsvec)
write(io, "), ss=(")
- show(io, p.ssx); write(io, ", "); show(io, p.ssy); write(io, ", "); show(io, p.ssz)
+ show(io, p.ssvec)
write(io, "), size=(")
show(io, p.w); write(io, ", "); show(io, p.h)
write(io, "))")
end
+function showgroup(io, p::DetGeomPanel, prefix)
+ println(io, prefix, "Panel ", p.name, " (",p.w,"×",p.h,")")
+end
+
+function showgroup(io, grp::DetGeomGroup, prefix)
+ println(io, prefix, "Group ", grp.name, " (serial number ", grp.serial, ")")
+ for child in grp.children
+ showgroup(io, child, prefix*" ")
+ end
+end
+
+function Base.show(io::IO, ::MIME"text/plain", dg::DetGeom)
+ println(io, "Detector geometry structure with ", length(dg.panels), " panels")
+ showgroup(io, dg.topgroup, " ")
+end
end # of module
diff --git a/julia/CrystFEL/src/image.jl b/julia/CrystFEL/src/image.jl
index d648dba4..cd24ce01 100644
--- a/julia/CrystFEL/src/image.jl
+++ b/julia/CrystFEL/src/image.jl
@@ -4,7 +4,7 @@ using Printf
import ..CrystFEL: libcrystfel
import ..CrystFEL.DataTemplates: DataTemplate, InternalDataTemplate
-import ..CrystFEL.DetGeoms: DetGeom
+import ..CrystFEL.DetGeoms: InternalDetGeom, copydetgeom
import ..CrystFEL.PeakLists: PeakList, InternalPeakList
import ..CrystFEL.Crystals: Crystal, InternalCrystal
import ..CrystFEL.RefLists: RefList, InternalRefList, UnmergedReflection
@@ -29,7 +29,7 @@ mutable struct InternalImage
n_crystals::Cint
indexed_by::Cint
n_indexing_tries::Cint
- detgeom::Ptr{DetGeom}
+ detgeom::Ptr{InternalDetGeom}
data_source_type::Cint
filename::Cstring
ev::Cstring
@@ -135,6 +135,9 @@ function Base.getproperty(image::Image, name::Symbol)
getfield(idata, :crystals),
getfield(idata, :n_crystals))
+ elseif name === :detgeom
+ return copydetgeom(getfield(idata, :detgeom))
+
else
getfield(idata, name)
end
diff --git a/julia/CrystFEL/src/indexing.jl b/julia/CrystFEL/src/indexing.jl
index 543246ec..81a59b52 100644
--- a/julia/CrystFEL/src/indexing.jl
+++ b/julia/CrystFEL/src/indexing.jl
@@ -144,7 +144,8 @@ function index(image::Image, idxr::Indexer; mille=nothing)
idxr.indexingpriv::Ptr{IndexingPriv},
C_NULL::Ptr{Cvoid},
C_NULL::Ptr{Cvoid},
- imille::Ptr{Cvoid})::Cvoid
+ imille::Ptr{Cvoid},
+ 99::Cint)::Cvoid
end
diff --git a/julia/plot-geom.jl b/julia/plot-geom.jl
new file mode 100644
index 00000000..754111e0
--- /dev/null
+++ b/julia/plot-geom.jl
@@ -0,0 +1,162 @@
+using CrystFEL
+using GLMakie
+
+function readmillepede(filename)
+ fh = open(filename, "r")
+ readline(fh) # discard header line
+ motions = map(eachline(fh)) do line
+ sgroupser,sdelta,_ = split(line)
+ (parse(Int,sgroupser), parse(Float64,sdelta))
+ end
+ return motions
+end
+
+function findeigenvector(fh, num)
+ while !eof(fh)
+ l = readline(fh)
+ bits = split(l)
+ if length(bits) == 5
+ if bits[1] == "Eigenvector"
+ if parse(Int, bits[2]) == num
+ return
+ end
+ end
+ end
+ end
+ error("Eigenvector not found")
+end
+
+function readeigenvector(filename, num)
+ fh = open(filename, "r")
+ findeigenvector(fh, num)
+ motions = []
+ while !eof(fh)
+ l = readline(fh)
+ length(l) < 3 && return motions
+ bits = split(l)
+ for i in 1:2:length(bits)
+ push!(motions, (parse(Int,bits[i]), parse(Float64,bits[i+1])))
+ end
+ end
+ return motions
+end
+
+function translate!(panel::DetGeomPanel, vec)
+ panel.corner += vec/panel.pixel_pitch
+end
+
+function translate!(group::DetGeomGroup, vec)
+ for child in group.children
+ translate!(child, vec)
+ end
+end
+
+function rotate2d!(p, c, ang)
+ nx = c[1] + (p[1]-c[1])*cos(ang) - (p[2]-c[2])*sin(ang);
+ ny = c[2] + (p[1]-c[1])*sin(ang) + (p[2]-c[2])*cos(ang);
+ p[1] = nx
+ p[2] = ny
+end
+
+function rotatex!(panel::DetGeomPanel, center, angle)
+ rotate2d!(view(panel.corner, 2:3), center[2:3]/panel.pixel_pitch, angle);
+ rotate2d!(view(panel.fsvec, 2:3), [0,0], angle);
+ rotate2d!(view(panel.ssvec, 2:3), [0,0], angle);
+end
+
+function rotatey!(panel::DetGeomPanel, center, angle)
+ rotate2d!(view(panel.corner, 3:-2:1), center[3:-2:1]/panel.pixel_pitch, angle);
+ rotate2d!(view(panel.fsvec, 3:-2:1), [0,0], angle);
+ rotate2d!(view(panel.ssvec, 3:-2:1), [0,0], angle);
+end
+
+function rotatez!(panel::DetGeomPanel, center, angle)
+ rotate2d!(view(panel.corner, 1:2), center[1:2]/panel.pixel_pitch, angle);
+ rotate2d!(view(panel.fsvec, 1:2), [0,0], angle);
+ rotate2d!(view(panel.ssvec, 1:2), [0,0], angle);
+end
+
+function rotatex!(group::DetGeomGroup, center, angle)
+ for child in group.children
+ rotatex!(child, center, angle)
+ end
+end
+
+function rotatey!(group::DetGeomGroup, center, angle)
+ for child in group.children
+ rotatey!(child, center, angle)
+ end
+end
+
+function rotatez!(group::DetGeomGroup, center, angle)
+ for child in group.children
+ rotatez!(child, center, angle)
+ end
+end
+
+function plotgeom!(dtempl, motions)
+
+ f = Figure(size=(1024,1024))
+ ax = Axis3(f[1,1], aspect=:equal, limits=(nothing,nothing,nothing,nothing,0,0.3),
+ xlabel="x (meters)", ylabel="y (meters)", zlabel="z (meters)")
+ sl = Slider(f[2,1], range=0:0.01:1)
+ btoggle = Toggle(f, halign=:left, tellwidth=false)
+ f[3,1] = grid!([1,1]=>Label(f, "Show beams", halign=:right, tellwidth=false), [1,2]=>btoggle)
+
+ cfimage = CrystFEL.Image(dtempl)
+ triangles = lift(sl.value) do trscale
+
+ dgmoved = cfimage.detgeom # Makes a fresh copy of underlying C structure
+
+ # Apply all `motions` in the same way as align_detector
+ for m in motions
+ param = m[1] % 100
+ group = findgroup(dgmoved, m[1]-param)
+ if param == 1
+ translate!(group, trscale*[-m[2],0,0])
+ elseif param == 2
+ translate!(group, trscale*[0,-m[2],0])
+ elseif param == 3
+ translate!(group, trscale*[0,0,-m[2]])
+ elseif param == 4
+ rotatex!(group, group.center, trscale*-m[2])
+ elseif param == 5
+ rotatey!(group, group.center, trscale*-m[2])
+ elseif param == 6
+ rotatez!(group, group.center, trscale*-m[2])
+ end
+ end
+
+ # Generate triangle mesh from panel descriptions
+ points = Point3f[]
+ for panel in dgmoved.panels
+
+ corner = panel.pixel_pitch*panel.corner
+ fs = panel.pixel_pitch*panel.w*panel.fsvec
+ ss = panel.pixel_pitch*panel.h*panel.ssvec
+
+ push!(points, corner)
+ push!(points, corner+fs)
+ push!(points, corner+fs+ss)
+ push!(points, corner+fs+ss)
+ push!(points, corner+ss)
+ push!(points, corner)
+
+ end
+
+ return points
+
+ end
+
+ beams = map(cfimage.detgeom.panels) do p
+ cen = (p.corner+p.fsvec*p.w/2+p.ssvec*p.h/2)*1.5*p.pixel_pitch
+ ((0,0,0), Tuple(cen))
+ end
+
+ mesh!(triangles, color="#7f7f7f")
+ beamv = lines!(collect(Iterators.flatten(beams[1:4:end])), color="#008080")
+ connect!(beamv.visible, btoggle.active)
+
+ return f
+
+end
diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c
index 80cdd955..a25accbc 100644
--- a/libcrystfel/src/cell-utils.c
+++ b/libcrystfel/src/cell-utils.c
@@ -2245,9 +2245,9 @@ static IntegerMatrix *check_permutations(UnitCell *cell_reduced, UnitCell *refer
best_diff = diff;
n_best = 0;
- }
+ best_m[n_best++] = intmat_copy(m);
- if ( diff < 1.001*best_diff ) {
+ } else if ( diff < 1.001*best_diff ) {
/* If the new solution is the same as the
* previous one, add it to the list */
diff --git a/libcrystfel/src/detgeom.c b/libcrystfel/src/detgeom.c
index 39b00663..2b38664c 100644
--- a/libcrystfel/src/detgeom.c
+++ b/libcrystfel/src/detgeom.c
@@ -269,6 +269,7 @@ gsl_matrix **make_panel_minvs(struct detgeom *dg)
gsl_matrix_set(M, 2, 2, p->pixel_pitch*p->ssz);
Minvs[i] = matrix_invert(M);
+ gsl_matrix_free(M);
if ( Minvs[i] == NULL ) {
ERROR("Failed to calculate inverse panel matrix for %s\n",
p->name);
diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c
index 12cd9190..5b0f742f 100644
--- a/libcrystfel/src/index.c
+++ b/libcrystfel/src/index.c
@@ -50,6 +50,7 @@
#include "cell-utils.h"
#include "predict-refine.h"
#include "profile.h"
+#include "crystfel-mille.h"
#include "indexers/dirax.h"
#include "indexers/asdf.h"
#include "indexers/mosflm.h"
@@ -774,6 +775,12 @@ static int try_indexer(struct image *image, IndexingMethod indm,
}
profile_end("cell-compare-to-others");
+ if ( (mille != NULL) && !crystal_get_user_flag(cr) ) {
+ profile_start("mille-write");
+ crystfel_mille_write_record(mille);
+ profile_end("mille-write");
+ }
+
}
n_bad = remove_flagged_crystals(image);
diff --git a/libcrystfel/src/indexers/pinkindexer.c b/libcrystfel/src/indexers/pinkindexer.c
index 180246c2..14e18548 100644
--- a/libcrystfel/src/indexers/pinkindexer.c
+++ b/libcrystfel/src/indexers/pinkindexer.c
@@ -33,7 +33,6 @@
#include <stdlib.h>
-#include <sys/errno.h>
#include <argp.h>
#include "utils.h"
diff --git a/libcrystfel/src/integration.c b/libcrystfel/src/integration.c
index d2c06db7..6d37116b 100644
--- a/libcrystfel/src/integration.c
+++ b/libcrystfel/src/integration.c
@@ -1467,11 +1467,6 @@ int integrate_rings_once(Reflection *refl,
* appropriate size */
if ( intensity < -aduph ) {
sig2_poisson = -aduph*intensity;
- } else if ( intensity < 0.0 ) {
- /* If the intensity is negative (by less than one
- * photon), assume the reflection is very weak and
- * therefore has a Poisson error of one photon. */
- sig2_poisson = aduph;
}
sigma = sqrt(sig2_poisson + bx->m*sig2_bg);
diff --git a/libcrystfel/src/predict-refine.c b/libcrystfel/src/predict-refine.c
index 6da0d3d1..cc740db3 100644
--- a/libcrystfel/src/predict-refine.c
+++ b/libcrystfel/src/predict-refine.c
@@ -811,7 +811,7 @@ int refine_prediction(struct image *image, Crystal *cr,
reflist = reflist_new();
n = pair_peaks(image, cr, reflist, rps);
- if ( n < 10 ) {
+ if ( n < 3 ) {
cffree(rps);
reflist_free(reflist);
return 1;
@@ -872,6 +872,7 @@ int refine_prediction(struct image *image, Crystal *cr,
crystal_add_notes(cr, tmp);
if ( mille != NULL ) {
+ crystfel_mille_delete_last_record(mille);
profile_start("mille-calc");
write_mille(mille, n, crystal_get_cell(cr), rps, image,
max_mille_level, Minvs);
@@ -887,18 +888,10 @@ int refine_prediction(struct image *image, Crystal *cr,
n = pair_peaks(image, cr, NULL, rps);
free_rps_noreflist(rps, n);
- if ( n < 10 ) {
- if ( mille != NULL ) {
- crystfel_mille_delete_last_record(mille);
- }
- return 1;
- }
- if ( mille != NULL ) {
- profile_start("mille-write");
- crystfel_mille_write_record(mille);
- profile_end("mille-write");
+ if ( n < 3 ) {
+ return 1;
+ } else {
+ return 0;
}
-
- return 0;
}
diff --git a/libcrystfel/src/utils.c b/libcrystfel/src/utils.c
index 7bfac487..0ff09b58 100644
--- a/libcrystfel/src/utils.c
+++ b/libcrystfel/src/utils.c
@@ -162,12 +162,30 @@ gsl_matrix *matrix_invert(gsl_matrix *m)
}
gsl_permutation_free(perm);
- gsl_matrix_free(m);
return inv;
}
+gsl_vector *solve_inv(gsl_vector *v, gsl_matrix *M)
+{
+ gsl_matrix *Minv;
+ gsl_vector *s;
+ int n;
+
+ n = v->size;
+ if ( v->size != M->size1 ) return NULL;
+ if ( v->size != M->size2 ) return NULL;
+
+ Minv = matrix_invert(M);
+ if ( Minv == NULL ) return NULL;
+
+ s = gsl_vector_calloc(n);
+ gsl_blas_dgemv(CblasNoTrans, 1.0, M, v, 0.0, s);
+ return s;
+}
+
+
static int check_eigen(gsl_vector *e_val, int verbose)
{
int i;
diff --git a/libcrystfel/src/utils.h b/libcrystfel/src/utils.h
index 30a7c4ef..08e059a7 100644
--- a/libcrystfel/src/utils.h
+++ b/libcrystfel/src/utils.h
@@ -75,6 +75,7 @@ extern "C" {
extern void show_matrix_eqn(gsl_matrix *M, gsl_vector *v);
extern void show_matrix(gsl_matrix *M);
extern void show_vector(gsl_vector *M);
+extern gsl_vector *solve_inv(gsl_vector *v, gsl_matrix *M);
extern gsl_vector *solve_svd(gsl_vector *v, gsl_matrix *M, int *n_filt,
int verbose);
extern gsl_matrix *matrix_mult2(gsl_matrix *A, gsl_matrix *B);
diff --git a/src/im-asapo.c b/src/im-asapo.c
index 6df14e93..9b57883c 100644
--- a/src/im-asapo.c
+++ b/src/im-asapo.c
@@ -55,6 +55,7 @@ struct im_asapo
AsapoProducerHandle producer;
AsapoStringHandle group_id;
int wait_for_stream;
+ int use_ack;
};
@@ -173,7 +174,10 @@ struct im_asapo *im_asapo_connect(struct im_asapo_params *params)
a->group_id = asapo_string_from_c_str(params->group_id);
a->wait_for_stream = params->wait_for_stream;
- asapo_consumer_set_resend_nacs(a->consumer, 1, 10000, 3);
+ a->use_ack = params->use_ack;
+ if ( a->use_ack ) {
+ asapo_consumer_set_resend_nacs(a->consumer, 1, 60000, 3);
+ }
asapo_free_handle(&cred);
@@ -275,13 +279,15 @@ void *im_asapo_fetch(struct im_asapo *a, size_t *pdata_size,
void im_asapo_finalise(struct im_asapo *a, uint64_t message_id)
{
- AsapoErrorHandle err = asapo_new_handle();
- asapo_consumer_acknowledge(a->consumer, a->group_id, message_id,
- a->stream, &err);
- if ( asapo_is_error(err) ) {
- show_asapo_error("Couldn't acknowledge ASAP::O message", err);
+ if ( a->use_ack ) {
+ AsapoErrorHandle err = asapo_new_handle();
+ asapo_consumer_acknowledge(a->consumer, a->group_id, message_id,
+ a->stream, &err);
+ if ( asapo_is_error(err) ) {
+ show_asapo_error("Couldn't acknowledge ASAP::O message", err);
+ }
+ asapo_free_handle(&err);
}
- asapo_free_handle(&err);
}
diff --git a/src/im-asapo.h b/src/im-asapo.h
index d06f9527..70f67fd0 100644
--- a/src/im-asapo.h
+++ b/src/im-asapo.h
@@ -45,6 +45,7 @@ struct im_asapo_params
int wait_for_stream;
int write_output_stream;
int consumer_timeout_ms;
+ int use_ack;
};
struct im_asapo;
diff --git a/src/indexamajig.c b/src/indexamajig.c
index 9416d234..00b15b55 100644
--- a/src/indexamajig.c
+++ b/src/indexamajig.c
@@ -474,6 +474,10 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
}
break;
+ case 226 :
+ args->asapo_params.use_ack = 1;
+ break;
+
/* ---------- Peak search ---------- */
case 't' :
@@ -932,6 +936,7 @@ int main(int argc, char *argv[])
args.asapo_params.wait_for_stream = 0;
args.asapo_params.write_output_stream = 0;
args.asapo_params.consumer_timeout_ms = 500;
+ args.asapo_params.use_ack = 0;
args.cpu_pin = 0;
args.serial_start = 1;
args.if_peaks = 1;
@@ -1065,6 +1070,7 @@ int main(int argc, char *argv[])
"Shut down after this many seconds without ASAP::O data"},
{"asapo-consumer-timeout", 225, "ms", OPTION_NO_USAGE,
"ASAP::O get_next timeout for one frame (milliseconds)"},
+ {"asapo-acks", 226, NULL, OPTION_NO_USAGE, "Use ASAP::O acknowledgements"},
{NULL, 0, 0, OPTION_DOC, "Peak search options:", 3},
{"peaks", 301, "method", 0, "Peak search method. Default: zaef"},