Click here to go to the corresponding page for the latest version of DIALS
Developer Tutorial¶
DIALS has been designed to be extensible. If you’ve got a great idea for a new integration algorithm, then, with a bit of work, you should be able to get it running within the DIALS framework. The following tutorial applies for both developers looking to put their algorithms within DIALS itself as well as for those adding algorithms in their own installation.
Spot Finding¶
Algorithms for computing the possible spot pixels used in spot finding should implement the following interface. An example can be found under “dials/extensions/kabsch_spotfinder_threshold_ext.py”.
class SpotFinderThresholdIface(interface.Interface):
def __init__(self, params, imageset):
pass
@interface.abstractmethod
def compute_threshold(self, image, mask):
pass
The algorithm is configured through phil parameters and the imageset.
The extension should also provide a compute_threshold
method which
takes an image and a mask and should return a flex.bool array of the same
dimensions where True
pixels are possible spot pixels and False
pixels are background.
Profile Modelling¶
Warning
The profile modelling framework is not very mature and may be changed. I’ll try and keep the documentation up-to-date.
Algorithms for computing the profile model should implement the following interface. An example can be found under “dials/extensions/gaussian_rs_profile_model_ext.py”.
class ProfileModelCreatorIface(interface.Interface):
@interface.abstractmethod
def create(cls, params, experiments, reflections=None):
pass
The profile algorithm should have a “create” method that is given phil parameters, experiments and (optionally) reflections. In the absence of reflections, the profile model should be constructable from phil parameters. When reflections are present, the create method should be able to construct the model from the input reflections and experiments.
The algorithm should return an instance of the ProfileModelList class (found in
dials.algorithms.profile_model.model_list
). The profile model list
should contain a list of objects which implement the interface given in
the dials.algorithms.profile_model.interface
module and shown in brief
below.
class ProfileModelIface(object):
@interface.abstractmethod
def predict_reflections(self, experiment, **kwargs):
pass
@interface.abstractmethod
def compute_bbox(self, experiment, reflections, **kwargs):
pass
@interface.abstractmethod
def compute_partiality(self, experiment, reflections, **kwargs):
pass
@interface.abstractmethod
def compute_mask(self, experiment, reflections, **kwargs):
pass
@interface.abstractmethod
def dump(self):
pass
The profile model should have methods for predicting the reflections, computing the bounding box of reflections for a number of experiments, computing the partiality of reflections and computing the foreground/background mask. Of these the bounding box and mask methods are crucial for integration to work; partiality is currently only used in reporting and can be a placeholder.
The extention should have the ability to dump the profile model to phil parameters so that it can be input via a profile.phil file to, for example, re-run integration with the same profile parameters.
Indexing¶
FIXME
Refinement¶
FIXME
Integration¶
Centroid algorithms¶
Algorithms for computing the reflection centroid should implement the following interface. An example can be found under “dials/extensions/simple_centroid_ext.py”.
class CentroidIface(interface.Interface):
def __init__(self, params, experiments):
pass
@interface.abstractmethod
def compute_centroid(self, reflections):
pass
The algorithm is configured through phil parameters and the list of experiments.
The extension should also provide a compute_centroid
method which
takes a list of reflections with extracted shoebox data. The “shoebox” column of
the reflection table should contain a list of dials.model.Shoebox
types.
The algorithm should fill the “xyzobs.px” column of the reflection table with
the observed centroid positions.
Background algorithms¶
Algorithms for computing the reflection background should implement the following interface. An example can be found under “dials/extensions/simple_background_ext.py”.
class BackgroundIface(interface.Interface):
def __init__(self, params, experiments):
pass
@interface.abstractmethod
def compute_background(self, reflections):
pass
The algorithm is configured through phil parameters and the list of experiments.
The extension should also provide a compute_background
method which
takes a list of reflections with extracted shoebox data. The “shoebox” column of
the reflection table should contain a list of dials.model.Shoebox
types.
The algorithm should fill the shoebox.background values and return the
reflection list.
Deploying algorithms¶
Within the DIALS project¶
The DIALS project has the following layout.
dials
|
|-- algorithms
| |
| |-- integration
| |
| |-- sum
| |
| |-- ...
|
|-- interfaces
| |
| |-- ...
|
|-- extensions
|
|-- summation_integration_ext.py
|
|-- ...
Each algorithm should have its implementation encapsulated within a package in the appropriate place. For example, summation integration is implemented within the “dials.algorithms.integration.sum” package. The extension class, which inherits from the appropriate interface, and configures and calls this algorithm should then be placed in the “dials/extensions” folder with an appropriate name. For example, the summation integration extension is placed in the module “dials.extensions.summation_integration_ext”. Modules within the dials.extension package will be automatically loaded when searching for algorithms and any class within these modules that inherits from an interface will be registered for use within the DIALS command line programs.
Within external projects¶
If you have a project containing algorithms written for use within DIALS that is built using the cctbx build system, it is easy to make DIALS aware of your new algorithms.
A typical project layout is shown below.
my_project
|
|-- algorithms
| |
| |-- integration
| |
| |-- my_algorithm
| |
| |-- ...
|
|-- extensions
|
|-- my_algorithm_intensity_ext.py
If your project has this directory structure, with an intensity algorithm implementation within the “my_algorithm” directory and the extension class (inheriting from the IntensityIface class) in the “extension” directory you can make DIALS aware of your algorithm by adding the following code to the libtbx_refresh.py scripy in the top level of your project. This will add the extensions directory in your project to the list of directories searched when loading available algorithms.
# libtbx_refresh.py
from __future__ import division
try:
from dials.framework import env
import libtbx.load_env
from os.path import join
path = libtbx.env.dist_path("my_project")
env.cache.add(join(path, "extensions"))
except Exception:
pass
Running “libtbx.refresh” or “make reconf” will update your build. You can check that your algorithm has been found properly by using the “dials.show_extensions” command-line program which should show a list of extensions implementing each interface with your algorithm listed with the other available algorithms.