def gen_crypt_masks(exp, input_run_type, run_type): """Generate crypt masks based on nuclei density and EdU count Args: exp (string): name of experiment input_run_type (str): cellprofiler pipeline output to use (merged, etc) run_type (str): name for current process ('crypt_mask') Returns: None """ # get file paths nuc_objs_dir = config.get_cp_output_nuc_objs(exp, input_run_type) for nuc_path in helpers.list_im_files(nuc_objs_dir): # paths im_name = config.get_im_name(nuc_path) csv_path = config.get_extract_csv_nuc_outpath(exp, input_run_type, im_name) # read in image nuc_im = cv2.imread(nuc_path, cv2.IMREAD_ANYDEPTH) # dense nuclei kn_size = config.get_crypt_finder_dilate_kn_size('crypt_masks') min_area = config.get_crypt_finder_min_area('crypt_masks') nuc_dense, label_mask = dense_objects(nuc_im, kernel_size=kn_size, min_area=min_area) # filter by edu edu_thresh = expinfo.get_thresh_edu(exp) min_edu_num = config.get_crypt_finder_min_edu_num(run_type) im_data = pd.read_csv(csv_path) edu_pos_objs = thresh_edu_objects(im_data, edu_thresh) nuc_crypt = filter_crypts(nuc_dense, label_mask, edu_pos_objs, min_edu_num) # give nuclei in same crypt the same label nuc_labeled = label_mask.copy() nuc_labeled[nuc_crypt==0] = 0 # convex hull on crypts # crypt_mask = chull_groups(nuc_labeled) # save images objs_fname = config.get_fpath_crypt_objs(exp, input_run_type, im_name) cv2.imwrite(objs_fname, nuc_crypt) label_fname = config.get_fpath_crypt_labels(exp, input_run_type, im_name) cv2.imwrite(label_fname, nuc_labeled)
def measure_props_no_paneth(exp, run_type, drop=False): """Measure properties for all wells in a plate Args: exp (str): plate name run_type (str): analysis output to use for measurements drop (bool): whether to drop frames Returns: None """ # measurement names crypt_measures = ['num_cells', 'num_edu', 'nuc_area', 'eccentricity', 'solidity', 'row', 'col', 'fld'] well_num_measures = ['num_cells', 'num_edu', 'num_crypt_cells', 'num_crypt_edu', 'num_villus_cells', 'num_villus_edu'] well_measures = well_num_measures + ['avg_eccentricity', 'avg_solidity', 'num_crypts'] # output directories crypt_dir = config.get_cp_output_crypt_measure(exp, run_type) well_dir = config.get_cp_output_well_measure(exp, run_type) # create output directories if not os.path.exists(crypt_dir): os.makedirs(crypt_dir) if not os.path.exists(well_dir): os.makedirs(well_dir) rows = constants.get_96_rows() cols = constants.get_96_cols() if drop: im_csv_path = config.get_extract_csv_im_drop_inpath(exp, run_type) # label drop_label = config.get_csv_drop_label() # matrices of well-level measurements well_mats = {k: np.zeros((len(rows), len(cols))) for k in well_measures} for r, row in enumerate(rows): for c, col in enumerate(cols): # store crypt-level measurements crypt_props = {k: [] for k in crypt_measures} # store well-level measurements well_nums = {k: [] for k in well_num_measures} # iterate over fields num_flds = expinfo.get_num_fields(exp) start = expinfo.get_field_start(exp) for fld in list(range(start, num_flds+start, 1)): im_name = config.build_im_name(exp, row, col, fld, 'dna') objs_path = config.get_fpath_crypt_objs(exp, run_type, im_name) label_path = config.get_fpath_crypt_labels(exp, run_type, im_name) im_data_path = config.get_extract_csv_nuc_outpath(exp, run_type, im_name) crypt_objs = cv2.imread(objs_path, cv2.IMREAD_ANYDEPTH) label_mask = cv2.imread(label_path, cv2.IMREAD_ANYDEPTH) im_data = pd.read_csv(im_data_path) edu_thresh = expinfo.get_thresh_edu(exp) edu_objs = thresh_edu_objects(im_data, edu_thresh) # crypt-level measurements crypt_props = measure_crypts_props_no_paneth(crypt_objs, label_mask, edu_objs, crypt_props, row, col, fld) # well-level measurements well_props = { 'num_cells': len(im_data), 'num_edu': len(edu_objs), 'num_crypt_cells': len(nonzero_unique(crypt_objs)), 'num_crypt_edu': count_stained_objs(crypt_objs, edu_objs), 'row': row, 'col': col, 'fld': fld } well_props.update({ 'num_villus_cells': well_props['num_cells'] - well_props['num_crypt_cells'], 'num_villus_edu': well_props['num_edu'] - well_props['num_crypt_edu'] }) for k in list(well_nums.keys()): well_nums[k].append(well_props[k]) for k in list(well_nums.keys()): well_nums[k].append(well_props[k]) # save well-level measurements for k in well_num_measures: well_mats[k][r][c] = np.sum(well_nums[k]) well_mats['avg_eccentricity'][r][c] = np.mean(crypt_props['eccentricity']) well_mats['avg_solidity'][r][c] = np.mean(crypt_props['solidity']) well_mats['num_crypts'][r][c] = len(crypt_props['num_cells']) # write crypt-level measurements to file well_name = config.build_well_name(row, col) out_path = config.get_fpath_crypt_measure(exp, run_type, well_name) helpers.dict_to_csv(out_path, crypt_props) # write well-level measurements to file for k in list(well_mats.keys()): out_path = config.get_fpath_well_measure(exp, run_type, k) np.savetxt(out_path, well_mats[k], delimiter=',')
def measure_dispersion(exp, run_type, drop=False): """Measure properties for all wells in a plate Args: exp (str): plate name run_type (str): analysis output to use for measurements drop (bool): whether to drop frames Returns: None """ # output directories well_dir = config.get_cp_output_well_measure(exp, run_type) # create output directories if not os.path.exists(well_dir): os.makedirs(well_dir) rows = constants.get_96_rows() cols = constants.get_96_cols() if drop: im_csv_path = config.get_extract_csv_im_drop_inpath(exp, run_type) # label drop_label = config.get_csv_drop_label() rows = ['A', 'B', 'C', 'D'] cols = [1,2, 5] # measurement names well_disp = pd.DataFrame() for r, row in enumerate(rows): for c, col in enumerate(cols): # wellname well_name = config.build_well_name(row, col) # store crypt-level measurements crypt_disp = [] # iterate over fields num_flds = expinfo.get_num_fields(exp) start = expinfo.get_field_start(exp) for fld in list(range(start, num_flds+start, 1)): im_name = config.build_im_name(exp, row, col, fld, 'dna') objs_path = config.get_fpath_crypt_objs(exp, run_type, im_name) label_path = config.get_fpath_crypt_labels(exp, run_type, im_name) im_data_path = config.get_extract_csv_nuc_outpath(exp, run_type, im_name) crypt_objs = cv2.imread(objs_path, cv2.IMREAD_ANYDEPTH) label_mask = cv2.imread(label_path, cv2.IMREAD_ANYDEPTH) im_data = pd.read_csv(im_data_path) edu_thresh = expinfo.get_thresh_edu(exp) edu_objs = thresh_edu_objects(im_data, edu_thresh) # list of crypt labels crypt_labels = nonzero_unique(label_mask) for l in crypt_labels: # measure properties for one crypt crypt_mask = get_object(label_mask, l) objs = mask_objects(crypt_objs, crypt_mask, mask_val=l) # add properties to dataframe edu_dist = measure_objs_dispersion(objs, edu_objs) # add data to dataframe if edu_dist is not None: crypt_disp = pd.DataFrame([{'d_nn': d, 'crypt_num': l, 'well': well_name} for d in edu_dist]) well_disp = well_disp.append(crypt_disp) out_path = config.get_fpath_well_measure(exp, run_type, 'edu_dispersion') well_disp.to_csv(out_path, index=False) print(out_path)