File: library_development.rst

package info (click to toggle)
openturns 1.24-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 66,204 kB
  • sloc: cpp: 256,662; python: 63,381; ansic: 4,414; javascript: 406; sh: 180; xml: 164; yacc: 123; makefile: 98; lex: 55
file content (456 lines) | stat: -rw-r--r-- 14,874 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
.. _library_development:

Library development
===================

This section provides information on how to develop within the
perimeter of the library and it’s documentation.

If you are willing to contribute the actual development of the library, please
consider reading our coding guidelines and contact us through the website.


Install a development version
-----------------------------

Install the required dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

See :ref:`dependencies` for the system requirements.

Download openturns
~~~~~~~~~~~~~~~~~~

You can retrieve the development master branch through the git
repository by issuing the following commands::

    git clone https://github.com/openturns/openturns.git
    cd openturns

Or, you can pick up a stable version::

    git clone -b v1.22 https://github.com/openturns/openturns.git
    cd openturns

Build openturns
~~~~~~~~~~~~~~~

CMake presets can be used on Linux, which sets debug build mode, warning flags, build dir, install prefix, etc::

    cmake --preset=linux-debug
    cmake --build build --target install --parallel 4

Run tests
~~~~~~~~~

Python tests can be run once the bindings are finished compiled::

    ctest --preset=python

C++ tests must be built prior to be launched::

    cmake --build build --target tests --parallel 4
    ctest --preset=cpp

and all the tests should be successful else check the log file
Testing/Temporary/LastTest.log.

Adding a single class to an existing directory
----------------------------------------------

This how-to explains the process that must be followed to fully
integrate a new class that provides an end-user facility (e.g. a new
distribution). We suppose that this class will take place in an existing
directory of the sources directories.

First, add the class to the C++ library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#. Create ``openturns/MyClass.hxx`` and ``MyClass.cxx`` in appropriate subdirectories of lib/src.
   The files must have the standard header comment, with a brief description
   of the class in Doxygen form and the standard reference to the LGPL license.

   For the header file ``MyClass.hxx``, the interface must be embraced
   between the preprocessing clauses:

   ::

       #ifndef OPENTURNS_MYCLASS_HXX
       #define OPENTURNS_MYCLASS_HXX

       BEGIN_NAMESPACE_OPENTURNS

       class OT_API MyClass
       {
       CLASSNAME;

       public:
         // default constructor
         MyClass();
       ...
       };

       END_NAMESPACE_OPENTURNS

       #endif // OPENTURNS_MYCLASS_HXX

   to prevent from multiple inclusions.

   See any pair of .hxx/.cxx files in the current directory and the PGQL
   document for the  coding rules: case convention for the static
   methods, the methods and the attributes, trailing underscore for the
   attribute names for naming a few.

#. Modify the ``CMakeLists.txt`` file in the directory containing
   ``MyClass.hxx`` and ``MyClass.cxx``:

   -  add ``MyClass.hxx`` to the headers using
      ``ot_install_header_file ( MyClass.hxx )``.

   -  add ``MyClass.cxx`` to the sources using
      ``ot_add_source_file ( MyClass.cxx )``.

#. Add ``MyClass.hxx`` to the file ``OTXXXXXX.hxx``, where ``XXXXXX`` is
   the name of the current directory.

#. Create a test file ``t_MyClass_std.cxx`` in the directory lib/test.
   This test file must use the standard functionalities of the class
   MyClass.
   Keep in mind there are over a thousand unit tests, so they should be
   reasonably quick to run, lasting preferably less than 10 seconds.

#. Create an expected output file ``t_MyClass_std.expout`` that contains
   a verbatim copy of the expected output (copy-paste the *validated*
   output of the test in this file).

#. Modify the ``CMakeLists.txt`` file in lib/test: add
   ``ot_check_test ( MyClass_std )`` in this file.

#. If the validation of your class involved advanced mathematics, or was
   a significant work using other tools, you can add this validation in
   the validation/src directory.

   -  copy all of your files in the validation/src directory.

   -  modify the validation/src/CMakeLists.txt file by appending the
      list of your files to the list of files to install.

#. You may want to update the Changelog file to mention new classes, bug fixes...

That’s it! Your class is integrated to the library and will be checked
for non-regression in all the subsequent versions of OpenTURNS, assuming
that your contribution has been incorporated in the “official”  release.
But nobody can use it!

Second, add your class to the Python interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#. Create MyClass.i in the python/src directory. In most situations, it
   should be:

   ::

       // SWIG file MyClass.i

       %{
       #include "openturns/MyClass.hxx"
       %}

       %include MyClass_doc.i

       %include openturns/MyClass.hxx
       namespace OT {
       %extend MyClass {

       MyClass(const MyClass & other)
       {
       return new OT::MyClass(other);
       }

       } // MyClass
       } // OT

#. Create MyClass\_doc.i.in docstring documentation in the python/src
   directory. This will be part of the HTML documentation generated by
   sphinx. Document every method of your class that’s not inherited. In
   most situations, it should look like this:

   ::

       %feature("docstring") OT::MyClass
       "MyClass class.

       Available constructors:
           MyClass()

           MyClass(*designPoint, limitStateVariable, isInFailureSpace*)

       Notes
       -----
       Structure created by the method run() of a :class:`~openturns.Analytical`
       and obtained thanks to the method *getAnalyticalResult*.

       Parameters
       ----------
       designPoint : float sequence
           Design point in the standard space resulting from the optimization
           algorithm.
       limitStateVariable : :class:`~openturns.RandomVector`
           Event of which the probability is calculated.
       isInFailureSpace : bool
           Indicates whether the origin of the standard space is in the failure space.

       Examples
       --------
       >>> import openturns as ot
       >>> ot.RandomGenerator.SetSeed(0)
       >>> dp = ot.Normal().getRealization()
       >>> inst = ot.MyClass(dp, 4.8)
       >>> print(inst)
       >>> 4.5677..."

       // ---------------------------------------------------------------------

       %feature("docstring") OT::MyClass::foo_method
       "...
       "

   Beware that docstring tests run from the Examples section share the same environment
   and they can be affected by global settings such as RandomGenerator seed or ResourceMap entries,
   so for example here we reset the RNG seed prior to sampling to avoid affecting the expected result.
   Also, these examples must be very quick because they are run as batches per module,
   more expensive tests can be run in the dedicated unit tests.

#. Modify the CMakeLists.txt file in python/src: add MyClass.i,
   MyClass\_doc.i.in to the relevant ``ot_add_python_module`` clause.

#. Locate and modify the file yyyy.i, where yyyy is the name of the
   python module related to MyClass, to include MyClass.i in the correct
   set of .i files (see the comments in yyyy.i file). In order to
   identify the correct python module, remember that the modules map
   quite closely the source tree organization.

#. Create a test file ``t_MyClass_std.py`` in the directory python/test.
   This test implements the same tests than ``t_MyClass_std.cxx``, but
   using python.
   Keep in mind there are over a thousand unit tests, so they should be
   reasonably quick to run, lasting preferably less than 10 seconds.

#. Modify the CMakeLists.txt file in python/test:

   -  add ``t_MyClass_std.py`` to the tests using
      ``ot_pyinstallcheck_test ( MyClass_std )``.

Document your contribution more thoroughly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If your class introduces important mathematical concepts or impacts the
library architecture it may be useful to add some more details in the
documentation, see :ref:`sphinx_doc`.

That’s all, folks!

Some timings from an  Guru: 2 days of work for the most trivial
contribution (a copy-paste of a class with 5 methods, no mathematical or
algorithmic tricks). For a well-trained  contributor, a user-visible
class with a dozen of methods and well-understood algorithms, a new
class should not be less than a week of work...


Adding a set of classes in a new subdirectory
---------------------------------------------

This how-to explains the process that must be followed to fully
integrate a set of classes that provides an end-user facility (e.g. a
new simulation algorithm) developed in a new subdirectory of the
existing sources. The task is very similar to the steps described in the
how-to, only the new steps will be described. We suppose
that the subdirectory has already been created, as well as the several
source files. There are three new steps in addition to those of the
how-to: the creation of the cmake infrastructure in the
new subdirectory, the modification of the infrastructure in the parent
directory and the modification of the infrastructure in the root
directory.

CMake infrastructure in the parent subdirectory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You have to set up the recursive call of Makefiles from a parent
directory to its subdirectories, and to aggregate the libraries related
to the subdirectories into the library associated to the parent
directory:

#. add NewDir subdirectory to the build:

   ::

       add_subdirectory (NewDir)

CMake infrastructure in the new subdirectory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You have to create a CMakeLists.txt file. Its general structure is given
by the following template:

