diff --git a/docs/source/data_import_export.rst b/docs/source/data_import_export.rst index a2ac528aa..d88ad253e 100644 --- a/docs/source/data_import_export.rst +++ b/docs/source/data_import_export.rst @@ -15,8 +15,11 @@ Importing and exporting data This section explains the different ways of importing and exporting data to and from a Spine database. +.. contents:: + :local: + Importing data with Importer ----------------------------- +**************************** Data importing is handled by the Importer project item which can import tabulated and to some degree tree-structured data @@ -27,53 +30,133 @@ but using an Importer item is preferred because then the process is documented a .. tip:: A Tool item can also be connected to Importer to import tool's output files to a database. -The heart of Importer is the **Import Editor** window in which the mappings from source data +The heart of Importer is the **Importer Specification Editor** window in which the mappings from source data to Spine database entities are set up. The editor window can be accessed -by the **Import Editor...** button in Importer's Properties dock. -Note, that you have to select one of the files in the **Source files** list before clicking the button. +by the |wrench| button in Importer's Properties dock where existing specifications can also be selected. .. image:: img/importer_properties.png :align: center -The **Import Editor** windows is divided into two parts: -**Sources** shows all the 'sheets' contained in the file, -some options for reading the file correctly, -and a preview table to visualize and configure how the data on the selected sheet would be mapped. -**Mappings**, on the other hand, shows the actual importing settings, the mappings from the input -data to database entities. +in the **Properties** tab there is also the option to cancel the import if an non-fatal error occurs during execution and +also three options for how to handle if some of the values that you are trying to import already exist in the target. +The three choices are: +*Keep existing*, *Replace* and *Merge indexes*. *Keep existing* means that the data that is already in the target Data Store will +be kept there and the new data the Importer tried to import is forgotten. *Replace* on the other hand means that +the newly imported data is put in place of the old data in the target Data Store. The *Merge indexes* -option works mostly like +the *Replace* option, but for indexed values like maps, time series and arrays the behavior is a little different. +With these value types the old index-value pairs in the target Data Store will be kept and the new value pairs will +be appended to it. If an index that is going to get imported already exist, the new imported value will be written +over the old value. + +When the specification editor is opened for an Importer without a specification, a list of the supported +connectors is presented. if the Importer is already connected to some data, it may have already selected +the proper connector and is only awaiting confirmation + +.. image:: img/importer_connector_type.png + :align: center + +When creating a Importer specification, it is usually helpful to have the data already connected to the Importer in +question so it is easier to visualize how the importer is handling the data. + +Importer specification editor +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The left side of the **Importer Specification Editor** contains four dock widgets that deal with the input source data. +**Source files** contains the filepath to the input file. **Source tables** contains all the different tables the file +has. If the file doesn't have tables or the file type doesn't have them, all of the files data will be in the one table. +These can be selected and deselected and only the selected ones will be imported. **Source options** has a few options +on how to handle the incoming data. **Source data** allows for the previewing of the data and also of the currently +selected mapping. + +The right side of the spec editor is all about mappings. **Mappings** lets you add, duplicate and remove mappings or +select a mapping to modify its options. **Mapping options** allow you to specify important things like what item type +you are importing. In **Mapping specification** you can select the specific places in the source data where the +object names, values etc. will be taken from. .. image:: img/import_editor_window.png :align: center -The options in the Mappings part declare if the currently selected sheet will be imported as an object or relationship -and what type of parameters, if any, the sheet contains. -The table can be used to configure how the input data is interpreted: -which row or column contains the entity class names, parameter values, time stamps and so on. +The filepath of the data that the importer will be importing is visible in the **Source files** -widget. +If the filetype supports tables, the tables that are to be importer can be selected under **Source tables**. +For flat data types like csv, all the data will be shown on a single table named after the file. +The option *Select All* is useful for selecting or deselecting all tables. If the Importer is opened in +`anonymous mode`_, there is also the option to add tables. + +**Source options** contains options to "format" the incoming data. the available options can differ depending on the +selected connector. The above picture shows the available options for excel files. Max rows specifies the amount of +rows from the input data that are considered by the importer. The option *Has header* converts the first row into +headers. *Skip rows* and *Skip columns* skip the first *N* specified rows or columns from the table. +If the table has empty rows or columns and some other data after that that you don't want to use, +*Read until empty row/column on first column/row* -options can be used to "crop" the imported data to the +first relevant block of information. Other possible options for different connector types include *Encoding, Delimiter, +Custom Delimiter, Quotechar* and *Maximum Depth*. **Load default mapping** sets all of the selections in the spec editor +to their default values. Be careful not to press this button unless you want to wipe the whole specification clean. + +.. note:: If you are working on a specification and accidentally press the *load default mapping* button + you can undo previous changes for the specification from the hamburger menu or by pressing **Ctrl+Z**. + To redo actions, or press **Crl+Y**. + +**Source data** shows the selected table's data and a preview of how the selected mapping will import the data. +An important aspect of data import is whether each item in the input data should be read as a string, a number, +a time stamp or something else. By default all input data is read as strings. +However, more often than not things like parameter values are actually numbers. Though types are usually casted automatically, +it is possible to manually control what type of data each column (and sometimes each row) contains from the preview table. +Clicking the data type indicator button on column or row headers pops up a menu with a selection of available data types. +Right clicking the column/row header also gives the opportunity to change the data type of all columns/rows at once. -.. image:: img/import_editor_mapping_options.png +.. image:: img/import_editor_column_data_type_menu.png :align: center -It might be helpful to fill in the mapping options using the preview table in the Sources part. -Right clicking on the table cells shows a popup menu -that lets one to configure how the rows and colunms are read upon importing. +Under **Mappings** you can manage mappings by adding new ones and removing or duplicating existing ones. +Each table has it's own mappings and every mapping has its own options. In **Mappings** you can select the mapping +that you want to start modifying. Having multiple mappings for a single table allows to for example import relationship +classes and object classes at the same time from a single table in a file. + +**Mapping options** helps the importer get a feel for what kind of data it will be importing. +The available *item type* options are *Object class, Relationship class, Object group, Alternative, Scenario, +Scenario alternative, Parameter value list, Feature, Tool, Tool feature* and *Tool feature method*. The other available +options are dependent on the Item type. *Import objects* allows to import th objects alongside the Relationship class +or object group. *Parameter type* is used to specify what type of parameters, if any, the sheet contains. It has options +*Value, Definition* and *None*. If *Value* or *Definition* is selected +the value or respectively the default value type can be set from the drop-down list. *Use before alternative* is only +available for *Scenario alternative* -item type. *Read data from row* lets you specify the row where the importer +starts to read the data. *Ignore columns* allow you to select individual columns that you want to exclude from the +whole importing process. *Number of dimensions* sets the amount of dimensions the relationship to be imported has. +*Repeat time series* does the same thing as everywhere else. *Map dimensions* is for map values. + +Once the everything in **Mapping options** is in order, the next step is to set the mapping specification. +**Mapping specification** is the part where the decisions are made on how the input data is interpreted: +which row or column contains the entity class names, parameter values, time stamps and so on. +The **Mapping specification** dock widget contains all of the targets that the selected mapping options specify. +Each target has a *Source reference* and a *Source type*. *Source type* specifies if the data for the target +is coming in the form of a column, row, table name etc. In the *Source ref.* section you can pinpoint to the +exact row, column etc. to use as the data. The *Filter* section can be used to further specify which values to +include using regular expressions. More on regular expressions in section `Basic regular expressions for filtering`_. + +It might be helpful to fill in the *Source type* and *Source ref.* using the preview table in the *Sources data*. +Right clicking on the table cells shows a popup menu that lets one to configure where the selected row/column/header +is mapped to. It can also be used to simultaneously map all headers to one target. .. image:: img/import_editor_preview_table_mapping_menu.png :align: center -An important aspect of data import is whether each item in the input data should be read as a string, a number, -a time stamp, or something else. -By default all input data is read as strings. -However, more often than not things like parameter values are actually numbers. -It is possible to control what type of data each column (and, sometimes, each row) contains from the preview table. -Clicking the data type indicator button on column headers pops up a menu with a selection of available data types. -Right clicking the column header also gives the opportunity to change the data type of all columns at once. +.. _anonymous mode: -.. image:: img/import_editor_column_data_type_menu.png +Anonymous mode +~~~~~~~~~~~~~~ + +The importer specification editor can be opened for a Importer that doesn't have any available resources. +In this case, the spec editor can be used to create generalized specifications. + +.. image:: img/importer_spec_editor_anonymous_mode.png :align: center +In anonymous mode new tables can be created in **Source tables** by double clicking ** +and writing in a name for the new table. The **Source data** will contain an infinite grid of cells on which you +can create different mappings. Exporting data with Exporter ----------------------------- +**************************** Exporter writes database data into regular files that can be used by Tools and external software that do not read the Spine database format. Various tabulated file formats are supported @@ -83,11 +166,11 @@ At its heart Exporter maps database items such as entity class or entity names t Each item has a user given output **position** on the table, for example a column number. By default data is mapped to columns but it is also possible to create pivot tables. -Exporter saves its settings or export **mappings** as a specification -that can be reused by other exporters or even other projects. +Exporter also uses specifications so the same configurations +can be reused by other exporters even in other projects. The specification can be edited in *Exporter specification editor* which is accessible by the |wrench| button in the item's Properties dock -or by double clicking exporter's icon on the Design view. +or by double clicking exporter's icon on the **Design View**. A specification that is not associated with any specific Exporter project item can be created and edited from the Main toolbar. @@ -104,8 +187,11 @@ Specification used by the active Exporter item can be selected from the *Specifi The |wrench| button opens *Exporter specification editor* where it is possible to edit the specification. -Databases available for export from connected project items such as Data stores are listed in -separate boxes below the Specification combobox. An output filename is required for each database. +Data Stores that are connected to the exporter and are available for export are listed below +the *Specification* combobox. An output label is required for each database and one Exporter +can't have the same output label for two different Data Stores at the same time. Two different +Exporters can have the same output label names since they are located in a different directory. +The default label for the output files is of the format ``_exported@``. Checking the *Time stamp output directories* box adds a time stamp to the item's output directories preventing output files from being overwritten. This may be useful for debugging purposes. @@ -126,11 +212,15 @@ Other formats which inherently cannot write multiple tables into a single file, such as csv, may end up exporting multiple files. See the sections below for format specific intricacies. -When opened for the first time Specification editor looks like in the figure below. +When opened for the first time Specification editor looks like in the image below. The window is tabbed allowing multiple specifications to be edited at the same time. Each tab consists of dock widgets which can be reorganized to suit the user's needs. The 'hamburger' menu on the top right corner gives access to some important actions such as *Save* and *Close*. *Undo* and *redo* can be found from the menu as well. +There is also a *Duplicate* option which creates a new tab in the spec editor that +is otherwise the same but has no name and is missing the database url under *Preview +controls*. This is handy if you want to create a new Exporter specification using an +existing template instead of always starting form the beginning. .. image:: img/exporter_specification_editor.png :align: center @@ -138,60 +228,77 @@ such as *Save* and *Close*. *Undo* and *redo* can be found from the menu as well The only requirement for a specification is a name. This can be given on the *Name* field field on the top bar. The *Description* field allows for an additional explanatory text. - The current output format can be changed by the *Format* combobox on *Export options* dock. -.. image:: img/exporter_mappings_dock.png - :align: center - -Specification's mappings are listed in the *Mappings* dock shown above. +Specification's mappings are listed in the *Mappings* dock widget shown below. The *Add* button adds a new mapping while the *Remove* button removes selected mappings. Mappings can be renamed by double clicking their names on the list. The checkbox in front of mapping's name shows if the mapping is currently enabled. +Only enabled mappings are exported when the Exporter is executed. Use the *Toggle enabled* button to toggle the enabled state of all mappings at once. +.. image:: img/exporter_mappings_dock.png + :align: center + The tables defined by the mappings are written in the order shown on the mapping list's *Write order* column. This may be important if the tables need to be in certain order in the output file or when multiple mappings output to a single table. Mappings can be sorted by their write order by clicking the header of the *Write order* column. The *Write earlier* and *Write later* buttons move the currently selected mapping up and down the list. +.. image:: img/exporter_preview_docks.png + :align: center + +A preview of what will be written to the output is available in the preview dock widgets. +To enable it, check the *Live preview* checkbox. +A database connection is needed to generate the preview. +The *Preview controls* dock provides widgets to choose an existing database or to load one from a file. +Once a database is available and the preview is enabled the mappings and the tables they would output +are listed on the *Preview tables* dock. +Selecting a table from the list shows the table's contents on the *Preview contents* dock. + +Mapping options +--------------- + +The currently selected mapping is edited using the controls in *Mapping options* and *Mapping specification* docks. +The *Mapping options* dock contains controls that apply to the mapping as a whole, e.g. what data the output tables +contain. It's important to choose *Item type* correctly since it determines what database items the mapping outputs +and also dictates the mapping types that will be visible in the *Mapping specification* dock widget. It has options +*Object class, Relationship class, Relationship class with object parameter, Object group, Alternative, Scenario, +Scenario alternative, Parameter value list, Feature, Tool, Tool feature* and *Tool feature method*. The rest of the +options beside *Group function* are item type specific and may not be available for all selections. + .. image:: img/exporter_mapping_options_dock.png :align: center +Checking the *Always export header* checkbox outputs a table that has fixed headers even if the table is +otherwise empty. If *Item type* is Relationship class, the *Relationship dimensions* spinbox can be used +to specify the maximum number of relationships' dimensions that the mapping is able to handle. +*Selected dimensions* option is only available for the *Relationship class with object parameter* -item +type and it is used to specify the relationship dimension where the object parameters are selected from. +Parameters can be outputted by choosing their value type using the *Parameter type* combobox. The *Value* +choice adds rows to *Mapping specification* for parameter values associated with individual entities while +*Default value* allows outputting parameters' default values. The maximum number of value dimensions in +case of indexed values (time series, maps, time patterns, arrays) the mapping can handle is controlled +by the *Parameter dimensions* spinbox. The *Fixed table name* checkbox enables giving a user defined +table name to the mapping's output table. In case the mapping is pivoted and *Mapping specification* +contains items that are *hidden*, it is possible that a number of data elements end up in the same +output table cell. The *Group function* combobox offers some basic functions to aggregate such data +into the cells. + +Mapping specification +--------------------- + .. image:: img/exporter_mapping_specification_dock.png :align: center -Currently selected mapping is edited using the controls in *Mapping options* and *Mapping specification* docks. -The *Mapping options* dock contains controls that apply to the mapping as a whole, -e.g. what data the output tables contain. *Mapping specification*, on the other hand, -contains a table which defines the structure of the mapping's output tables. - -What database items the mapping outputs is chosen using the *Item type* combobox in *Mapping options* dock. -For instance, the *Object classes* option outputs object classes, objects -and, optionally, object parameters and related items -while the *Relationship classes* option outputs relationship classes and relationships. -Checking the *Always export header* checkbox outputs a table that has fixed headers -even if the table is otherwise empty. -If *Item type* is Relationship class, -the *Relationship dimensions* spinbox can be used to specify the maximum number -of relationships' dimensions that the mapping is able to handle. -Parameters can be outputted by choosing their value type using the *Parameter type* combobox. -The *Value* choice adds rows to *Mapping specification* for parameter values associated with -individual entities while *Default value* allows outputting parameters' default values. -The maximum number of value dimensions in case of indexed values -(time series, maps, time patterns, arrays) -the mapping can handle is controlled by the *Parameter dimensions* spinbox. -The *Fixed table name* checkbox enables giving a user defined table name to the mapping's output table. -In case the mapping is pivoted and *Mapping specification* contains items that are *hidden*, -it is possible that a number of data elements end up in the same output table cell. -The *Group function* combobox offers some basic functions to aggregate such data into the cells. - -The contents of the table on the *Mapping specification* dock depends on choices on *Mapping options*, +*Mapping specification* contains a table which defines the structure of the mapping's output tables. +Like mentioned before, the contents of the table depends on choices on *Mapping options*, e.g. the item type, parameter type or dimensions. Each row corresponds to an item in the database: object class names, object names, parameter values etc. The item's name is given in the *Mapping type* column. The colors help to identify the corresponding elements in the preview. + The *Map to* column defines the **position** of the item, that is, where the item is written or otherwise used when the output tables are generated. By default, a plain integral number in this column means that the item is written to that column in the output table. @@ -202,6 +309,7 @@ in the database, each named after the class. Each table in turn will contain the parameters and objects of the table's object class. If multiple mappings generate a table with a common name then each mapping appends to the same table in the order specified by the *Write order* column on *Mappings* dock. + The *column header* position makes the item a column header for a **buddy item**. Buddy items have some kind of logical relationship with their column header, for instance the buddy of an object class is its objects; @@ -212,9 +320,10 @@ setting the object class to *column header* will write the name of the class as Therefore, *column header* will not always produce sensible results. Changing the column and pivot header row positions leaves sometimes gaps in the output table. -If such gaps are not desirable the *Compact* button reorders the positions by removing the gaps. +If such gaps are not desirable the **Compact** button reorders the positions by removing the gaps. This may be useful when the output format requires such gapless tables. + The checkboxes in *Pivoted* column on the *Mapping specification* dock toggle the mapping into pivoted mode. One or more items on the table can be set as pivoted. They then act as a pivot header for the data item which is the last non-hidden item on the list. @@ -228,48 +337,14 @@ Continuing the example, checking the *Nullable* checkbox for *Objects* would pro all object classes including ones without objects. The position where objects would normally be outputted are left empty for those classes. -Besides the *column header* position it is possible give fixed column headers to items +Besides the *column header* position it is possible to give fixed column headers to items using the *Header* column in *Mapping specification* dock. Note that checking the *Always export header* option in the *Mapping options* dock outputs the fixed headers even if there is no other data in a table. The *Mapping specification* dock's *Filter* column provides refined control on which database items the mapping outputs. -The column uses `regular expressions `_ -to filter what gets outputted. See _`Basic regular expression for filtering`. - -.. image:: img/exporter_preview_docks.png - :align: center - -A preview of what will be written to the output is available in the preview dock widgets. -A database connection is needed to generate the preview. -The *Preview controls* dock provides widgets to choose an existing database or to load one from a file. -Once a database is available and the preview is enabled the mappings and the tables they would output -are listed on the *Preview tables* dock. -Selecting a table from the list shows the table's contents on the *Preview contents* dock. -The colors on the table correspond to the colors in *Mapping specification* dock. - -Basic regular expressions for filtering -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The *Filter* field in *Mapping specification* accepts -`regular expressions `_ -to filter what data gets outputted by that mapping item. -Below are examples on how to create some basic filters. - -*Single item* - -Writing the item's name to the field filters out all other items. -For example, to output the object class called 'node' only, write :literal:`node` to the *Filter* field. - -*OR operator* - -The vertical bar :literal:`|` serves as the OR operator. -:literal:`node|unit` as a filter for object classes would output classes named 'node' and 'unit'. - -*Excluding an item* - -While perhaps not the most suitable task for regular expressions it is still possible to 'negate' a filter. -`^(?!node).` would exclude all items names of which start with 'node'. +The column uses regular expressions (see section `Basic regular expressions for filtering`_) +to filter what gets outputted. Csv and multiple tables ~~~~~~~~~~~~~~~~~~~~~~~ @@ -278,15 +353,22 @@ Csv files are flat text files and therefore do not directly support multiple tab Instead, multiple tables are handled as separate output files. Only mappings that output an **anonymous table** -actually write to the file specified on the Exporter's properties dock. +actually write to the file/label specified on the Exporter's properties dock. Named tables get written to files named after the table plus the :literal:`.csv` extension. -For example, a table named :literal:`node` would result in a file called `node.csv`. +For example, a table named :literal:`node` would result in a file called ``node.csv``. SQL export ~~~~~~~~~~ -.. note:: - Currently only sqlite is supported. +To set up export to a remote database, first an Exporter specification with SQL selected as the format needs +to be saved. The Exporter needs to also be connected to some input Data Store. From the Exporters **Properties** +dock widget an output database can be specified for each input Data Store respectively by clicking the **Set URL...** +button. A small new window opens with a few settings to set up the output database. Currently only mysql and sqlite +are supported, even though mssql, postgresql and oracle are also listed as options for the dialect. Once a URL is set +it can be removed by pressing the **Clear URL** button on the **Properties** tab. + +.. image:: img/select_url_for_remote_db_export.png + :align: center The SQL backend writes the tables to the target database in a relatively straightforward way: @@ -334,3 +416,29 @@ The gdx backend turns the output tables to GAMS sets, parameters and scalars fol * A table that contains a numerical value in the top left cell is considered a GAMS scalar. Everything else (except the table name) is ignored. * The data in the top left cell is the scalar's value. + +.. _Basic regular expressions for filtering: + +Basic regular expressions for filtering +*************************************** + +See regular expressions on `wikipedia `_ and on +Python's `documentation `_. +Both the Exporter and Importer have applications for regular expressions in their respective +*Mapping specifications* dock widgets. Below are examples on how to create some basic filters +for these applications. + +*Single item* + +Writing the item's name to the field filters out all other items. +For example, to output the object class called 'node' only, write :literal:`node` to the *Filter* field. + +*OR operator* + +The vertical bar :literal:`|` serves as the OR operator. +:literal:`node|unit` as a filter for object classes would output classes named 'node' and 'unit'. + +*Excluding an item* + +While perhaps not the most suitable task for regular expressions it is still possible to 'negate' a filter. +:literal:`^(?!node)`. would exclude all items names of which start with 'node'. diff --git a/docs/source/img/exporter_mapping_options_dock.png b/docs/source/img/exporter_mapping_options_dock.png index b03d4374d..3e6acb876 100644 Binary files a/docs/source/img/exporter_mapping_options_dock.png and b/docs/source/img/exporter_mapping_options_dock.png differ diff --git a/docs/source/img/exporter_mapping_specification_dock.png b/docs/source/img/exporter_mapping_specification_dock.png index 3c5cbaf73..f55acdd6c 100644 Binary files a/docs/source/img/exporter_mapping_specification_dock.png and b/docs/source/img/exporter_mapping_specification_dock.png differ diff --git a/docs/source/img/exporter_preview_docks.png b/docs/source/img/exporter_preview_docks.png index 442a25f3e..cf921a7e0 100644 Binary files a/docs/source/img/exporter_preview_docks.png and b/docs/source/img/exporter_preview_docks.png differ diff --git a/docs/source/img/exporter_properties.png b/docs/source/img/exporter_properties.png index 30cce9a65..b33057ff1 100644 Binary files a/docs/source/img/exporter_properties.png and b/docs/source/img/exporter_properties.png differ diff --git a/docs/source/img/exporter_specification_editor.png b/docs/source/img/exporter_specification_editor.png index 152bfbbee..be65015c9 100644 Binary files a/docs/source/img/exporter_specification_editor.png and b/docs/source/img/exporter_specification_editor.png differ diff --git a/docs/source/img/import_editor_column_data_type_menu.png b/docs/source/img/import_editor_column_data_type_menu.png index 984c9b916..c17685ba9 100644 Binary files a/docs/source/img/import_editor_column_data_type_menu.png and b/docs/source/img/import_editor_column_data_type_menu.png differ diff --git a/docs/source/img/import_editor_preview_table_mapping_menu.png b/docs/source/img/import_editor_preview_table_mapping_menu.png index 912e69287..0c94820eb 100644 Binary files a/docs/source/img/import_editor_preview_table_mapping_menu.png and b/docs/source/img/import_editor_preview_table_mapping_menu.png differ diff --git a/docs/source/img/import_editor_window.png b/docs/source/img/import_editor_window.png index b82b1f1f9..724d5cc6c 100644 Binary files a/docs/source/img/import_editor_window.png and b/docs/source/img/import_editor_window.png differ diff --git a/docs/source/img/importer_connector_type.png b/docs/source/img/importer_connector_type.png new file mode 100644 index 000000000..41ccc9ac5 Binary files /dev/null and b/docs/source/img/importer_connector_type.png differ diff --git a/docs/source/img/importer_properties.png b/docs/source/img/importer_properties.png index 2a76959c5..31e02a892 100644 Binary files a/docs/source/img/importer_properties.png and b/docs/source/img/importer_properties.png differ diff --git a/docs/source/img/importer_spec_editor_anonymous_mode.png b/docs/source/img/importer_spec_editor_anonymous_mode.png new file mode 100644 index 000000000..a5a11d4ac Binary files /dev/null and b/docs/source/img/importer_spec_editor_anonymous_mode.png differ diff --git a/docs/source/img/select_url_for_remote_db_export.png b/docs/source/img/select_url_for_remote_db_export.png new file mode 100644 index 000000000..406d6840f Binary files /dev/null and b/docs/source/img/select_url_for_remote_db_export.png differ