Repository: PMEAL/OpenPNM
Pull request #1243 (2019-04-17 14:14:56)

Export time series
Exception when trying to export transient data using a format other than "xdmf".


Patch:
diff --git a/example_transient_Fickian_diffusion.py b/example_transient_Fickian_diffusion.py
index ff8435413..7fa30170b 100644
--- a/example_transient_Fickian_diffusion.py
+++ b/example_transient_Fickian_diffusion.py
@@ -35,4 +35,4 @@ phase.update(fd.results())
 
 # output results to a vtk file
 phase.update(fd.results())
-proj.export_data(phases=[phase], filename='OUT', filetype='vtk')
+proj.export_data(phases=[phase], filename='OUT', filetype='xdmf')
diff --git a/openpnm/io/CSV.py b/openpnm/io/CSV.py
index 2b751e508..adddea2db 100644
--- a/openpnm/io/CSV.py
+++ b/openpnm/io/CSV.py
@@ -72,7 +72,6 @@ class CSV(GenericIO):
                                                    phases=phases)
         df = Pandas.to_dataframe(network=network, phases=phases,
                                  join=True, delim=delim)
-
         # Write to file
         if filename == '':
             filename = project.name
diff --git a/openpnm/io/HDF5.py b/openpnm/io/HDF5.py
index 1ce11cdba..e2d9f6d35 100644
--- a/openpnm/io/HDF5.py
+++ b/openpnm/io/HDF5.py
@@ -67,7 +67,6 @@ class HDF5(GenericIO):
         """
         project, network, phases = cls._parse_args(network=network,
                                                    phases=phases)
-
         if filename == '':
             filename = project.name
         filename = cls._parse_filename(filename, ext='hdf')
diff --git a/openpnm/io/VTK.py b/openpnm/io/VTK.py
index 1c4ec5aa8..833dd54f1 100644
--- a/openpnm/io/VTK.py
+++ b/openpnm/io/VTK.py
@@ -61,7 +61,11 @@ class VTK(GenericIO):
         """
         project, network, phases = cls._parse_args(network=network,
                                                    phases=phases)
-
+        # Check if any of the phases has time series
+        transient = GenericIO.is_transient(phases=phases)
+        if transient:
+            logger.warning('vtp format does not support transient data, ' +
+                           'use xdmf instead')
         if filename == '':
             filename = project.name
         filename = cls._parse_filename(filename=filename, ext='vtp')
diff --git a/openpnm/io/XDMF.py b/openpnm/io/XDMF.py
index 1b87afdd7..38884e823 100644
--- a/openpnm/io/XDMF.py
+++ b/openpnm/io/XDMF.py
@@ -43,6 +43,9 @@ class XDMF(GenericIO):
         project, network, phases = cls._parse_args(network=network,
                                                    phases=phases)
         network = network[0]
+        # Check if any of the phases has time series
+        transient = GenericIO.is_transient(phases=phases)
+
         if filename == '':
             filename = project.name
         path = cls._parse_filename(filename=filename, ext='xmf')
@@ -53,13 +56,14 @@ class XDMF(GenericIO):
         D = FlatDict(d, delimiter='/')
         # Identify time steps
         t_steps = []
-        for key in D.keys():
-            if '@' in key:
-                t_steps.append(key.split('@')[1])
+        if transient:
+            for key in D.keys():
+                if '@' in key:
+                    t_steps.append(key.split('@')[1])
         t_grid = create_grid(Name="TimeSeries", GridType="Collection",
                              CollectionType="Temporal")
         # If steady-state, define '0' time step
-        if t_steps == []:
+        if not transient:
             t_steps.append('0')
         # Setup xdmf file
         root = create_root('Xdmf')
@@ -67,7 +71,10 @@ class XDMF(GenericIO):
         # Iterate over time steps present
         for t in range(len(t_steps)):
             # Define the hdf file
-            fname_hdf = path.stem+'_'+t_steps[t]+".hdf"
+            if not transient:
+                fname_hdf = path.stem+".hdf"
+            else:
+                fname_hdf = path.stem+'@'+t_steps[t]+".hdf"
             path_p = path.parent
             f = h5py.File(path_p.joinpath(fname_hdf), "w")
             # Add coordinate and connection information to top of HDF5 file
@@ -99,8 +106,8 @@ class XDMF(GenericIO):
                     del D[item]
                 elif 'U' in str(D[item][0].dtype):
                     pass
