Code guidelines

When you contribute new code or make changes to existing code, please consider the following guidelines.

Implementing a new high-level function

A high-level FieldTrip function always should behave like this

[outputargs] = ft_functionname(cfg, inputargs)

where some functions might not need inputargs and some functions might not return outputargs.

The function should always start with a help section, that explains the purpose of the function, the type of input data that it expects, the type of output data that it will produce and the configurable options that the user has to control the behaviour of the function.

The best-practice example function

The easiest way to get started with writing a new high-level FieldTrip function is to take a close look at ft_examplefunction, which is located in FT's core (root) directory. (Note: this is true as of Feb 11, 2011.) It shows the best practices that one should adhere to concerning input and output structure and data handling. Also, it demonstrates how one should document the function according to FT standard guidelines.

Adding new configuration options

Any new configuration option should have a default set at the beginning of the function. If you don't know a good default value, you should specify the default value as empty, i.e. cfg.newoption = [].

If you add a configuration option, you should check in the configuration index whether a cfg option with similar functionality already exist in another function. Use identical names for identical functionality and try to keep the help similar if possible.

Renaming configuration options or values

Whenever you rename a configuration option, you have to ensure backward compatibility with the end-users' scripts that they have carefully crafted. Forcing the users to update the scripts every time we change something will scare them away. That is why you should use

cfg = ft_checkconfig(cfg, 'renamed', {'oldoption', 'newoption'})

or

cfg = ft_checkconfig(cfg, 'renamedval', {'option', 'oldval', 'newval'})

This will ensure that the user script will continue to work. Furthermore, he/she will get warning or error (depending on whether cfg.checkconfig is 'silent', 'loose' or 'pedantic').

Removing configuration options

If you remove a configuration option from a function, you should ensure that the user of that function becomes aware of it. Sending an email to the mailing list is one option (and in general good), but it might be that he/she is not subscribed to the mailing list. That is why you should also add the following to the function

cfg = ft_checkconfig(cfg, 'forbidden', 'oldoption')

In case the user still specifies the option, he/she will get warning or error (depending on whether cfg.checkconfig is 'loose' or 'pedantic').

SVN log messages

SVN log entries should describe the change to the file or files. The log message should allow an end-user to realize that a recent change in the code may relate to the changed behaviour that he/she observes. The log message should also allow another developer that is familiar with the particular code to understand why the code was changed, and what part of the code is changed.

Log messages don't have to be long, but they have to be clear to the intended audience: end-users and colleague developers. Log messages should also be clear for yourself, because sometimes you'll have to go back in a function to fix problems that were introduced by your own previous change.

To allow better human and machine readable changelogs, please start your log message with a single descriptive word and a hyphen to separates it from the actual description. Whenever applicable you should use the description “bugfix”, “enhancement”, “documentation”, “restructuring”.

Examples of good and useful log messages are

documentation - changed the documentation, no change to the code
  
enhancement - added support for the new cfg.whatever option

restructuring - changed the structure of the code, instead of .... it now works like ...

bugfix - fixed a problem in xxx, in case of ... it did ..., whereas it should be doing ...

bugfix - fixed the problem described in http://bugzilla.fcdonders.nl/show_bug.cgi?id=50

Examples of bad log messages are

<empty>

made a change in this function

lot of small changes

fixed a bug

Public and private functions

In FieldTrip the interface towards the user is controlled by making only those functions publicly available that the end-user is supposed to call from the command-line or from a Matlab script. Those functions are public and should be in the main directory or in one of the module directories.

Low-level functions that are only supposed to be called by other FieldTrip functions but not by the end-user should be in the private directory.

Calling functions that are located elsewhere

Functions in a module, i.e. sub-directory, should not be calling any FieldTrip functions at a higher level. E.g. a function like fileio/xxx.m should only call other functions in fileio, in fileio/private or in an external toolbox. If you don't know how to work with svn autosycn, please ask the senior developers.

This requirement on the dependencies ensures the modular design.

Varargin arguments

Generally functions (i.e. in the plotting directory) have optional arguments as a pair of inputs describing the name of one property and its value. These arguments have to be handled at the very beginning inside the function, by setting a default value, like this:

function ft_plot_mesh(bnd, varargin)
...
% get the optional input arguments
facecolor   = keyval('facecolor',   varargin); if isempty(facecolor),   facecolor='white';end
vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor), vertexcolor='none';end

The function keyval is specific to check syntactic consinstency of the arguments, and the if statement checks if the variable has been specified, otherwise assigns a default value. In this way the variables which are used in the function are always correctly initialized.

File names for executable/compiled binaries

Since we support FieldTrip on all currently popular platforms regarding hardware and software, we have to create executables for all platforms that we can. If an executable cannot be compiled on a particular platform, e.g. because it depends on windows specific DLLs, then you of course don't have to bother.

Ensuring that all executables can co-exist on all platforms (and especially on the unix base platforms) means that they should have unique file names. The choice for that is based on the specification according to the MATLAB function “computer”, i.e.

