< MINC < SoftwareDevelopment < EZMINC

Opening a minc file for reading

#include "minc_1_rw.h"
using namespace minc;
//...
try
{
 minc_1_reader rdr;
 rdr.open(input_minc_file);
} catch (const minc::generic_error & err) {
 std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
 std::cerr << err.msg()<<std::endl;
}

Opening minc file for writing

Minc file is a complex structure, many parameters have to be setup properly to produce meaningful file, the easies way is to copy them from another minc file:

minc_1_writer wrt;
wrt.open(output_minc_file,example_minc_file);

Or, if another file is already open:

wrt.open(output_minc_file,rdr);

Or, if only the dimensions need to be preserved (create a file with voxels of type float, and 2D slices):

wrt.open(output_minc_file,rdr.info(),2,NC_FLOAT);

Analyzing MINC file meta information

  • Determining number of dimensions: rdr.dim_no()
  • calculating the matrix size, resolution :

std::cout<<"Dimensions:"<<std::endl
<< " Vector:"<<rdr.ndim(0)<<std::endl
<< " X:"<<rdr.ndim(1)<<" step:"<<rdr.nspacing(1)<<" start:"<<rdr.nstart(1)<<std::endl
<< " Y:"<<rdr.ndim(2)<<" step:"<<rdr.nspacing(2)<<" start:"<<rdr.nstart(2)<<std::endl
<< " Z:"<<rdr.ndim(3)<<" step:"<<rdr.nspacing(3)<<" start:"<<rdr.nstart(3)<<std::endl
<< " Time:"<<rdr.ndim(4)<<" step:"<<rdr.nspacing(4)<<" start:"<<rdr.nstart(4)<<std::endl;

Note that these are physical parameters, which don't depend on the way how information is stored in a minc file

  • Output direction cosine matrix

for(int i=0;i<3;i++)
{
if(rdr.have_dir_cos(i))
 for(int j=0;j<3;j++)
   std::cout<<rdr.ndir_cos(i,j)<<" ";
 std::cout<<std::endl;
}

  • Read a minc file history

std::cout<<"Minc history:"<<rdr.history().c_str()<<std::endl;

  • Read a string attribute

std::cout<<"Subject name:"<<rdr.att_value_string("patient","full_name").c_str()<<std::endl;

  • Read a double attribute

std::cout<<"Echo time:"<<rdr.att_value_double("acquisition","echo_time")[0]<<std::endl;

Note: reading double attribute returns std::vector<double> by value

Reading Image

Imaging data is stored as a multidimensional array of values a given type. Array is organized in slices (could be just one slice for the whole file), values stored inside the minc file may be normalized, see MINC/Reference for complete details. EZMINC was developed to hide the complexity of the data representation from programmer , but to allow complete control over how data is stored, if it is needed. There are several ways to read imaging information from a file using EZMINC library:

  • The easiest, the whole volume is copied into a multidimensional array in memory. Usually this is the most convenient method:
    • Reading a volume representing real values (interpret them as float)

#include <minc_1_simple.h>
#include <minc_1_simple_rw.h>
using namespace minc;
//....
simple_volume<float> src;
minc_1_reader rdr;
rdr1.open(input_file);
load_simple_volume<float>(rdr,src);
std::cout<<"Voxel at voxel coordinates (1,2,3) is "<<src.get(1,2,3)<<std::endl;
//using safe_get to make sure that we don't read beyond the allocated space
std::cout<<"Voxel at world coordinates (1,2,3) is "<<src.safe_get(src.world_to_voxel(IDX<double>(1.0,2.0,3.0)))<<std::endl;

    • Reading a volume with a binary mask (or discrete labels)

#include <minc_io_simple_volume.h>
#include <minc_1_simple.h>
#include <minc_1_simple_rw.h>
using namespace minc;
//....
simple_volume<unsigned char> src;
minc_1_reader rdr;
rdr1.open(input_file);
load_simple_volume<unsigned char>(rdr,src);
std::cout<<"Labels at (1,2,3) is "<<(int)src.get(1,2,3)<<std::endl;

    • Reading a 4D volume

simple_4d_volume<float> vol;
load_4d_volume<float>(rdr,vol);
std::cout<<"Voxel at voxel coordinates (1,2,3) slice 0 is "<<src.get(1,2,3,0)<<std::endl;

  • reading the whole minc file as a single continuous buffer, organized with vector_dimension the fastest varying (if present), X,Y,Z, and time the slowest varyuing (if present)

#include <minc_1_rw.h>
#include <minc_1_simple.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type

size_t size=1;
for(i=0;i<rdr.dim_no();i++)
   size*=rdr.dim(i).length;
 
float* array=new float[size];

load_standard_volume<float>(rdr,array);

  • reading the whole minc file voxel-by-voxel, in the order that data is stored inside file. This method is really usefull when working with big number of input files, and storing them all together in memory is problematic

#include <minc_1_rw.h>
#include <minc_1_simple.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
minc_input_iterator<float> in(rdr);

double avg=0;
int cnt=0;
for(in.begin();!in.last();in.next())
{
   avg+=in.value()
   cnt++;
}
std::cout<<"Average value="<<avg/cnt<<std::endl;

  • lowest-level interface, reading the minc file slice-by-slice in the order that data is stored

#include <minc_1_rw.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
float* slice_buffer=new float[rdr.slice_len()];
for(rdr.begin();!rdr.last();rdr.next_slice())//minc_1_reader is actually an iterator!
{
   rdr.read(slice_buffer);
   //do something usefull with the data
}

Writing MINC file meta information

  • copying history NOTE: if using first for of minc_1_writer::open history will be copied automatically

wrt.copy_headers(rdr);

  • Appending new line into MINC history

wrt.append_history("minc_test was used to produce this file\n");

  • Write a string attribute
wrt.insert("patient","full_name","John Doe");
  • Writing a double attribute
wrt.insert("acquisition","echo_time",0.120); //echo time was 120ms
  • Writing an array of double values
std::vector<double> bvalues(64);
//...
wrt.insert("acquisition","bvalues",bvalues);
  • Copying all headers from another minc file
wrt.copy_headers(rdr);

Writing Images

  • Simplest interface, using simple_volume or simple_4d_volume

simple_volume<float> output_vol;
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
save_simple_volume<float>(wrt,output_vol); 

simple_4d_volume<float> output_vol;
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
save_4d_volume(wrt,vol);

  • Writing image from a continuous array

float *output_vol=new float[size];
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
wrt.setup_write_float(); //have to setup the data type
save_standard_volume<float>(wrt,output_vol); 

  • Using output iterator

   //adding a value c to all voxels
   minc_1_reader rdr;
   rdr.open(input_minc);
   rdr.setup_read_float();
   
   minc_1_writer wrt;
   wrt.open(output_minc,rdr);
   wrt.setup_write_float();
    
   minc_input_iterator<float> in(rdr);
   minc_output_iterator<float> out(wrt);
   for(in.begin(),out.begin();!in.last();in.next(),out.next())
   {
     out.value(in.value()+c);
   }

  • lowest-level, writing image slice-by-slice

#include <minc_1_rw.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
minc_1_writer wrt;
wrt.open(output_minc,rdr);
wrt.setup_write_float();
float* slice_buffer=new float[rdr.slice_len()];
for(rdr.begin(),wrt.begin();!rdr.last();rdr.next_slice(),wrt.next_slice())
{
   rdr.read(slice_buffer);
   //do something usefull with the data
   wrt.write(slice_buffer);
}

This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.