| Bsoft 2.0.5 Bernard's software package

bmask.cpp
Go to the documentation of this file.
1
9 #include "rwimg.h"
10 #include "symmetry.h"
11 #include "options.h"
12 #include "utilities.h"
13 #include "timer.h"
14
15 // Declaration of global variables
16 extern int verbose; // Level of output to the screen
17
18 // Usage assistance
19 const char* use[] = {
20 " ",
21 "Usage: bmask [options] input.img output.img",
22 "-------------------------------------------",
23 "Generates and uses binary masks of the size given or of the input image.",
24 "The selected regions have value 1 and the omitted regions 0.",
25 "The default is a blank mask created of the same size as the input image.",
26 " ",
27 "Actions for mask creation:",
28 "-create 20,60,30 Create a new mask of this size in place of input image",
29 "-threshold -0.55,1.2 One or more thresholds to generate a mask.",
30 "-variance 5,1 Generate mask based on local variance in a kernel of a given size,",
31 " and flag to generate a background with value -1.",
32 " ",
33 "Actions for mask modification:",
34 "-invert Invert mask.",
35 //"-operation xor Binary operation for mask modifications: replace/and/or/xor (default replace).",
36 "-dilate 2 Dilate mask a number of times.",
37 "-erode 3 Erode mask a number of times.",
38 "-open 4 Open (erode-dilate) mask a number of times.",
39 "-close 2 Close (dilate-erode) mask a number of times.",
40 "-hole 3,56,23 Fill a hole indicated by the voxel.",
41 "-plane 0.3,0.5,-0.1,0,3,25 Mask on one side of a plane with the given normal and origin.",
42 "-rectangle 40,20,45 Rectangular mask with given length, width and rotation angle.",
43 "-radius 10,45 Generate a mask inside these radii.",
44 "-asu D3 Generate an asymmetric unit mask.",
45 "-color size Generate a RGBA image (random/size).",
46 "-size Convert level mask to region size map.",
47 " ",
48 "Actions for multi-level masks:",
49 "-collapse Convert a multi-level mask to a binary mask.",
50 "-select 1,5-7 Select levels in a multi-level mask.",
51 "-voxel 23,241,193 Select the level including this voxel.",
52 "-level 134 Convert a mask to multiple levels, with the given voxels per level.",
53 "-bands 250,-1,150,1,30,0 Banded mask for reciprocal space (pairs of numbers: angstrom,value).",
54 " Band with 0: Not used.",
55 " Band with 1: Use for orientation determination.",
56 " Band with -1: Use for cross-validation.",
57 " ",
58 "Actions for mask application:",
59 "-apply Apply the mask to the input image (default output mask).",
60 "-rescaleapply 0.5,2.3 Rescale region inside mask and apply the mask to the input image.",
61 " ",
62 "Parameters:",
63 "-verbose 1 Verbosity of output.",
64 "-datatype u Force writing of a new data type.",
65 "-sampling 1.5,1.5,1.5 Sampling (A/pixel; a single value can be given).",
66 "-origin 110,50,44 Origin for the mask (default from input image).",
67 "-fill 28.3 Fill value (default average).",
68 "-wrap Flag to wrap around image boundaries (default not).",
69 " ",
70 "Input:",
71 "-Mask file.img Input mask to apply or get difference with main input image.",
72 " ",
73 "Examples:",
74 "1. Creating a new mask:",
75 " bmask -v 7 -create 100,100,50 -radius 10,20 -origin 50,50,25 mask.mrc",
76 " ",
77 "2. Generating a mask from an image:",
78 " bmask -v 7 -threshold 1.5 test.map mask.mrc",
79 " ",
80 "3. Applying a mask to an image:",
81 " bmask -v 7 -Mask mask.mrc test.map new.map",
82 " ",
83 "4. Generating and applying a mask to an image:",
84 " bmask -v 7 -apply -radius 50,80 -origin 100,100,100 test.map new.map",
85 " ",
86 NULL
87 };
88
89 int main(int argc, char **argv)
90 {
91 // Initialize variables
92 DataType nudatatype(Unknown_Type); // Conversion to new type
93 Vector3<double> sam; // Units for the three axes (A/pixel)
94 int invert(0); // Inversion flag
95 // int operation(0); // Default operation is and
96 Vector3<long> nusize; // Size of new mask
97 vector<double> threshold; // Threshold array
98 int var_kernel(0); // Variance filter kernel size
99 int bgk_flag(0); // Low variance threshold
100 double rect_length(0); // Rectangular mask length
101 double rect_width(0); // Rectangular mask width
102 double rect_angle(0); // Rectangular mask rotation angle
103 double rad_min(0); // Minimum radius
104 double rad_max(0); // Maximum radius, not used if 0
105 Bsymmetry* asu_sym = NULL; // Asymmetric unit mask symmmetry
106 Vector3<double> origin; // Mask origin
107 Vector3<double> plane_origin; // Point on plane
108 Vector3<double> plane_normal; // Plane normal
109 int set_origin(0); // Flag to set origin
110 int wrap(0); // Flag to wrap
111 int apply_flag(0); // Flag to apply mask
112 double nuavg(0), nustd(0); // Rescaling to average and stdev
113 int dilate(0); // Number of times to dilate
114 int erode(0); // Number of times to erode
115 int open(0); // Number of times to open
116 int close(0); // Number of times to close
117 Vector3<long> fill_voxel; // Voxel to fill from
118 Bstring color; // Generate RGBA image: random or size-based colors
119 int convert_size(0); // Flag to cenvert level mask to region size
120 int collapse(0); // Collapse a multi-level mask to a binary mask
121 Bstring level_select; // Selection of levels
122 Vector3<long> voxel(-1,0,0); // Voxel to select a level
123 int level(0); // Number of voxels per level
124 vector<double> band; // Reciprocal space bands
125 int fill_type(FILL_AVERAGE); // Use average
126 double fill(0); // Default fill is average
127 Bstring mask_file; // Mask file
128
129 int optind;
130 Boption* option = get_option_list(use, argc, argv, optind);
131 Boption* curropt;
132 for ( curropt = option; curropt; curropt = curropt->next ) {
133 if ( curropt->tag == "create" )
134 nusize = curropt->size();
135 if ( curropt->tag == "datatype" )
136 nudatatype = curropt->datatype();
137 if ( curropt->tag == "sampling" )
138 sam = curropt->sampling();
139 if ( curropt->tag == "threshold" ) {
140 threshold = curropt->value.split_into_doubles(",");
141 if ( threshold.size() < 1 )
142 cerr << "-threshold: At least one threshold must be specified!" << endl;
143 }
144 if ( curropt->tag == "variance" )
145 if ( curropt->values(var_kernel, bgk_flag) < 1 )
146 cerr << "-variance: The kernel edge size must be specified!" << endl;
147 if ( curropt->tag == "plane" )
148 if ( curropt->box(plane_normal, plane_origin) < 3 )
149 cerr << "-plane: The plane normal must be specified" << endl;
150 if ( curropt->tag == "rectangle" ) {
151 if ( curropt->values(rect_length, rect_width, rect_angle) < 2 )
152 cerr << "-rectangle: Both length and width must be specified" << endl;
153 rect_angle *= M_PI/180.0;
154 }
155 if ( curropt->tag == "radius" )
156 if ( curropt->values(rad_min, rad_max) < 2 )
157 cerr << "-radius: Both radii must be specified" << endl;
158 if ( curropt->tag == "asu" )
159 asu_sym = curropt->symmetry();
160 if ( curropt->tag == "origin" ) {
161 if ( curropt->value[0] == 'c' ) {
162 set_origin = 2;
163 } else {
164 origin = curropt->origin();
165 set_origin = 1;
166 }
167 }
168 if ( curropt->tag == "fill" )
169 fill = curropt->fill(fill_type);
170 if ( curropt->tag == "wrap" )
171 wrap = 1;
172 if ( curropt->tag == "apply" )
173 apply_flag = 1;
174 if ( curropt->tag == "rescaleapply" )
175 if ( curropt->values(nuavg, nustd) < 2 )
176 cerr << "-rescaleapply: Both average and standard deviation must be specified!" << endl;
177 if ( curropt->tag == "invert" )
178 invert = 1;
179 /* if ( curropt->tag == "operation" ) {
180 if ( curropt->value.contains("xor") ) operation = 3;
181 else if ( curropt->value.contains("or") ) operation = 2;
182 else if ( curropt->value.contains("and") ) operation = 1;
183 else operation = 0;
184 }*/
185 if ( curropt->tag == "dilate" )
186 if ( ( dilate = curropt->value.integer() ) < 1 )
187 cerr << "-dilate: A number of times to dilate must be specified!" << endl;
188 if ( curropt->tag == "erode" )
189 if ( ( erode = curropt->value.integer() ) < 1 )
190 cerr << "-erode: A number of times to erode must be specified!" << endl;
191 if ( curropt->tag == "open" )
192 if ( ( open = curropt->value.integer() ) < 1 )
193 cerr << "-open: A number of times to open must be specified!" << endl;
194 if ( curropt->tag == "close" )
195 if ( ( close = curropt->value.integer() ) < 1 )
196 cerr << "-close: A number of times to close must be specified!" << endl;
197 if ( curropt->tag == "hole" )
198 if ( curropt->values(fill_voxel[0], fill_voxel[1], fill_voxel[2]) < 3 )
199 cerr << "-hole: A voxel must be specified!" << endl;
200 if ( curropt->tag == "color" )
201 color = curropt->value;
202 if ( curropt->tag == "size" )
203 convert_size = 1;
204 if ( curropt->tag == "collapse" )
205 collapse = 1;
206 if ( curropt->tag == "select" ) {
207 level_select = curropt->value;
208 if ( level_select.length() < 1 )
209 cerr << "-select: Level numbers must be specified!" << endl;
210 }
211 if ( curropt->tag == "voxel" )
212 if ( curropt->values(voxel[0], voxel[1], voxel[2]) < 3 )
213 cerr << "-voxel: A voxel must be specified!" << endl;
214 if ( curropt->tag == "level" )
215 if ( ( level = curropt->value.integer() ) < 1 )
216 cerr << "-level: The voxels per level must be specified!" << endl;
217 if ( curropt->tag == "bands" ) {
218 band = curropt->value.split_into_doubles(",");
219 if ( band.size() < 2 )
220 cerr << "-bands: At least two pairs of numbers must be specified!" << endl;
221 band[band.size()] = 0;
222 }
223 if ( curropt->tag == "Mask" )
224 mask_file = curropt->filename();
225 }
226 option_kill(option);
227
228 double ti = timer_start();
229
230 Bimage* p = NULL;
231 Bimage* pmask = NULL;
232 if ( nusize.volume() > 0 ) { // Create the mask in place of an input image
233 if ( verbose & VERB_PROCESS )
234 cout << "Creating a mask of size: " << nusize << endl;
235 if ( nudatatype == Unknown_Type ) nudatatype = UCharacter;
236 pmask = new Bimage(nudatatype, TSimple, nusize, 1);
237 if ( set_origin ) {
238 if ( set_origin == 2 ) origin = pmask->default_origin();
239 pmask->origin(origin);
240 }
241 // operation = 0; // Default operation is replace
242 pmask->fill(fill);
243 } else {
244 p = read_img(argv[optind++], 1, -1);
245 if ( p == NULL ) bexit(-1);
246 if ( set_origin ) {
247 if ( set_origin == 2 ) origin = p->default_origin();
248 p->origin(origin);
249 }
250 if ( sam.volume() > 0 ) p->sampling(sam);
251 if ( fill_type == FILL_AVERAGE ) fill = p->average();
252 if ( fill_type == FILL_BACKGROUND ) fill = p->background(long(0));
253 }
254
255 if ( !pmask ) { // Generate the mask from other sources
256 if ( mask_file.length() ) {
257 pmask = read_img(mask_file, 1, -1);
258 if ( pmask == NULL ) bexit(-1);
259 apply_flag = 1;
260 } else if ( threshold.size() > 0 ) {
261 pmask = p->mask_by_thresholds(threshold);
262 } else if ( var_kernel > 2 ) {
263 pmask = p->variance_mask(var_kernel, 1e-6, bgk_flag);
264 } else {
265 pmask = p->copy();
266 }
267 }
268
269 if ( level_select.length() ) pmask->levelmask_select(level_select);
270
271 if ( voxel[0] >= 0 ) pmask->levelmask_select(0, voxel);
272
273 if ( collapse ) pmask->levelmask_collapse();
274
275 if ( sam.volume() > 0 ) pmask->sampling(sam);
276
277 if ( plane_normal.length() > 0 )
278 pmask->mask_plane(plane_origin, plane_normal);
279
280 if ( rect_length*rect_width > 0 )
281 pmask->mask_rectangle(rect_length, rect_width, rect_angle, wrap);
282
283 if ( rad_max )
284 pmask->mask_shell(origin, rad_min, rad_max);
285
286 if ( band.size() && band[0] )
287 pmask->mask_fspace_banded(band);
288
289 Bimage* psymmask = NULL;
290 if ( asu_sym ) {
291 psymmask = pmask->levelmask_asymmetric_units(asu_sym, 1);
292 pmask->multiply(psymmask);
293 kill_symmetry(asu_sym);
294 delete psymmask;
295 }
296
297 if ( dilate > 0 )
298 pmask->mask_dilate(dilate);
299
300 if ( erode > 0 )
301 pmask->mask_erode(erode);
302
303 if ( open > 0 )
304 pmask->mask_open(open);
305
306 if ( close > 0 )
307 pmask->mask_close(close);
308
309 if ( fill_voxel.length() )
310 pmask->mask_fill(fill_voxel);
311
312 if ( invert ) pmask->mask_invert();
313
314 if ( p ) {
315 if ( nustd > 0 ) {
316 p->rescale_to_avg_std(nuavg, nustd, pmask);
317 p->multiply(pmask);
318 } else if ( apply_flag ) {
319 p->mask(pmask, fill); // For output of image
320 } else {
321 delete p;
322 p = pmask; // For output of mask
323 }
324 } else {
325 p = pmask; // For output of mask
326 }
327
328 if ( level ) pmask->mask_split(level);
329
330 if ( color.length() ) {
331 if ( color[0] == 'r' ) pmask->simple_to_rgba();
332 else if ( color[0] == 's' ) p = pmask->levelmask_color_by_size();
333 } else if ( convert_size ) pmask->levelmask_region_size();
334
335 pmask->mask_stats();
336
337 if ( optind < argc ) {
338 p->change_type(nudatatype);
339 p->label(get_cmd_line(argc, argv));
340 write_img(argv[optind], p, 0);
341 }
342
343 if ( p != pmask ) delete pmask;
344 delete p;
345
346 if ( verbose & VERB_TIME )
347 timer_report(ti);
348
349 bexit(0);
350 }
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
Bimage::mask
long mask(Bimage *pmask, double fill)
Masks an image.
Definition: Bimage_mask.cpp:26
Boption::fill
double fill(int &fill_type)
Definition: options.h:138
FILL_BACKGROUND
#define FILL_BACKGROUND
Definition: utilities.h:174
DataType
DataType
Base data type specifier.
Definition: utilities.h:146
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
Vector3::length
double length()
Definition: Vector3.h:222
symmetry.h
Header file for general symmetry functions.
Bimage::mask_stats
long mask_stats()
Calculates statistics for a mask.
Definition: Bimage_mask.cpp:165
Bimage::levelmask_region_size
int levelmask_region_size()
Convert a mask to reflect region sizes.
Definition: Bimage_mask.cpp:1981
utilities.h
Header file for general utilities.
Boption::sampling
Vector3< double > sampling()
Definition: options.h:202
Boption::value
Bstring value
Definition: options.h:30
Boption::tag
Bstring tag
Definition: options.h:29
Bimage::mask_invert
long mask_invert()
Inverts a mask.
Definition: Bimage_mask.cpp:221
FILL_AVERAGE
#define FILL_AVERAGE
Definition: utilities.h:173
Bstring::length
long length() const
Definition: Bstring.cpp:263
Bimage::mask_fspace_banded
int mask_fspace_banded(vector< double > &band)
Generate reciprocal space mask based on a specification of bands.
Definition: Bimage_mask.cpp:814
kill_symmetry
int kill_symmetry(Bsymmetry *sym)
Deallocates a symmetry structure.
Definition: symmetry.cpp:207
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
use
const char * use[]
Definition: bmask.cpp:19
Bimage::multiply
void multiply(long j, Complex< double > cv)
Definition: Bimage.h:312
get_option_list
Boption * get_option_list(const char *use[], int argc, char *argv[], int &optind)
Parses command line arguments based on a template.
Definition: options.cpp:40
read_img
Bimage * read_img(char *filename, int readdata, int img_select)
General driver function to read multiple image formats.
Definition: rwimg.cpp:76
get_cmd_line
string get_cmd_line(int argc, char **argv)
Returns the command line as a string.
Definition: utilities.cpp:36
Boption::filename
Bstring filename()
Definition: options.h:85
Bimage::mask_shell
long mask_shell(Vector3< double > origin, double rad_min, double rad_max)
Definition: Bimage.h:1314
TSimple
Definition: Bimage.h:58
timer.h
Utilities for timing functions.
Bimage::levelmask_collapse
long levelmask_collapse()
Collapse a multi-level mask to a binary mask.
Definition: Bimage_mask.cpp:1503
Bimage
General image parameter class.
Definition: Bimage.h:163
Boption::size
Vector3< long > size()
Definition: options.h:163
Bimage::mask_open
long mask_open(int times=1)
Opens a binary mask.
Definition: Bimage_mask.cpp:462
M_PI
#define M_PI
Definition: utilities.h:59
Boption::box
long box(Vector3< T1 > &st, Vector3< T2 > &sz)
Definition: options.h:214
Boption
A class for a command line input option.
Definition: options.h:26
Bimage::label
void label(string s)
Definition: Bimage.h:235
verbose
int verbose
VERB_TIME
#define VERB_TIME
Definition: utilities.h:110
Bimage::rescale_to_avg_std
int rescale_to_avg_std(double nuavg, double nustd)
Rescales the image data to a given average and standard deviation.
Definition: Bimage_rescale.cpp:163
Boption::symmetry
Bsymmetry * symmetry()
Definition: options.h:252
Bimage::levelmask_select
long levelmask_select(Bstring &select_list)
Retains the selected levels in a multi-level mask.
Definition: Bimage_mask.cpp:1650
write_img
int write_img(const char *filename, Bimage *p, int compression)
General driver function to write multiple image formats.
Definition: rwimg.cpp:280
Bimage::variance_mask
Bimage * variance_mask(long kernel_size, double lowvar=1e-6, int bkg_flag=0)
Calculates a mask based on local variance.
Definition: Bimage_mask.cpp:1367
level
size_t level(0)
Bimage::mask_rectangle
long mask_rectangle(double length, double width, double rect_angle, int wrap)
Generates a mask along an axis within a 2D image.
Definition: Bimage_mask.cpp:569
Bstring::split_into_doubles
vector< double > split_into_doubles(const Bstring &delim)
Definition: Bstring.cpp:665
Bimage::mask_split
long mask_split(long voxels_per_level)
Converts a mask to a multilevel mask with a given number of voxels per level.
Definition: Bimage_mask.cpp:1453
Bsymmetry
Definition: symmetry.h:38
Bimage::levelmask_color_by_size
Bimage * levelmask_color_by_size()
Color a multi-level mask based on the volumes of regions.
Definition: Bimage_mask.cpp:1924
Boption::datatype
DataType datatype()
Definition: options.h:93
Boption::next
Boption * next
Definition: options.h:28
Bimage::levelmask_asymmetric_units
Bimage * levelmask_asymmetric_units(Bsymmetry *sym, int index)
Calculates a multi-level mask to indicate asymmetric units.
Definition: Bimage_symmetry.cpp:898
UCharacter
Definition: utilities.h:149
Bstring
Definition: Bstring.h:29
Bimage::copy
Bimage * copy()
Copies the header information and data of an image into a new image structure.
Definition: Bimage.cpp:2695
Bimage::default_origin
Vector3< double > default_origin()
Definition: Bimage.h:585
Bimage::mask_fill
long mask_fill(Vector3< long > voxel)
Fills an empty part of a mask indicated by the given voxel.
Definition: Bimage_mask.cpp:500
Bimage::mask_erode
long mask_erode(long times=1)
Erodes a binary mask.
Definition: Bimage_mask.cpp:444
Vector3< double >
Boption::origin
Vector3< double > origin()
Definition: options.h:180
timer_report
double timer_report(double lasttime)
Reports the time elapsed since a given time.
Definition: timer.cpp:67
Bimage::mask_dilate
long mask_dilate(long times=1)
Dilates a binary mask.
Definition: Bimage_mask.cpp:424
Bimage::mask_close
long mask_close(int times=1)
Closes a binary mask.
Definition: Bimage_mask.cpp:482
option_kill
int option_kill(Boption *option)
Deallocates a linked list of option structures.
Definition: options.cpp:109
Bstring::integer
long integer()
Definition: Bstring.cpp:539
Bimage::average
double average(long cc, double xf, double yf, double zf, long nn, double iscale)
Averages in 3D when scaling is less than 1.
Definition: Bimage.cpp:1349
Unknown_Type
Definition: utilities.h:147
rwimg.h
Header file for 2D and 3D image I/O.
options.h
Header file for option handlers.
Bimage::fill
void fill(double v)
Definition: Bimage.h:698
Vector3::volume
double volume()
Definition: Vector3.h:235
Bimage::background
double background(long nn)
Definition: Bimage.h:542
Bimage::mask_plane
long mask_plane(Vector3< double > origin, Vector3< double > normal)
Generates a mask on one side of a plane.
Definition: Bimage_mask.cpp:514
Boption::values
long values(T1 &v1, T2 &v2)
Definition: options.h:115
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
timer_start
double timer_start()
Starts timer and prints the time.
Definition: timer.cpp:52
Bimage::origin
void origin(double ox, double oy, double oz)
Definition: Bimage.h:563
Bimage::mask_by_thresholds
Bimage * mask_by_thresholds(vector< double > threshold)
Generates a mask based on an image at a given threshold.
Definition: Bimage_mask.cpp:129
Bimage::simple_to_rgba
void simple_to_rgba()
A simple image is converted to a color image.
Definition: Bimage_color.cpp:58
main
int main(int argc, char **argv)
Definition: bmask.cpp:89