::

    #                                               -*- cmake -*-
    #
    #  CMakeLists.txt
    #
    #  Copyright 2005-2024 Airbus-EDF-IMACS-ONERA-Phimeca
    #
    #  This library is free software: you can redistribute it and/or modify
    #  it under the terms of the GNU Lesser General Public License as published by
    #  the Free Software Foundation, either version 3 of the License, or
    #  (at your option) any later version.
    #
    #  This library is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU Lesser General Public License for more details.
    #
    #  You should have received a copy of the GNU Lesser General Public License
    #  along with this library.  If not, see <http://www.gnu.org/licenses/>.
    #

    # Register current directory files
    ot_add_current_dir_to_include_dirs ()

    ot_add_source_file (FirstFile.cxx)
    # ...
    ot_add_source_file (LastFile.cxx)

    ot_install_header_file (FirstFile.hxx)
    # ...
    ot_install_header_file (LastFile.hxx)

    # Recurse in subdirectories
    add_subdirectory (FirstDir)
    # ...
    add_subdirectory (LastDir)

Version control
---------------

The versioning system used for the development of the whole platform is Git.

The git repositories are hosted at `Gihub <https://github.com/openturns/openturns/>`_
where sources can be browsed.

.. figure:: Figures/BrowseSource.png
   :alt: GitHub interface: the source browser

Bug tracking
~~~~~~~~~~~~

GitHub’s tracker is called *Issues*, and has its own section in every repository.

The snapshot of the library `bug-tracker <https://github.com/openturns/openturns/issues>`_
shows the list of active tickets:

.. figure:: Figures/Tickets1.png
   :alt: GitHub interface: the ticket browser

Each ticket features attributes to help classification, interactive
comments and file attachment. This snapshot exposes the details
of a ticket:

.. figure:: Figures/Tickets2.png
   :alt: GitHub interface: details of a ticket report

Other requirements
------------------

Namespace
~~~~~~~~~

All the classes of the library are accessible within a single namespace
named OT and aliased as OpenTURNS. It allows one to insulate these classes
from classes from another project that could share the same name. Macros
are provided to enclose your code in the namespace as follow:

::

    BEGIN_NAMESPACE_OPENTURNS
    // code
    END_NAMESPACE_OPENTURNS

Internationalization
~~~~~~~~~~~~~~~~~~~~

The platform is meant to be widely distributed within the
scientific community revolving around probability and statistics, which
is essentially an international community. Therefore, the platform
should be designed so as to be adjustable to the users, particularly
those who do not speak English [1]_.

This involves not using any messages directly in the source code of the
platform, but rather to create a resource catalogue that can be loaded,
according to the locale setting of the user, when the application is
launched.

Another consequence of internationalization is the need for the Unicode
extended character set to be used for all strings.

Accessibility
~~~~~~~~~~~~~

The platform shall be accessible to disabled users. This has
implications on the ergonomics and the design of the User Interface,
particularly the GUI which should offer keyboard shortcuts for any
available function as well as keyboard-based (rather than mouse-based)
mechanisms to handle and select objects.

Profiling
~~~~~~~~~

`Flame Graphs <http://www.brendangregg.com/flamegraphs.html>`_ can help visualize
where your functions spends the most time. Here are some commands to profile your
code paths using the `perf <https://perf.wiki.kernel.org/index.php/Main_Page>`_ tool
and generate the associated graph with `FlameGraph <https://github.com/brendangregg/FlameGraph>`_.

.. figure:: Figures/perf_welch.png
   :alt: Flame graph of WelchFactory

First retrieve the graphing scripts:

::

    git clone https://github.com/brendangregg/FlameGraph.git /tmp/FlameGraph

You will need to build without parallelization and with debug flags:

::

    cmake -DUSE_TBB=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS="-fno-omit-frame-pointer" .

You will also want to disable openblas threads or openmp at any other level:

::

    export OMP_NUM_THREADS=1

Now you are ready to profile your executable:

::

    perf record --call-graph dwarf -o /tmp/perf.data ./lib/test/t_WelchFactory_std

Some Linux distros prevent normal users from collecting stats, in that case:

::

    echo "-1" | sudo tee /proc/sys/kernel/perf_event_paranoid
    echo "0" | sudo tee /proc/sys/kernel/kptr_restrict

At this point you should be able to generate the graph from the perf data:

::

    perf script -i /tmp/perf.data | /tmp/FlameGraph/stackcollapse-perf.pl | /tmp/FlameGraph/flamegraph.pl > /tmp/perf.svg



.. [1]
   English has been chosen as the native language for the platform.