Boolean Combinations of Gates
This notebook demonstrates how to make a set of Boolean gates from a set of gates that define positive populations. For example, consider we have positive populations for 3 markers: A, B, and C. The goal is to get the set of all 2**3 combinations:
A+ B+ C+
A- B+ C+
A+ B- C+
A+ B+ C-
A- B- C+
A- B+ C-
A+ B- C-
A- B- C-
We’ll do this using 2 different methods. First, using BooleanGate objects within a Session. And, since FlowKit Workspace objects are read-only, we’ll extract the Boolean gate membership arrays from the analyzed results and perform the operations on those arrays directly.
[1]:
import itertools
import os
import pickle
import numpy as np
import pandas as pd
import flowkit as fk
%matplotlib inline
Session method using BooleanGate objects
[2]:
base_dir = "../../../data/8_color_data_set"
sample_path = os.path.join(base_dir, "fcs_files")
session_path = os.path.join(base_dir, "8_color_ICS_session.pkl")
Import previous Session (see replicate-flowjo-wsp.ipynb)
In a previous tutorial we programmatically built a gating strategy using the Session class. We’ll use that gate tree here to make a set of Boolean gates for the set of cytokine populations.
[3]:
with open(session_path, 'rb') as f:
session = pickle.load(f)
Preview loaded Sample IDs & gate tree
[4]:
sample_ids = sorted(session.get_sample_ids())
[5]:
sample_ids
[5]:
['101_DEN084Y5_15_E01_008_clean.fcs',
'101_DEN084Y5_15_E03_009_clean.fcs',
'101_DEN084Y5_15_E05_010_clean.fcs']
[6]:
print(session.get_gate_hierarchy())
root
╰── Time
╰── Singlets
╰── aAmine-
╰── CD3+
├── CD4+
│ ├── CD107a+
│ ├── IFNg+
│ ├── IL2+
│ ╰── TNFa+
╰── CD8+
├── CD107a+
├── IFNg+
├── IL2+
╰── TNFa+
Gather info for CD4+ cytokine gates
[7]:
cd4_child_gate_ids = session.get_child_gate_ids('CD4+')
[8]:
cd4_child_gate_ids
[8]:
[('CD107a+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('IFNg+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('IL2+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('TNFa+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'))]
[9]:
cd4_gate_path = cd4_child_gate_ids[0][1]
[10]:
cd4_gate_path
[10]:
('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')
[11]:
cd4_child_gate_names = [i[0] for i in cd4_child_gate_ids]
[12]:
cd4_child_gate_names
[12]:
['CD107a+', 'IFNg+', 'IL2+', 'TNFa+']
Build Boolean combo data structures
[13]:
n_channels = len(cd4_child_gate_ids)
bool_combos = list(itertools.product([True, False], repeat=n_channels))
[14]:
bool_combos
[14]:
[(True, True, True, True),
(True, True, True, False),
(True, True, False, True),
(True, True, False, False),
(True, False, True, True),
(True, False, True, False),
(True, False, False, True),
(True, False, False, False),
(False, True, True, True),
(False, True, True, False),
(False, True, False, True),
(False, True, False, False),
(False, False, True, True),
(False, False, True, False),
(False, False, False, True),
(False, False, False, False)]
[15]:
def generate_bool_gate_name(gate_labels, bool_list, prefix=None):
# convert Boolean values to strings '+' or '-'
bool_strings = ['+' if b else '-' for b in bool_list]
# Our gate names have a trailing '+'
# Remove these so we can append '+' or '-' as appropriate for each bool combo
new_gate_labels = [l[:-1] if l[-1] == '+' else l for l in gate_labels]
# Now, map the trailing '+' or '-' to each item, matching the bool list
new_gate_labels = list(map(lambda gate_label, b: gate_label + b, new_gate_labels, bool_strings))
# Start building the new gate name for the entire set,
# starting with the optional prefix
if prefix is not None:
gate_name = prefix + ':'
else:
gate_name = ''
return gate_name + "_".join(new_gate_labels)
[16]:
bool_gate_labels = []
for bc in bool_combos:
tmp_label = generate_bool_gate_name(cd4_child_gate_names, bc, prefix='CD4')
bool_gate_labels.append(tmp_label)
[17]:
bool_gate_labels
[17]:
['CD4:CD107a+_IFNg+_IL2+_TNFa+',
'CD4:CD107a+_IFNg+_IL2+_TNFa-',
'CD4:CD107a+_IFNg+_IL2-_TNFa+',
'CD4:CD107a+_IFNg+_IL2-_TNFa-',
'CD4:CD107a+_IFNg-_IL2+_TNFa+',
'CD4:CD107a+_IFNg-_IL2+_TNFa-',
'CD4:CD107a+_IFNg-_IL2-_TNFa+',
'CD4:CD107a+_IFNg-_IL2-_TNFa-',
'CD4:CD107a-_IFNg+_IL2+_TNFa+',
'CD4:CD107a-_IFNg+_IL2+_TNFa-',
'CD4:CD107a-_IFNg+_IL2-_TNFa+',
'CD4:CD107a-_IFNg+_IL2-_TNFa-',
'CD4:CD107a-_IFNg-_IL2+_TNFa+',
'CD4:CD107a-_IFNg-_IL2+_TNFa-',
'CD4:CD107a-_IFNg-_IL2-_TNFa+',
'CD4:CD107a-_IFNg-_IL2-_TNFa-']
Create the BooleanGate instances
[18]:
bool_gates = []
for i, bool_gate_name in enumerate(bool_gate_labels):
# boolean gates need gate references
# one for each of the 4 gates
# and the 'complement' controls the True/False or +/-
# where complement=True is the inverse, so the - of our + gates
gate_refs = []
# and grab the specific bool combo for this new bool gate label
bool_combo = bool_combos[i]
for j, child_gate_name in enumerate(cd4_child_gate_names):
gate_ref = {
'ref': child_gate_name,
'path': cd4_gate_path,
'complement': not bool_combo[j]
}
gate_refs.append(gate_ref)
bool_gate = fk.gates.BooleanGate(
bool_gate_name,
'and',
gate_refs
)
bool_gates.append(bool_gate)
[19]:
bool_gates
[19]:
[BooleanGate(CD4:CD107a+_IFNg+_IL2+_TNFa+, type: and),
BooleanGate(CD4:CD107a+_IFNg+_IL2+_TNFa-, type: and),
BooleanGate(CD4:CD107a+_IFNg+_IL2-_TNFa+, type: and),
BooleanGate(CD4:CD107a+_IFNg+_IL2-_TNFa-, type: and),
BooleanGate(CD4:CD107a+_IFNg-_IL2+_TNFa+, type: and),
BooleanGate(CD4:CD107a+_IFNg-_IL2+_TNFa-, type: and),
BooleanGate(CD4:CD107a+_IFNg-_IL2-_TNFa+, type: and),
BooleanGate(CD4:CD107a+_IFNg-_IL2-_TNFa-, type: and),
BooleanGate(CD4:CD107a-_IFNg+_IL2+_TNFa+, type: and),
BooleanGate(CD4:CD107a-_IFNg+_IL2+_TNFa-, type: and),
BooleanGate(CD4:CD107a-_IFNg+_IL2-_TNFa+, type: and),
BooleanGate(CD4:CD107a-_IFNg+_IL2-_TNFa-, type: and),
BooleanGate(CD4:CD107a-_IFNg-_IL2+_TNFa+, type: and),
BooleanGate(CD4:CD107a-_IFNg-_IL2+_TNFa-, type: and),
BooleanGate(CD4:CD107a-_IFNg-_IL2-_TNFa+, type: and),
BooleanGate(CD4:CD107a-_IFNg-_IL2-_TNFa-, type: and)]
[20]:
bool_gates[5].gate_name
[20]:
'CD4:CD107a+_IFNg-_IL2+_TNFa-'
[21]:
bool_gates[5].gate_refs
[21]:
[{'ref': 'CD107a+',
'path': ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'),
'complement': False},
{'ref': 'IFNg+',
'path': ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'),
'complement': True},
{'ref': 'IL2+',
'path': ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'),
'complement': False},
{'ref': 'TNFa+',
'path': ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'),
'complement': True}]
Add new gates to Session
[22]:
for bool_gate in bool_gates:
session.add_gate(bool_gate, cd4_gate_path)
[23]:
print(session.get_gate_hierarchy())
root
╰── Time
╰── Singlets
╰── aAmine-
╰── CD3+
├── CD4+
│ ├── CD107a+
│ ├── IFNg+
│ ├── IL2+
│ ├── TNFa+
│ ├── CD4:CD107a+_IFNg+_IL2+_TNFa+
│ ├── CD4:CD107a+_IFNg+_IL2+_TNFa-
│ ├── CD4:CD107a+_IFNg+_IL2-_TNFa+
│ ├── CD4:CD107a+_IFNg+_IL2-_TNFa-
│ ├── CD4:CD107a+_IFNg-_IL2+_TNFa+
│ ├── CD4:CD107a+_IFNg-_IL2+_TNFa-
│ ├── CD4:CD107a+_IFNg-_IL2-_TNFa+
│ ├── CD4:CD107a+_IFNg-_IL2-_TNFa-
│ ├── CD4:CD107a-_IFNg+_IL2+_TNFa+
│ ├── CD4:CD107a-_IFNg+_IL2+_TNFa-
│ ├── CD4:CD107a-_IFNg+_IL2-_TNFa+
│ ├── CD4:CD107a-_IFNg+_IL2-_TNFa-
│ ├── CD4:CD107a-_IFNg-_IL2+_TNFa+
│ ├── CD4:CD107a-_IFNg-_IL2+_TNFa-
│ ├── CD4:CD107a-_IFNg-_IL2-_TNFa+
│ ╰── CD4:CD107a-_IFNg-_IL2-_TNFa-
╰── CD8+
├── CD107a+
├── IFNg+
├── IL2+
╰── TNFa+
Re-analyze samples with new Boolean gates
[24]:
session.analyze_samples()
[25]:
report = session.get_analysis_report()
[26]:
report_cols = list(report.columns)
report_cols.remove('gate_path')
report_cols.remove('quadrant_parent')
report[
(report['sample_id'] == '101_DEN084Y5_15_E01_008_clean.fcs') &
(
(report['parent'] == 'CD4+') |
(report['gate_name'] == 'CD4+')
)
][report_cols]
[26]:
| sample_id | gate_name | gate_type | parent | count | absolute_percent | relative_percent | level | |
|---|---|---|---|---|---|---|---|---|
| 34 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4+ | PolygonGate | CD3+ | 74407 | 25.642378 | 61.780848 | 5 |
| 36 | 101_DEN084Y5_15_E01_008_clean.fcs | CD107a+ | RectangleGate | CD4+ | 56 | 0.019299 | 0.075262 | 6 |
| 38 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg+_IL2+_TNFa+ | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 39 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg+_IL2+_TNFa- | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 40 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg+_IL2-_TNFa+ | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 41 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg+_IL2-_TNFa- | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 42 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg-_IL2+_TNFa+ | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 43 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg-_IL2+_TNFa- | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 44 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg-_IL2-_TNFa+ | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 45 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a+_IFNg-_IL2-_TNFa- | BooleanGate | CD4+ | 56 | 0.019299 | 0.075262 | 6 |
| 46 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg+_IL2+_TNFa+ | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 47 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg+_IL2+_TNFa- | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 48 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg+_IL2-_TNFa+ | BooleanGate | CD4+ | 4 | 0.001378 | 0.005376 | 6 |
| 49 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg+_IL2-_TNFa- | BooleanGate | CD4+ | 0 | 0.000000 | 0.000000 | 6 |
| 50 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg-_IL2+_TNFa+ | BooleanGate | CD4+ | 1 | 0.000345 | 0.001344 | 6 |
| 51 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg-_IL2+_TNFa- | BooleanGate | CD4+ | 3 | 0.001034 | 0.004032 | 6 |
| 52 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg-_IL2-_TNFa+ | BooleanGate | CD4+ | 15 | 0.005169 | 0.020159 | 6 |
| 53 | 101_DEN084Y5_15_E01_008_clean.fcs | CD4:CD107a-_IFNg-_IL2-_TNFa- | BooleanGate | CD4+ | 74328 | 25.615152 | 99.893827 | 6 |
| 54 | 101_DEN084Y5_15_E01_008_clean.fcs | IFNg+ | RectangleGate | CD4+ | 4 | 0.001378 | 0.005376 | 6 |
| 56 | 101_DEN084Y5_15_E01_008_clean.fcs | IL2+ | RectangleGate | CD4+ | 4 | 0.001378 | 0.005376 | 6 |
| 58 | 101_DEN084Y5_15_E01_008_clean.fcs | TNFa+ | RectangleGate | CD4+ | 20 | 0.006892 | 0.026879 | 6 |
Workspace method using Boolean gate membership arrays
Import FlowJo 10 workspace & preview gate info
[27]:
wsp_path = os.path.join(base_dir, "8_color_ICS.wsp")
workspace = fk.Workspace(wsp_path, fcs_samples=sample_path)
[28]:
workspace.summary()
[28]:
| samples | loaded_samples | gates | max_gate_depth | |
|---|---|---|---|---|
| group_name | ||||
| All Samples | 3 | 3 | 14 | 6 |
| DEN | 3 | 3 | 14 | 6 |
| GEN | 0 | 0 | 0 | 0 |
| G69 | 0 | 0 | 0 | 0 |
| Lyo Cells | 0 | 0 | 0 | 0 |
[29]:
sample_ids = workspace.get_sample_ids()
[30]:
sample_ids
[30]:
['101_DEN084Y5_15_E01_008_clean.fcs',
'101_DEN084Y5_15_E03_009_clean.fcs',
'101_DEN084Y5_15_E05_010_clean.fcs']
[31]:
print(workspace.get_gate_hierarchy(sample_id=sample_ids[0]))
root
╰── Time
╰── Singlets
╰── aAmine-
╰── CD3+
├── CD4+
│ ├── CD107a+
│ ├── IFNg+
│ ├── IL2+
│ ╰── TNFa+
╰── CD8+
├── CD107a+
├── IFNg+
├── IL2+
╰── TNFa+
Gather info for CD4+ cytokine gates
[32]:
cd4_child_gate_ids = workspace.get_child_gate_ids(sample_ids[0], 'CD4+')
[33]:
cd4_child_gate_ids
[33]:
[('CD107a+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('IFNg+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('IL2+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')),
('TNFa+', ('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+'))]
[34]:
cd4_gate_path = cd4_child_gate_ids[0][1]
[35]:
cd4_gate_path
[35]:
('root', 'Time', 'Singlets', 'aAmine-', 'CD3+', 'CD4+')
[36]:
cd4_child_gate_names = [i[0] for i in cd4_child_gate_ids]
[37]:
cd4_child_gate_names
[37]:
['CD107a+', 'IFNg+', 'IL2+', 'TNFa+']
Build Boolean combo data structures
[38]:
n_channels = len(cd4_child_gate_ids)
bool_combos = list(itertools.product([True, False], repeat=n_channels))
[39]:
bool_combos
[39]:
[(True, True, True, True),
(True, True, True, False),
(True, True, False, True),
(True, True, False, False),
(True, False, True, True),
(True, False, True, False),
(True, False, False, True),
(True, False, False, False),
(False, True, True, True),
(False, True, True, False),
(False, True, False, True),
(False, True, False, False),
(False, False, True, True),
(False, False, True, False),
(False, False, False, True),
(False, False, False, False)]
[40]:
bool_gate_labels = []
for bc in bool_combos:
# here we call the same function we created in the Session version
tmp_label = generate_bool_gate_name(cd4_child_gate_names, bc, prefix='CD4')
bool_gate_labels.append(tmp_label)
[41]:
bool_gate_labels
[41]:
['CD4:CD107a+_IFNg+_IL2+_TNFa+',
'CD4:CD107a+_IFNg+_IL2+_TNFa-',
'CD4:CD107a+_IFNg+_IL2-_TNFa+',
'CD4:CD107a+_IFNg+_IL2-_TNFa-',
'CD4:CD107a+_IFNg-_IL2+_TNFa+',
'CD4:CD107a+_IFNg-_IL2+_TNFa-',
'CD4:CD107a+_IFNg-_IL2-_TNFa+',
'CD4:CD107a+_IFNg-_IL2-_TNFa-',
'CD4:CD107a-_IFNg+_IL2+_TNFa+',
'CD4:CD107a-_IFNg+_IL2+_TNFa-',
'CD4:CD107a-_IFNg+_IL2-_TNFa+',
'CD4:CD107a-_IFNg+_IL2-_TNFa-',
'CD4:CD107a-_IFNg-_IL2+_TNFa+',
'CD4:CD107a-_IFNg-_IL2+_TNFa-',
'CD4:CD107a-_IFNg-_IL2-_TNFa+',
'CD4:CD107a-_IFNg-_IL2-_TNFa-']
Analyze samples & extract cytokine gate membership arrays
Call analyze_samples() for the sample group and collectgate membership arrays for a Sample.
[42]:
workspace.analyze_samples('DEN')
[43]:
cd4_gate_memb = workspace.get_gate_membership(sample_ids[0], 'CD4+')
[44]:
cd4_event_count = cd4_gate_memb.sum()
print(cd4_event_count)
82484
[45]:
cd4_cytokine_gate_memb_lut = {}
for child_gate_name, child_gate_path in cd4_child_gate_ids:
tmp_gate_memb = workspace.get_gate_membership(sample_ids[0], child_gate_name, child_gate_path)
# filter for just the CD4+ events
tmp_gate_memb = tmp_gate_memb[cd4_gate_memb]
cd4_cytokine_gate_memb_lut[child_gate_name] = tmp_gate_memb
[46]:
cd4_cytokine_gate_memb_lut
[46]:
{'CD107a+': array([False, False, False, ..., False, False, False], shape=(82484,)),
'IFNg+': array([False, False, False, ..., False, False, False], shape=(82484,)),
'IL2+': array([False, False, False, ..., False, False, False], shape=(82484,)),
'TNFa+': array([False, False, False, ..., False, False, False], shape=(82484,))}
[47]:
# Make into a DataFrame
df_cd4_cytokine_gate_memb = pd.DataFrame(cd4_cytokine_gate_memb_lut)
[48]:
df_cd4_cytokine_gate_memb.head()
[48]:
| CD107a+ | IFNg+ | IL2+ | TNFa+ | |
|---|---|---|---|---|
| 0 | False | False | False | False |
| 1 | False | False | False | False |
| 2 | False | False | False | False |
| 3 | False | False | False | False |
| 4 | False | False | False | False |
Create Boolean combos from the cytokine gate memberships
[49]:
# Compare underlying NumPy array to the list of Bool combos
cd4_cytokine_combo_result = np.all(df_cd4_cytokine_gate_memb.values[:, np.newaxis, :] == bool_combos, axis=2)
[50]:
# Create the new DataFrame
df_cd4_cytokine_bool_combos = pd.DataFrame(
cd4_cytokine_combo_result,
columns=bool_gate_labels
)
[51]:
df_cd4_cytokine_bool_combos
[51]:
| CD4:CD107a+_IFNg+_IL2+_TNFa+ | CD4:CD107a+_IFNg+_IL2+_TNFa- | CD4:CD107a+_IFNg+_IL2-_TNFa+ | CD4:CD107a+_IFNg+_IL2-_TNFa- | CD4:CD107a+_IFNg-_IL2+_TNFa+ | CD4:CD107a+_IFNg-_IL2+_TNFa- | CD4:CD107a+_IFNg-_IL2-_TNFa+ | CD4:CD107a+_IFNg-_IL2-_TNFa- | CD4:CD107a-_IFNg+_IL2+_TNFa+ | CD4:CD107a-_IFNg+_IL2+_TNFa- | CD4:CD107a-_IFNg+_IL2-_TNFa+ | CD4:CD107a-_IFNg+_IL2-_TNFa- | CD4:CD107a-_IFNg-_IL2+_TNFa+ | CD4:CD107a-_IFNg-_IL2+_TNFa- | CD4:CD107a-_IFNg-_IL2-_TNFa+ | CD4:CD107a-_IFNg-_IL2-_TNFa- | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 1 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 2 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 3 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 4 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 82479 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 82480 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 82481 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 82482 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
| 82483 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True |
82484 rows × 16 columns
[52]:
# Get the event counts using sum()
df_cd4_cytokine_bool_combos.sum()
[52]:
CD4:CD107a+_IFNg+_IL2+_TNFa+ 0
CD4:CD107a+_IFNg+_IL2+_TNFa- 0
CD4:CD107a+_IFNg+_IL2-_TNFa+ 0
CD4:CD107a+_IFNg+_IL2-_TNFa- 0
CD4:CD107a+_IFNg-_IL2+_TNFa+ 0
CD4:CD107a+_IFNg-_IL2+_TNFa- 0
CD4:CD107a+_IFNg-_IL2-_TNFa+ 0
CD4:CD107a+_IFNg-_IL2-_TNFa- 68
CD4:CD107a-_IFNg+_IL2+_TNFa+ 0
CD4:CD107a-_IFNg+_IL2+_TNFa- 0
CD4:CD107a-_IFNg+_IL2-_TNFa+ 4
CD4:CD107a-_IFNg+_IL2-_TNFa- 0
CD4:CD107a-_IFNg-_IL2+_TNFa+ 1
CD4:CD107a-_IFNg-_IL2+_TNFa- 5
CD4:CD107a-_IFNg-_IL2-_TNFa+ 16
CD4:CD107a-_IFNg-_IL2-_TNFa- 82390
dtype: int64
[53]:
# One final tip, use np.where to get the original indices if you need them.
# The original CD4+ gate membership array has length of the entire event array.
# The True values are what we filtered on, so those corresponde to the bool combo rows
np.where(cd4_gate_memb)
[53]:
(array([ 6, 9, 10, ..., 290163, 290164, 290171],
shape=(82484,)),)