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 * Configure cmake: hit c
24 * Generate the makefiles (or dsw): hit g
27 - Run the tests manually (optional):
28 Caveat: if you run the tests before installing, you NEED to positionate
29 the environment variable GDCM_DICT_PATH to GDCM/Dicts e.g.
30 export GDCM_DICT_PATH=~/cvs/gdcm/Dicts
31 Assuming your cwd is GDCMBIN, three modes are then available:
32 -- 1/ acces to a by number:
34 -- 2/ acces to a test by it's name, by passing it as argument to
36 ./Test/gdcmCxxTests hashtest
37 -- 3/ launch all the full test suite (again we assume cwd is GDCMBIN):
39 This is equivalent to "make test".
40 Note: ctest supports the argument filtering with regexp and
43 proposes the tests containing "print" in their name and
44 makes a verbose output. For other options refer to the
45 documentation at http://www.cmake.org.
47 * Sending the result to kitware's dashboard (optional)
49 The results should appear in
50 http://public.kitware.com/dashboard.php?name=public
51 under the name of your machine (uname), but for ease of use you can
52 change the SITE variable in your CMakeCache.txt to something more
53 accurate such as: GDCM-my_machine_name. The entry will then be within
54 the "Experimental Builds" entry.
56 * Install gdcm (as specified by CMAKE_INSTALL_PREFIX)
58 Note: the dictionaries used by gdcm are now located in
59 CMAKE_INSTALL_PREFIX + /share/ (i.e. GDCMINSTALL + /share/ if you
60 followed the above instructions).
62 * Python related section.
63 Depending on the cmake flags you used in order to compile gdcm could
64 be wrapped in two ways:
65 - the first python wrappers of gdcm uses Swig (http://www.swig.org). These
66 are the one generated when using autogen.sh --enable-python.
67 The entry point here is the file gdcmPython/gdcm.i which uses the
68 Swig syntax. As the last lines of this file (the ones starting
69 with the %include directive) only some classes are wrapped for python.
70 In theory only the library interface (basically the classes gdcmHeader
71 and gdcmFile) should be wrapped, but the time being some additional
72 classes are added (just to make sure those classes are Swig compatible:
73 swig is here used as some link checker!?).
74 Since gdcm is written in C++, Swig will produce two different outputs:
75 -- some C based low level wrapper (see gdcmPython/gdcm_wrap.c)
76 -- some Python based object oriented so called "shadow classes" (see
77 file gdcmPython/gdcm.py)
78 We also added the file gdcmPython/__init__.py which is the one that
79 actually gets loaded when one uses the gdcmPython Python package.
80 The file __init__.py loads the Swig generated shadow classes (gdcm.py)
81 but will only re-export the interface of gdcm which corresponds to
83 gdcmHeader = gdcm.gdcmHeader
84 gdcmDictSet = gdcm.gdcmDictSet
85 gdcmFile = gdcm.gdcmFile
87 Hence this whole Swig wrapping process is quite odd since we shall
88 wrap more classes (%include in swig.i) that eventually get exported to
89 the final user by gdcmPython/__init__.py.
90 - the second python wrappers uses the vtk (http://public.kitware.com/VTK/)
91 native wrappers i.e. the binary vtkWrapPython. But it should be noticed
92 that the purpose is here a bit different than the one of the Swig
93 generated Python wrappers. When using vtkWrapPython the goal is to
94 wrap a single vtk class namely vtkGdcmReader as defined in files
95 vtk/vtkGdcmReader.h and vtk/vtkGdcmReader.cxx (and of course those
96 files are hand made vtk oriented wrappers of gdcm).
97 Those wrappers are the one generated when using
98 autogen.sh --enable-python --enable-vtk
99 - In order to understand the difference between both wrappers you should
100 compare both demo scripts gdcmPython/demo/vtkGdcmDemo.py and
101 gdcmPython/demo/vtkGdcmReader.py. The first one only uses the
102 Swig wrapped classes ("from gdcmPython import gdcmHeader') as opposed
103 to vtkGdcmReader.py which also uses vtkWrapPython wrapped classes
104 ("from gdcmPython.vtkgdcmPython import *").
106 ------------------------------------------------------------------------------
107 gdcm coding style and religious/agnostic beliefs (proposition)
110 The following coding style intends to ease the work of developpers
111 themselves but also of users who will study, maintain, fix, and extend
112 the code. Any bread crumbs that you can drop in the way of explanatory
113 names and comments will go a long way towards helping other readers and
115 Keep in mind that to a large extent the structure of code directly
116 expresses its implementation.
119 - C++ (for the kernel) and Python (for the wrappers).
120 - all the names (variables, members, methods, functions) and comments
121 should be based on English. Documentation, guides, web site and other
122 informations should be in English.
123 Make sure you use correct (basic) English and complete, grammatically
124 correct sentences for comments and documentation.
127 - Each line of code should take no more than 79 characters. Break the code
128 across multiple lines as necessary.
129 - Methods and functions should keep a reasonable number of lines when
130 possible (a typical editor displays 50 lines). Avoid code duplication.
131 Always prefer creating a new method or function to duplication.
132 A high indentation level generally suggests the need for a new
134 - All the code should be properly indented. The appropriate indentation
135 level is three spaces for each level of indentation. DO NOT USE TABS.
136 Set up your editor to insert spaces. Using tabs may look good in your
137 editor but will wreak havoc in others, or in external tools (e.g. side
139 - The declaration of variables within classes, methods, and functions
140 should be one declaration per line. Provide them with default values
141 and don't rely on compilers for default initialization.
143 * Naming conventions:
145 In general, names are constructued by using case change to indicate
146 separate words, as in ImageDataSize (standing for "image data size").
147 Underscores are not used. Variable names are chosen carefully with the
148 intention to convey the meaning behind the code. Names are generally
149 spelled out; use of abbreviations is discouraged.
150 [Note: abbreviation are allowable when in common use, and should be in
151 uppercase as in LUT or RGBA.]
152 While this does result in long names, it self-documents the code.
154 Files should have the same name as the class, with a "gdcm" prepended.
155 Header files are named .h, while implementation files are named either
156 .cxx or .txx, depending on whether they are implementations of templated
157 classes. For example, the class gdcm::Document is declared and defined
158 in the files gdcmDocument.h and gdcmDocument.cxx.
159 - Naming Class Data Members, Methods, and Functions:
160 Class data members are named beginning with a capital letter as in
162 Global functions and class methods, either static or class members, are
163 named beginning with a capital letter, as in GetImageDataSize().
164 - Naming Local Variables:
165 Local variables begin in lowercase. There is more flexibility in the
166 naming of local variables although they still should convey some
170 - Don't use the inline keyword when defining an inline function
171 within a class definition.
172 - Do not repeat the virtual keyword when overriding virtual base methods
173 in declaration of subclasses:
176 virtual void foo(...);
180 void foo(...); // and not: virtual void foo(...);
182 - The public, protected, private declarations should be at the
183 same indent level as the class. Use
191 - Method and functions devoided of arguments should not use the void
193 SomeType Header::GetPixelData()
195 SomeType Header::GetPixelData(void).
198 - Braces must be used to delimit the scope of an if, for, while, switch, or
199 other control structure. Braces are placed on a line by themselves, and
200 at the same indentation level as the control structure to which they
202 for (i=0; * i<3; i++)
211 else if ( other condition )
219 You can choose to use braces on a line with a code block when
220 the block consists of a single line:
221 if ( condition ) { foo=1; }
222 else if ( condition2 ) { foo=3; }
225 for (i=0; i<3; ++i) {x[i]=0.0;}
226 Methods and functions should follow the same usage of braces:
227 void File::ParsePixelData()
233 - Avoid code mixed with comments on a single line. Instead, prepend the
234 logical blocks of code with the concerned comments.
235 - Use parantheses around conditions e.g. with an if statement:
236 if ( someLocalVariable == 2 ) { ... }
237 - Add spaces around parantheses, or braces. Use
238 if ( someLocalVariable == 2 ) { ClassMenber += 1; }
240 if (someLocalVariable == 2) {ClassMenber += 1;}
241 - Add spaces around each side of the assignement operator, and
242 around binary operators used in boolean expression. Use
243 someLocalVariable = ClassMember * 2;
244 if ( someLocalVariable == 2 || ClassMember == 2 ) ...
246 someLocalVariable=ClassMember*2;
247 if ( someLocalVariable==2||ClassMember==2 ) ...
250 - Don't use underscores. Don't use tabs. Don't use control characters
251 like ^M. Anyhow, cvs is configured to reject such commits.
252 - Comments should be in C++ style ("// ...", two slashes, per line). Don't
253 use C style comments ("/* ... */").
254 - The last line of a file should terminate with "\n".
255 - Returned arguments of methods and functions should not be wrapped with
259 return ( iter->second );
261 * Debugging and Verbose modes:
262 Never use std::cout. Instead use the gdcmDebug class through the
263 global instance dbg. Example:
264 #include "gdcmDebug.h"
267 dbg.Verbose(3, "Local function name: entering.");
270 will send the message to std::cout when dbg.Debug() is called
274 The Doxygen open-source system is used to generate on-line documentation.
275 Doxygen requires the embedding of simple comments in the code which is in
276 turn extracted and formatted into documentation. See
277 http://www.stack.nl/ dimitri/doxygen/
278 for more information about Doxygen.
279 - Documenting a class:
280 Classes should be documented using the class and brief doxygen commands,
281 followed by the detailed class description:
284 * \brief Header acts as container of Dicom elements of an image.
286 * Detailed description of the class is provided here
289 The key here is that the comment starts with /**, each subsequent line has
290 an aligned *, and the comment block terminates with a */.
291 - Documenting class members and inline methods:
292 All the members and the inline methods should be documented within
293 the class declaration as shown in the following example:
296 /// True when parsing was succefull. False otherwise.
297 bool Readable = false;
299 /// \brief The number of lines of the image as interpreted from
300 /// the various elements encountered at header parsing.
301 int NumberOfLines = -1;
303 /// Predicate implemented as accessor around \ref Readable.
304 bool IsReadable() { return Readable; }
306 - Documenting a Method:
307 Methods should be documented using the following comment block style
308 as shown in the following example:
311 * \brief Within the Dicom Elements (parsed with the public and private
312 * dictionaries), look for the element value representation of
314 * @param group Group number of the searched tag.
315 * @param element Element number of the searched tag.
316 * @return Corresponding element value representation when it exists,
317 * and the string "gdcm::Unfound" otherwise.
319 std::string Document::GetEntryByNumber(guint16 group, guint16 element)
324 * External includes and C style:
325 - Only the C++ standard library and the STL includes should be used.
326 When including don't use the .h extension (use #include <iostream>
327 instead of #include <iostream.h>).
328 - Don't use the C standard library. Don't include stdio.h, ctype.h...
329 Don't use printf(), sprinf(), FILE*...
330 - Don't use the NULL notation (either as macro, or as const int NULL=0).
331 A pointer that doesn't refer to an object should simply be defined as
332 DataPointer* MyDataPointer = 0;
335 - Assume T is a given type. When declaring or defining with the
336 "pointer to T" notation, the * character must be adjacent to
337 the type and not the variable. That is use
341 - Always define a typedef for a new type and be consistent in usage.
343 typedef Header* HeaderPointer;
344 HeaderPointer MyHeaderPointer;
345 - One notorious counter example for non using C style inclusion concerns
346 exact-width intergers (since there seem to be no equivalent for C++).
347 When using exact-width integers use the typedef names defined by
348 the Basic ISO C99: 7.18 Integer types i.e.
349 int8_t int16_t int32_t int64_t (signed integers)
351 uint8_t uint16_t uint32_t uint64_t (unsigned integers).
352 Hence do not use declarations like "unsigned int".
353 With g++, accessing those typedef is achieved by the following
355 ------------------------------------------------
357 * All the commits should be atomic. They must preserve the compilation
358 in order to prevent checkouts with broken code.
359 * All the commits must correspond to a stade of the code where ctest
360 runs and has no failing subtest. Always run ctest before commiting.
361 Note: * you can start ctest in verbose mode through the command
363 * you can start a single test through ctest with
364 ctest -R FailingTestName -V >& log
365 ------------------------------------------------