Tools

Camera configuration

class crappy.tool.cameraConfig.Camera_config(camera)[source]

This class is a GUI allowing the user to visualize the images from a camera before a Crappy test starts, and to tune the settings of the camera.

It is meant to be user-friendly and interactive. It is possible to zoom on the image using the mousewheel, and to move on the zoomed image by left-clicking and dragging.

In addition to the image, the interface also displays a histogram of the pixel values, an FPS counter, a detected bits counter, the minimum and maximum pixel values and the value and position of the pixel currently under the mouse. A checkbox allows auto-adjusting the pixel range to get a better contrast.

__init__(camera) None[source]

Initializes the interface and starts displaying the first image.

Parameters:

camera – The camera object in charge of acquiring the images.

main() None[source]

Constantly updates the image and the information on the GUI, until asked to stop.

Comedi Bind

This file contains the code for binding the C++ Comedi library in Python.

The bindings haven’t been tested for a while.

class crappy.tool.comedi_bind.comedi_range[source]
class crappy.tool.comedi_bind.comedi_t[source]

Discorrel tool

class crappy.tool.discorrel.DISCorrel(fields: List[str] | None = None, alpha: float = 3, delta: float = 1, gamma: float = 0, finest_scale: int = 1, init: bool = True, iterations: int = 1, gradient_iterations: int = 10, patch_size: int = 8, patch_stride: int = 3)[source]

This class simply stores the data needed for performing image correlation using DisFlow, and also performs the correlation.

Multiple parameters of DisFlow can be tuned, but not all of them. The class also takes care of projecting the image on the chosen base of fields, and optionally to estimate the residuals of the correlation process.

__init__(fields: List[str] | None = None, alpha: float = 3, delta: float = 1, gamma: float = 0, finest_scale: int = 1, init: bool = True, iterations: int = 1, gradient_iterations: int = 10, patch_size: int = 8, patch_stride: int = 3) None[source]

Sets the parameters of DisFlow.

Parameters:
  • fields

    The base of fields to use for the projection, given as a list of str. The available fields are :

    'x', 'y', 'r', 'exx', 'eyy', 'exy', 'eyx', 'exy2', 'z'
    

  • alpha – Weight of the smoothness term in DisFlow.

  • delta – Weight of the color constancy term in DisFlow.

  • gamma – Weight of the gradient constancy term in DisFlow

  • finest_scale – Finest level of the Gaussian pyramid on which the flow is computed in DisFlow (0 means full scale).

  • init – If True, the last field is used to initialize the calculation for the next one.

  • iterations – Maximum number of gradient descent iterations in the patch inverse search stage in DisFlow.

  • gradient_iterations – Maximum number of gradient descent iterations in the patch inverse search stage in DisFlow.

  • patch_size – Size of an image patch for matching in DisFlow (in pixels).

  • patch_stride – Stride between neighbor patches in DisFlow. Must be less than patch size.

get_data(img: ndarray, residuals: bool = False) List[float][source]

Processes the input image and returns the required data in a list.

Parameters:
  • img – The new image to process.

  • residuals – Whether the residuals should be calculated or not for the image.

Returns:

A list containing the data to calculate, and the residuals at the end if requested.

set_box(box: Box) None[source]

Sets the region of interest to use for the correlation, and initializes other attributes.

set_img0(img0: ndarray) None[source]

Sets the initial image to use for the correlation.

Discorrel configuration

class crappy.tool.discorrelConfig.DISConfig(camera)[source]

Class similar to Camera configuration but also allowing to select the area on which the correlation will be performed.

It is meant to be used for configuring the Discorrel block.

__init__(camera) None[source]

Initializes the parent class and sets the correl box.

property box: Box

Returns the Box object containing the region of interest.

Disve tool

class crappy.tool.disve.DISVE(patches: Spot_boxes, method: str = 'Disflow', alpha: float = 3, delta: float = 1, gamma: float = 0, finest_scale: int = 1, iterations: int = 1, gradient_iterations: int = 10, patch_size: int = 8, patch_stride: int = 3, border: float = 0.2, safe: bool = True, follow: bool = True)[source]

This tool computes the displacement of regions of interest (patches) on an image compared to a reference image.

It relies on cross-correlation algorithms to calculate the displacement. Different algorithms are available depending on the needs. This tool is mainly used to perform video-extensometry on speckled surfaces, although it can as well be of use for other applications.

