You are on page 1of 13

PRIDE Tips

&
Coding Guidelines

AUTHOR: Richard Philipsen


DATE: 02-07-2001
DOC. VERSION: 1.2
PRIDE VERSION: 1.0

Philips Medical Systems

TRAD Philips’ proprietary,  2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 2 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

1. Introduction
The main purpose of this document and the guidelines is to simplify the development, review and re-use of
PRIDE based IDL applications by promoting a form of unity in the code. This will greatly simplify the
exchange of PRIDE software.

The guidelines stated in this document are not mandatory and the first concerns of any application should
clinical relevance and proper functioning. However, be aware that adherence to the guidelines and some form of
structure within the application will make help during development and follow-up of the application much
easier.

The PRIDE intranet contains the latest up-to-date version of this document as well as some more advanced tips
and tricks on using IDL and the PRIDE library objects.

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 3 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

2. Guidelines
2.1. Code outline guidelines
1. Use 4 spaces or a TAB to indent to the next level (e.g., BEGIN). The END-statement is not indented.

IF (phase NE max_phase) THEN BEGIN


phase = phase + 1
ENDIF

and not

IF (phase NE max_phase) THEN BEGIN


phase = phase + 1
ENDIF

2. Keep the number of characters on a single line below 81.

3. When possible, use BEGIN and END statements in stead of multiline commands separated by a ‘$’.

IF ((phase NE max_phase) AND (phase GT min_phase)) THEN BEGIN


phase = phase + 1
ENDIF

and not

IF ((phase GT min_phase) AND (phase LT max_phase)) THEN $


phase = phase + 1

4. Use parentheses to delineate logical tests.

IF ((phase NE max_phase) AND (phase GT min_phase)) THEN BEGIN

and not

IF phase NE max_phase AND phase GT min_phase THEN BEGIN

5. Differentiate between accessing array indices and passing parameters to function calls.
Address array elements with square brackets, pass parameters to function calls using round brackets.

my_array = INTARR(100)
my_array[10] = 123
result = my_function(my_array)

and not

my_array(10) = 123 ; This gets very confusing!

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 4 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

2.2. Naming conventions


1. Give variables sensible names. Stay away from cryptic and over-descriptive names.
Use underscores to separate between words in a variable. In IDL messages, the variables are displayed in
uppercase which makes variables without underscores hard to read.
Also refer to the IDL manual, Building IDL Applications, on naming variables, procedures, functions, etc.
An example of what to do and what not to do is listed below:

perform_registration(images)

and not

do_my_thing_now_and_return_from_routine(my_array_of_image_objects)

or
pr(x)

2. Use all lower cases to identify variables and user created functions/procedures. Use all uppercases for IDL
routines and commands.
my_array = INTARR(10)

FOR i = 0, 10 DO BEGIN
FOR j = 0, 10 DO BEGIN
PRINT, ‘something interesting’
do_something_interesting(i, j, my_array)
END
END

and not

My_Array = intarr(10)

for I = 0, 10 do begin
For j = 0, 10 do begin
print, ‘something interesting’
DO_SOMETHING_INTERESTING(I, j, My_Array)
End
end

3. Use a prefix (about 2 to 4 letters in length) when naming external functions and procedures. This prevents
naming conflicts within IDL and it indicates which package the function originates from.
E.g. rw_common or ex_subtraction or pflh_viewport_put_image. Also use these prefixes when naming the
files containing the procedures/functions.
When using a slightly altered function or routine from IDL or public domain, keep the original name (and
credit), but add a prefix to the function name.

4. To avoid problems with name clashes, ensure functions have unique names. This can be done by adding the
same prefix described above to all a module’s local functions as well. An example of this can be seen in the
zoom_pan example in the ex_sample project. The local functions in the module have the prefix “zp_”.
This is especially important when several different programs are contained in a single IDL project, or when
not using IDL projects, just modules.

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 5 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

5. Use a single blank line to separate between blocks of code belonging together

dim_x = 256
dim_y = 256
nr_masks = 5
an_image = INTARR(dim_x, dim_y)
mask = INTARR(dim_x, dim_y, nr_masks)

FOR i = 0, nr_masks-1 THEN BEGIN


mask[*,*,i] = determine_mask(an_image, i)
END

and not

dim_x = 256

dim_y = 256

nr_masks = 5
an_image = INTARR(dim_x, dim_y)
mask = INTARR(dim_x, dim_y, nr_masks)
FOR i = 0, nr_masks-1 THEN BEGIN