-                elif ('@' and '@'+t_steps[t] in item):
-                    f.create_dataset(name='/'+item.split('@')[0]+'_t',
+                elif ('@' in item and t_steps[t] == item.split('@')[1]):
+                    f.create_dataset(name='/'+item.split('@')[0]+'@t',
                                      shape=D[item].shape,
                                      dtype=D[item].dtype,
                                      data=D[item])
@@ -114,18 +121,19 @@ class XDMF(GenericIO):
             # Add pore and throat properties
             for item in D.keys():
                 if item not in ['coordinates', 'connections']:
-                    if ('@' and '@'+t_steps[t] in item) or ('@' not in item):
+                    if (('@' in item and t_steps[t] == item.split('@')[1]) or
+                            ('@' not in item)):
                         attr_type = 'Scalar'
                         shape = D[item].shape
                         dims = (''.join([str(i) +
                                          ' ' for i in list(shape)[::-1]]))
                         if '@' in item:
-                            item = item.split('@')[0]+'_t'
+                            item = item.split('@')[0]+'@t'
                             hdf_loc = fname_hdf + ":" + item
                         elif ('@' not in item and t == 0):
                             hdf_loc = fname_hdf + ":" + item
                         elif ('@' not in item and t > 0):
-                            hdf_loc = (path.stem+'_'+t_steps[0]+".hdf" +
+                            hdf_loc = (path.stem+'@'+t_steps[0]+".hdf" +
                                        ":" + item)
                         attr = create_data_item(value=hdf_loc,
                                                 Dimensions=dims,
diff --git a/openpnm/utils/Project.py b/openpnm/utils/Project.py
index a7bf705af..7cf57d986 100644
--- a/openpnm/utils/Project.py
+++ b/openpnm/utils/Project.py
@@ -1,14 +1,10 @@
 import time
-import pickle
 import h5py
 import numpy as np
 import openpnm
 from copy import deepcopy
-from pathlib import Path
-from openpnm.utils import (SettingsDict, HealthDict, PrintableList, Workspace,
-                           logging)
+from openpnm.utils import SettingsDict, HealthDict, Workspace
 ws = Workspace()
-logger = logging.getLogger(__name__)
 
 
 class Project(list):
@@ -581,37 +577,28 @@ class Project(list):
         network = self.network
         if filename is None:
             filename = project.name + '_' + time.strftime('%Y%b%d_%H%M%p')
-        # Check if any of the phases has time series
-        transient = openpnm.io.GenericIO.is_transient(phases=phases)
-        # Infer filetype from extension on file name..., if given
+        # Infer filetype from extension on file name...if given
         if '.' in filename:
             exts = ['vtk', 'vtp', 'vtu', 'csv', 'xmf', 'xdmf', 'hdf', 'hdf5',
                     'h5', 'mat']
             if filename.split('.')[-1] in exts:
                 filename, filetype = filename.rsplit('.', 1)
-        if transient:
-            if filetype.lower() not in ['xmf', 'xdmf']:
-                logger.warning(filetype.lower() + ' filetype not supported ' +
-                               'for transient data, xdmf is used instead')
+        if filetype.lower() in ['vtk', 'vtp', 'vtu']:
+            openpnm.io.VTK.save(network=network, phases=phases,
+                                filename=filename)
+        if filetype.lower() == 'csv':
+            openpnm.io.CSV.save(network=network, phases=phases,
+                                filename=filename)
+        if filetype.lower() in ['xmf', 'xdmf']:
             openpnm.io.XDMF.save(network=network, phases=phases,
                                  filename=filename)
-        else:
-            if filetype.lower() in ['vtk', 'vtp', 'vtu']:
-                openpnm.io.VTK.save(network=network, phases=phases,
-                                    filename=filename)
-            if filetype.lower() == 'csv':
-                openpnm.io.CSV.save(network=network, phases=phases,
-                                    filename=filename)
-            if filetype.lower() in ['xmf', 'xdmf']:
-                openpnm.io.XDMF.save(network=network, phases=phases,
-                                     filename=filename)
-            if filetype.lower() in ['hdf5', 'hdf', 'h5']:
-                f = openpnm.io.HDF5.to_hdf5(network=network, phases=phases,
-                                            filename=filename)
-                f.close()
-            if filetype.lower() == 'mat':
-                openpnm.io.MAT.save(network=network, phases=phases,
-                                    filename=filename)
+        if filetype.lower() in ['hdf5', 'hdf', 'h5']:
+            f = openpnm.io.HDF5.to_hdf5(network=network, phases=phases,
+                                        filename=filename)
+            f.close()
+        if filetype.lower() == 'mat':
+            openpnm.io.MAT.save(network=network, phases=phases,
+                                filename=filename)
 
     def _dump_data(self, mode=['props']):
         r"""


Test patch:
diff --git a/tests/unit/io/XDMFTest.py b/tests/unit/io/XDMFTest.py
index 7165722ec..0acffee52 100644
--- a/tests/unit/io/XDMFTest.py
+++ b/tests/unit/io/XDMFTest.py
@@ -65,7 +65,7 @@ class XDMFTest:
     def test_save(self, tmpdir):
         fname = tmpdir.join('test_file')
         op.io.XDMF.save(network=self.net, phases=self.phase_1, filename=fname)
-        os.remove(tmpdir.join('test_file_0.hdf'))
+        os.remove(tmpdir.join('test_file.hdf'))
         os.remove(tmpdir.join('test_file.xmf'))
 
 
diff --git a/tests/unit/utils/ProjectTest.py b/tests/unit/utils/ProjectTest.py
index 93c6fd86a..7090f7086 100644
--- a/tests/unit/utils/ProjectTest.py
+++ b/tests/unit/utils/ProjectTest.py
@@ -365,7 +365,7 @@ class ProjectTest:
         self.proj.export_data(phases=self.phase1, filename=fname,
                               filetype='xmf')
         os.remove(fname+'.xmf')
-        os.remove(fname+'_0.hdf')
+        os.remove(fname+'.hdf')
         self.proj.export_data(phases=self.phase1, filename=fname,
                               filetype='hdf')
         os.remove(fname+'.hdf')