__init__(patches: Spot_boxes, method: str = 'Disflow', alpha: float = 3, delta: float = 1, gamma: float = 0, finest_scale: int = 1, iterations: int = 1, gradient_iterations: int = 10, patch_size: int = 8, patch_stride: int = 3, border: float = 0.2, safe: bool = True, follow: bool = True) None[source]

Sets a few attributes and initializes Disflow if this method was selected.

Parameters:
  • patches – The regions to track, given as a Spot_boxes object.

  • method – The method to use to calculate the displacement. Disflow uses opencv’s DISOpticalFlow and Lucas Kanade uses opencv’s calcOpticalFlowPyrLK, while all other methods are based on a basic cross-correlation in the Fourier domain. Pixel precision calculates the displacement by getting the position of the maximum of the cross-correlation, and has thus a 1-pixel resolution. It is mainly meant for debugging. Parabola refines the result of Pixel precision by interpolating the neighborhood of the maximum, and have thus sub-pixel resolutions.

  • alpha – Weight of the smoothness term in DisFlow.

  • delta – Weight of the color constancy term in DisFlow.

  • gamma – Weight of the gradient constancy term in DisFlow.

  • finest_scale – Finest level of the Gaussian pyramid on which the flow is computed in DisFlow (0 means full scale).

  • iterations – Maximum number of gradient descent iterations in the patch inverse search stage in DisFlow.

  • gradient_iterations – Maximum number of gradient descent iterations in the patch inverse search stage in DisFlow.

  • patch_size – Size of an image patch for matching in DisFlow (in pixels).

  • patch_stride – Stride between neighbor patches in DisFlow. Must be less than patch size.

  • border – Crop the patch on each side according to this value before calculating the displacements. 0 means no cropping, 1 means the entire patch is cropped.

  • safe – If True, checks whether the patches aren’t exiting the image, and raises an error if that’s the case.

  • follow – It True, the patches will move to follow the displacement of the image.

calculate_displacement(img: ndarray) List[float][source]

Returns the displacement of every patch, calculated according to the chosen method.

Also updates the patch offsets if required, and updates the window for following the patches if any.

set_img0(img0: ndarray) None[source]

Sets the reference image for the cross-correlation.

Disve configuration

class crappy.tool.disveConfig.DISVE_config(camera, patches: Spot_boxes)[source]

Class similar to Camera configuration but also displaying the bounding boxes of the regions defined as patches.

It is meant to be used for configuring the Disve block.

__init__(camera, patches: Spot_boxes) None[source]

Sets the patches and initializes the parent class.

Parameters:
  • camera – The camera object in charge of acquiring the images.

  • patches – The patches to follow for image correlation.

Fields

crappy.tool.fields.get_field(field_string: str, h: int, w: int) -> (<class 'numpy.ndarray'>, <class 'numpy.ndarray'>)[source]

Creates and returns the two fields on which the image will be projected, as numpy arrays.

Parameters:
  • field_string – The string describing the field on which to project the image for correlation.

  • h – The height of the image.

  • w – The width of the image.

crappy.tool.fields.get_res(ref: ndarray, img: ndarray, flow: ndarray) ndarray[source]
Calculates the difference between the original image and the one

reconstructed from the current image and the calculated flow.

Parameters:
  • ref – The reference image for calculating the optical flow

  • img – The current image for calculating the optical flow

  • flow – The calculated optical flow

FT232H

class crappy.tool.ft232h.ft232h.Find_serial_number(serial_number: str)[source]

A class used for finding USB devices matching a given serial number, using the usb.core.find method.

class crappy.tool.ft232h.ft232h.ft232h(mode: str, serial_nr: str | None = None, i2c_speed: float = 100000.0, spi_turbo: bool = False)[source]

A class for controlling FTDI’s USB to Serial FT232H.

Communication in SPI and I2C are implemented, along with GPIO control. The name of the methods for SPI and I2C communication are those of smbus and spidev libraries, in order to facilitate the use and the integration in a multi-backend environment. This class also allows to write a USB serial number in the EEPROM, as there’s no default serial number on the chip.

Note

The FT232H does not support clock stretching and this may cause bugs with some I2C devices. Lowering the i2c_speed may solve the problem.

Important

If using Adafruit’s board, its I2C Mode switch should of course be set to the correct value according to the chosen mode.

Important

Only for Linux users: In order to drive the FT232H, the appropriate udev rule should be set. This can be done using the udev_rule_setter utility in crappy’s util folder. It is also possible to add it manually by running:

$ echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0403\", MODE=\"0666\"" | sudo tee ftdi.rules > /dev/null 2>&1

