F2PY Transform Extension Module (pyirt._transform)

This module is a C extension built with F2PY, implementing critical functions of the transform.

Python interface

pyirt._transform.iterate(n, materials, accumulator, normals, refraction_indices, max_depth, max_length, diff_type, do_rms, rand_seed=-1)

This function will follow n rays through the image defined by materials and accumulate the paths of the rays in accumulator. The values of normals are used to calculate the correct refraction or reflection angle while refraction_indices is used to convert intensities to a refractive index. max_length and max_depth define when a ray should stop being followed, and diff_type specifies in which circumstances the ray should refract. do_rms sets whether the root mean squared difference between the accumulator should be calculated and rand_seed sets whether to seed the RNG from the time or a specified number.

C extension module

If you’re looking to change the transform significantly, it is likely that you’ll need to work with this code. It’s advisable to get in there and look at the comments, but below should give you a higher level understanding of what happens.

Main data structures

A ray is made up of a number of ray_segment structs in an array.

ray_segment

This stores information about a section of a ray, from the point where it is initialised (x0, y0) until it refracts or reflects, and a new ray segment is generated. x, y and distance are updated at each timestep whilst the other variables do not change.

double x0

Initial x position.

double y0

Initial y position.

double x

Current x position.

double y

current y position.

double vx

x direction.

double vy

y direction.

int depth

Number of refractions or reflections undergone.

double distance

Distance travelled.

Three arrays store most of important information about the transform.

ray_segment* rays

An array of ray_segment, of size (max_depth + 1) that has a new ray_segment initialised each time the ray being traced refracts or reflects. The ray_segment at index 0 is set to the initial random values.

double* accumulator

An array of size w x h that is incremented by one when a ray passes through it for the first time.

double* marked

An array that stops a single ray accumulating a pixel more than once. It only accumulates if the value of the pixel in this array is different to its id, and then sets the marked value to its id.

Functions

Parameters omitted for clarity.

void iterate()

Sets up the appropriate arrays, creates a ray_struct randomly and then calls trace_ray() n times.

int trace_ray()

Moves through the ray array, calling repeatedly move_ray() on each ray_struct until it refracts/reflects or hits a limit.

int move_ray()

Accumulates, and then attempts to move the ray 1 unit in its direction. If that’s not possible it will calculate the earliest boundary cross with earliest_cross(), and then check if there is a difference in refractive index. If so it calls split_rays() to calculate the new direction. Throughout it checks whether the ray has exited the image or whether max_depth has been exceeded.

int earliest_cross()

Calculates the time and position of the first boundary cross, so that reflections and refractions can be found.

int split_rays()

Figures out whether the ray refracts or reflects, calculates the new direction and puts it in the next space in the rays array of ray_segments.

void accumulate()

If the ray hasn’t already accumulated in this pixel, it accumulates and then sets the marked array to indicate that it has done so.

void seed_rng()

Called at the start to set the random number generator, with either the time or a given value. Only sets on the first call after loading the module. If using multiprocessing must be careful with this, as each process needs to be seeded with a different number.

void normalise_accumulator()

Needed to calculate the root mean squared difference values. Just normalises an array to between 0 and 255.

double rms_diff()

Compares two accumulators to find the RMS difference between them.