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 
00030 Hdf5DataReader::Hdf5DataReader(std::string directory, std::string baseName, bool make_absolute) :
00031         mDirectory(directory),
00032         mBaseName(baseName),
00033         mIsUnlimitedDimensionSet(false),
00034         mNumberTimesteps(1),
00035         mIsDataComplete(true)
00036 {
00037     std::string results_dir;
00038 
00039     // Find out where files are really stored
00040     if (make_absolute)
00041     {
00042         OutputFileHandler output_file_handler(directory, false);
00043         results_dir = output_file_handler.GetOutputDirectoryFullPath();
00044     }
00045     else
00046     {
00047         // Add a trailing slash if needed
00048         if ( !(*(directory.end()-1) == '/'))
00049         {
00050             results_dir = directory + "/";
00051         }
00052     }
00053 
00054     std::string file_name = results_dir + mBaseName + ".h5";
00055 
00056     // Open the file and the main dataset
00057     mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
00058 
00059     if (mFileId <=0 )
00060     {
00061         EXCEPTION("Hdf5DataReader could not open "+file_name);
00062     }
00063     mVariablesDatasetId = H5Dopen(mFileId, "Data");
00064 
00065     hid_t variables_dataspace = H5Dget_space(mVariablesDatasetId);
00066     mVariablesDatasetRank = H5Sget_simple_extent_ndims(variables_dataspace);
00067     // Get the dataset/dataspace dimensions
00068     hsize_t dataset_max_sizes[MAX_DATASET_RANK];
00069     H5Sget_simple_extent_dims(variables_dataspace, mVariablesDatasetSizes, dataset_max_sizes);
00070 
00071     for (unsigned i=1; i<MAX_DATASET_RANK; i++)  //Zero is excluded since it may be unlimited
00072     {
00073         assert(mVariablesDatasetSizes[i] == dataset_max_sizes[i]);
00074     }
00075     // Check if an unlimited dimension has been defined
00076     if (dataset_max_sizes[0] == H5S_UNLIMITED)
00077     {
00078         mIsUnlimitedDimensionSet = true;
00079         mTimeDatasetId = H5Dopen(mFileId, "Time");
00080 
00081         hid_t timestep_dataspace = H5Dget_space(mTimeDatasetId);
00082 
00083         // Get the dataset/dataspace dimensions
00084         H5Sget_simple_extent_dims(timestep_dataspace, &mNumberTimesteps, NULL);
00085 
00086     }
00087 
00088     // Get the attribute where the name of the variables are stored
00089     hid_t attribute_id = H5Aopen_name(mVariablesDatasetId, "Variable Details");
00090 
00091     // Get attribute datatype, dataspace, rank, and dimensions.
00092     hid_t attribute_type  = H5Aget_type(attribute_id);
00093     hid_t attribute_space = H5Aget_space(attribute_id);
00094 
00095     hsize_t attr_dataspace_dim;
00096     H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim, NULL);
00097 
00098     // Defined in writer class, todo: define it just once
00099     const unsigned MAX_STRING_SIZE=100;
00100 
00101     unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
00102     char* string_array = (char *)malloc(sizeof(char)*MAX_STRING_SIZE*(int)num_columns);
00103     H5Aread(attribute_id, attribute_type, string_array);
00104 
00105     // Loop over column names and store them.
00106     for (unsigned index=0; index < num_columns; index++)
00107     {
00108         // Read the string from the raw vector
00109         std::string column_name_unit(&string_array[MAX_STRING_SIZE*index]);
00110 
00111         // Find beginning of unit definition.
00112         size_t name_length = column_name_unit.find('(');
00113         size_t unit_length = column_name_unit.find(')') - name_length - 1;
00114 
00115         std::string column_name = column_name_unit.substr(0, name_length);
00116         std::string column_unit = column_name_unit.substr(name_length+1, unit_length);
00117 
00118         mVariableNames.push_back(column_name);
00119         mVariableToColumnIndex[column_name] = index;
00120         mVariableToUnit[column_name] = column_unit;
00121     }
00122 
00123 
00124     // Release all the identifiers
00125     H5Tclose(attribute_type);
00126     H5Sclose(attribute_space);
00127     H5Aclose(attribute_id);
00128 
00129     // Free allocated memory
00130     free(string_array);
00131 
00132     //Find out if it's incomplete data
00133     attribute_id = H5Aopen_name(mVariablesDatasetId, "IsDataComplete");
00134     if (attribute_id < 0)
00135     {
00136        //This is in the old format (before we added the IsDataComplete attribute).
00137        //Just quit (leaving a nasty hdf5 error).
00138        return;
00139     }
00140 
00141 
00142     attribute_type  = H5Aget_type(attribute_id);
00143     attribute_space = H5Aget_space(attribute_id);
00144     unsigned is_data_complete;
00145     H5Aread(attribute_id, attribute_type, &is_data_complete);
00146     // Release all the identifiers
00147     H5Tclose(attribute_type);
00148     H5Sclose(attribute_space);
00149     H5Aclose(attribute_id);
00150     mIsDataComplete = (is_data_complete == 1) ? true : false;
00151 
00152 
00153     if (is_data_complete)
00154     {
00155         return;
00156     }
00157 
00158     //Incomplete data
00159     //Read the vector thing
00160     attribute_id = H5Aopen_name(mVariablesDatasetId, "NodeMap");
00161     attribute_type  = H5Aget_type(attribute_id);
00162     attribute_space = H5Aget_space(attribute_id);
00163 
00164     // Get the dataset/dataspace dimensions
00165     unsigned num_node_indices = H5Sget_simple_extent_npoints(attribute_space);
00166 
00167     // Read data from hyperslab in the file into the hyperslab in memory
00168     mIncompleteNodeIndices.clear();
00169     mIncompleteNodeIndices.resize(num_node_indices);
00170     H5Aread(attribute_id, attribute_type, &mIncompleteNodeIndices[0]);
00171 
00172     H5Tclose(attribute_type);
00173     H5Sclose(attribute_space);
00174     H5Aclose(attribute_id);
00175 
00176 }
00177 
00178 
00179 std::vector<double> Hdf5DataReader::GetVariableOverTime(std::string variableName, unsigned nodeIndex)
00180 {
00181     if (!mIsUnlimitedDimensionSet)
00182     {
00183         EXCEPTION("The file does not contain time dependant data");
00184     }
00185 
00186     unsigned actual_node_index=nodeIndex;
00187     if (!mIsDataComplete)
00188     {
00189         unsigned node_index=0;
00190         for (node_index=0; node_index<mIncompleteNodeIndices.size(); node_index++)
00191         {
00192             if (mIncompleteNodeIndices[node_index]==nodeIndex)
00193             {
00194                 actual_node_index = node_index;
00195                 break;
00196             }
00197         }
00198         if ( node_index == mIncompleteNodeIndices.size())
00199         {
00200             EXCEPTION("The incomplete file does not contain info of node " + nodeIndex);
00201         }
00202     }
00203     if (actual_node_index >= mVariablesDatasetSizes[1])
00204     {
00205         EXCEPTION("The file doesn't contain info of node " + nodeIndex);
00206     }
00207 
00208     std::map<std::string, unsigned>::iterator col_iter = mVariableToColumnIndex.find(variableName);
00209     if (col_iter == mVariableToColumnIndex.end())
00210     {
00211         EXCEPTION("The file doesn't contain data for variable " + variableName);
00212     }
00213     int column_index = (*col_iter).second;
00214 
00215     // Define hyperslab in the dataset.
00216     hsize_t offset[3] = {0, actual_node_index, column_index};
00217     hsize_t count[3]  = {mVariablesDatasetSizes[0], 1, 1};
00218     hid_t variables_dataspace = H5Dget_space(mVariablesDatasetId);
00219     H5Sselect_hyperslab(variables_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
00220 
00221     // Define a simple memory dataspace
00222     hid_t memspace = H5Screate_simple(1, &mVariablesDatasetSizes[0] ,NULL);
00223 
00224     // Data buffer to return
00225     std::vector<double> ret(mVariablesDatasetSizes[0]);
00226 
00227     // Read data from hyperslab in the file into the hyperslab in memory
00228     H5Dread(mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, variables_dataspace, H5P_DEFAULT, &ret[0]);
00229 
00230     H5Sclose(variables_dataspace);
00231     H5Sclose(memspace);
00232 
00233     return ret;
00234 }
00235 
00236 
00237 void Hdf5DataReader::GetVariableOverNodes(Vec data, std::string variableName, unsigned timestep)
00238 {
00239     if (!mIsDataComplete)
00240     {
00241         EXCEPTION("You can only get a vector for complete data");
00242     }
00243     if (!mIsUnlimitedDimensionSet && timestep!=0)
00244     {
00245         EXCEPTION("The file does not contain time dependant data");
00246     }
00247 
00248     std::map<std::string, unsigned>::iterator col_iter = mVariableToColumnIndex.find(variableName);
00249     if (col_iter == mVariableToColumnIndex.end())
00250     {
00251         EXCEPTION("The file does not contain data for variable " + variableName);
00252     }
00253     int column_index = (*col_iter).second;
00254 
00255     // Check for valid timestep
00256     if (timestep >= mNumberTimesteps)
00257     {
00258         EXCEPTION("The file does not contain data for timestep number" + timestep);
00259     }
00260 
00262     int lo, hi, size;
00263     VecGetSize(data, &size);
00264     if ((unsigned)size != mVariablesDatasetSizes[1])
00265     {
00266         EXCEPTION("Could not read data because Vec is the wrong size");
00267     }
00268     // Get range owned by each processor
00269     VecGetOwnershipRange(data, &lo, &hi);
00270 
00271     // Define a dataset in memory for this process
00272     hsize_t v_size[1] = {hi-lo};
00273     hid_t memspace = H5Screate_simple(1, v_size, NULL);
00274 
00275     // Select hyperslab in the file.
00276     hsize_t offset[3] = {timestep, lo, column_index};
00277     hsize_t count[3]  = {1, hi-lo, 1};
00278     hid_t hyperslab_space = H5Dget_space(mVariablesDatasetId);
00279     H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset, NULL, count, NULL);
00280 
00281 
00282     double* p_petsc_vector;
00283     VecGetArray(data, &p_petsc_vector);
00284     herr_t err;
00285     err=H5Dread(mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, p_petsc_vector);
00286     assert(err==0);
00287     VecRestoreArray(data, &p_petsc_vector);
00288 
00289 
00290     H5Sclose(hyperslab_space);
00291     H5Sclose(memspace);
00292 }
00293 
00294 std::vector<double> Hdf5DataReader::GetUnlimitedDimensionValues()
00295 {
00296     // Data buffer to return
00297     std::vector<double> ret(mNumberTimesteps);
00298 
00299     if (!mIsUnlimitedDimensionSet)
00300     {
00301         //Fake it
00302         assert(mNumberTimesteps==1);
00303         ret[0]=0.0;
00304         return ret;
00305     }
00306     // Define hyperslab in the dataset.
00307     hid_t time_dataspace = H5Dget_space(mTimeDatasetId);
00308 
00309     // Define a simple memory dataspace
00310     hid_t memspace = H5Screate_simple(1, &mNumberTimesteps ,NULL);
00311 
00312 
00313     // Read data from hyperslab in the file into the hyperslab in memory
00314     H5Dread(mTimeDatasetId, H5T_NATIVE_DOUBLE, memspace, time_dataspace, H5P_DEFAULT, &ret[0]);
00315 
00316     H5Sclose(time_dataspace);
00317     H5Sclose(memspace);
00318 
00319     return ret;
00320 }
00321 
00322 void Hdf5DataReader::Close()
00323 {
00324     // todo: move code to the destructor???
00325     H5Dclose(mVariablesDatasetId);
00326 
00327     if (mIsUnlimitedDimensionSet)
00328     {
00329         H5Dclose(mTimeDatasetId);
00330     }
00331 
00332     H5Fclose(mFileId);
00333 }

Generated on Wed Mar 18 12:51:52 2009 for Chaste by  doxygen 1.5.5