in a shell opened in /etc/udev/rules.d.

Important

For controlling several FT232H from the same computer, it is first necessary to set their USB serial numbers. Otherwise, an error will be raised. This can be done using the crappy utility Set_ft232h_serial_nr.py.

class BitMode(value)[source]

Commands for changing the bit mode.

__init__(mode: str, serial_nr: str | None = None, i2c_speed: float = 100000.0, spi_turbo: bool = False) None[source]

Checks the arguments validity, initializes the device and sets the locks.

Parameters:
  • mode (str) –

    The communication mode, can be :

    'SPI', 'I2C', 'GPIO_only', 'Write_serial_nr'
    

    GPIOs can be driven in any mode, but faster speeds are achievable in GPIO_only mode.

  • serial_nr (str, optional) – The serial number of the FT232H to drive. In Write_serial_nr mode, the serial number to be written.

  • i2c_speed (str, optional) –

    In I2C mode, the I2C bus clock frequency in Hz. Available values are :

    100E3, 400E3, 1E6
    

    or any value between 10kHz and 100kHz. Lowering below the default value may solve I2C clock stretching issues on some devices.

  • spi_turbo (str, optional) – Increases the achievable bus speed, but may not work with some devices.

Note

  • CS pin: The CS pin for selecting SPI devices is always D3. This pin is reserved and cannot be used as a GPIO. If you want to drive the CS line manually, it is possible not to drive the CS pin by setting the SPI parameter no_cs to True and to drive the CS line from a GPIO instead.

  • mode: It is not possible to simultaneously control slaves over SPI and I2C, due to different hardware requirements for the two protocols. Trying to do so will most likely raise an error or lead to inconsistent behavior.

property bits_per_word: int

Number of bits per SPI words.

Can only be set to 8.

close() None[source]

Closes the FTDI interface/port.

property cshigh: bool

If True, the polarity of the CS line is inverted.

get_gpio(gpio_str: str) bool[source]

Reads the 3.3V-logic voltage value of the specified pin.

Parameters:

gpio_str (str) – Name of the GPIO to be read

Returns:

3.3V-logic value corresponding to the input voltage

i2c_rdwr(*i2c_msgs) None[source]

Exchanges messages with a slave that doesn’t feature registers.

A start condition is sent at the beginning of each transaction, but only one stop condition is sent after the last transaction.

Parameters:

*i2c_msgs – Messages to exchange with the slave. They are either read or write messages.

property loop: bool

If True, the loopback mode is enabled.

property lsbfirst: bool

If True, data is sent and received LSB first.

property max_speed_hz: float

The SPI bus clock frequency in Hz.

In SPI modes 1 and 3, the actual bus clock frequency is 50% higher than the input value because the FT232H is switched to 3-phase clock mode.

property mode: int

The SPI mode used for communicating with the slave.

When changing the SPI mode, the bus clock frequency may be reloaded.

property no_cs: bool

If True, the CS line is not driven.

read_byte(i2c_addr: int) int[source]

Reads a single byte from an I2C slave, from the register 0.

Parameters:

i2c_addr (int) – I2C address of the slave

Returns:

Value of the read register

read_byte_data(i2c_addr: int, register: int) int[source]

Reads a single byte from an I2C slave, from the specified register.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the register to be read

Returns:

Value of the read register

read_i2c_block_data(i2c_addr: int, register: int, length: int) list[source]

Reads a given number of bytes from an I2C slave, starting at the specified register.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the first register to be read

  • length (int) – Number of bytes to read

Returns:

Values of read registers as a list

read_word_data(i2c_addr: int, register: int) int[source]

Reads 2 bytes from an I2C slave, starting at the specified register, and returns them as one single value.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the first register to be read

Returns:

Value of the read registers

readbytes(len: int, start: bool = True, stop: bool = True) list[source]

Reads the specified number of bytes from an SPI slave.

Parameters:
  • len (int) – Number of bytes to read

  • start (bool) – If False, the CS line is not driven before reading data, and remains in its previous state.

  • stop (bool) – If False, the CS line is not driven after reading data, and remains in its previous state.

Returns:

List of read bytes

set_gpio(gpio_str: str, value: int) None[source]

Sets the specified GPIO as an output and sets its output value.

Parameters:
  • gpio_str (str) – Name of the GPIO to be set

  • value (int) – 1 for setting the GPIO high, 0 for setting it low

property threewire: bool