>> help computer
 COMPUTER Computer type.
    C = COMPUTER returns string C denoting the type of computer
    on which MATLAB is executing. Possibilities are:
 
                                              ISPC   ISUNIX   ISMAC       
    32-Bit Platforms
      PCWIN    - Microsoft Windows on x86       1       0       0
      GLNX86   - Linux on x86                   0       1       0
      MACI     - Apple Mac OS X on x86          0       1       1
 
    64-Bit Platforms
      PCWIN64  - Microsoft Windows on x64       1       0       0
      GLNXA64  - Linux on x86_64                0       1       0
      SOL64    - Sun Solaris on SPARC           0       1       0
      MACI64   - Apple Mac OS X on x86_64       0       1       1
  
    [C,MAXSIZE] = COMPUTER also returns integer MAXSIZE which 
    contains the maximum number of elements allowed in a matrix
    on this version of MATLAB.
 
    [C,MAXSIZE,ENDIAN] = COMPUTER also returns either 'L' for
    little endian byte ordering or 'B' for big endian byte ordering.
 
    HPUX, HP700, ALPHA, IBM_RS, SGI, and Mac for PowerPC are no
    longer supported.
 
    See also ispc, isunix, ismac.
 

The binaries for the different versions of the unix platforms (Linux, OS X) should have an extension corresponding to the computer type, e.g. the buffer executable would be named

  • buffer.exe for Microsoft Windows
  • buffer.glnx86 for 32-bit Linux
  • buffer.glnxa64 for 64-bit Linux
  • buffer.mac for 32-bit Mac OS X on PPC hardware
  • buffer.maci for 32-bit Mac OS X on Intel hardware
  • buffer.maci64 for 64-bit Mac OS X on Intel hardware

Note that on Windows the executable is required to have the file extension “exe”. In general it is sufficient to only provide a 32-bit version of the executable. For 64-bit Windows there is no convention yet.

Check the requirements

FieldTrip of course depends on MATLAB, but there are additional requirements, such as operating systems (for mex files) and external toolboxes. We want to develop FieldTrip such that it can be used by as many people as possible, which means that we want to control and minimize the additional requirements

Please consider the general requirements when extending or changing the FieldTrip code. Keep in mind that FieldTrip should not only run on the latest and greatest MATLAB version that you happen to have installed on your personal “supercomputer”, but also on the more modest computers of many other people with other (older or newer) MATLAB versions and operating systems.

Ensure that it runs on older MATLAB versions

Although you may be developing FieldTrip on the latest MATLAB version, we try to support it for previous MATLAB versions up to five years old.

version number release name release date
MATLAB 7.13 R2011b 13 Aug 2011
MATLAB 7.12 R2011a 08 Apr 2011
MATLAB 7.11 R2010b 03 Sep 2010
MATLAB 7.10 R2010a 05 Mar 2010
MATLAB 7.9 R2009b 04 Sep 2009
MATLAB 7.8 R2009a 06 Mar 2009
MATLAB 7.7 R2008b 09 Oct 2008
MATLAB 7.6 R2008a 01 Mar 2008
MATLAB 7.5 R2007b 01 Sep 2007
MATLAB 7.4 R2007a 01 Mar 2007
MATLAB 7.3 R2006b 03 Aug 2006
MATLAB 7.2 R2006a 27 Jan 2006
MATLAB 7.1.0 R14-SP3 02 Aug 2005
MATLAB 7.0.4 R14-SP2 29 Jan 2005
MATLAB 7.0.0 R14 06 May 2004
MATLAB 6.5.1 R13-SP1 04 Aug 2003
MATLAB 6.5.0 R13 27 Jun 2002

To facilitate supporting older MATLAB versions, below we list some known incompatibilities:

  • the nargout function in Matlab 6.5 and older does not work on function handles
  • the “try … catch me …” statement fails in Matlab 7.4, see this bug

Avoid using nested functions

Although a nested function has certain advantages, it makes maintaining the code more difficult. Furthermore, ft_preamble and eval are not fully compatible with nested functions.

Use a consistent tab spacing

It is annoying to get large svn diffs just because of changes in the whitespace. That is why all developers are encouraged to work with two spaces instead of tabs. In the MATLAB editor you can specify this in preferences→editor→tab, where you can specify “2” and “tab key inserts spaces”.

With Ctrl-A, Ctrl-I you can auto-indent the whole m-file and ensure that the horizontal whitespaces are consistent.

Ask for help

If you are unsure about the choices that you should make in developing new code or contributing to existing code, please ask one of the experienced developers for help. Robert, Jan-Mathijs, Ingrid and Saskia all have a good understanding of the FieldTrip programming philosophy.

Suggested further reading

Please also consider the documentation guidelines when making contributions to the FieldTrip project.

code_guidelines.txt · Last modified: 2012/01/26 20:34 by 85.223.67.170

You are here: startcode_guidelines
This DokuWiki features an Anymorphic Webdesign theme, customised by Eelke Spaak and Stephen Whitmarsh.
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0