mask [*,*,i] = determine_mask(an_image, i)


END

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 6 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

2.3. Commenting Strategy


1. Provide information at the top of the file in a standard format. Keep track of major adaptations. Note that it
is custom in IDL to start the comment at the top of the file with “ ;+” and end the first comment block with
“;-”.

;+
; NAME:
; Project Name
;
; PURPOSE/DESCRIPTION:
; A description describing the purpose and use of the module.
;
; GENERAL DESIGN:
; A description of the general design decisions used in the file.
;
; LIST OF ROUTINES:
; Exported routines - Short description of each function/procedure.
;
; MODIFICATION HISTORY:
; Written: Author Name Creation Date
; Update : Author Name Update Date: Short Description
;-

2. Provide information at the beginning of a function.


(At least any externally used function, smaller/internal functions need only have a few lines describing the
general purpose of the function.)

; FUNCTION NAME: Name


or
; PROCEDURE NAME: Name
;
; DESCRIPTION:
; A description of the purpose and functionality of the
; function/procedure.
;
; PARAMETERS:
; A list of parameters (Input/Output) each with a quick description.
;
; RETURN VALUE: (Only in case of a FUNCTION)
; Description of the return value in case of a function.
;===============================================================================
PRO/FUNCTION Name, Parameter(s)

3. Comments should precede the line(s) for which they are intended and should be indented at the same level.

long_axis = 15.0

; Display 10 of ellipses with different short axes.


FOR i = 1, 10 DO BEGIN
short_axis = long_axis/i
draw_ellipse(long_axis, short_axis)
END

and not

long_axis = 15.0
FOR i = 1, 10 DO BEGIN
; Display 10 of ellipses with different short axes.
short_axis = long_axis/i
draw_ellipse(long_axis, short_axis)
END

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 7 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

4. Do not leave source lines which are commented out in your code, unless specific comments have been
added as to why it’s still there. Without any additional comments, the commented out code can be very
confusing. (e.g. Did someone forget to remove these comments?)

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 8 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

2.4. Architectural considerations


1. Use projects as defined in IDL to order your programs. Give projects a sensible name containing the prefix
used for the source files and the routines. Keep the original project hierarchy:

pr_some_project.prj
Source
pr_my_file_1.pro
pr_my_file_2.pro
pr_my_GUI.pro

GUI
pr_my_GUI_builder.prc (GUI Builder Resource File)

Data (Any data other required/generated)
Bitmaps
pr_splash_screen.bmp
pr_intera_open.bmp
Other (Used by PRIDE library)

2. Event handlers should be viewport independent. When a mouse button is pressed, the resulting event
contains the widget id of the widget which triggered the event.
(See the example of bullet number 3.)

3. Any generic events such as mouse movements, clicks on draw widgets, etc. are caught in the event handler
assigned in the XMANAGER call in the GUI creation routine. The name of that function can be set using the
EVENT_HANDLER keyword in the XMANAGER procedure.

; The generic GUI event handler for my_zoom_program as set below in the
; XMANAGER call.
PRO mz_event_handler, event
; Retrieve the info structure from the top widget.
WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY

; If a button is pressed in the draw area, perform the required actions.


IF((event.press) AND (event.id EQ info.draw_widget)) THEN BEGIN
; Get the widget index of the clicked draw widget.
WIDGET_CONTROL, event.id, GET_VALUE = current_widget_idx

; Zoom in on the proper window


; (Passing along any required information.)
mz_do_zoom, current_widget_idx, info
ENDIF

; Restore the info structure into the top widget.


WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
END

PRO, mz_my_zoom_program
; Create GUI
; Initialise parameters including the info structure.

; Create the GUI, assigning mz_event_handler as the generic GUI callback.
XMANAGER, 'my_zoom', top_wid, EVENT_HANDLER = ‘mz_event_handler’, $
/NO_BLOCK
END

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 9 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

4. Avoid routines that change the currently active viewport. In general this can be done by first storing the
active viewport, displaying the relevant items in the proper viewport(s), and finally resetting the original
viewport. (This is only applicable for direct graphics programming.)
Here is such an example of a display_image routine:

PRO display_image, my_image


current_wid = !D.WINDOW

WSET, some_window
TVSCL, my_image, /ORDER

WSET, current_wid
END

5. Avoid GOTO’s.