If True, indicates that the MISO and MOSI lines are connected together. Not currently implemented.

write_block_data(i2c_addr: int, register: int, data: list) None[source]

Actually calls write_i2c_block_data().

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the first register to be written

  • data (list) – List of bytes to write

write_byte(i2c_addr: int, value: int) None[source]

Writes a single byte to an I2C slave, in register 0.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • value (int) – The value to write

write_byte_data(i2c_addr: int, register: int, value: int) None[source]

Writes a single byte to an I2C slave, in the specified register.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the register to be written

  • value (int) – The value to write

write_i2c_block_data(i2c_addr: int, register: int, data: list) None[source]

Writes bytes from a list to an I2C slave, starting at the specified register.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the first register to be written

  • data (list) – List of bytes to write

write_word_data(i2c_addr: int, register: int, value: int) None[source]

Writes 2 bytes to an I2C slave from a single int value, starting at the specified register.

Depending on the size of the registers, the next register may be written as well.

Parameters:
  • i2c_addr (int) – I2C address of the slave

  • register (int) – Index of the first register to be written

  • value (int) – The value to write

writebytes(values: list, start: bool = True, stop: bool = True) None[source]

Write bytes from a list to an SPI slave.

Parameters:
  • values (list) – List of bytes to write

  • start (bool) – If False, the CS line is not driven before reading data, and remains in its previous state.

  • stop (bool) – If False, the CS line is not driven after reading data, and remains in its previous state.

writebytes2(values: list, start: bool = True, stop: bool = True) None[source]

Actually calls the writebytes() method with the same arguments.

xfer(values: list, speed: float | None = None, delay: float = 0.0, bits: int = 8, start: bool = True, stop: bool = True) list[source]

Simultaneously reads and write bytes to an SPI slave.

The number of bytes to read is equal to the number of bytes in the write buffer.

Parameters:
  • values (list) – List of bytes to write

  • speed (float) – Sets the bus clock frequency before issuing the command (in Hz)

  • delay (float) – Not implemented, should be 0.0

  • bits (int) – Not implemented, should be 8

  • start (bool) – If False, the CS line is not driven before reading data, and remains in its previous state.

  • stop (bool) – If False, the CS line is not driven after reading data, and remains in its previous state.

Returns:

List of read bytes

xfer2(values: list, speed: float = 6000000.0, delay: float = 0.0, bits: int = 8, start: bool = True, stop: bool = True) list[source]

Actually calls the xfer() method with the same arguments.

xfer3(values: list, speed: float = 6000000.0, delay: float = 0.0, bits: int = 8, start: bool = True, stop: bool = True) list[source]

Actually calls the xfer() method with the same arguments.

crappy.tool.ft232h.ft232h.ft232h_i2c_timings

alias of I2CTimings

FT232H Server

crappy.tool.ft232h.ft232h_server.ft232h_i2c_timings

alias of I2CTimings

class crappy.tool.ft232h.ft232h_server.ft232h_server(mode: str, block_number: int, current_file: FileIO, command_file: FileIO, answer_file: FileIO, block_lock: RLock, current_lock: RLock, serial_nr: str | None = None, i2c_speed: float = 100000.0, spi_turbo: bool = False)[source]

A class for controlling FTDI’s USB to Serial FT232H.

This class is very similar to the ft232h except it doesn’t directly instantiate the USB device nor send commands to it directly. Instead, the commands are sent to a USB server managing communication with the different FT232H devices.

Communication in SPI and I2C are implemented, along with GPIO control. The name of the methods for SPI and I2C communication are those of smbus and spidev libraries, in order to facilitate the use and the integration in a multi-backend environment. This class also allows to write a USB serial number in the EEPROM, as there’s no default serial number on the chip.

Note

The FT232H does not support clock stretching and this may cause bugs with some I2C devices. Lowering the i2c_speed may solve the problem.

Important

If using Adafruit’s board, its I2C Mode switch should of course be set to the correct value according to the chosen mode.

Important

Only for Linux users: In order to drive the FT232H, the appropriate udev rule should be set. This can be done using the udev_rule_setter utility in crappy’s util folder. It is also possible to add it manually by running:

$ echo "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0403\", MODE=\"0666\"" | sudo tee ftdi.rules > /dev/null 2>&1

in a shell opened in /etc/udev/rules.d.

Important

For controlling several FT232H from the same computer, it is first necessary to set their USB serial numbers. Otherwise, an error will be raised. This can be done using the crappy utility Set_ft232h_serial_nr.py.

