# 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
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
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.

FIXME

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