6. When possible, avoid hard coded (magical) numbers. Whenever they are used, add a simple comment
stating what the number represents and why it is used.

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 10 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

2.5. Uniformity issues


1. In general, it is attempted to keep the mouse button functionality as close to the Gyroview functions as
possible.
Note that the button assignments are NOT mandatory and in fact not recommended when not using object
oriented graphics!

The Gyroview button assignments are as follows:


 Left Button
This button is left for application purposes. It is often used to set or select items relevant to the current
application
 Right Button
This button is left for application purposes. It is often used to display an item's attributes.
 Center Button
This button is generally reserved for windowing and leveling.
 Left-Center Buttons
This button combination is used for panning the image.
 Right-Center Buttons
This button combination is used for zooming the image.

For an example on interactive zooming, panning and windowing according to these mouse-button
combinations, see the ex_zoom_pan module in the ex_sample project.

This is also a relatively simple example on using object oriented graphics.

2. Use data size independent viewports: do not let the size of your viewports depend on the data size of the
images displayed inside. It does not matter if the data being displayed is 1024x1024 or 64x64, re-scaling
the bulk to the size of the viewport(s) when displaying it results in a much more predictable GUI.

3. When displaying multiple images, use smaller viewports, for example 256x256. If only a single image is
displayed the viewport can be larger, for example 512x512. Note that having viewports that are easy to
resize in the code is very nice to have as it allows the program to run well on displays using other
resolutions than your own.

4. Avoid over-use of pop-up windows. It’s much clearer to use a panel in the main window to display relevant
information. Use pop-up windows only in exceptional cases such as error windows or file selection or if
there simply is not enough screen space.

5. In order to maximize available space on the GUI, e.g. for viewports, it is easily possible to build a
Windows style menu bar for common actions such as opening of data and exiting the application.
Examples for this can be found in the standard IDL demos and examples.

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 11 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

3. Tips and Tricks


1. Before implementing a new program first check existing PRIDE examples and routines on the PRIDE
intranet. The program might already exist (or is being built by someone) or one of the existing programs
can be used as a starting point.
There is no point in writing the same piece of code over and over again.

2. Avoid common blocks by using an event control “info” structure. Use the /NO_COPY option to avoid
copying large chunks of data. (See pg. 263 of IDL programming techniques by D. Fanning for a
comprehensive explanation of this /NO_COPY mechanism.)
In general only one info-structure is used in your file to store all the global data. The info-structure is
generally stored as the user defined value of the top level widget. This allows access to the structure from
anywhere in the file.
A routine where the info structure is needed, such as during event control, grabs it by a GET_UVALUE
with the /NO_COPY keyword parameter. Be sure to put the structure back using a SET_UVALUE call
with the /NO_COPY keyword parameter so other procedures can access it afterwards. Only during
termination of the program is it not required to put the info structure back after grabbing it.
Below is an example consisting of two procedures. The first procedure defines the event control info
structure and stores it in the top level widget. The second procedure is a typical event procedure which
updates information in the structure.

PRO my_main_routine
…… Create UI ……
…… Perform initializion ……

; Define the global information structure of this program.


info = {pixel_size: 1.0, $ ; pixel size in mm. (square pixels)
other_values: 9.99} ; other relevant values in the info struct.

; Store the global information structure in the top level widget.


WIDGET_CONTROL, top_widget, SET_UVALUE = info, /NO_COPY
…… Etc. ……
END

PRO qflow_pixel_change_cb, event


; Get the info structure.
WIDGET_CONTROL, event.top, GET_UVALUE = info, /NO_COPY

; Retrieve the pixel size value and store it in the INFO struct.
WIDGET_CONTROL, event.id, GET_VALUE = p_size
info.pixel_size = FLOAT(p_size[0])

; Put info structure back.


WIDGET_CONTROL, event.top, SET_UVALUE = info, /NO_COPY
END

3. In the IDL ‘examples\widgets’ directory, an example demonstrating the different GUI controls and their
related callbacks can be found: xnothing.pro. Many examples are given here, but be aware that some, such
as the radio buttons, use obsolete functions and procedures!
(Note that depending on what version of IDL is used, the example might be in a different directory.)
The various PRIDE examples such as ex_zoom_pan.pro and ex_subtraction.pro are also good examples on
building GUI’s.

4. To get a unique unit number to open or close files, use the keyword /GET_LUN
OPENW, unit_number, file_name, /GET_LUN
…Do something with the file…
CLOSE, unit_number

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 12 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

5. Integers in IDL are limited in value from –32768 to 32767.


So: 256 * 128 = –32768 and 256*256 = 0.
This often forms a problem when accessing (image) arrays or performing integer calculations (such as
image multiplication). FOR loops or counters on large arrays are also an area where this problem often
arises. An integer counter value might wrap around causing errors or strange behavior.
Long integers are used to avoid this problem. (See converting types below.)

6. Care must be taken in IDL when converting to double or long integers. One conversion in an expression
does not necessarily mean that the whole expression is converted .
To properly force the result of a calculation to type long integer, convert the integer to type long integer
before multiplication. This can be done by adding ‘L’ after the value, or using the LONG(value) function.
E.g.: 256 * 256 + 1 = 1
256 * 256 + 1L = 1L
256 * 256L + 1 = 65537L
LONG(256 * 256 + 1) = 1L
LONG(256) * 256 + 1 = 65537L

7. Arguments in routines can only be updated when these are not passed to the routine as expressions (e.g.
structure fields or array elements.

info.my_value = 1
add_one(info.my_value)
PRINT, info.my_value
IDL> 1

and

my_array[2] = 1
add_one(my_array[2])
PRINT, my_array[2]
IDL> 1

but

my_value = 1
add_one(my_value)
PRINT, my_value
IDL> 2

and store the value like so


info.my_value = my_value
my_array[2] = my_value

8. Compile options, such as "save before compiling", only work when compiling individual files and not
when building or running a whole project. This can be extremely confusing since the file you are looking at
is not necessarily the file compiled, thus the code which is currently running. Be careful of this especially
when debugging an application.
This has gotten somewhat better in the later versions of IDL (5.4+), but can still cause for confusing
situations.

9. Especially when creating a new IDL project by copying an existing one, be aware that the open code
windows when first starting your new project do not necessarily show the code of the new project. IDL uses
hard-coded paths and you might be looking at (and changing) the code of the original project!
The safe workaround is to copy only the source files and the directories, but create a new project file from
scratch. This way, the files must be manually added to the project, ensuring the correct files are displayed.
The quick workaround this is to close all open code windows when first opening the project.

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved
PRIDE: CAUTION: Investigation Device Page 13 of 13
Tips & Coding Guidelines Limited by Federal Law to investigational use 02-07-2001

10.When in the IDL editor, the keyboard combination ‘CTRL-D’ can be used to jump to declaration of the
function/procedure the cursor is currently at.

11.It is important to keep the following tips handy whenever performance is a main issue in an IDL project.
 Avoid IF statements wherever possible.
e.g. in stead of: IF(a EQ x) THEN b = 1 you can use: b = (a EQ x)
 Avoid (nested) loops wherever possible. It is usually possible through the use of modulo and division to avoid a
nested FOR loop. One way to avoid FOR loops is by using IDL's array indexes such as '*' and '0:5'.
 Avoid declaring arrays that are larger than the amount of RAM in the PC.
(Though this is hard to check for, try to manage your memory as best as possible…)
 Especially when you are incrementing sizable arrays, use the TEMPORARY function to limit memory usage.
So in stead of: large_array = large_array + 1 use
large_array = TEMPORARY(large_array) + 1
 To truly optimize array access put the fastest changing indexes last (unlike other languages such as C!) and keep
the number of array dimensions as small as possible, e.g. using the REFORM command.
When accessing the bulk of an array of image slices, the array would be set up as follows:
array[slices][x][y]
with slices being the slowest changing index first.
Note that in fact the x, y should be reversed as well, but this severely hampers the readability and
maintainability of the code.

12.When continuously updating the display (e.g. display a moving crosshair or a fast movie display) look into
the use of pixmaps. One important note is that the amount of memory in the PC is a severely limiting factor
as in how many images can be displayed smoothly!
More information on pixmaps can be found in the IDL help (WINDOW and DEVICE procedures) as well
as on the internet. (The PRIDE intranet contains links to IDL links on the internet.)

13. Use the Help provided in IDL. It contains a comprehensive reference guide for the available
functions/procedures as well as several guides. Some interesting generic information on IDL can be found
in “ContentsBuilding IDL ApplicationsProgramming in IDL”. This section contains some of the
things to be avoided (and how to avoid them) as well as some IDL’s global principles.

<<< END OF DOCUMENT >>>

TRAD Philips’ proprietary, © 2001 Philips Electronics N.V. All rights reserved

You might also like