__init__(mode: str, block_number: int, current_file: FileIO, command_file: FileIO, answer_file: FileIO, block_lock: RLock, current_lock: RLock, serial_nr: str | None = None, i2c_speed: float = 100000.0, spi_turbo: bool = False) None[source]

Checks the argument validity and initializes the device.

Parameters:
  • mode

    The communication mode, can be :

    'SPI', 'I2C', 'GPIO_only', 'Write_serial_nr'
    

    GPIOs can be driven in any mode, but faster speeds are achievable in GPIO_only mode.

  • block_number – The index the block driving this ft232h_server instance has been assigned.

  • current_file – A file in which the index of the block currently allowed to drive the USB server is written.

  • command_file – A file in which the current command to be executed by the USB server is written.

  • answer_file – A file in which the answer to the current command is written.

  • block_lock – A lock assigned to this block only, for signaling the USB server when the command has been written in the command_file.

  • current_lock – A lock common to all the blocks that allows the one block holding it to communicate with the USB server.

  • serial_nr (str, optional) – The serial number of the FT232H to drive. In Write_serial_nr mode, the serial number to be written.

  • i2c_speed

    In I2C mode, the I2C bus clock frequency in Hz. Available values are :

    100E3, 400E3, 1E6
    

    or any value between 10kHz and 100kHz. Lowering below the default value may solve I2C clock stretching issues on some devices.

  • spi_turbo – Increases the achievable bus speed, but may not work with some devices.

Note

  • CS pin: The CS pin for selecting SPI devices is always D3. This pin is reserved and cannot be used as a GPIO. If you want to drive the CS line manually, it is possible not to drive the CS pin by setting the SPI parameter no_cs to True and to drive the CS line from a GPIO instead.

  • mode: It is not possible to simultaneously control slaves over SPI and I2C, due to different hardware requirements for the two protocols. Trying to do so will most likely raise an error or lead to inconsistent behavior.

close() None[source]

Closes the FTDI interface/port.

GPU Correl

class crappy.tool.gpucorrel.CorrelStage(img_size: Tuple[int, int], verbose: int = 0, iterations: int = 5, mul: float = 3, n_fields: int | None = None, kernel_file: Path | str | None = None)[source]

Represents a stage of the pyramid used by the GPUCorrel tool for performing GPU correlation.

This class actually performs the GPU computation, while the calling classes only manage the data.

__init__(img_size: Tuple[int, int], verbose: int = 0, iterations: int = 5, mul: float = 3, n_fields: int | None = None, kernel_file: Path | str | None = None) None[source]

Sets the args and instantiates the pycuda objects.

Parameters:
  • img_size – The shape of the images to process. It is given beforehand so that the memory can be allocated before the test starts.

  • verbose – The verbose level as an integer, between 0 and 3. At level 0 no information is printed, and at level 3 so much information is printed that is slows the code down.

  • iterations – The maximum number of iterations to run before returning the results. The results may be returned before if the residuals start increasing.

  • mul – The scalar by which the direction will be multiplied before being added to the solution. If it’s too high, the convergence will be fast but there’s a risk that to go past the solution and to diverge. If it’s too low, the convergence will be slower and require more iterations. 3 was found to be an acceptable value in most cases, but it is recommended to tune this value for each application so that the convergence is neither too slow nor too fast.

  • n_fields – The number of fields to project the displacement on.

  • kernel_file – The path to the file containing the kernels to use for the correlation. Can be a pathlib.Path object or a str.

get_data_display() ndarray[source]

Returns the necessary data for displaying the difference between the reference and current image.

get_disp(img_d=None) Any[source]

Projects the displacement on the base fields, and returns the result.

prepare() None[source]

Computes all the necessary tables to perform correlation.

resample_d(new_y: int, new_x: int) Any[source]

Resamples the texture with a new dimension and returns it in a GPU array.

resample_orig(new_y: int, new_x: int, dev_out) None[source]

Resamples the original image with a new dimension.

set_disp(x) None[source]

Sets the displacement fields computed from the previous stages.

set_fields(fields_x, fields_y) None[source]

Sets the fields on which hto project the displacement.

set_image(img_d) None[source]

Set the current image, to be compared with the reference image.

set_mask(mask) None[source]

Sets the mask to use for weighting the images.

set_orig(img) None[source]

Sets the original image from a given CPU or GPU array

update_orig() None[source]

Updates the original image.

