Hdf5DataReader.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 #include "Hdf5DataReader.hpp"
00029 #include "Exception.hpp"
00030 #include "OutputFileHandler.hpp"
00031 
00032 #include <cassert>
00033 
00034 
00035 Hdf5DataReader::Hdf5DataReader(const std::string& rDirectory,
00036                                const std::string& rBaseName,
00037                                bool makeAbsolute)
00038     : mDirectory(rDirectory),
00039       mBaseName(rBaseName),
00040       mIsUnlimitedDimensionSet(false),
00041       mNumberTimesteps(1),
00042       mIsDataComplete(true)
00043 {
00044     std::string results_dir;
00045 
00046     // Find out where files are really stored
00047     if (makeAbsolute)
00048     {
00049         OutputFileHandler output_file_handler(rDirectory, false);
00050         results_dir = output_file_handler.GetOutputDirectoryFullPath();
00051     }
00052     else
00053     {
00054         // Add a trailing slash if needed
00055         if ( !(*(rDirectory.end()-1) == '/'))
00056         {
00057             results_dir = rDirectory + "/";
00058         }
00059     }
00060 
00061     std::string file_name = results_dir + mBaseName + ".h5";
00062 
00063     // Open the file and the main dataset
00064     mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
00065 
00066     if (mFileId <= 0)
00067     {
00068         EXCEPTION("Hdf5DataReader could not open " + file_name);
00069     }
00070     mVariablesDatasetId = H5Dopen(mFileId, "Data");
00071 
00072     hid_t variables_dataspace = H5Dget_space(mVariablesDatasetId);
00073     mVariablesDatasetRank = H5Sget_simple_extent_ndims(variables_dataspace);
00074 
00075     // Get the dataset/dataspace dimensions
00076     hsize_t dataset_max_sizes[MAX_DATASET_RANK];
00077     H5Sget_simple_extent_dims(variables_dataspace, mVariablesDatasetSizes, dataset_max_sizes);
00078 
00079     for (unsigned i=1; i<MAX_DATASET_RANK; i++)  // Zero is excluded since it may be unlimited
00080     {
00081         assert(mVariablesDatasetSizes[i] == dataset_max_sizes[i]);
00082     }
00083 
00084     // Check if an unlimited dimension has been defined
00085     if (dataset_max_sizes[0] == H5S_UNLIMITED)
00086     {
00087         mIsUnlimitedDimensionSet = true;
00088         mTimeDatasetId = H5Dopen(mFileId, "Time");
00089 
00090         hid_t timestep_dataspace = H5Dget_space(mTimeDatasetId);
00091 
00092         // Get the dataset/dataspace dimensions
00093         H5Sget_simple_extent_dims(timestep_dataspace, &mNumberTimesteps, NULL);
00094 
00095     }
00096 
00097     // Get the attribute where the name of the variables are stored
00098     hid_t attribute_id = H5Aopen_name(mVariablesDatasetId, "Variable Details");
00099 
00100     // Get attribute datatype, dataspace, rank, and dimensions
00101     hid_t attribute_type  = H5Aget_type(attribute_id);
00102     hid_t attribute_space = H5Aget_space(attribute_id);
00103 
00104     hsize_t attr_dataspace_dim;
00105     H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim, NULL);
00106 
00107     // Defined in writer class, todo: define it just once
00108     const unsigned MAX_STRING_SIZE=100;
00109 
00110     unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
00111     char* string_array = (char *)malloc(sizeof(char)*MAX_STRING_SIZE*(int)num_columns);
00112     H5Aread(attribute_id, attribute_type, string_array);
00113 
00114     // Loop over column names and store them.
00115     for (unsigned index=0; index < num_columns; index++)
00116     {
00117         // Read the string from the raw vector
00118         std::string column_name_unit(&string_array[MAX_STRING_SIZE*index]);
00119 
00120         // Find beginning of unit definition.
00121         size_t name_length = column_name_unit.find('(');
00122         size_t unit_length = column_name_unit.find(')') - name_length - 1;
00123 
00124         std::string column_name = column_name_unit.substr(0, name_length);
00125         std::string column_unit = column_name_unit.substr(name_length+1, unit_length);
00126 
00127         mVariableNames.push_back(column_name);
00128         mVariableToColumnIndex[column_name] = index;
00129         mVariableToUnit[column_name] = column_unit;
00130     }
00131 
00132     // Release all the identifiers
00133     H5Tclose(attribute_type);
00134     H5Sclose(attribute_space);
00135     H5Aclose(attribute_id);
00136 
00137     // Free allocated memory
00138     free(string_array);
00139 
00140     // Find out if it's incomplete data
00141     attribute_id = H5Aopen_name(mVariablesDatasetId, "IsDataComplete");
00142     if (attribute_id < 0)
00143     {
00144         // This is in the old format (before we added the IsDataComplete attribute).
00145         // Just quit (leaving a nasty hdf5 error).
00146         return;
00147     }
00148 
00149     attribute_type  = H5Aget_type(attribute_id);
00150     attribute_space = H5Aget_space(attribute_id);
00151     unsigned is_data_complete;
00152     H5Aread(attribute_id, attribute_type, &is_data_complete);
00153 
00154     // Release all the identifiers
00155     H5Tclose(attribute_type);
00156     H5Sclose(attribute_space);
00157     H5Aclose(attribute_id);
00158     mIsDataComplete = (is_data_complete == 1) ? true : false;
00159 
00160     if (is_data_complete)
00161     {
00162         return;
00163     }
00164 
00165     // Incomplete data
00166     // Read the vector thing
00167     attribute_id = H5Aopen_name(mVariablesDatasetId, "NodeMap");
00168     attribute_type  = H5Aget_type(attribute_id);
00169     attribute_space = H5Aget_space(attribute_id);
00170 
00171     // Get the dataset/dataspace dimensions
00172     unsigned num_node_indices = H5Sget_simple_extent_npoints(attribute_space);
00173 
00174     // Read data from hyperslab in the file into the hyperslab in memory
00175     mIncompleteNodeIndices.clear();
00176     mIncompleteNodeIndices.resize(num_node_indices);
00177     H5Aread(attribute_id, attribute_type, &mIncompleteNodeIndices[0]);
00178 
00179     H5Tclose(attribute_type);
00180     H5Sclose(attribute_space);
00181     H5Aclose(attribute_id);
00182 }
00183 
00184 std::vector<double> Hdf5DataReader::GetVariableOverTime(const std::string& rVariableName,
00185                                                         unsigned nodeIndex)
00186 {
00187     if (!mIsUnlimitedDimensionSet)
00188     {
00189         EXCEPTION("The file does not contain time dependent data");
00190     }
00191 
00192     unsigned actual_node_index = nodeIndex;
00193     if (!mIsDataComplete)
00194     {
00195         unsigned node_index = 0;
00196         for (node_index=0; node_index<mIncompleteNodeIndices.size(); node_index++)
00197         {
00198             if (mIncompleteNodeIndices[node_index]==nodeIndex)
00199             {
00200                 actual_node_index = node_index;
00201                 break;
00202             }
00203         }
00204         if ( node_index == mIncompleteNodeIndices.size())
00205         {
00206             EXCEPTION("The incomplete file does not contain info of node " + nodeIndex);
00207         }
00208     }
00209     if (actual_node_index >= mVariablesDatasetSizes[1])
00210     {
00211         EXCEPTION("The file doesn't contain info of node " + nodeIndex);
00212     }
00213 
00214     std::map<std::string, unsigned>::iterator col_iter = mVariableToColumnIndex.find(rVariableName);
00215     if (col_iter == mVariableToColumnIndex.end())
00216     {
00217         EXCEPTION("The file doesn't contain data for variable " + rVariableName);
00218     }
00219     int column_index = (*col_iter).second;
00220 
00221     // Define hyperslab in the dataset.
00222     hsize_t offset[3] = {0, actual_node_index, column_index};
00223     hsize_t count[3]  = {mVariablesDatasetSizes[0], 1, 1};
00224     hid_t variables_dataspace = H5Dget_space(mVariablesDatasetId);
00225     H5Sselect_hyperslab(variables_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
00226 
00227     // Define a simple memory dataspace
00228     hid_t memspace = H5Screate_simple(1, &mVariablesDatasetSizes[0] ,NULL);
00229 
00230     // Data buffer to return
00231     std::vector<double> ret(mVariablesDatasetSizes[0]);
00232 
00233     // Read data from hyperslab in the file into the hyperslab in memory
00234     H5Dread(mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, variables_dataspace, H5P_DEFAULT, &ret[0]);
00235 
00236     H5Sclose(variables_dataspace);
00237     H5Sclose(memspace);
00238 
00239     return ret;
00240 }
00241 
00242 void Hdf5DataReader::GetVariableOverNodes(Vec data,
00243                                           const std::string& rVariableName,
00244                                           unsigned timestep)
00245 {
00246     if (!mIsDataComplete)
00247     {
00248         EXCEPTION("You can only get a vector for complete data");
00249     }
00250     if (!mIsUnlimitedDimensionSet && timestep!=0)
00251     {
00252         EXCEPTION("The file does not contain time dependent data");
00253     }
00254 
00255     std::map<std::string, unsigned>::iterator col_iter = mVariableToColumnIndex.find(rVariableName);
00256     if (col_iter == mVariableToColumnIndex.end())
00257     {
00258         EXCEPTION("The file does not contain data for variable " + rVariableName);
00259     }
00260     int column_index = (*col_iter).second;
00261 
00262     // Check for valid timestep
00263     if (timestep >= mNumberTimesteps)
00264     {
00265         EXCEPTION("The file does not contain data for timestep number" + timestep);
00266     }
00267 
00269     int lo, hi, size;
00270     VecGetSize(data, &size);
00271     if ((unsigned)size != mVariablesDatasetSizes[1])
00272     {
00273         EXCEPTION("Could not read data because Vec is the wrong size");
00274     }
00275     // Get range owned by each processor
00276     VecGetOwnershipRange(data, &lo, &hi);
00277 
00278     // Define a dataset in memory for this process
00279     hsize_t v_size[1] = {hi-lo};
00280     hid_t memspace = H5Screate_simple(1, v_size, NULL);
00281 
00282     // Select hyperslab in the file.
00283     hsize_t offset[3] = {timestep, lo, column_index};
00284     hsize_t count[3]  = {1, hi-lo, 1};
00285     hid_t hyperslab_space = H5Dget_space(mVariablesDatasetId);
00286     H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset, NULL, count, NULL);
00287 
00288     double *p_petsc_vector;
00289     VecGetArray(data, &p_petsc_vector);
00290     herr_t err;
00291     err=H5Dread(mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, p_petsc_vector);
00292     assert(err==0);
00293     VecRestoreArray(data, &p_petsc_vector);
00294 
00295     H5Sclose(hyperslab_space);
00296     H5Sclose(memspace);
00297 }
00298 
00299 std::vector<double> Hdf5DataReader::GetUnlimitedDimensionValues()
00300 {
00301     // Data buffer to return
00302     std::vector<double> ret(mNumberTimesteps);
00303 
00304     if (!mIsUnlimitedDimensionSet)
00305     {
00306         // Fake it
00307         assert(mNumberTimesteps==1);
00308         ret[0] = 0.0;
00309         return ret;
00310     }
00311     // Define hyperslab in the dataset
00312     hid_t time_dataspace = H5Dget_space(mTimeDatasetId);
00313 
00314     // Define a simple memory dataspace
00315     hid_t memspace = H5Screate_simple(1, &mNumberTimesteps ,NULL);
00316 
00317     // Read data from hyperslab in the file into the hyperslab in memory
00318     H5Dread(mTimeDatasetId, H5T_NATIVE_DOUBLE, memspace, time_dataspace, H5P_DEFAULT, &ret[0]);
00319 
00320     H5Sclose(time_dataspace);
00321     H5Sclose(memspace);
00322 
00323     return ret;
00324 }
00325 
00326 void Hdf5DataReader::Close()
00327 {
00328     // todo: move code to the destructor???
00329     H5Dclose(mVariablesDatasetId);
00330 
00331     if (mIsUnlimitedDimensionSet)
00332     {
00333         H5Dclose(mTimeDatasetId);
00334     }
00335 
00336     H5Fclose(mFileId);
00337 }
00338 
00339 unsigned Hdf5DataReader::GetNumberOfRows()
00340 {
00341     return mVariablesDatasetSizes[1];
00342 }
00343 
00344 std::vector<std::string> Hdf5DataReader::GetVariableNames()
00345 {
00346     return mVariableNames;
00347 }
00348 
00349 std::string Hdf5DataReader::GetUnit(const std::string& rVariableName)
00350 {
00351     return mVariableToUnit[rVariableName];
00352 }
00353 
00354 bool Hdf5DataReader::IsDataComplete()
00355 {
00356     return mIsDataComplete;
00357 }
00358 
00359 std::vector<unsigned> Hdf5DataReader::GetIncompleteNodeMap()
00360 {
00361     return mIncompleteNodeIndices;
00362 }

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5