1 The following comments are intended for core gdcm developpers.
4 - Checkout the sources to an arbitrary directory noted GDCM (e.g. ~/cvs/gdcm).
5 - Checkout the test images to an arbitrary directory noted GDCMDATA
6 (e.g. ~/cvs/gdcm/gdcmData).
7 - Optionally create a temporary installation directory GDCMINSTALL e.g.
9 - Create a target directory GDCMBIN e.g.
11 - Configure cmake from GDCMBIN:
14 * Toggle and adjust the required options and parameters, mainly
15 -- GDCM_DATA_ROOT should be set to GDCMDATA
16 -- CMAKE_INSTALL_PREFIX (equivalent of --prefix of the autotools)
17 should be set to GDCMINSTALL
18 -- CMAKE_BUILD_TYPE set to Debug or Release
20 -- GDCM_VTK When this option is on VTK_DIR might require manual
23 -- CMAKE_CXX_FLAGS (when working with gcc of course) should be set to
24 -g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter
25 -Wunused-function -Wunused -Wno-system-headers -Wno-deprecated
27 (this is to avoid spurious problems with overloading)
28 * Configure cmake: hit c
29 * Generate the makefiles (or dsw): hit g
32 - Run the tests manually (optional):
33 Caveat: if you run the tests before installing, you NEED to positionate
34 the environment variable GDCM_DICT_PATH to GDCM/Dicts e.g.
35 export GDCM_DICT_PATH=~/cvs/gdcm/Dicts
36 Assuming your cwd is GDCMBIN, three modes are then available:
37 -- 1/ acces to a by number:
39 -- 2/ acces to a test by it's name, by passing it as argument to
41 ./Test/gdcmCxxTests hashtest
42 -- 3/ launch all the full test suite (again we assume cwd is GDCMBIN):
44 This is equivalent to "make test".
45 Note: ctest supports the argument filtering with regexp and
48 proposes the tests containing "print" in their name and
49 makes a verbose output. For other options refer to the
50 documentation at http://www.cmake.org.
52 * Sending the result to kitware's dashboard (optional)
54 The results should appear in
55 http://public.kitware.com/dashboard.php?name=public
56 under the name of your machine (uname), but for ease of use you can
57 change the SITE variable in your CMakeCache.txt to something more
58 accurate such as: GDCM-my_machine_name. The entry will then be within
59 the "Experimental Builds" entry.
61 * Install gdcm (as specified by CMAKE_INSTALL_PREFIX)
63 Note: the dictionaries used by gdcm are now located in
64 CMAKE_INSTALL_PREFIX + /share/ (i.e. GDCMINSTALL + /share/ if you
65 followed the above instructions).
67 * Python related section.
68 Depending on the cmake flags you used in order to compile gdcm could
69 be wrapped in two ways:
70 - the first python wrappers of gdcm uses Swig (http://www.swig.org). These
71 are the one generated when using autogen.sh --enable-python.
72 The entry point here is the file gdcmPython/gdcm.i which uses the
73 Swig syntax. As the last lines of this file (the ones starting
74 with the %include directive) only some classes are wrapped for python.
75 In theory only the library interface (basically the classes gdcmHeader
76 and gdcmFile) should be wrapped, but the time being some additional
77 classes are added (just to make sure those classes are Swig compatible:
78 swig is here used as some link checker!?).
79 Since gdcm is written in C++, Swig will produce two different outputs:
80 -- some C based low level wrapper (see gdcmPython/gdcm_wrap.c)
81 -- some Python based object oriented so called "shadow classes" (see
82 file gdcmPython/gdcm.py)
83 We also added the file gdcmPython/__init__.py which is the one that
84 actually gets loaded when one uses the gdcmPython Python package.
85 The file __init__.py loads the Swig generated shadow classes (gdcm.py)
86 but will only re-export the interface of gdcm which corresponds to
88 gdcmHeader = gdcm.gdcmHeader
89 gdcmDictSet = gdcm.gdcmDictSet
90 gdcmFile = gdcm.gdcmFile
92 Hence this whole Swig wrapping process is quite odd since we shall
93 wrap more classes (%include in swig.i) that eventually get exported to
94 the final user by gdcmPython/__init__.py.
95 - the second python wrappers uses the vtk (http://public.kitware.com/VTK/)
96 native wrappers i.e. the binary vtkWrapPython. But it should be noticed
97 that the purpose is here a bit different than the one of the Swig
98 generated Python wrappers. When using vtkWrapPython the goal is to
99 wrap a single vtk class namely vtkGdcmReader as defined in files
100 vtk/vtkGdcmReader.h and vtk/vtkGdcmReader.cxx (and of course those
101 files are hand made vtk oriented wrappers of gdcm).
102 Those wrappers are the one generated when using
103 autogen.sh --enable-python --enable-vtk
104 - In order to understand the difference between both wrappers you should
105 compare both demo scripts gdcmPython/demo/vtkGdcmDemo.py and
106 gdcmPython/demo/vtkGdcmReader.py. The first one only uses the
107 Swig wrapped classes ("from gdcmPython import gdcmHeader') as opposed
108 to vtkGdcmReader.py which also uses vtkWrapPython wrapped classes
109 ("from gdcmPython.vtkgdcmPython import *").
111 ------------------------------------------------------------------------------
112 gdcm coding style and religious/agnostic beliefs (proposition)
115 The following coding style intends to ease the work of developpers
116 themselves but also of users who will study, maintain, fix, and extend
117 the code. Any bread crumbs that you can drop in the way of explanatory
118 names and comments will go a long way towards helping other readers and
120 Keep in mind that to a large extent the structure of code directly
121 expresses its implementation.
124 - C++ (for the kernel) and Python (for the wrappers).
125 - all the names (variables, members, methods, functions) and comments
126 should be based on English. Documentation, guides, web site and other
127 informations should be in English.
128 Make sure you use correct (basic) English and complete, grammatically
129 correct sentences for comments and documentation.
132 - Each line of code should take no more than 79 characters. Break the code
133 across multiple lines as necessary.
134 - Methods and functions should keep a reasonable number of lines when
135 possible (a typical editor displays 50 lines). Avoid code duplication.
136 Always prefer creating a new method or function to duplication.
137 A high indentation level generally suggests the need for a new
139 - All the code should be properly indented. The appropriate indentation
140 level is three spaces for each level of indentation. DO NOT USE TABS.
141 Set up your editor to insert spaces. Using tabs may look good in your
142 editor but will wreak havoc in others, or in external tools (e.g. side
144 - The declaration of variables within classes, methods, and functions
145 should be one declaration per line. Provide them with default values
146 and don't rely on compilers for default initialization.
148 * Naming conventions:
150 In general, names are constructued by using case change to indicate
151 separate words, as in ImageDataSize (standing for "image data size").
152 Underscores are not used. Variable names are chosen carefully with the
153 intention to convey the meaning behind the code. Names are generally
154 spelled out; use of abbreviations is discouraged.
155 [Note: abbreviation are allowable when in common use, and should be in
156 uppercase as in LUT or RGBA.]
157 While this does result in long names, it self-documents the code.
159 Files should have the same name as the class, with a "gdcm" prepended.
160 Header files are named .h, while implementation files are named either
161 .cxx or .txx, depending on whether they are implementations of templated
162 classes. For example, the class gdcm::Document is declared and defined
163 in the files gdcmDocument.h and gdcmDocument.cxx.
164 - Naming Class Data Members, Methods, and Functions:
165 Class data members are named beginning with a capital letter as in
167 Global functions and class methods, either static or class members, are
168 named beginning with a capital letter, as in GetImageDataSize().
169 - Naming Local Variables:
170 Local variables begin in lowercase. There is more flexibility in the
171 naming of local variables although they still should convey some
175 - Don't use the inline keyword when defining an inline function
176 within a class definition.
177 - Do not repeat the virtual keyword when overriding virtual base methods
178 in declaration of subclasses:
181 virtual void foo(...);
185 void foo(...); // and not: virtual void foo(...);
187 - The public, protected, private declarations should be at the
188 same indent level as the class. Use
196 - Method and functions devoided of arguments should not use the void
198 SomeType Header::GetPixelData()
200 SomeType Header::GetPixelData(void).
203 - Braces must be used to delimit the scope of an if, for, while, switch, or
204 other control structure. Braces are placed on a line by themselves, and
205 at the same indentation level as the control structure to which they
207 for (i=0; * i<3; i++)
216 else if ( other condition )
224 You can choose to use braces on a line with a code block when
225 the block consists of a single line:
226 if ( condition ) { foo=1; }
227 else if ( condition2 ) { foo=3; }
230 for (i=0; i<3; ++i) {x[i]=0.0;}
231 Methods and functions should follow the same usage of braces:
232 void File::ParsePixelData()
238 - Avoid code mixed with comments on a single line. Instead, prepend the
239 logical blocks of code with the concerned comments.
240 - Use parantheses around conditions e.g. with an if statement:
241 if ( someLocalVariable == 2 ) { ... }
242 - Add spaces around parantheses, or braces. Use
243 if ( someLocalVariable == 2 ) { ClassMenber += 1; }
245 if (someLocalVariable == 2) {ClassMenber += 1;}
246 - Add spaces around each side of the assignement operator, and
247 around binary operators used in boolean expression. Use
248 someLocalVariable = ClassMember * 2;
249 if ( someLocalVariable == 2 || ClassMember == 2 ) ...
251 someLocalVariable=ClassMember*2;
252 if ( someLocalVariable==2||ClassMember==2 ) ...
255 - Don't use underscores. Don't use tabs. Don't use control characters
256 like ^M. Anyhow, cvs is configured to reject such commits.
257 - Comments should be in C++ style ("// ...", two slashes, per line). Don't
258 use C style comments ("/* ... */").
259 - The last line of a file should terminate with "\n".
260 - Returned arguments of methods and functions should not be wrapped with
264 return ( iter->second );
266 * Debugging and Verbose modes:
267 Never use std::cout. Instead use the gdcmDebug class through the
268 global instance dbg. Example:
269 #include "gdcmDebug.h"
272 dbg.Verbose(3, "Local function name: entering.");
275 will send the message to std::cout when dbg.Debug() is called
279 The Doxygen open-source system is used to generate on-line documentation.
280 Doxygen requires the embedding of simple comments in the code which is in
281 turn extracted and formatted into documentation. See
282 http://www.stack.nl/ dimitri/doxygen/
283 for more information about Doxygen.
284 - Documenting a class:
285 Classes should be documented using the class and brief doxygen commands,
286 followed by the detailed class description:
289 * \brief Header acts as container of Dicom elements of an image.
291 * Detailed description of the class is provided here
294 The key here is that the comment starts with /**, each subsequent line has
295 an aligned *, and the comment block terminates with a */.
296 - Documenting class members and inline methods:
297 All the members and the inline methods should be documented within
298 the class declaration as shown in the following example:
301 /// True when parsing was succefull. False otherwise.
302 bool Readable = false;
304 /// \brief The number of lines of the image as interpreted from
305 /// the various elements encountered at header parsing.
306 int NumberOfLines = -1;
308 /// Predicate implemented as accessor around \ref Readable.
309 bool IsReadable() { return Readable; }
311 - Documenting a Method:
312 Methods should be documented using the following comment block style
313 as shown in the following example:
316 * \brief Within the Dicom Elements (parsed with the public and private
317 * dictionaries), look for the element value representation of
319 * @param group Group number of the searched tag.
320 * @param element Element number of the searched tag.
321 * @return Corresponding element value representation when it exists,
322 * and the string "gdcm::Unfound" otherwise.
324 std::string Document::GetEntryByNumber(guint16 group, guint16 element)
329 * External includes and C style:
330 - Only the C++ standard library and the STL includes should be used.
331 When including don't use the .h extension (use #include <iostream>
332 instead of #include <iostream.h>).
333 - Don't use the C standard library. Don't include stdio.h, ctype.h...
334 Don't use printf(), sprinf(), FILE*...
335 - Don't use the NULL notation (either as macro, or as const int NULL=0).
336 A pointer that doesn't refer to an object should simply be defined as
337 DataPointer* MyDataPointer = 0;
340 - Assume T is a given type. When declaring or defining with the
341 "pointer to T" notation, the * character must be adjacent to
342 the type and not the variable. That is use
346 - Always define a typedef for a new type and be consistent in usage.
348 typedef Header* HeaderPointer;
349 HeaderPointer MyHeaderPointer;
350 - One notorious counter example for non using C style inclusion concerns
351 exact-width integers (since there seem to be no equivalent for C++).
352 When using exact-width integers use the typedef names defined by
353 the Basic ISO C99: 7.18 Integer types i.e.
354 int8_t int16_t int32_t int64_t (signed integers)
356 uint8_t uint16_t uint32_t uint64_t (unsigned integers).
357 Conversion table is then:
358 unsigned char -> uint8_t;
359 unsigned short -> uint16_t;
360 unsigned int -> uint32_t;
361 unsigned long -> uint32_t;
362 unsigned long long -> uint64_t;
363 (signed) char -> int8_t;
367 long long -> int64_t;
368 Hence do not use declarations like "unsigned int".
369 With g++, accessing those typedef is achieved by the following
371 ------------------------------------------------
373 * All the commits should be atomic. They must preserve the compilation
374 in order to prevent checkouts with broken code.
375 * All the commits must correspond to a stade of the code where ctest
376 runs and has no failing subtest. Always run ctest before commiting.
377 Note: * you can start ctest in verbose mode through the command
379 * you can start a single test through ctest with
380 ctest -R FailingTestName -V >& log
381 ------------------------------------------------
382 Compiler flags policy:
383 When working with gcc please use the flags specified in DEVELOPPER file
384 (in order to avoid difficult overloading problems).
385 ------------------------------------------------