class crappy.tool.gpucorrel.GPUCorrel(context: Any | None = None, verbose: int = 0, levels: int = 5, resampling_factor: float = 2, kernel_file: Path | str | None = None, iterations: int = 4, fields: List[str] | None = None, ref_img: ndarray | None = None, mask: ndarray | None = None, mul: float = 3)[source]

This tool performs GPU correlation between two images in order to identify fields of rigid body displacements.

This class is meant to be efficient enough to run in real-time. It relies on CorrelStage to perform correlation on different scales. It mainly takes a list of base fields and a reference image as inputs, and project the displacement between the current image and the reference one on the base of fields. The optimal fit is achieved by lowering the residuals with a least-squares method.

The projection on the base is performed sequentially, using the results obtained at stages with low resolution to initialize the computation on on stages with higher resolution. A newton method is used to converge towards an optimal solution.

__init__(context: Any | None = None, verbose: int = 0, levels: int = 5, resampling_factor: float = 2, kernel_file: Path | str | None = None, iterations: int = 4, fields: List[str] | None = None, ref_img: ndarray | None = None, mask: ndarray | None = None, mul: float = 3) None[source]

Sets the args and a few parameters of pycuda.

Parameters:
  • context – Optionally, the pycuda context to use. If not specified, a new context is instantiated.

  • verbose – The verbose level as an integer, between 0 and 3. At level 0 no information is printed, and at level 3 so much information is printed that is slows the code down.

  • levels – Number of levels of the pyramid. More levels may help converging on images with large strain, but may fail on images that don’t contain low spatial frequency. Fewer levels mean that the program runs faster.

  • resampling_factor – the factor by which the resolution is divided between each stage of the pyramid. A low factor ensures coherence between the stages, but is more computationally intensive. A high factor allows reaching a finer detail level, but may lead to a coherence loss between the stages.

  • kernel_file – The path to the file containing the kernels to use for the correlation. Can be a pathlib.Path object or a str.

  • iterations – The maximum number of iterations to run before returning the results. The results may be returned before if the residuals start increasing.

  • fields

    A list of str representing the base of fields on which the image will be projected during correlation. The possible fields are :

    'x', 'y', 'r', 'exx', 'eyy', 'exy', 'eyx', 'exy2', 'z'
    

  • ref_img – the reference image, as a 2D numpy array with dtype float32. It can either be given at __init__, or set later with set_orig().

  • mask – The mask used for weighting the region of interest on the image. It is generally used to prevent unexpected behavior on the border of the image.

  • mul – The scalar by which the direction will be multiplied before being added to the solution. If it’s too high, the convergence will be fast but there’s a risk that to go past the solution and to diverge. If it’s too low, the convergence will be slower and require more iterations. 3 was found to be an acceptable value in most cases, but it is recommended to tune this value for each application so that the convergence is neither too slow nor too fast.

static clean()[source]

Needs to be called at the end, to destroy the pycuda context properly.

get_data_display() ndarray[source]

Returns the necessary data for displaying the difference between the reference and current image.

get_disp(img_d: ndarray | None = None) Any[source]

To get the displacement.

This will perform the correlation routine on each stage, initializing with the previous values every time it will return the computed parameters as a list.

get_res(lvl: int = 0)[source]

Returns the last residual of the specified level.

prepare() None[source]

Prepares all the stages before starting the test.

set_img_size(img_size: Tuple[int, int]) None[source]

Sets the image shape, and calls the methods that need this information for running.

set_orig(img: ndarray) None[source]

Sets the reference image, to which the following images will be compared.

crappy.tool.gpucorrel.interp_nearest(arr: ndarray, ny: int, nx: int) ndarray[source]

Reshapes an input array to the specified dimension using the nearest interpolation, using only numpy methods.

Parameters:
  • arr – The array to interpolate.

  • ny – The new dimension along the y axis.

  • nx – The new dimension along the y axis.

Returns:

A reshaped version of the input array obtained with the nearest interpolation.

I2C Message FT232H

class crappy.tool.ft232h.i2c_message_ft232h.i2c_msg_ft232h(type_: str, address: int, length: int | None = None, buf: list | None = None)[source]

Class that mimics the i2c_msg class of the smbus2 module.

__init__(type_: str, address: int, length: int | None = None, buf: list | None = None) None[source]

Simply sets the attributes of the class, that characterise the i2c message.

Parameters:
  • type (str) – Either a read (‘r’) or a write (‘w’) message

  • address (int) – The address of the I2C slave.

  • length (int, optional) – For a read message, the number of bytes to read.

  • buf (list, optional) – For a write message, the list of bytes to be written.

