Salome HOME
4e6497af640fb25450ed763bd20354856fde5222
[modules/med.git] / doc / dev / sphinx / medcalc-userguide-gui.rst
1 .. meta::
2    :keywords: mesh, field, manipulation, user guide
3    :author: Guillaume Boulant
4
5 .. include:: medcalc-definitions.rst
6
7 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8 FIELDS module: User guide for graphical interface
9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
11 This document is a quick guide for Graphical User Interface of FIELDS module. It
12 shows how to use this module on the basis of a few reference examples, built
13 from use cases identified during requirement analysis stage.
14
15 .. warning:: This document is self-contained, but it is strongly advised to
16              read :doc:`the specification document<medcalc-specifications>` (in
17              french), at least to clarify concepts and terminology.
18
19 .. contents:: Contents
20    :local:
21    :backlinks: none
22
23 .. warning:: Screenshots are not up-to-date. They were extracted from SALOME
24              6 with data visualization achieved using VISU module. In SALOME
25              7, VISU module has been replaced by PARAVIS module. The
26              look-and-feel may thus be slightly different.
27
28 General presentation of FIELDS module
29 =====================================
30
31 The overall ergonomics of FIELDS module for field manipulation is inspired by
32 software such as octave or scilab. It combines a graphical interface (GUI) to
33 select and prepare data, with a textual interface (the python console, TUI)
34 for actual work on data.
35
36 This module provides two user environments that are marked by the red and
37 green rectangles on the screenshot below:
38
39 * **The data space** (*dataspace*), in which user defines the MED data sources
40   (*datasource*), that is to say the med files from which meshes and fields
41   are read. This data space allows for the exploration of meshes and fields
42   provided by the different data sources.
43 * **The workspace** (*workspace*), in which user may drop fields selected in
44   the source space, and then use them for example to produce new fields using
45   the operations on fields provided by the TUI.
46
47 .. image:: images/xmed-gui-withframe.png
48    :align: center
49
50 A typical use of field manipulation functions is:
51
52 1. Load a med file in the data space and explore its contents: meshes and
53    fields defined on these meshes, defined for one or several time steps.
54 2. Select (using GUI) fields to be manipulated in workspace ; it is possible
55    to introduce restrictions on time steps, components or groups of cells.
56 3. Create new fields executing algebraic operations (+,-,*,/) on fields,
57    applying simple mathematical functions (pow, sqrt, abs), or initializing
58    them "from scratch" on a support mesh.
59 4. Visually control produced fields, using PARAVIS module in SALOME,
60    automatically controlled from user interface.
61 5. Save (parts of) produced fields to a med file.
62
63
64 Quick tour on functions available in FIELDS module
65 ==================================================
66
67 This section presents some use examples of FIELDS module like a "storyboard",
68 illustrating the functions proposed by the module.
69
70 .. warning:: This section is under construction. Please consider that its
71              contents and organization are still incomplete and may change
72              until this warning is removed.
73
74 Example 1: Explore data sources
75 -------------------------------
76
77 .. note:: This example illustrates the following functions:
78
79    * add a data source
80    * "Extends field series" and "Visualize" functions
81
82 .. |ICO_DATASOURCE_ADD| image:: images/ico_datasource_add.png
83                         :height: 16px
84
85 .. |ICO_XMED| image:: images/ico_xmed.png
86               :height: 16px
87
88 .. |ICO_DATASOURCE_EXPAND| image:: images/ico_datasource_expandfield.png
89                            :height: 16px
90
91 .. |ICO_DATASOURCE_VIEW| image:: images/ico_datasource_view.png
92                          :height: 16px
93
94 At startup the field manipulation module, identified by icon |ICO_XMED|, shows
95 an empty interface:
96
97 .. image:: images/xmed-gui-start.png
98    :align: center
99    :width: 800px
100
101 The first step consists in adding one or several med data sources in
102 "dataspace". For this, user clicks on icon "Add datasource"
103 |ICO_DATASOURCE_ADD| to select a med file:
104
105 .. image:: images/xmed-gui-datasource-selectfile.png
106    :align: center
107    :width: 800px
108
109 This operation adds a new entry (datasource) in data space. The contents can
110 be explored using the data tree. The figure below (left image) shows the
111 result of loading the file ``timeseries.med`` containing a mesh named
112 ``Grid_80x80`` on which a field on nodes named ``Pulse`` is defined. By
113 default, the field composition (in terms of time steps and components) is not
114 displayed to avoid visual congestion of data tree. User must explicitly ask
115 for visualization using the command "Expand field timeseries"
116 |ICO_DATASOURCE_EXPAND| available in the field contextual menu. The result is
117 displayed on center image. The list of field ``Pulse`` iterations can be advised.
118
119 .. |IMG_DATASOURCE_EXPLORE| image:: images/xmed-gui-datasource-explore-zoom.png
120                             :height: 340px
121 .. |IMG_DATASOURCE_MENUCON| image:: images/xmed-gui-datasource-menucontextuel-zoom.png
122                             :height: 340px
123 .. |IMG_DATASOURCE_EXPANDF| image:: images/xmed-gui-datasource-expand-zoom.png
124                             :height: 340px
125
126 +--------------------------+--------------------------+--------------------------+
127 | |IMG_DATASOURCE_EXPLORE| | |IMG_DATASOURCE_MENUCON| | |IMG_DATASOURCE_EXPANDF| |
128 +--------------------------+--------------------------+--------------------------+
129
130 .. note:: Strictly speaking,  the *field* concept in MED model corresponds to
131           a given iteration. A set of iterations is identified by the term
132           *field time series*. If there is no ambiguity, the field name will
133           refer to both the field itself or the time series it belongs to.
134
135 Finally, it is possible from dataspace to visualize the field general shape
136 using a scalar map displayed in SALOME viewer. For this, user selects the time step to
137 display then uses the command "Visualize" |ICO_DATASOURCE_VIEW| available in
138 the associated contextual menu:
139
140 .. image:: images/xmed-gui-datasource-visualize-zoom.png
141    :align: center
142    :width: 800px
143
144 .. note:: This graphical representation aims at providing a quick visual
145           control. Scalar maps are displayed using the PARAVIS module.
146
147 Example 2: Combine fields from different sources
148 ------------------------------------------------
149
150 .. note:: This example illustrates the following functions:
151
152    * function "Use in workspace"
153    * function "Save"
154
155 .. |ICO_DATASOURCE_USE| image:: images/ico_datasource_use.png
156                         :height: 16px
157 .. |ICO_WORKSPACE_SAVE| image:: images/ico_workspace_save.png
158                         :height: 16px
159
160 The objective is to access data contained in several med files, then to
161 combine them in the same output file.
162
163 User starts by adding med data sources in dataspace. In the example below,
164 dataspace contains two sources names ``parametric_01.med`` and
165 ``smallmesh_varfiled.med``. The first one contains the mesh ``Grid_80x80_01``
166 on which the field ``StiffExp_01`` is defined. The second source contains the
167 mesh ``My2DMesh`` on which the two fields ``testfield1`` are ``testfield2``
168 are defined:
169
170 .. image:: images/xmed-userguide-example2-datasource.png
171    :align: center
172    :width: 800px
173
174 In this example, ``StiffExp_01`` and ``testfield2`` are combined then saved to
175 ``result.med`` file. The procedure consists in importing the two fields in
176 workspace, then to save the workspace. For this user selects the fields and
177 uses the command "Use in workspace" |ICO_DATASOURCE_USE| available in the
178 contextual menu. Both selected fields appear in the workspace tree:
179
180 .. image:: images/xmed-userguide-example2-workspace.png
181    :align: center
182    :width: 800px
183
184 Workspace is saved using the command "Save workspace" |ICO_WORKSPACE_SAVE|
185 available in the module toolbar. A dialog window lets user set the save
186 file name:
187
188 .. image:: images/xmed-userguide-example2-workspace-save.png
189    :align: center
190    :width: 800px
191
192 The file ``result.med`` can then be reloaded in FIELDS module (or PARAVIS module)
193 to check the presence of saved fields.
194
195 .. BUG: plantage à l'utilsation dans XMED d'un fichier rechargé
196 .. (invalid mesh on field)
197
198 .. _xmed.userguide.exemple3:
199
200 Example 3: Apply a formula on fields
201 ------------------------------------
202
203 .. note:: This example illustrates the following functions:
204
205    * execute mathematical operations in TUI console
206    * function "put" to refer to a work field in the list of persisting fields.
207    * function "Visualize" from TUI.
208
209 The most common usage of field manipulation module is to execute mathematical
210 operations on fields or on their components.
211
212 Assume data sources are already defined in dataspace (in the following example
213 a temporal series named ``Pulse`` contains 10 time steps defined on a mesh
214 named ``Grid_80x80``, all read from ``timeseries.med`` data source).
215
216 As previously seen, a field can be manipulated in workspace after selecting
217 the field and applying the command "Use in
218 workspace" |ICO_DATASOURCE_USE| from contextual menu. Here only one file is
219 selected (two in the previous example) and the command then opens a dialog
220 window to select data to work on and the way they will be manipulated:
221
222 .. image:: images/xmed-gui-datasource-useinworkspace-alias.png
223    :align: center
224    :width: 800px
225
226 .. note:: In the current state of development, the interface only propose to
227           define the name of a variable representing the field in TUI. In
228           a next version, user will have the possibility to specify the field
229           component(s) to be used and a group of cells to introduce
230           a geometrical restriction. Conversely it will be possible to select
231           a complete time series to apply global operations on all time steps.
232
233 After validation, the field if put in workspace tree and a variable
234 ``<alias>`` is automatically created in the TUI to designate the field. In
235 this example, ``<alias>`` is ``f3``, as set by user to recall that variable
236 corresponds to the third time step:
237
238 .. image:: images/xmed-gui-workspace.png
239    :align: center
240    :width: 800px
241
242 Field manipulation can start. In the example below, use creates the field``r``
243 as the result of an affine transformation of field ``f3`` (multiplication of
244 field by a scale factor 2.7 then addition of offset 5.2)::
245
246  >>> r=2.7*f3+5.2
247
248 Other operations can be applied, as detailed in module specifications
249 (cf. :ref:`Spécification des opérations<xmed-specifications>`):
250
251  >>> r=f3/1000     # the values of r are the ones of f3 reduced by a factor 1000
252  >>> r=1/f3        # the values of r are the inverted values of f3
253  >>> r=f3*f3       # the values of r are the squared values of f3
254  >>> r=pow(f3,2)   # same result
255  >>> r=abs(f3)     # absolute value of field f3
256  >>> ...
257
258 The two operands can be fields. If ``f4`` is the fourth time step of field
259 ``Pulse``, then algebraic combinations of fields can be computed::
260
261  >>> r=f3+f4
262  >>> r=f3-f4
263  >>> r=f3/f4
264  >>> r=f3*f4
265
266 Scalar variables can be used if needed::
267
268  >>> r=4*f3-f4/1000
269  >>> ...
270
271 In these examples, the variable ``r`` corresponds to a work field containing
272 the operation result. By default the field is nor referenced in workspace
273 tree. If user wants to add it, for example to make it considered when saving,
274 then the following command is used::
275
276  >>> put(r)
277
278 The function ``put`` aims at tagging the field as persisting, the to store it
279 in the workspace tree to make it visible and selectable. Among all fields that
280 could be created in console during the work session, all do not need to be
281 saved. Some may only be temporary variables used in the construction of final
282 fields. That is why only fields in workspace tree are saved when saving the
283 workspace.
284
285 Variables defined in console have other uses. First they allow for printing
286 information relative to the manipulated field. For this one enters the
287 variable name then validates::
288
289  >>> f3
290  field name (id)         = Pulse (3)
291  mesh name (id)          = Grid_80x80 (0)
292  discretization          = ON_NODES
293  (iter, order)           = (3,-1)
294  data source             = file:///home/gboulant/development/projets/salome/MEDOP/XMED/xmed/resources/datafiles/timeseries.med
295
296 Second, variables can be used as command arguments (the list of commands
297 available in TUI is described in section :ref:`Documentation of textual
298 interface<xmed.userguide.tui>`). For example the function ``view`` displays
299 the field scalar map in the viewer::
300
301  >>> view(f3)
302
303 Results in:
304
305 .. image:: images/xmed-gui-workspace-view.png
306    :align: center
307    :width: 800px
308
309 .. note:: It is easy to compare two time steps of a field, computing the
310           difference ``f3-f4``, then producing a scalar map preview using the
311           function ``view``::
312
313           >>> view(f3-f4)
314
315 Finally the field data can be displayed using the command``print``::
316
317  >>> print f3
318  Data content :
319  Tuple #0 : -0.6
320  Tuple #1 : -0.1
321  Tuple #2 : 0.4
322  Tuple #3 : -0.1
323  Tuple #4 : 0.4
324  ...
325  Tuple #6556 : 3.5
326  Tuple #6557 : 3.3
327  Tuple #6558 : 1.5
328  Tuple #6559 : 0.3
329  Tuple #6560 : 0.2
330
331 It is important to note that operations between fields can only be applied if
332 fields are defined on the same mesh. It corresponds to a specification of MED
333 model that forbids operations between fields defined on meshes geometrically
334 different. Technically it means that the conceptual objects *fields* must share
335 the same conceptual object *mesh*.
336
337 If user do want to use fields defined on different meshes, for example to
338 manipulate the field values at the interface of two meshes sharing a 2D
339 geometrical area, it is necessary first to make all fields be defined on the
340 same surface mesh using a projection operation.
341
342 .. note:: Such projection operations are available in the MEDCoupling library.
343
344 Another classical need is using fields defined on meshes geometrically
345 identical, but technically different for example when they are loaded from
346 different med files. For such a case, the MEDCoupling library proposes
347 a function "Change support mesh" ; its use in field manipulation module is
348 illustrated in :ref:`example 4<xmed.userguide.exemple4>` described hereafter.
349
350 .. _xmed.userguide.exemple4:
351
352 Example 4: Compare fields derived from different sources
353 --------------------------------------------------------
354
355 .. note:: This example illustrates the following function:
356
357    * Change the underlying (support) mesh
358
359 Assume here that fields have been defined on same mesh, geometrically
360 speaking, but saved in different med files. This occurs for example for
361 a parametric study in which several computations are achieved with variants on
362 some parameters of the simulated model, each computation producing a med file.
363
364 Let ``parametric_01.med`` and ``parametric_02.med`` be two med files
365 containing the fields to compare, for example computing the difference of
366 their values and visualizing the result.
367
368 After loading data sources user sees two meshes, this time from the technical
369 point of view, that is to say fields are associated to different conceptual
370 mesh objects, while geometrically identical.
371
372 However field manipulation functions do not allow operations on fields lying
373 on different support meshes (see remark at the end of  :ref:`example
374 3<xmed.userguide.exemple3>`).
375
376 To circumvent this issue, the module offers the function "Change underlying
377 mesh" to replace a field mesh support by another, provided that the two meshes
378 are geometrically identical, that is to say nodes have the same spatial
379 coordinates.
380
381 .. |ICO_DATASOURCE_CHG| image:: images/ico_datasource_changeUnderlyingMesh.png
382                         :height: 16px
383
384 In the proposed example, user selects the first time step of field
385 ``StiffExp_01`` in data source ``parametric_01.med``, and imports it in
386 workspace using the command "Use in workspace" |ICO_DATASOURCE_USE|. User then
387 selects the first time step of field ``StiffExp_02`` in data source
388 ``parametric_02.med``, but imports it in workspace using the command "Change
389 underlying mesh" |ICO_DATASOURCE_CHG|. The following dialog window appears to
390 let user select the new support mesh in dataspace tree:
391
392 .. image:: images/xmed-gui-datasource-changeUnderlyingMesh.png
393    :align: center
394
395 In this example, the support mesh ``Grid_80x80_01`` of field ``StiffExp_01``
396 to compare with is selected. After validation the workspace tree contains the
397 field ``StiffExp_02`` defined on mesh ``Grid_80x80_01``:
398
399 .. image:: images/xmed-gui-datasource-changeUnderlyingMesh_wsview.png
400    :align: center
401
402 .. note:: The function "Change underlying mesh" does not modify the field
403           selected in dataspace (basic running principle of dataspace), but
404           creates a field copy in workspace to then change support mesh. This
405           explains the default name for field ``dup(<name of selected
406           field>)`` (dup stands for "duplicate").
407
408 All we have to do now is to associate a variable to this field, in order to
409 manipulate it in TUI. This can be done using the command "Use in console"
410 available in workspace contextual menu.
411
412 Finally, if ``f1`` is a field from datasource ``parametric_01.med`` and ``f2``
413 is a field from datasource
414 ``parametric_02.med`` according to the above procedure, then comparison values
415 can be achieved as explained in :ref:`example 3<xmed.userguide.exemple3>`::
416
417  >>> r=f1-f2
418  >>> view(r)
419
420 .. note:: As a general remark concerning this example, one may note:
421
422    * the geometrical equality of two meshes is constrained to a numerical
423      error that can be technically set, but not through the module interface.
424      This tolerance is empirically set to a standard value regarding to
425      success of most of the use cases. The usefulness of setting this value in
426      the interface could be later investigated.
427
428    * User must explicitly ask for changing a field support mesh, in order to
429      compare fields coming from different data sources. This choice has been
430      made to keep trace of modifications made on data (no modification is made
431      without user knowing, even to improve ergonomics).
432
433
434 Example 5: Create a field on a spatial domain
435 ---------------------------------------------
436
437 .. note:: This example illustrates the following functions:
438
439    * initialize with function of spatial position
440    * initialize on a group of cells
441
442 The geometrical domain on which the field to create is defined is here given
443 by cell group data. This use case is provided for producing initial load
444 conditions of a structure, for example defining a field on a geometry surface
445 identified by a group of cells.
446
447 .. warning:: DEVELOPMENT IN PROGRESS
448
449 Example 6: Extract a field part
450 -------------------------------
451
452 .. note:: This example illustrates the following functions:
453
454    * extract a component (or a subset of components)
455    * extract a geometrical domain (values on a group of cells)
456    * extract one or several time steps
457
458 .. warning:: DEVELOPMENT IN PROGRESS
459
460    Here the restriction functions that allow to get some components only, have
461    to be illustrated. The principle is creating a new field that is
462    a restriction of input field to a list of given components (use the
463    function __call__ of fieldproxy).
464
465 For time step extraction, we can reduce to the case of example 2 with a single
466 data source.
467
468 Example 7: Create a field from a to[mp]ographic image
469 -----------------------------------------------------
470
471 .. note:: This example illustrates the following function:
472
473    * Create a field without data source (neither mesh nor field), from an
474      image file
475
476 In tomography or topography studies, measurement devices produce images that
477 represent a physical quantity using gray levels on a given cutting plane. The
478 following image represents for example a internal view of human body obtained
479 by MRI:
480
481 .. image:: images/xmed-irm.png
482    :align: center
483    :width: 600px
484
485 This image is a subset of pixels organized on a Cartesian grid. It can thus be
486 represented as a scalar field whose values are defined on cells of a mesh
487 having the same dimension as the image (number of pixels):
488
489 .. image:: images/xmed-irm-field.png
490    :align: center
491    :width: 600px
492
493 The field manipulation module provides a tool named ``image2med.py`` to
494 convert a file image to a med file containing the image representation as
495 a scalar field (only the gray level is kept)::
496
497   $ <xmed_root_dir>/bin/salome/xmed/image2med.py -i myimage.png -m myfield.med
498
499 .. |ICO_IMAGESOURCE| image:: images/ico_imagesource.png
500                         :height: 16px
501
502 This conversion operation can be automatically achieved using the command "Add
503 Image Source" |ICO_IMAGESOURCE| available in GUI toolbar. This command opens
504 the following window to let user select a file image:
505
506 .. image:: images/medop_image2med_dialog.png
507    :align: center
508
509 The name of result med file is set by default (changing file extension to
510 ``*.med``) but can be modified. Finally user can ask for automatic load of
511 this med file in data space. Fields can then be manipulated like presented in
512 the standard use cases.
513
514 For example, the image below depicts the result of the difference between two
515 images, added to the reference image: if i1 and i2 are the fields created from
516 these two images, then ``r = i1 + 5*(i2-i1)`` with 5 an arbitrary factor to
517 amplify the region of interest (above the left eye):
518
519 .. image:: images/xmed-irm-diff.png
520    :align: center
521    :width: 600px
522
523 The example below is the result of loading a tomographic image courtesy of MAP
524 project (Charles Toulemonde, EDF/R&D/MMC). The tomographic image:
525
526 .. image:: images/champ_altitude_MAP.png
527    :align: center
528    :width: 600px
529
530 The result of loading:
531
532 .. image:: images/medop_image2med_tomographie.png
533    :align: center
534    :width: 800px
535
536 Example 8: Continue analysis in PARAVIS
537 ---------------------------------------
538
539 .. note:: This example illustrates the following functio:
540
541    * Export fields to PARAVIS module
542
543 The solutions for field representation in FIELDS module aims at proposing a quick
544 visual control.
545
546 For a detailed analysis of fields, user shall switch to PARAVIS. The field
547 manipulation module has a function to facilitate this transition, with
548 automatic load in PARAVIS and proposing a default visualization (scalar map).
549
550 For this user selects in workspace the fields to export, then call the export
551 function from contextual menu:
552
553 .. image:: images/medop_exportparavis.png
554    :align: center
555
556 Selected fields are grouped in a single MED entry in PARAVIS, and the first
557 field is depicted as a scalar map:
558
559 .. image:: images/medop_exportparavis_result.png
560    :align: center
561    :width: 800px
562
563 .. note:: The export function is a convenience function. The same operation
564           can be manually achieved, first saving fields to a med file then
565           loading the created file in PARAVIS module for visualization.
566
567 .. _xmed.userguide.tui:
568
569 Using the textual interface (TUI)
570 =================================
571
572 All operations driven through GUI can be done (more or less easily) using TUI.
573 The field manipulation module can even be used exclusively in textual mode.
574
575 For this run the command:
576
577  $ <path/to/appli>/medop.sh
578
579 This command opens a command console ``medop>``. A med file can be loaded and
580 manipulated, for example to create fields from file data.
581
582 Whatever textual or graphical mode is used, a typical workflow in console
583 looks like the following instructions::
584
585  >>> medcalc.LoadDataSource("/path/to/mydata.med")
586  >>> la
587  id=0    name    = testfield1
588  id=1    name    = testfield2
589  >>> f1=accessField(0)
590  >>> f2=accessField(1)
591  >>>    ls
592  f1      (id=0, name=testfield1)
593  f2      (id=1, name=testfield2)
594  >>> r=f1+f2
595  >>> ls
596  f1      (id=0, name=testfield1)
597  f2      (id=1, name=testfield2)
598  r       (id=2, name=testfield1+testfield2)
599  >>> r.update(name="toto")
600  >>> ls
601  f1      (id=0, name=testfield1)
602  f2      (id=1, name=testfield2)
603  r       (id=2, name=toto)
604  >>> putInWorkspace(r)
605  >>> saveWorkspace("result.med")
606
607 The main commands are:
608
609 * ``LoadDataSource``: load a med file in data base (useful in pure textual mode)::
610
611   >>> LoadDataSource("/path/to/datafile.med")
612
613 * ``LoadImageAsDataSource``: load an image as a med file
614
615 * ``la``: show the list of all fields loaded in data base ("list all")
616 * ``accessField``: set a field in workspace from its identifier (useful in pure
617   textual mode ; this operation can be done in GUI selecting a field from data
618   space).::
619
620   >>> f=accessField(fieldId)
621
622 * ``ls``: show the list of fields available in workspace ("list")
623 * ``putInWorkspace``: put a reference to a field in *management space*::
624
625   >>> putInWorkspace(f)
626
627 * ``saveWorkspace``: save to a med a file all fields referenced in management space::
628
629   >>> saveWorkspace("/path/to/resultfile.med")
630
631 .. note::
632
633    * the ``LoadDataSource`` command only loads metadata describing meshes and fields
634      (names, discretization types, list of time steps). Meshes and physical
635      quantities on fields are loaded later (and automatically) as soon as an
636      operation needs them. In all cases med data (mete-information and values)
637      are physically stored in *data base* environment.
638    * the ``accessField`` command defines a *field handler* in workspace, i.e.
639      a variable that links to the physical field hosted in data base. Physical
640      data never transit between environments but remain centralized in data
641      base.
642
643 The following TUI commands need to work in graphical environment:
644
645 * ``medcalc.MakeDeflectionShape``
646 * ``medcalc.MakeIsoSurface``
647 * ``medcalc.MakePointSprite``
648 * ``medcalc.MakeScalarMap``
649 * ``medcalc.MakeSlices``
650 * ``medcalc.MakeVectorField``
651
652
653 ..  LocalWords:  softwares