#include <processor.h>
Inheritance diagram for EMAN::AutoMask3D2Processor:
Public Member Functions | |
virtual void | process_inplace (EMData *image) |
To process an image in-place. | |
virtual string | get_name () const |
Get the processor's name. | |
virtual string | get_desc () const |
Get the descrition of this specific processor. | |
virtual TypeDict | get_param_types () const |
Get processor parameter information in a dictionary. | |
Static Public Member Functions | |
static Processor * | NEW () |
Static Public Attributes | |
static const string | NAME = "mask.auto3d" |
radius | Pixel radius of a ball which is used to seed the flood filling operation | |
threshold | An isosurface threshold that suitably encases the mass | |
nshells | The number of dilation operations | |
nshellsgauss | number of Gaussian pixels to expand, following the dilation operations If true the result of the operation will produce the mask, not the masked volume |
Definition at line 5056 of file processor.h.
virtual string EMAN::AutoMask3D2Processor::get_desc | ( | ) | const [inline, virtual] |
Get the descrition of this specific processor.
This function must be overwritten by a subclass.
Implements EMAN::Processor.
Definition at line 5071 of file processor.h.
05072 { 05073 return "This will mask a 3-D volume using a 'flood filling' approach. It begins with a seed generated either as a sphere with \ 05074 specified 'radius' or with the 'nmaxseed' highest values. It then includes any mass connected to the seed with value higher than 'threshold'.\ 05075 Next, the mask is expanded by 'nshells'+'nshellsgauss'/2 voxels. Finally a gaussian low-pass filter is applied with a width of 'nshellsgauss'."; 05076 }
virtual string EMAN::AutoMask3D2Processor::get_name | ( | ) | const [inline, virtual] |
Get the processor's name.
Each processor is identified by a unique name.
Implements EMAN::Processor.
Definition at line 5061 of file processor.h.
References NAME.
05062 { 05063 return NAME; 05064 }
virtual TypeDict EMAN::AutoMask3D2Processor::get_param_types | ( | ) | const [inline, virtual] |
Get processor parameter information in a dictionary.
Each parameter has one record in the dictionary. Each record contains its name, data-type, and description.
Reimplemented from EMAN::Processor.
Definition at line 5078 of file processor.h.
References EMAN::EMObject::BOOL, EMAN::EMObject::FLOAT, EMAN::EMObject::INT, and EMAN::TypeDict::put().
05079 { 05080 TypeDict d; 05081 d.put("radius", EMObject::INT,"Pixel radius of a ball which is used to seed the flood filling operation. "); 05082 d.put("nmaxseed",EMObject::INT,"Use the n highest valued pixels in the map as a seed. Alternative to radius. Useful for viruses."); 05083 d.put("threshold", EMObject::FLOAT, "An isosurface threshold that suitably encases the mass."); 05084 d.put("sigma", EMObject::FLOAT, "Alternative to threshold based on mean + x*sigma"); 05085 d.put("nshells", EMObject::INT, "Number of 1-voxel shells to expand the mask by."); 05086 d.put("nshellsgauss", EMObject::INT, "Width in voxels of a Gaussian decay at the edge of the mask."); 05087 d.put("return_mask", EMObject::BOOL, "If true the result of the operation will produce the mask, not the masked volume."); 05088 d.put("verbose", EMObject::INT, "How verbose to be (stdout)"); 05089 return d; 05090 }
static Processor* EMAN::AutoMask3D2Processor::NEW | ( | ) | [inline, static] |
Definition at line 5066 of file processor.h.
05067 { 05068 return new AutoMask3D2Processor(); 05069 }
void AutoMask3D2Processor::process_inplace | ( | EMData * | image | ) | [virtual] |
To process an image in-place.
For those processors which can only be processed out-of-place, override this function to just print out some error message to remind user call the out-of-place version.
image | The image to be processed. |
Implements EMAN::Processor.
Definition at line 6607 of file processor.cpp.
References abs, EMAN::EMData::calc_n_highest_locations(), EMAN::EMData::get_attr(), EMAN::EMData::get_data(), EMAN::EMData::get_ndim(), EMAN::EMData::get_size(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), ImageDimensionException, LOGWARN, EMAN::EMData::mult(), EMAN::Processor::params, EMAN::EMData::process_inplace(), EMAN::Dict::set_default(), EMAN::EMData::set_size(), EMAN::EMData::set_value_at(), and EMAN::EMData::update().
06608 { 06609 if (!image) { 06610 LOGWARN("NULL Image"); 06611 return; 06612 } 06613 06614 if (image->get_ndim() != 3) { 06615 throw ImageDimensionException("This processor was only ever designed to work on 3D images."); 06616 } 06617 06618 /* 06619 The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor 06620 To get around this just use the return_mask parameter. 06621 string mask_output = params.set_default("write_mask", ""); 06622 if ( mask_output != "") { 06623 if (Util::is_file_exist(mask_output) ) throw InvalidParameterException("The mask output file name already exists. Please remove it if you don't need it."); 06624 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized"); 06625 } 06626 */ 06627 06628 int radius=0; 06629 if (params.has_key("radius")) { 06630 radius = params["radius"]; 06631 } 06632 int nmaxseed=0; 06633 if (params.has_key("nmaxseed")) { 06634 nmaxseed = params["nmaxseed"]; 06635 } 06636 06637 float threshold=0.0; 06638 if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"]; 06639 else threshold=params["threshold"]; 06640 06641 int nshells = params["nshells"]; 06642 int nshellsgauss = params["nshellsgauss"]; 06643 int verbose=params.set_default("verbose",0); 06644 06645 int nx = image->get_xsize(); 06646 int ny = image->get_ysize(); 06647 int nz = image->get_zsize(); 06648 int nxy=nx*ny; 06649 06650 EMData *amask = new EMData(); 06651 amask->set_size(nx, ny, nz); 06652 06653 float *dat = image->get_data(); 06654 float *dat2 = amask->get_data(); 06655 int i,j,k; 06656 size_t l = 0; 06657 06658 // Seeds with the highest valued pixels 06659 if (nmaxseed>0) { 06660 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed); 06661 06662 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) { 06663 amask->set_value_at((*i).x,(*i).y,(*i).z,1.0); 06664 if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value); 06665 } 06666 } 06667 06668 // Seeds with a sphere 06669 if (radius>0) { 06670 // start with an initial sphere 06671 for (k = -nz / 2; k < nz / 2; ++k) { 06672 for (j = -ny / 2; j < ny / 2; ++j) { 06673 for (i = -nx / 2; i < nx / 2; ++i,++l) { 06674 if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue; 06675 if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue; 06676 dat2[l] = 1.0f; 06677 } 06678 } 06679 } 06680 } 06681 06682 06683 // iteratively 'flood fills' the map... recursion would be better 06684 int done=0; 06685 int iter=0; 06686 while (!done) { 06687 iter++; 06688 done=1; 06689 if (verbose && iter%10==0) printf("%d iterations\n",iter); 06690 for (k=1; k<nz-1; ++k) { 06691 for (j=1; j<ny-1; ++j) { 06692 for (i=1; i<nx-1; ++i) { 06693 l=i+j*nx+k*nx*ny; 06694 if (dat2[l]) continue; 06695 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) { 06696 dat2[l]=1.0; 06697 done=0; 06698 } 06699 } 06700 } 06701 } 06702 } 06703 06704 amask->update(); 06705 06706 if (verbose) printf("expanding mask\n"); 06707 amask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0)); 06708 if (verbose) printf("filtering mask\n"); 06709 amask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss))); 06710 amask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002)); // this makes the value exactly 0 beyond ~2.5 sigma 06711 06712 bool return_mask = params.set_default("return_mask",false); 06713 if (return_mask) { 06714 // Yes there is probably a much more efficient way of getting the mask itself, but I am only providing a stop gap at the moment. 06715 dat = image->get_data(); 06716 dat2 = amask->get_data(); 06717 memcpy(dat,dat2,image->get_size()*sizeof(float)); 06718 } else { 06719 image->mult(*amask); 06720 } 06721 06722 // EMAN2 policy is not to allow file io from with a processor 06723 //if (mask_output != "") { 06724 // amask->write_image(mask_output); 06725 //} 06726 06727 06728 delete amask; 06729 }
const string AutoMask3D2Processor::NAME = "mask.auto3d" [static] |