property addr: int

The address of the I2C slave.

property buf: list

The list of bytes to be written, or the list of bytes read.

property len: int

The number of bytes to read.

classmethod read(address: int, length: int) Iterable[source]

Instantiates an i2c_msg_ft232h object for reading bytes.

Parameters:
  • address (int) – The address of the I2C slave.

  • length (int) – The number of bytes to read.

classmethod write(address: int, buf: list) object[source]

Instantiates an i2c_msg_ft232h object for writing bytes.

Parameters:
  • address (int) – The address of the I2C slave.

  • buf (list) – The list of bytes to be written.

Py SPCM

This file contains the code for binding the C++ Spectrum library in Python.

The bindings haven’t been tested for a while.

exception crappy.tool.pyspcm.SpectrumError[source]

USB server

class crappy.tool.ft232h.usb_server.Server_process(new_block_recv: Connection, current_file: FileIO, command_file: FileIO, answer_file: FileIO, lock_pool: List[RLock], current_lock: RLock, dev_dict: Dict[str, Any])[source]

Process actually communicating with the FT232H device.

It receives the commands, sends them to the device, and returns the answer. This architecture is necessary as pyusb doesn’t support multiprocessing.

__init__(new_block_recv: Connection, current_file: FileIO, command_file: FileIO, answer_file: FileIO, lock_pool: List[RLock], current_lock: RLock, dev_dict: Dict[str, Any])[source]

Simply passes the args as instance attributes.

Parameters:
  • new_block_recv – A pipe connection through which new blocks send information.

  • current_file – A temporary file in which the index of the block currently communicating with the server is written.

  • command_file – A temporary file containing the command the server has to send to the ft232h.

  • answer_file – A temporary file containing the answer from the device after a command was sent.

  • lock_pool – A list of RLocks, with each one affected to a different block. They indicate to the server that a command is ready, or to the block that an answer is ready.

  • current_lock – A unique RLock that determines which block has control over the server. The different blocks all try to acquire this lock.

  • dev_dict – A dict whose keys are the serial numbers of the connected ft232h and values are the associated pyusb Device objects.

run() None[source]

Main loop of the server.

It runs an infinite loop for receiving the commands and sending back the answers to the blocks.

class crappy.tool.ft232h.usb_server.Usb_server(serial_nr: str, backend: str)[source]

Class for starting a server controlling communication with the FT232H devices.

The In / Out objects wishing to communicate through an FT232H inherit from this class.

Note

There is a limitation to 10 blocks accessing ft232h devices from the same machine in Crappy. This limit can be increased at will, but it is necessary to change the code of this class and build Crappy yourself.

__del__() None[source]

Stops the server upon deletion of the In / Out object.

__init__(serial_nr: str, backend: str) None[source]

Simply receives the attributes from the In / Out object.

Parameters:
  • serial_nr (int) – The serial number of the FT232H to use.

  • backend (str) – The server won’t be started if the chosen backend is not 'ft232h'.

start_server() tuple[source]

Starts the server for communicating with the FT232H devices.

If the server is already started, doesn’t start it twice. Then initializes the connection with the server and receives a block number.

Returns:

The different multiprocessing objects needed as arguments by the FT232H in order to run properly.

Video extenso

exception crappy.tool.videoextenso.LostSpotError[source]

Exception raised when a spot is lost, or when there’s too much overlapping.

class crappy.tool.videoextenso.Tracker(pipe: Connection, white_spots: bool = False, thresh: int | None = None, blur: float | None = 5)[source]

Process whose task is to track a spot on an image.

It receives a subframe centered on the last known position of the spot, and returns the updated position of the detected spot.

__init__(pipe: Connection, white_spots: bool = False, thresh: int | None = None, blur: float | None = 5) None[source]

Sets the args.

Parameters:
  • pipe – The multiprocessing.connection.Connection object through which the image is received and the updated coordinates of the spot are sent back.

  • white_spots – If True, detects white objects on a black background, else black objects on a white background.

  • thresh – If given, this threshold value will always be used for isolating the spot from the background. If not given (None), a new threshold is recalculated for each new subframe. Spots are less likely to be lost with an adaptive threshold, but it takes a bit more time.

  • blur – If not None, the subframe is first blurred before trying to detect the spot. This argument gives the size of the kernel to use for blurring. Better results are obtained with blurring, but it takes a bit more time.

run() None[source]

