17#ifndef __fixel_helpers_h__
18#define __fixel_helpers_h__
44 if (!in.datatype().is_floating_point())
45 throw Exception (
"Image \"" + in.name() +
"\" is not a valid peaks image: Does not contain floating-point data");
47 check_effective_dimensionality (in, 4);
49 throw Exception (
e,
"Image \"" + in.name() +
"\" is not a valid peaks image: Expect 4 dimensions");
52 throw Exception (
"Image \"" + in.name() +
"\" is not a valid peaks image: Number of volumes must be a multiple of 3");
68 template <
class HeaderType>
76 template <
class HeaderType>
80 throw InvalidImageException (
index.name() +
" is not a valid fixel index image. Image must be 4D with 2 volumes in the 4th dimension");
83 template <
class HeaderType>
86 return in.ndim() == 3 && in.size(2) == 1;
100 template <
class HeaderType>
112 template <
class HeaderType>
116 throw InvalidImageException (in.name() +
" is not a valid fixel data file. Expected a 3-dimensional image of size n x m x 1");
122 if (fixel_directory.empty())
124 return fixel_directory;
128 template <
class IndexHeaderType>
132 return std::stoul (index_header.keyval().at(
n_fixels_key));
135 index_image.index(3) = 1;
138 for (
auto i =
MR::Loop (index_image, 0, 3) (index_image); i; ++i) {
139 if (index_image.value() > max_offset) {
140 max_offset = index_image.value();
141 index_image.index(3) = 0;
142 num_fixels = index_image.value();
143 index_image.index(3) = 1;
146 return (max_offset + num_fixels);
151 template <
class IndexHeaderType,
class DataHeaderType>
161 index_image.index(3) = 1;
164 for (
auto i =
MR::Loop (index_image, 0, 3) (index_image); i; ++i) {
165 if (index_image.value() > max_offset) {
166 max_offset = index_image.value();
167 index_image.index(3) = 0;
168 num_fixels = index_image.value();
169 index_image.index(3) = 1;
186 throw InvalidImageException (
"Fixel number mismatch between index image " + index_h.name() +
" and data image " + data_h.name());
192 std::string path_temp = path;
201 else throw Exception (
"Fixel directory (" +
str(path_temp) +
") does not exist");
204 throw Exception (
str(path_temp) +
" is not a directory");
206 if (check_if_empty &&
Path::Dir (path_temp).read_name ().size () != 0)
207 throw Exception (
"Output fixel directory \"" + path_temp +
"\" is not empty"
209 " (-force option cannot safely be applied on directories; please erase manually instead)" :
221 std::string full_path =
Path::join (fixel_directory_path,
"index" + *it);
225 header = Header::open (full_path);
239 auto dir_walker =
Path::Dir (fixel_directory_path);
243 while ((temp = dir_walker.read_name()).size())
244 file_names.push_back (temp);
246 std::sort (file_names.begin(), file_names.end());
249 for (
auto fname : file_names) {
252 auto H = Header::open (
Path::join (fixel_directory_path, fname));
256 data_headers.emplace_back (std::move (
H));
258 WARN (
"fixel data file (" + fname +
") does not contain the same number of elements as fixels in the index file");
262 WARN (
"unable to open file \"" + fname +
"\" as potential fixel data file");
274 bool directions_found (
false);
279 auto dir_walker =
Path::Dir (fixel_directory_path);
281 while ((fname = dir_walker.read_name()).size()) {
283 Header tmp_header = Header::open (
Path::join (fixel_directory_path, fname));
286 if (directions_found ==
true)
287 throw Exception (
"multiple directions files found in fixel image directory: " + fixel_directory_path);
288 directions_found =
true;
289 header = std::move (tmp_header);
291 WARN (
"fixel directions file (" + fname +
") does not contain the same number of elements as fixels in the index file" );
297 if (!directions_found)
304 template <
class IndexHeaderType>
311 header.stride(0) = 1;
312 header.stride(1) = 2;
313 header.stride(2) = 3;
314 header.transform() = transform_type::Identity();
316 header.datatype().set_byte_order_native();
321 template <
class IndexHeaderType>
332 Header input_header = Header::open (input_file_path);
333 auto input_image = input_header.get_image<
float>();
347 auto input_image = input_header.get_image<
index_type>();
350 throw Exception (
"output fixel directory \"" + output_directory +
"\" already contains index file, "
351 +
"which is not the same as the expected output"
353 " (-force option cannot safely be applied on directories; please erase manually instead)" :
357 auto input_image = input_header.get_image<
index_type>();
369 auto input_image = input_header.get_image<
float>();
372 throw Exception (
"output fixel directory \"" + output_directory +
"\" already contains directions file, "
373 +
"which is not the same as the expected output"
375 " (-force option cannot safely be applied on directories; please erase manually instead)" :
379 auto input_image = input_header.get_image<
float>();
398 template <
class ValueType>
401 throw Exception (
"please input the specific fixel data file to be converted (not the fixel directory)");
403 Header in_data_header = Header::open (input_file);
405 auto in_data_image = in_data_header.get_image<ValueType>();
408 if (input_file == in_index_header.name())
409 throw Exception (
"input fixel data file cannot be the index file");
411 return in_data_image;
static constexpr uint8_t Float32
functions and classes related to image data input/output
static Image create(const std::string &image_name, const Header &template_header, bool add_to_command_history=true)
static Image open(const std::string &image_name, bool read_write_if_existing=false)
InvalidFixelDirectoryException(const Exception &previous_exception, const std::string &msg)
InvalidFixelDirectoryException(const std::string &msg)
FORCE_INLINE LoopAlongAxes Loop()
void mkdir(const std::string &folder)
FORCE_INLINE bool fixels_match(const IndexHeaderType &index_header, const DataHeaderType &data_header)
FORCE_INLINE Header directions_header_from_index(IndexHeaderType &index)
Generate a header for a fixel directions data file (Nx3x1) using an index image as a template.
FORCE_INLINE void check_index_image(const HeaderType &index)
FORCE_INLINE void check_fixel_directory(const std::string &path, bool create_if_missing=false, bool check_if_empty=false)
FORCE_INLINE bool is_index_image(const HeaderType &in)
FORCE_INLINE std::string get_fixel_directory(const std::string &fixel_file)
FORCE_INLINE bool is_index_filename(const std::string &path)
FORCE_INLINE vector< Header > find_data_headers(const std::string &fixel_directory_path, const Header &index_header, const bool include_directions=false)
FORCE_INLINE void copy_all_data_files(const std::string &input_directory, const std::string &output_directory)
Copy all data files in a fixel directory into another directory. Data files do not include the index ...
FORCE_INLINE Header data_header_from_index(IndexHeaderType &index)
Generate a header for a sparse data file (Nx1x1) using an index image as a template.
FORCE_INLINE void copy_directions_file(const std::string &input_directory, const std::string &output_directory)
Copy the directions file from one fixel directory into another.
FORCE_INLINE bool is_directions_file(const HeaderType &in)
FORCE_INLINE void check_data_file(const HeaderType &in)
FORCE_INLINE void check_fixel_size(const Header &index_h, const Header &data_h)
FORCE_INLINE Header find_directions_header(const std::string fixel_directory_path)
FORCE_INLINE Header find_index_header(const std::string &fixel_directory_path)
FORCE_INLINE void copy_index_file(const std::string &input_directory, const std::string &output_directory)
Copy the index file from one fixel directory into another.
const std::initializer_list< const std::string > supported_sparse_formats
Image< ValueType > open_fixel_data_file(const std::string &input_file)
open a data file. checks that a user has not input a fixel directory or index image
FORCE_INLINE bool is_data_file(const HeaderType &in)
FORCE_INLINE index_type get_number_of_fixels(IndexHeaderType &index_header)
FORCE_INLINE void copy_fixel_file(const std::string &input_file_path, const std::string &output_directory)
Copy a file from one fixel directory into another.
const std::string n_fixels_key("nfixels")
FORCE_INLINE void copy_index_and_directions_file(const std::string &input_directory, const std::string &output_directory)
FORCE_INLINE bool is_directions_filename(const std::string &path)
std::string join(const std::string &first, const std::string &second)
std::string basename(const std::string &name)
std::string dirname(const std::string &name)
bool exists(const std::string &path)
bool is_dir(const std::string &path)
bool has_suffix(const std::string &name, const std::string &suffix)
FORCE_INLINE void check(const Header &in)
bool images_match_abs(ImageType1 &in1, ImageType2 &in2, const double tol=0.0)
check images are the same within a absolute tolerance
std::string str(const T &value, int precision=0)
void threaded_copy(InputImageType &source, OutputImageType &destination, const vector< size_t > &axes, size_t num_axes_in_thread=1)