diff --git a/include/Configuration.h b/include/Configuration.h index 02da865..69c3eb3 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -24,6 +24,7 @@ namespace pbnj { int dataXDim; int dataYDim; int dataZDim; + unsigned int dataNumComponents; int imageWidth; int imageHeight; diff --git a/include/DataFile.h b/include/DataFile.h index bce2158..e6d2194 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -12,7 +12,7 @@ namespace pbnj { class DataFile { public: - DataFile(int x, int y, int z); + DataFile(int x, int y, int z, unsigned int components=1); ~DataFile(); void loadFromFile(std::string filename, std::string variable="", @@ -30,6 +30,7 @@ namespace pbnj { unsigned long int yDim; unsigned long int zDim; unsigned long int numValues; + unsigned int numComponents; float minVal; // these should float maxVal; // diff --git a/include/TimeSeries.h b/include/TimeSeries.h index 87d8b56..9bef999 100644 --- a/include/TimeSeries.h +++ b/include/TimeSeries.h @@ -13,9 +13,9 @@ namespace pbnj { class TimeSeries { public: - TimeSeries(std::vector filenames, int x, int y, int z); + TimeSeries(std::vector filenames, int x, int y, int z, unsigned int components=1); TimeSeries(std::vector filenames, std::string varname, - int x, int y, int z); + int x, int y, int z, unsigned int components=1); ~TimeSeries(); Volume *getVolume(unsigned int index); @@ -38,6 +38,7 @@ namespace pbnj { int xDim; int yDim; int zDim; + unsigned int numComponents; unsigned int dataSize; unsigned int maxVolumes; unsigned int currentVolumes; diff --git a/include/Volume.h b/include/Volume.h index d5ca4cd..572a906 100644 --- a/include/Volume.h +++ b/include/Volume.h @@ -16,9 +16,9 @@ namespace pbnj { public: //Volume(DataFile *df); Volume(std::string filename, int x, int y, int z, - bool memmap=false); + bool memmap=false, unsigned int components=1); Volume(std::string filename, std::string var_name, int x, int y, - int z, bool memmap=false); + int z, bool memmap=false, unsigned int components=1); ~Volume(); void attenuateOpacity(float amount); diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 13a36ab..1a4034e 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -188,6 +188,15 @@ Configuration::Configuration(rapidjson::Document& json) else { this->specularity = 0.1; } + + // number of data components + // defaults to 1 in DataFile if not used + if(json.HasMember("components")) { + this->dataNumComponents = json["components"].GetUint(); + } + else { + this->dataNumComponents = 1; + } } void Configuration::selectColorMap(std::string userInput) diff --git a/src/DataFile.cpp b/src/DataFile.cpp index 0f36dd5..dfad01d 100644 --- a/src/DataFile.cpp +++ b/src/DataFile.cpp @@ -19,8 +19,9 @@ namespace pbnj { -DataFile::DataFile(int x, int y, int z) : - xDim(x), yDim(y), zDim(z), numValues(x*y*z), statsCalculated(false) +DataFile::DataFile(int x, int y, int z, unsigned int components) : + xDim(x), yDim(y), zDim(z), numValues(x*y*z), statsCalculated(false), + numComponents(components) { this->numValues = xDim * yDim * zDim; } @@ -86,9 +87,28 @@ void DataFile::loadFromFile(std::string filename, std::string var_name, } else { if(memmap) { - int fd = fileno(dataFile); - this->data = (float *)mmap(NULL, this->numValues*sizeof(float), - PROT_READ, MAP_SHARED, fd, 0); + if(this->numComponents == 1) { + int fd = fileno(dataFile); + this->data = (float *)mmap(NULL, this->numValues*sizeof(float), + PROT_READ, MAP_SHARED, fd, 0); + } + else { + this->data = (float *)malloc(this->numValues * sizeof(float)); + if(this->data == MAP_FAILED) { + switch(errno) { + case ENOMEM: + std::cerr << "ENOMEM out of memory" << std::endl; + break; + } + } + float *chunk = (float *)malloc(this->numComponents*sizeof(float)); + for(int i = 0; i < this->numValues; i++) { + size_t numbytes = fread(chunk, sizeof(float), + this->numComponents, dataFile); + this->data[i] = std::sqrt(chunk[0]*chunk[0] + + chunk[1]*chunk[1] + chunk[2]*chunk[2]); + } + } } else { this->data = (float *)malloc(this->numValues * sizeof(float)); @@ -99,8 +119,19 @@ void DataFile::loadFromFile(std::string filename, std::string var_name, break; } } - size_t bytes = fread(this->data, sizeof(float), this->numValues, - dataFile); + if(this->numComponents == 1) { + size_t bytes = fread(this->data, sizeof(float), + this->numValues, dataFile); + } + else { + float *chunk = (float *)malloc(this->numComponents*sizeof(float)); + for(int i = 0; i < this->numValues; i++) { + size_t numbytes = fread(chunk, sizeof(float), + this->numComponents, dataFile); + this->data[i] = std::sqrt(chunk[0]*chunk[0] + + chunk[1]*chunk[1] + chunk[2]*chunk[2]); + } + } } fclose(dataFile); } diff --git a/src/TimeSeries.cpp b/src/TimeSeries.cpp index 6d25257..2bc6b23 100644 --- a/src/TimeSeries.cpp +++ b/src/TimeSeries.cpp @@ -8,9 +8,9 @@ namespace pbnj { TimeSeries::TimeSeries(std::vector filenames, - int x, int y, int z) : + int x, int y, int z, unsigned int components) : dataFilenames(filenames), length(filenames.size()), xDim(x), yDim(y), - zDim(z), dataSize(x*y*z*4) + zDim(z), dataSize(x*y*z*4), numComponents(components) { this->volumes = new Volume*[this->length]; for(int i = 0; i < this->length; i++) @@ -22,9 +22,9 @@ TimeSeries::TimeSeries(std::vector filenames, } TimeSeries::TimeSeries(std::vector filenames, - std::string varname, int x, int y, int z) : + std::string varname, int x, int y, int z, unsigned int components) : dataFilenames(filenames), length(filenames.size()), dataVariable(varname), - xDim(x), yDim(y), zDim(z), dataSize(x*y*z*4) + xDim(x), yDim(y), zDim(z), dataSize(x*y*z*4), numComponents(components) { this->volumes = new Volume*[this->length]; for(int i = 0; i < this->length; i++) @@ -110,11 +110,12 @@ Volume *TimeSeries::getVolume(unsigned int index) // load the volume if(this->dataVariable.empty()) this->volumes[index] = new Volume(this->dataFilenames[index], - this->xDim, this->yDim, this->zDim, this->doMemoryMap); + this->xDim, this->yDim, this->zDim, this->doMemoryMap, + this->numComponents); else this->volumes[index] = new Volume(this->dataFilenames[index], this->dataVariable, this->xDim, this->yDim, this->zDim, - this->doMemoryMap); + this->doMemoryMap, this->numComponents); // set any given attributes if(!this->colorMap.empty()) diff --git a/src/Volume.cpp b/src/Volume.cpp index b86eab2..d48d823 100644 --- a/src/Volume.cpp +++ b/src/Volume.cpp @@ -8,24 +8,25 @@ namespace pbnj { -Volume::Volume(std::string filename, int x, int y, int z, bool memmap) +Volume::Volume(std::string filename, int x, int y, int z, bool memmap, + unsigned int components) { this->ID = createID(); //volumes contain a datafile //one datafile per volume, one volume per renderer/camera - this->dataFile = new DataFile(x, y, z); + this->dataFile = new DataFile(x, y, z, components); this->loadFromFile(filename, "", memmap); this->init(); } Volume::Volume(std::string filename, std::string var_name, int x, int y, int z, - bool memmap) + bool memmap, unsigned int components) { this->ID = createID(); //volumes contain a datafile //one datafile per volume, one volume per renderer/camera - this->dataFile = new DataFile(x, y, z); + this->dataFile = new DataFile(x, y, z, components); this->loadFromFile(filename, var_name, memmap); this->init(); diff --git a/src/test/simpleVolumeRender.cpp b/src/test/simpleVolumeRender.cpp index 2318e27..c736f62 100644 --- a/src/test/simpleVolumeRender.cpp +++ b/src/test/simpleVolumeRender.cpp @@ -59,18 +59,19 @@ int main(int argc, const char **argv) case pbnj::SINGLE_NOVAR: std::cout << "Single volume, no variable" << std::endl; volume = new pbnj::Volume(config->dataFilename, config->dataXDim, - config->dataYDim, config->dataZDim, true); + config->dataYDim, config->dataZDim, true, config->dataNumComponents); break; case pbnj::SINGLE_VAR: std::cout << "Single volume, variable" << std::endl; volume = new pbnj::Volume(config->dataFilename, config->dataVariable, config->dataXDim, config->dataYDim, - config->dataZDim); + config->dataZDim, config->dataNumComponents); break; case pbnj::MULTI_NOVAR: std::cout << "Multiple volumes, no variable" << std::endl; timeSeries = new pbnj::TimeSeries(config->globbedFilenames, - config->dataXDim, config->dataYDim, config->dataZDim); + config->dataXDim, config->dataYDim, config->dataZDim, + config->dataNumComponents); timeSeries->setColorMap(config->colorMap); timeSeries->setOpacityMap(config->opacityMap); timeSeries->setOpacityAttenuation(config->opacityAttenuation); @@ -81,7 +82,7 @@ int main(int argc, const char **argv) std::cout << "Multiple volumes, variable" << std::endl; timeSeries = new pbnj::TimeSeries(config->globbedFilenames, config->dataVariable, config->dataXDim, config->dataYDim, - config->dataZDim); + config->dataZDim, config->dataNumComponents); timeSeries->setColorMap(config->colorMap); timeSeries->setOpacityMap(config->opacityMap); timeSeries->setOpacityAttenuation(config->opacityAttenuation);