Commit f11f8ea6 authored by incardon's avatar incardon

Adding Image raw reader

parent 9e538a9a
Pipeline #2277 passed with stages
in 41 seconds
......@@ -105,6 +105,12 @@ install(FILES HDF5_wr/HDF5_wr.hpp
HDF5_wr/HDF5_reader_vd.hpp
DESTINATION openfpm_io/include/HDF5_wr)
install(FILES RawReader/InitGridWithPixel.hpp
DESTINATION openfpm/io/include/RawReader/)
install(FILES util/PathAndFiles.hpp
DESTINATION openfpm_io/include/util)
install(FILES Plot/GoogleChart.hpp Plot/util.hpp
DESTINATION openfpm_io/include/Plot )
......
//
// Created by jstark on 2019-11-07.
//
/**
* @file InitGridWithPixel.hpp
*
* @brief Header file containing functions for loading pixel values from 2D image or 3D image stack (volume) stored
* in a binary file onto an openFPM grid.
*
* @details Can be run in parallel.
*
* @author Justina Stark
* @date November 2019 - August 2020
*/
#ifndef IMAGE_BASED_RECONSTRUCTION_GETINITIALGRID_HPP
#define IMAGE_BASED_RECONSTRUCTION_GETINITIALGRID_HPP
#include <iostream>
#include <typeinfo>
#include <cmath>
#include "Vector/vector_dist.hpp"
#include "Grid/grid_dist_id.hpp"
#include "data_type/aggregate.hpp"
#include "Decomposition/CartDecomposition.hpp"
#include "../redistancing_Sussman/HelpFunctionsForGrid.hpp"
typedef signed char BYTE;
/**@brief Read the number of pixels per dimension from a csv-file in order to create a grid with the same size.
*
* @param path_to_file Std::string containing the path to the csv file that holds the image/volume size in
* #pixels per dimension.
* @return Std::vector containing the count of pixels for each dimension as it was read from the csv file.
*/
std::vector<size_t> get_size(const std::string & path_to_file)
{
std::vector<size_t> stack_dimst_1d;
// stream input csv file and error check
std::ifstream file(path_to_file);
if (!file)
{
std::cout << "Error opening file" << std::endl;
exit (EXIT_FAILURE);
}
// get its size
std::streampos fileSize;
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// reserve capacity
stack_dimst_1d.reserve(fileSize);
std::string field;
while ( getline(file, field) ) // 1 field per axis
{
std::istringstream iss(field);
size_t val;
iss >> val;
stack_dimst_1d.push_back(val); // add the #pixels for current axis to the array
}
// reverse order to compensate reverse reading
std::reverse(std::begin(stack_dimst_1d), std::end(stack_dimst_1d));
return stack_dimst_1d;
}
/**@brief Converts the pixel values stored in a binary file into doubles and loads them onto an OpenFPM grid.
*
* @tparam Phi_0 Index of property in which pixel value should be stored.
* @tparam grid_type Type of OpenFPM grid.
* @param grid Grid of type grid_type, on which image / image-stack should be loaded.
* @param file_name Std::string containing the path + name of the binary file that stores the pixel values.
* @param stack_dims Size_t variable that contains the dimensionality of the image / image stack. Can be given
* manually or loaded from a csv file before (see: #get_size())
*/
template <size_t Phi_0, typename grid_type>
void load_pixel_onto_grid(grid_type & grid, std::string file_name, std::vector <size_t> & stack_dims)
{
constexpr size_t x = 0;
constexpr size_t y = 1;
constexpr size_t z = 2;
std::ifstream file_stream (file_name, std::ifstream::binary);
auto & v_cl = create_vcluster();
if (v_cl.rank() == 0)
{
for (size_t d = 0; d < grid_type::dims; d++)
{
std::cout << "# grid points in dimension " << d << " = " << grid.size(d) << std::endl;
}
}
// initialize complete grid including ghost layer with -1
init_grid_and_ghost<Phi_0>(grid, -1.0);
// assign pixel values to domain. For each pixel get factor_refinement number of grid points with corresponding value
auto dom = grid.getDomainIterator();
std::vector<BYTE> pixel_line; // one x-line of the image stack which will be read
size_t sz_img[grid_type::dims];
for (size_t d = 0; d < grid_type::dims; d++)
{
sz_img[d] = stack_dims[d];
}
grid_sm<grid_type::dims,void> ginfo_image(sz_img); // in order to get the image related key later on
double refinement[grid_type::dims];
for (size_t d = 0; d < grid_type::dims; d++)
{
refinement[d] = (double) grid.size(d) / (double)stack_dims[d]; // get the factor, by which the grid resolution differs from the image stack resolution
if (v_cl.rank() == 0) std::cout << "effective refinement in dimension " << d << " = " << refinement[d] << std::endl;
}
while(dom.isNext())
{
auto key = dom.get();
auto gkey = grid.getGKey(key);
// get l as the length of one x-line of the original image stack for the specific patch on the processor
auto & gbox = grid.getLocalGridsInfo();
auto & DomBox = gbox.get(key.getSub()).Dbox;
int l = (size_t) std::round((DomBox.getHigh(0) - DomBox.getLow(0) + 1) / refinement[x]);
// in case that the grid has a different resolution than the underlying image stack:
// create a key which is used to get the offset for the file reading
// the indices in this key are corrected by the refinement factor
for (size_t d = 1; d < grid_type::dims; d++)
{
gkey.set_d(d, std::round(gkey.get(d) / refinement[d]));
}
// the offset matches the pixel from the image stack to the corresponding current position of the iterator
// in the grid
size_t offset = ginfo_image.LinId(gkey);
file_stream.seekg(offset); // jump to the correct position in the file
// prepare space for the pixel values of one x-line in the original image stack
pixel_line.resize(l);
// stream the file and fill pixel values into pixel_line
file_stream.read((char*) & pixel_line[0], l);
// run over a whole grid-line in x and assign pixel values from pixel_line to grid nodes
// if the grid is finer in x as the image stack, the same pixel value from pixel_line is
// assigned refinement[x] times
for (size_t i = 0; i < l * refinement[x]; i++)
{
auto key = dom.get();
grid.template get<Phi_0>(key) = (double) pixel_line[(size_t)floor(i / refinement[x])];
++dom;
}
// now one grid line in x is finished and the iterator dom has advanced accordingly s.t. next loop continues
// with next line, meaning that y increased by 1 (or z respectivley, when y = ymax + 1)
}
grid.template ghost_get<Phi_0>();
}
#endif //IMAGE_BASED_RECONSTRUCTION_GETINITIALGRID_HPP
//
// Created by jstark on 2019-12-03.
//
/**
* @file PathsAndFiles.hpp
*
* @brief Header file containing functions for creating files and folders.
*
* @author Justina Stark
* @date December 2019
*/
#ifndef FILES_READ_AND_WRITE_PATHSANDFILES_HPP
#define FILES_READ_AND_WRITE_PATHSANDFILES_HPP
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>
/**@brief Gets the current working directory and returns path as string without the "cmake-build-debug".
*
* @return Std::string of path to current working directory.
*/
std::string get_cwd()
{
char *cwd = nullptr;
size_t size;
cwd = getcwd(cwd, size);
// convert current directory to string
std::string s_cwd;
s_cwd = cwd;
// split string into file and path (to get rid of "cmake-build-debug" at the end of cwd)
std::size_t botDirPos = s_cwd.find_last_of("/");
std::string dir = s_cwd.substr(0, botDirPos);
dir = dir + "/";
// std::cout << "The current working directory is: " << dir << std::endl;
return dir;
}
/**@brief Checks if a file already exists.
*
* @param path Std::string with path of file for which existence should be checked.
* @return True, if file exists, false if not.
*/
bool check_if_file_exists(std::string path)
{
try
{
// Create a filesystem::path object from given path string
boost::filesystem::path pathObj(path);
if (boost::filesystem::exists(pathObj) && boost::filesystem::is_regular_file(pathObj))
{
return true;
// BOOST_LOG_TRIVIAL(info) << path << " -> File exists.";
}
}
catch (boost::filesystem::filesystem_error & e)
{
std::cerr << e.what() << std::endl;
// BOOST_LOG_TRIVIAL(error) << "Error when checking existence of file ( " << path << " ): " << e.what();
}
return false;
}
/**@brief Creates a file if not already existent.
*
* @param path Std::string that contains path including filename of the file that should be created.
*/
void create_file_if_not_exist(std::string path)
{
auto & v_cl = create_vcluster();
if (v_cl.rank() == 0)
{
if ( ! check_if_file_exists(path))
{
std::ofstream outfile (path);
// BOOST_LOG_TRIVIAL(info) << "Created file with name: " << path;
}
}
}
/**@brief Checks if a directory already exists.
*
* @param path Std::string with path of directory for which existence should be checked.
* @return True, if directory exists, false if not.
*/
bool check_if_directory_exists(std::string path)
{
try
{
// Create a filesystem::path object from given path string
boost::filesystem::path pathObj(path);
if (boost::filesystem::exists(pathObj) && boost::filesystem::is_directory(pathObj)) return true;
}
catch (boost::filesystem::filesystem_error & e)
{
std::cerr << e.what() << std::endl;
}
return false;
}
/**@brief Creates a directory if not already existent.
*
* @param path Std::string that contains path including name of the folder that should be created.
*/
void create_directory_if_not_exist(std::string path)
{
auto & v_cl = create_vcluster();
if (v_cl.rank() == 0)
{
if ( ! check_if_directory_exists(path))
{
boost::filesystem::create_directory(path);
// BOOST_LOG_TRIVIAL(info) << "Created directory with name: " << path;
}
else std::cout << "Folder for current settings ( '" << path << "' ) already exists. New files will be saved to this folder." << std::endl;
// BOOST_LOG_TRIVIAL(info) << "Folder for current settings ( '" << path << "' ) already exists. New files will be saved to this folder.";
}
}
#endif //FILES_READ_AND_WRITE_PATHSANDFILES_HPP
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment