Beispiel #1
0
 void add_end_roi(const image::geometry<3>& geo,
                  const std::vector<image::vector<3,short> >& points)
 {
     end.push_back(std::make_shared<Roi>(geo));
     for(unsigned int index = 0; index < points.size(); ++index)
         end.back()->addPoint(points[index]);
 }
Beispiel #2
0
 void add_terminate_roi(const image::geometry<3>& geo,
                        const std::vector<image::vector<3,short> >& points)
 {
     if(!terminate.get())
         terminate.reset(new Roi(geo));
     for(unsigned int index = 0; index < points.size(); ++index)
         terminate->addPoint(points[index]);
 }
Beispiel #3
0
 void thread_run(unsigned char thread_index,unsigned char thread_count,
                 const std::vector<unsigned char>& mask)
 {
     unsigned int sum_mask = std::accumulate(mask.begin(),mask.end(),(unsigned int)0)/thread_count;
     unsigned int cur = 0;
     for(unsigned int voxel_index = thread_index;
         voxel_index < dim.size() &&
         (thread_index != 0 || check_prog(cur,sum_mask));voxel_index += thread_count)
     {
         if (!mask[voxel_index])
             continue;
         cur += mask[voxel_index];
         voxel_data[thread_index].init();
         voxel_data[thread_index].voxel_index = voxel_index;
         for (int index = 0; index < process_list.size(); ++index)
             process_list[index].run(*this,voxel_data[thread_index]);
         if(prog_aborted())
             break;
     }
 }
Beispiel #4
0
std::pair<float,float> evaluate_fib(
        const image::geometry<3>& dim,
        const std::vector<std::vector<float> >& fib_fa,
        const std::vector<std::vector<float> >& fib_dir)
{
    unsigned char num_fib = fib_fa.size();
    char dx[13] = {1,0,0,1,1,0, 1, 1, 0, 1,-1, 1, 1};
    char dy[13] = {0,1,0,1,0,1,-1, 0, 1, 1, 1,-1, 1};
    char dz[13] = {0,0,1,0,1,1, 0,-1,-1, 1, 1, 1,-1};
    std::vector<image::vector<3> > dis(13);
    for(unsigned int i = 0;i < 13;++i)
    {
        dis[i] = image::vector<3>(dx[i],dy[i],dz[i]);
        dis[i].normalize();
    }
    float otsu = *std::max_element(fib_fa[0].begin(),fib_fa[0].end())*0.1;
    std::vector<std::vector<unsigned char> > connected(fib_fa.size());
    for(unsigned int index = 0;index < connected.size();++index)
        connected[index].resize(dim.size());
    float connection_count = 0;
    for(image::pixel_index<3> index(dim);index < dim.size();++index)
    {
        if(fib_fa[0][index.index()] <= otsu)
            continue;
        unsigned int index3 = index.index()+index.index()+index.index();
        for(unsigned char fib1 = 0;fib1 < num_fib;++fib1)
        {
            if(fib_fa[fib1][index.index()] <= otsu)
                break;
            for(unsigned int j = 0;j < 2;++j)
            for(unsigned int i = 0;i < 13;++i)
            {
                image::vector<3,int> pos;
                pos = j ? image::vector<3,int>(index[0] + dx[i],index[1] + dy[i],index[2] + dz[i])
                          :image::vector<3,int>(index[0] - dx[i],index[1] - dy[i],index[2] - dz[i]);
                if(!dim.is_valid(pos))
                    continue;
                image::pixel_index<3> other_index(pos[0],pos[1],pos[2],dim);
                unsigned int other_index3 = other_index.index()+other_index.index()+other_index.index();
                if(std::abs(image::vector<3>(&fib_dir[fib1][index3])*dis[i]) <= 0.8665)
                    continue;
                for(unsigned char fib2 = 0;fib2 < num_fib;++fib2)
                    if(fib_fa[fib2][other_index.index()] > otsu &&
                            std::abs(image::vector<3>(&fib_dir[fib2][other_index3])*dis[i]) > 0.8665)
                    {
                        connected[fib1][index.index()] = 1;
                        connected[fib2][other_index.index()] = 1;
                        connection_count += fib_fa[fib2][other_index.index()];
                    }
            }
        }
    }
    float no_connection_count = 0;
    for(image::pixel_index<3> index(dim);index < dim.size();++index)
    {
        for(unsigned int i = 0;i < num_fib;++i)
            if(fib_fa[i][index.index()] > otsu && !connected[i][index.index()])
            {
                no_connection_count += fib_fa[i][index.index()];
            }

    }

    return std::make_pair(connection_count,no_connection_count);
}
    virtual void init(Voxel& voxel)
    {
        if(voxel.vs[0] == 0.0 ||
           voxel.vs[1] == 0.0 ||
           voxel.vs[2] == 0.0)
            throw std::runtime_error("No spatial information found in src file. Recreate src file or contact developer for assistance");

        begin_prog("normalization");

        VG = fa_template_imp.I;
        VF = voxel.fa_map;

        image::filter::gaussian(voxel.fa_map);
        image::filter::gaussian(voxel.fa_map);
        image::filter::gaussian(voxel.qa_map);
        image::filter::gaussian(voxel.qa_map);
        image::normalize(voxel.fa_map,1.0);
        image::normalize(voxel.qa_map,1.0);
        for(unsigned int index = 0;index < voxel.qa_map.size();++index)
            if(voxel.qa_map[index] == 0.0 || voxel.fa_map[index]/voxel.qa_map[index] > 2.5)
                VF[index] = 0.0;
        image::filter::gaussian(VF);

        src_geo = VF.geometry();

        image::normalize(VF,1.0);
        //VF.save_to_file<image::io::nifti<> >("VF.nii");

        image::normalize(VG,1.0);

        // get rid of the gray matters
        image::minus_constant(VF.begin(),VF.end(),0.3);
        image::lower_threshold(VF.begin(),VF.end(),0.00);
        image::normalize(VF,1.0);

        image::minus_constant(VG.begin(),VG.end(),0.3);
        image::lower_threshold(VG.begin(),VG.end(),0.00);
        image::normalize(VG,1.0);

        VGvs[0] = std::fabs(fa_template_imp.tran[0]);
        VGvs[1] = std::fabs(fa_template_imp.tran[5]);
        VGvs[2] = std::fabs(fa_template_imp.tran[10]);

        image::affine_transform<3,double> arg_min;
        // VG: FA TEMPLATE
        // VF: SUBJECT QA
        arg_min.scaling[0] = voxel.vs[0] / VGvs[0];
        arg_min.scaling[1] = voxel.vs[1] / VGvs[1];
        arg_min.scaling[2] = voxel.vs[2] / VGvs[2];
        voxel_volume_scale = arg_min.scaling[0]*arg_min.scaling[1]*arg_min.scaling[2];
        // calculate center of mass
        image::vector<3,double> mF = center_of_mass(VF);
        image::vector<3,double> mG = center_of_mass(VG);

        arg_min.translocation[0] = mG[0]-mF[0]*arg_min.scaling[0];
        arg_min.translocation[1] = mG[1]-mF[1]*arg_min.scaling[1];
        arg_min.translocation[2] = mG[2]-mF[2]*arg_min.scaling[2];


        bool terminated = false;
        set_title("linear registration");
        begin_prog("conducting registration");
        check_prog(0,2);
        image::reg::linear(VF,VG,arg_min,image::reg::affine,image::reg::square_error(),terminated,0.25);
        check_prog(1,2);

        // create VFF the affine transformed VF
        image::basic_image<float,3> VFF(VG.geometry());
        {

            affine = arg_min;
            image::reg::linear_get_trans(VF.geometry(),VG.geometry(),affine);
            {
                std::vector<double> T(16);
                affine.save_to_transform(T.begin());
                T[15] = 1.0;
                math::matrix_inverse(T.begin(),math::dim<4,4>());
                affine.load_from_transform(T.begin());
            }

            image::resample(VF,VFF,affine);

            //VFF.save_to_file<image::io::nifti<> >("VFF.nii");
            //VG.save_to_file<image::io::nifti<> >("VG.nii");

        }
        {
            switch(voxel.reg_method)
            {
                case 0:
                    mni.normalize(VG,VFF);
                break;
                case 1:
                    mni.normalize(VG,VFF,12,14,12,4,8);
                break;
            }

            //calculate the goodness of fit
            std::vector<float> x,y;
            x.reserve(VG.size());
            y.reserve(VG.size());
            image::interpolation<image::linear_weighting,3> trilinear_interpolation;
            for(image::pixel_index<3> index;VG.geometry().is_valid(index);
                    index.next(VG.geometry()))
                if(VG[index.index()] != 0)
                {
                    image::vector<3,double> pos;
                    mni.warp_coordinate(index,pos);
                    double value = 0.0;
                    if(!trilinear_interpolation.estimate(VFF,pos,value))
                        continue;
                    x.push_back(VG[index.index()]);
                    y.push_back(value);
                }
            R2 = x.empty() ? 0.0 : image::correlation(x.begin(),x.end(),y.begin());
            R2 *= R2;
            std::cout << "R2 = " << R2 << std::endl;
        }

        check_prog(2,2);


        // setup output bounding box
        {
            //setBoundingBox(-78,-112,-50,78,76,85,1.0);
            float voxel_size = voxel.param[1];
            bounding_box_lower[0] = std::floor(-78.0/voxel_size+0.5)*voxel_size;
            bounding_box_lower[1] = std::floor(-112.0/voxel_size+0.5)*voxel_size;
            bounding_box_lower[2] = std::floor(-50.0/voxel_size+0.5)*voxel_size;
            bounding_box_upper[0] = std::floor(78.0/voxel_size+0.5)*voxel_size;
            bounding_box_upper[1] = std::floor(76.0/voxel_size+0.5)*voxel_size;
            bounding_box_upper[2] = std::floor(85.0/voxel_size+0.5)*voxel_size;
            des_geo[0] = (bounding_box_upper[0]-bounding_box_lower[0])/voxel_size+1;//79
            des_geo[1] = (bounding_box_upper[1]-bounding_box_lower[1])/voxel_size+1;//95
            des_geo[2] = (bounding_box_upper[2]-bounding_box_lower[2])/voxel_size+1;//69
            des_offset[0] = bounding_box_lower[0]/VGvs[0]-fa_template_imp.tran[3]/fa_template_imp.tran[0];
            des_offset[1] = bounding_box_lower[1]/VGvs[1]-fa_template_imp.tran[7]/fa_template_imp.tran[5];
            des_offset[2] = bounding_box_lower[2]/VGvs[2]-fa_template_imp.tran[11]/fa_template_imp.tran[10];
            scale[0] = voxel_size/VGvs[0];
            scale[1] = voxel_size/VGvs[1];
            scale[2] = voxel_size/VGvs[2];
        }

        begin_prog("q-space diffeomorphic reconstruction");


        float sigma = voxel.param[0]; //diffusion sampling length ratio, optimal 1.24
        // setup mask
        {
            // set the current mask to template space
            voxel.image_model->set_dimension(des_geo[0],des_geo[1],des_geo[2]);
            for(image::pixel_index<3> index;des_geo.is_valid(index);index.next(des_geo))
            {
                image::vector<3,int> mni_pos(index);
                mni_pos *= voxel.param[1];
                mni_pos[0] /= VGvs[0];
                mni_pos[1] /= VGvs[1];
                mni_pos[2] /= VGvs[2];
                mni_pos += des_offset;
                voxel.image_model->mask[index.index()] =
                        fa_template_imp.I.at(mni_pos[0],mni_pos[1],mni_pos[2]) > 0.0? 1: 0;
            }
        }


        q_vectors_time.resize(voxel.bvalues.size());
        for (unsigned int index = 0; index < voxel.bvalues.size(); ++index)
        {
            q_vectors_time[index] = voxel.bvectors[index];
            q_vectors_time[index] *= std::sqrt(voxel.bvalues[index]*0.01506);// get q in (mm) -1
            q_vectors_time[index] *= sigma;
        }

        b0_index = -1;
        if(voxel.half_sphere)
            for(unsigned int index = 0;index < voxel.bvalues.size();++index)
                if(voxel.bvalues[index] == 0)
                    b0_index = index;

        ptr_images.clear();
        for (unsigned int index = 0; index < voxel.image_model->dwi_data.size(); ++index)
            ptr_images.push_back(point_image_type((const unsigned short*)voxel.image_model->dwi_data[index],src_geo));


        voxel.qa_scaling = voxel.reponse_function_scaling/voxel.vs[0]/voxel.vs[1]/voxel.vs[2];
        max_accumulated_qa = 0;

        std::fill(voxel.vs.begin(),voxel.vs.end(),voxel.param[1]);

        jdet.resize(des_geo.size());


        if (voxel.odf_deconvolusion)
        {
            gqi.init(voxel);
            deconvolution.init(voxel);
        }
        if (voxel.odf_decomposition)
        {
            gqi.init(voxel);
            decomposition.init(voxel);
        }
        angle_variance = 8; //degress;
        angle_variance *= M_PI/180;
        angle_variance *= angle_variance;
        angle_variance *= 2.0;

    }
Beispiel #6
0
    void createLayout(const char* file_name,
                      float fa_value,
                      const std::vector<float>& angle_iteration,
                      unsigned int repeat_num,
                      unsigned int phantom_width,
                      unsigned int boundary)
    {
        float iso_fraction = 0.2;
        float fiber_fraction = 1.0-iso_fraction;
        dim[0] = phantom_width+boundary+boundary;
        dim[1] = phantom_width+boundary+boundary;
        dim[2] = std::max<int>(1,angle_iteration.size())*repeat_num;

        unsigned int total_size = dim.size();
        std::vector<float> fa[2];
        std::vector<float> gfa;
        std::vector<short> findex[2];

        models.resize(total_size);
        fa[0].resize(total_size);
        fa[1].resize(total_size);

        gfa.resize(total_size);
        findex[0].resize(total_size);
        findex[1].resize(total_size);


        unsigned int main_fiber_index = ti.discretize(image::vector<3>(1.0,0.0,0.0));

        std::fill(models.begin(),models.end(),(MixGaussianModel*)0);
        begin_prog("creating layout");

        if(angle_iteration.empty()) // use 0 to 90 degrees crossing
            for (unsigned int n = 0,index = 0; n < repeat_num; ++n)
                    {
                        if (!check_prog(index,total_size))
                            break;
                        float fa2 = fa_value*fa_value;
                        //fa*fa = (r*r-2*r+1)/(r*r+2)
                        float r = (1.0+fa_value*std::sqrt(3-2*fa2))/(1-fa2);
                        float l2 = mean_dif*3.0/(2.0+r);
                        float l1 = r*l2;
                        for (unsigned int y = 0; y < dim[1]; ++y)
                        {
                            for (unsigned int x = 0; x < dim[0]; ++x,++index)
                            {
                                if (x >= boundary &&
                                    x < boundary+phantom_width &&
                                    y >= boundary &&
                                    y < boundary+phantom_width)
                                {
                                    float xf = ((float)x - boundary + 1)/((float)phantom_width);//from 0.02 to 1.00
                                    xf = 1.0-xf;//0.00 to 0.98
                                    xf = 0.5+0.5*xf;//0.50 to 0.99
                                    float angle = ((float)y - boundary)/((float)phantom_width);//0.00 to 0.98
                                    angle = 1.0-angle;//0.02 to 1.00
                                    angle *= M_PI*0.5;//1.8 degrees 90 degrees
                                    models[index] = new MixGaussianModel(l1,l2,mean_dif,angle,
                                                                         fiber_fraction*xf,
                                                                         fiber_fraction*(1.0-xf));
                                    fa[0][index] = fiber_fraction*xf;
                                    fa[1][index] = fiber_fraction*(1.0-xf);
                                    gfa[index] = fa_value;
                                    findex[0][index] = main_fiber_index;
                                    findex[1][index] = ti.discretize(image::vector<3>(std::cos(angle),std::sin(angle),0.0));
                                }
                            }
                        }
                    }
        else
            for (unsigned int j = 0,index = 0; j < angle_iteration.size(); ++j)
                for (unsigned int n = 0; n < repeat_num; ++n)
                {
                    if (!check_prog(index,total_size))
                        break;
                    float inner_angle = angle_iteration[j]*M_PI/180.0;
                    float fa2 = fa_value*fa_value;
                    //fa*fa = (r*r-2*r+1)/(r*r+2)
                    float r = (1.0+fa_value*std::sqrt(3-2*fa2))/(1-fa2);
                    float l2 = mean_dif*3.0/(2.0+r);
                    float l1 = r*l2;
                    for (unsigned int y = 0; y < dim[1]; ++y)
                    {
                        for (unsigned int x = 0; x < dim[0]; ++x,++index)
                        {
                            if (x >= boundary &&
                                x < boundary+phantom_width &&
                                y >= boundary &&
                                y < boundary+phantom_width)
                            {
                                if(inner_angle >= 0.0)
                                    models[index] = new MixGaussianModel(l1,l2,mean_dif,inner_angle,0.5,0.5);
                                else
                                    models[index] = new GaussianDispersion(l1,l2,mean_dif,inner_angle,1.0);
                                fa[0][index] = fiber_fraction/2.0;
                                fa[1][index] = fiber_fraction/2.0;
                                gfa[index] = fa_value;
                                findex[0][index] = main_fiber_index;
                                findex[1][index] = ti.discretize(image::vector<3>(std::cos(inner_angle),std::sin(inner_angle),0.0));
                            }
                        }
                    }
                }

        set_title("Generating images");

        std::string fib_file_name(file_name);
        fib_file_name += ".layout.fib";
        gz_mat_write mat_writer(file_name),mat_layout(fib_file_name.c_str());
        // output dimension
        {
            mat_writer.write("dimension",&*dim.begin(),1,3);
            mat_layout.write("dimension",&*dim.begin(),1,3);
        }
        // output vexol size
        {
            float vs[3] = {1.0,1.0,1.0};
            mat_writer.write("voxel_size",vs,1,3);
            mat_layout.write("voxel_size",vs,1,3);
        }
        // output b_table
        {
            std::vector<float> buffer;
            buffer.reserve(bvalues.size()*4);
            for (unsigned int index = 0; index < bvalues.size(); ++index)
            {
                buffer.push_back(bvalues[index]);
                std::copy(bvectors[index].begin(),bvectors[index].end(),std::back_inserter(buffer));
            }
            mat_writer.write("b_table",&*buffer.begin(),4,bvalues.size());
        }
        // output images
        {
            std::vector<short> buffer(models.size());
            begin_prog("generating images");
            for (unsigned int index = 0; check_prog(index,bvectors.size()); ++index)
            {
                for (unsigned int i = 0; i < models.size(); ++i)
                {
                    if (models[i])
                        buffer[i] = encodeNoise((*models[i])(bvalues[index]/1000.0,bvectors[index])*spin_density*0.5); // 0.5 volume of water
                    else
                        buffer[i] = encodeNoise(spin_density*exp(-bvalues[index]*0.0016));
                    // water its coefficient is 0.0016 mm?/s
                }
                std::ostringstream out;
                out << "image" << index;
                mat_writer.write(out.str().c_str(),&*buffer.begin(),1,buffer.size());
            }
        }
        // output layout
        {
            std::vector<float> float_data;
            std::vector<short> short_data;
            ti.save_to_buffer(float_data,short_data);
            mat_layout.write("odf_vertices",&*float_data.begin(),3,ti.vertices_count);
            mat_layout.write("odf_faces",&*short_data.begin(),3,ti.faces.size());
            mat_layout.write("fa0",&*fa[0].begin(),1,fa[0].size());
            mat_layout.write("fa1",&*fa[1].begin(),1,fa[1].size());
            mat_layout.write("gfa",&*gfa.begin(),1,gfa.size());
            mat_layout.write("index0",&*findex[0].begin(),1,findex[0].size());
            mat_layout.write("index1",&*findex[1].begin(),1,findex[1].size());

        }


    }