def remove_bad_particles(st, min_rad='<STR_LIT>', max_rad='<STR_LIT>', min_edge_dist=<NUM_LIT>,<EOL>check_rad_cutoff=[<NUM_LIT>, <NUM_LIT:15>], check_outside_im=True,<EOL>tries=<NUM_LIT:50>, im_change_frac=<NUM_LIT>, **kwargs):
is_near_im_edge = lambda pos, pad: (((pos + st.pad) < pad) | (pos ><EOL>np.array(st.ishape.shape) + st.pad - pad)).any(axis=<NUM_LIT:1>)<EOL>removed = <NUM_LIT:0><EOL>attempts = <NUM_LIT:0><EOL>n_tot_part = st.obj_get_positions().shape[<NUM_LIT:0>]<EOL>q10 = int(<NUM_LIT:0.1> * n_tot_part)  <EOL>r_sig = np.sort(st.obj_get_radii())[q10:-q10].std()<EOL>r_med = np.median(st.obj_get_radii())<EOL>if max_rad == '<STR_LIT>':<EOL><INDENT>max_rad = r_med + <NUM_LIT:15>*r_sig<EOL><DEDENT>if min_rad == '<STR_LIT>':<EOL><INDENT>min_rad = r_med - <NUM_LIT>*r_sig<EOL><DEDENT>if check_rad_cutoff == '<STR_LIT>':<EOL><INDENT>check_rad_cutoff = [r_med - <NUM_LIT>*r_sig, r_med + <NUM_LIT>*r_sig]<EOL><DEDENT>rad_wrong_size = np.nonzero(<EOL>(st.obj_get_radii() < min_rad) | (st.obj_get_radii() > max_rad))[<NUM_LIT:0>]<EOL>near_im_edge = np.nonzero(is_near_im_edge(st.obj_get_positions(),<EOL>min_edge_dist - st.pad))[<NUM_LIT:0>]<EOL>delete_inds = np.unique(np.append(rad_wrong_size, near_im_edge)).tolist()<EOL>delete_poses = st.obj_get_positions()[delete_inds].tolist()<EOL>message = ('<STR_LIT:->'*<NUM_LIT> + '<STR_LIT>' + '<STR_LIT:->'*<NUM_LIT> +<EOL>'<STR_LIT>')<EOL>with log.noformat():<EOL><INDENT>CLOG.info(message)<EOL><DEDENT>for pos in delete_poses:<EOL><INDENT>ind = st.obj_closest_particle(pos)<EOL>old_err = st.error<EOL>p, r = st.obj_remove_particle(ind)<EOL>p = p[<NUM_LIT:0>]<EOL>r = r[<NUM_LIT:0>]<EOL>part_msg = '<STR_LIT>' % (<EOL>tuple(p) + (r,) + (old_err, st.error))<EOL>with log.noformat():<EOL><INDENT>CLOG.info(part_msg)<EOL><DEDENT>removed += <NUM_LIT:1><EOL><DEDENT>check_rad_inds = np.nonzero((st.obj_get_radii() < check_rad_cutoff[<NUM_LIT:0>]) |<EOL>(st.obj_get_radii() > check_rad_cutoff[<NUM_LIT:1>]))[<NUM_LIT:0>]<EOL>if check_outside_im:<EOL><INDENT>check_edge_inds = np.nonzero(<EOL>is_near_im_edge(st.obj_get_positions(), st.pad))[<NUM_LIT:0>]<EOL>check_inds = np.unique(np.append(check_rad_inds, check_edge_inds))<EOL><DEDENT>else:<EOL><INDENT>check_inds = check_rad_inds<EOL><DEDENT>check_inds = check_inds[np.argsort(st.obj_get_radii()[check_inds])]<EOL>tries = np.min([tries, check_inds.size])<EOL>check_poses = st.obj_get_positions()[check_inds[:tries]].copy()<EOL>for pos in check_poses:<EOL><INDENT>old_err = st.error<EOL>ind = st.obj_closest_particle(pos)<EOL>killed, p, r = check_remove_particle(<EOL>st, ind, im_change_frac=im_change_frac)<EOL>if killed:<EOL><INDENT>removed += <NUM_LIT:1><EOL>check_inds[check_inds > ind] -= <NUM_LIT:1>  <EOL>delete_poses.append(pos)<EOL>part_msg = '<STR_LIT>' % (<EOL>p + r + (old_err, st.error))<EOL>with log.noformat():<EOL><INDENT>CLOG.info(part_msg)<EOL><DEDENT><DEDENT><DEDENT>return removed, delete_poses<EOL>
Removes improperly-featured particles from the state, based on a
combination of particle size and the change in error on removal.

Parameters
-----------
st : :class:`peri.states.State`
    The state to remove bad particles from.
min_rad : Float, optional
    All particles with radius below min_rad are automatically deleted.
    Set to 'calc' to make it the median rad - 25* radius std.
    Default is 'calc'.

max_rad : Float, optional
    All particles with radius above max_rad are automatically deleted.
    Set to 'calc' to make it the median rad + 15* radius std.
    Default is 'calc'.

min_edge_dist : Float, optional
    All particles within min_edge_dist of the (padded) image
    edges are automatically deleted. Default is 2.0

check_rad_cutoff : 2-element list of floats, optional
    Particles with radii < check_rad_cutoff[0] or > check_rad_cutoff[1]
    are checked if they should be deleted. Set to 'calc' to make it the
    median rad +- 3.5 * radius std. Default is [3.5, 15].

check_outside_im : Bool, optional
    If True, checks if particles located outside the unpadded image
    should be deleted. Default is True.

tries : Int, optional
    The maximum number of particles with radii < check_rad_cutoff
    to try to remove. Checks in increasing order of radius size.
    Default is 50.

im_change_frac : Float, , optional
    Number between 0 and 1. If removing a particle decreases the
    error by less than im_change_frac*the change in the image, then
    the particle is deleted. Default is 0.2

Returns
-------
removed: Int
    The cumulative number of particles removed.