aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2024-01-18 17:55:45 +0100
committerThomas White <taw@physics.org>2024-02-06 16:59:35 +0100
commit1b4fdfa5cc1ab4fe9a1cdcbb0bf1602834eaec13 (patch)
tree03061175385337244c7605c5810db1d6affcd779
parentff89f33377133352838f27057525701e71c9df7c (diff)
Julia: MM semantics for Image.crystals
-rw-r--r--julia/CrystFEL/src/image.jl42
-rw-r--r--julia/make-indexed.jl26
-rw-r--r--libcrystfel/src/image.c10
-rw-r--r--libcrystfel/src/image.h2
4 files changed, 70 insertions, 10 deletions
diff --git a/julia/CrystFEL/src/image.jl b/julia/CrystFEL/src/image.jl
index a9d9c28f..3384f0c9 100644
--- a/julia/CrystFEL/src/image.jl
+++ b/julia/CrystFEL/src/image.jl
@@ -14,6 +14,8 @@ const HEADER_CACHE_SIZE = 128
mutable struct CrystalRefListPair
crystal::Ptr{InternalCrystal}
reflist::Ptr{InternalRefList}
+ owns_crystal::Cint
+ owns_reflist::Cint
end
mutable struct InternalImage
@@ -55,7 +57,7 @@ mutable struct Image
end
-function makecrystallist(listptr, n)
+function makecrystallist(image, listptr, n)
crystals = []
@@ -65,16 +67,33 @@ function makecrystallist(listptr, n)
for i in 1:n
pairptr = unsafe_load(listptr, i)
- cr = Crystal(pairptr.crystal)
+
+ # Re-use old Crystal if possible
+ n = findfirst(getfield(image, :crystals)) do x
+ x.internalptr == pairptr.crystal
+ end
+
+ if n !== nothing
+ cr = getfield(image, :crystals)[n]
+ else
+ cr = Crystal(pairptr.crystal)
+ end
+
if pairptr.reflist == C_NULL
reflist = nothing
else
reflist = RefList{UnmergedReflection}(pairptr.reflist, SymOpList("1"))
+ pairptr.owns_reflist = 0
end
push!(crystals, (crystal=cr, reflections=reflist))
+ pairptr.owns_crystal = 0
+ unsafe_store!(listptr, pairptr, i)
+ # We are now responsible for freeing the Crystal and RefList
end
- crystals
+ image.crystals = map(x->x.crystal, crystals)
+ image.reflists = map(x->x.reflections, crystals)
+ return crystals
end
@@ -104,11 +123,12 @@ function Base.getproperty(image::Image, name::Symbol)
idata = unsafe_load(image.internalptr)
if name === :crystals
- return makecrystallist(getproperty(idata, :crystals),
- getproperty(idata, :n_crystals))
+ return makecrystallist(image,
+ getfield(idata, :crystals),
+ getfield(idata, :n_crystals))
else
- getproperty(idata, name)
+ getfield(idata, name)
end
end
end
@@ -155,6 +175,12 @@ function Base.setproperty!(image::Image, name::Symbol, val)
assert_type(val, AbstractString)
val = strdup(val)
+ elseif name === :crystals
+ return setfield!(image, :crystals, val)
+
+ elseif name === :reflists
+ return setfield!(image, :reflists, val)
+
end
idata = unsafe_load(image.internalptr)
@@ -202,7 +228,7 @@ function Image(dtempl::DataTemplate)
throw(ArgumentError("Failed to create image"))
end
- image = Image(out, nothing)
+ image = Image(out, nothing, [], [])
finalizer(image) do x
ccall((:image_free, libcrystfel), Cvoid, (Ptr{InternalImage},), x.internalptr)
@@ -234,7 +260,7 @@ function Image(dtempl::DataTemplate,
throw(ArgumentError("Failed to load image"))
end
- image = Image(out, nothing)
+ image = Image(out, nothing, [], [])
finalizer(image) do x
ccall((:image_free, libcrystfel), Cvoid, (Ptr{InternalImage},), x.internalptr)
diff --git a/julia/make-indexed.jl b/julia/make-indexed.jl
new file mode 100644
index 00000000..7a24f606
--- /dev/null
+++ b/julia/make-indexed.jl
@@ -0,0 +1,26 @@
+using CrystFEL
+using Random
+
+# "Simulate" a diffraction pattern from the reflections
+function sketch_pattern(image, cr)
+ reflist = predictreflections(cr, image)
+ peaklist = PeakList()
+ for refl in reflist
+ if randn() > 0
+ let dpos = refl.detectorposition
+ push!(peaklist, dpos.fs, dpos.ss, dpos.panelnumber, 100.0)
+ end
+ end
+ end
+ return peaklist
+end
+
+
+dtempl = loaddatatemplate("julia/alignment-test.geom")
+cell = UnitCell(MonoclinicLattice, PrimitiveCell, 123, 45, 80, 90, 97, 90)
+indexer = Indexer("asdf", dtempl, cell, retry=false, multilattice=false, refine=true)
+
+image = Image(dtempl)
+cr = Crystal(rotatecell(cell))
+image.peaklist = sketch_pattern(image, cr)
+index(image, indexer)
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index ab4518a9..e91c09d6 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -333,6 +333,8 @@ void image_add_crystal_refls(struct image *image,
crs[n].cr = cryst;
crs[n].refls = reflist;
+ crs[n].image_owns_crystal = 1;
+ crs[n].image_owns_refls = 1;
image->crystals = crs;
image->n_crystals = n+1;
}
@@ -373,8 +375,12 @@ void free_all_crystals(struct image *image)
int i;
if ( image->crystals == NULL ) return;
for ( i=0; i<image->n_crystals; i++ ) {
- crystal_free(image->crystals[i].cr);
- reflist_free(image->crystals[i].refls);
+ if ( image->crystals[i].image_owns_crystal ) {
+ crystal_free(image->crystals[i].cr);
+ }
+ if ( image->crystals[i].image_owns_refls ) {
+ reflist_free(image->crystals[i].refls);
+ }
}
cffree(image->crystals);
image->crystals = NULL;
diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h
index 74ff6eee..3db7de18 100644
--- a/libcrystfel/src/image.h
+++ b/libcrystfel/src/image.h
@@ -114,6 +114,8 @@ struct crystal_refls
{
Crystal *cr;
RefList *refls;
+ int image_owns_crystal;
+ int image_owns_refls;
};
struct image