Continuously reads incoming subframes, tries to detect a spot and sends back the coordinates of the detected spot.

Can only be stopped either with a KeyboardInterrupt or when receiving a text message from the parent VideoExtenso class.

class crappy.tool.videoextenso.VideoExtenso(white_spots: bool = False, update_thresh: bool = False, num_spots: int | None = None, safe_mode: bool = False, border: int = 5, min_area: int = 150, blur: int | None = 5)[source]

This class tracks up to 4 spots on successive images, and computes the strain on the material based on the displacement of the spots from their original position.

The first step is to detect the spots to track. Once this is done, the initial distances in x and y between the spots is saved. For each spot, a Process in charge of tracking it is started. When a new image is received, subframes based on the last known positions of the spots are sent to the tracker processes, and they return the new positions of the detected spots. Based on these new positions, updated strain values are returned.

It is possible to track only one spot, in which case only the position of its center is returned and the strain values are left to 0.

__del__() None[source]

Security to ensure there are no zombie processes left when exiting.

__init__(white_spots: bool = False, update_thresh: bool = False, num_spots: int | None = None, safe_mode: bool = False, border: int = 5, min_area: int = 150, blur: int | None = 5) None[source]

Sets the args and the other instance attributes.

Parameters:
  • white_spots – If True, detects white objects on a black background, else black objects on a white background.

  • update_thresh – If True, the threshold for detecting the spots is re-calculated for each new image. Otherwise, the first calculated threshold is kept for the entire test. The spots are less likely to be lost with adaptive threshold, but the measurement will be more noisy. Adaptive threshold may also yield inconsistent results when spots are lost.

  • num_spots – The number of spots to detect, between 1 and 4. The class will then try to detect this exact number of spots, and won’t work if not enough spots can be found. If this argument is not given, at most 4 spots can be detected but the class will work with any number of detected spots between 1 and 4.

  • safe_mode – If True, the class will stop and raise an exception as soon as overlapping is detected. Otherwise, it will first try to reduce the detection window to get rid of overlapping. This argument should be used when inconsistency in the results may have critical consequences.

  • border – When searching for the new position of a spot, the class will search in the last known bounding box of this spot plus a few additional pixels in each direction. This argument sets the number of additional pixels to use. It should be greater than the expected “speed” of the spots, in pixels / frame. But if it’s too big, noise or other spots might hinder the detection.

  • min_area – The minimum area an object should have to be potentially detected as a spot. The value is given in pixels, as a surface unit. It must of course be adapted depending on the resolution of camera and the size of the spots to detect.

  • blur – The size in pixels of the kernel to use for applying a median blur to the image before the spot detection. If not given, no blurring is performed. A slight blur improves the spot detection by smoothening the noise, but also takes a bit more time compared to no blurring.

detect_spots(img: ndarray, y_orig: int, x_orig: int) Spot_boxes | None[source]

Transforms the image to improve spot detection, detects up to 4 spots and return a Spot_boxes object containing all the detected spots.

Parameters:
  • img – The sub-image on which the spots should be detected.

  • y_orig – The y coordinate of the top-left pixel of the sub-image on the entire image.

  • x_orig – The x coordinate of the top-left pixel of the sub-image on the entire image.

Returns:

A Spot_boxes object containing all the detected spots.

get_data(img: ndarray) Tuple[List[Tuple[float, ...]], float, float] | None[source]

Takes an image as an input, performs spot detection on it, computes the strain from the newly detected spots, and returns the spot positions and strain values.

Parameters:

img – The image on which the spots should be detected.

Returns:

A list containing tuples with the coordinates of the centers of the detected spots, and the calculated x and y strain values.

save_length() bool[source]

Saves the initial length in x and y between the detected spots.

start_tracking() None[source]

Creates a Tracker process for each detected spot, and starts it.

Also creates a Pipe for each spot to communicate with the Tracker process.

stop_tracking() None[source]

Stops all the active Tracker processes, either gently or by terminating them if they don’t stop by themselves.

Video extenso configuration

class crappy.tool.videoextensoConfig.VE_config(camera, video_extenso)[source]

Class similar to Camera configuration but also displaying the bounding boxes of the detected spots, and allowing to select the area where to detect the spots by drawing a box with the left mouse button.

It is meant to be used for configuring the VideoExtenso block.

__init__(camera, video_extenso) None[source]

Sets the args and initializes the parent class.

Parameters:
  • camera – The camera object in charge of acquiring the images.

  • video_extenso – The video extenso tool in charge of tracking the spots.