def test_plot_gates(self): fks = fk.Session(fcs_path) fks.add_sample_group('my_group', gml_path) group_name = 'my_group' sample_name = 'B07' fks.assign_sample(sample_name, group_name) gate_ids = fks.get_gate_ids(group_name) for gate_id in gate_ids: gate = fks.get_gate(group_name, sample_name, gate_id) if isinstance(gate, fk.gates.Quadrant): # cannot plot single quadrants of a quadrant gate continue try: p = fks.plot_gate('my_group', sample_name, gate_id) except NotImplementedError: continue self.assertIsInstance(p, Figure)
def test_plot_gates(self): fks = fk.Session(copy.deepcopy(test_sample)) fks.add_sample_group('my_group', copy.deepcopy(test_gating_strategy)) group_name = 'my_group' sample_name = 'B07' fks.assign_samples(sample_name, group_name) gate_tuples = fks.get_gate_ids(group_name) fks.analyze_samples(group_name, sample_id=sample_name) for gate_name, ancestors in gate_tuples: gate = fks.get_gate(group_name, gate_name, sample_id=sample_name) if isinstance(gate, fk.gates.Quadrant): # cannot plot single quadrants of a quadrant gate continue try: p = fks.plot_gate('my_group', sample_name, gate_name) except NotImplementedError: continue self.assertIsInstance(p, bk_Figure)
def test_plot_gated_scatter(self): fks = fk.Session(fcs_path) fks.add_sample_group('my_group', gml_path) group_name = 'my_group' sample_name = 'B07' fks.assign_sample(sample_name, group_name) x_dim = fk.Dimension('FL2-H', compensation_ref='MySpill', transformation_ref='Logicle_10000_0.5_4.5_0') y_dim = fk.Dimension('FL3-H', compensation_ref='MySpill', transformation_ref='Logicle_10000_0.5_4.5_0') p = fks.plot_scatter(sample_name, x_dim, y_dim, sample_group=group_name, gate_id='ScaleRect1') self.assertIsInstance(p, Figure)
def test_plot_gated_scatter(self): fks = fk.Session(copy.deepcopy(test_sample)) fks.add_sample_group('my_group', copy.deepcopy(test_gating_strategy)) group_name = 'my_group' sample_name = 'B07' fks.assign_samples(sample_name, group_name) fks.analyze_samples(group_name, sample_id=sample_name) x_dim = fk.Dimension('FL2-H', compensation_ref='MySpill', transformation_ref='Logicle_10000_0.5_4.5_0') y_dim = fk.Dimension('FL3-H', compensation_ref='MySpill', transformation_ref='Logicle_10000_0.5_4.5_0') p = fks.plot_scatter( sample_name, x_dim, y_dim, group_name=group_name, gate_name='ScaleRect1', subsample=True ) self.assertIsInstance(p, bk_Figure)
def extract_gated_data(output_dir, wsp_file, fcs_dir, sample_group, event_columns=None, exclude_samples=None, verbose=False): """ Extracts pre-processed event data and gate membership for each of the FCS files referenced in given FlowJo10 workspace file (wsp file). Both event and gate membership data are saved as Feather files to the provided output directory. Two subdirectories, 'events' and 'gates', will be created in the output directory where 2 Feather files will be created for each FCS file, one in the 'events' directory (prepended with 'events_') and one in the 'gates' directory (prepended with 'gates_'). :param output_dir: File path location for output Feather files :param wsp_file: File path of FlowJo 10 workspace (wsp file) :param fcs_dir: Directory path containing FCS files :param sample_group: Sample group label within the WSP file from which gated events and gate membership data will be extracted :param event_columns: List of channels/markers to include in the preprocessed event data. If None, all channels are exported. :param exclude_samples: List of FCS sample IDs to exclude from export :param verbose: If True, prints various issues found when parsing the workspace and FCS files (missing FCS files, missing channel columns, missing gates, and output array shapes) :return: None """ fs = fk.Session() fs.import_flowjo_workspace(wsp_file, ignore_missing_files=True) # find FCS files in given fcs_dir fcs_files = [f for f in os.listdir(fcs_dir) if re.search(r'.*\.fcs$', f)] sample_ids = fs.get_group_sample_ids(sample_group, loaded_only=False) events_dir = os.path.join(output_dir, 'events') gates_dir = os.path.join(output_dir, 'gates') os.makedirs(output_dir, exist_ok=True) os.makedirs(events_dir, exist_ok=True) os.makedirs(gates_dir, exist_ok=True) sample_paths_to_load = [] samples_to_process = [] for f in sample_ids: if f in exclude_samples: continue if f not in fcs_files and verbose: print('%s not found in our list' % f) sample_paths_to_load.append(os.path.join(fcs_dir, f)) samples_to_process.append(f) fs.add_samples(sample_paths_to_load) fs.analyze_samples(sample_group) for sample_id in samples_to_process: # extract all processed events using gate ID as None events_df = fs.get_wsp_gated_events(sample_group, [sample_id], gate_name=None, gate_path=None)[0] if event_columns: try: events_df = events_df[event_columns] except KeyError: print(f'Sample to exclude: {sample_id}') continue # now get gate membership for all gates & all events gates_df = pd.DataFrame() gate_ids = fs.get_gate_ids(sample_group) for gate_name, gate_path in gate_ids: try: s_gate_membership = fs.get_gate_membership(sample_group, sample_id, gate_name=gate_name, gate_path=gate_path) gates_df['/'.join([*gate_path, gate_name])] = s_gate_membership except KeyError: if verbose: print("Gate %s (%s) not found in sample group" % (gate_name, gate_path)) # add sample_id field to gate DataFrame & put it first gates_df['sample_id'] = sample_id sample_id_col = gates_df.pop('sample_id') gates_df.insert(0, sample_id_col.name, sample_id_col) # save events_df & gates_df to feather here sample_feather_basename = sample_id.replace('fcs', 'feather') events_filename = "events_" + sample_feather_basename gates_filename = "gates_" + sample_feather_basename events_path = os.path.join(events_dir, events_filename) gates_path = os.path.join(gates_dir, gates_filename) if not os.path.exists(events_path): events_df.reset_index(drop=True, inplace=True) events_df.to_feather(events_path) print(events_df.shape) if not os.path.exists(gates_path): gates_df.reset_index(drop=True, inplace=True) gates_df.to_feather(gates_path) print(gates_df.shape)