Skip to content

Commit 25d2e46

Browse files
committed
remove max emd
1 parent 1654886 commit 25d2e46

3 files changed

Lines changed: 14 additions & 113 deletions

File tree

src/metrics/emd/config.vsh.yaml

Lines changed: 1 addition & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -55,50 +55,6 @@ info:
5555
max: .inf
5656
# Whether a higher value represents a 'better' solution (required)
5757
maximize: false
58-
59-
# A unique identifier for your metric (required).
60-
# Can contain only lowercase letters or underscores.
61-
- name: emd_max_ct_horiz
62-
# A relatively short label, used when rendering visualisarions (required)
63-
label: EMD Max CT Horizontal
64-
# A one sentence summary of how this metric works (required). Used when
65-
# rendering summary tables.
66-
summary: "Max Earth Mover Distance calculated horizontally across donors for each cell type and marker."
67-
# A multi-line description of how this component works (required). Used
68-
# when rendering reference documentation.
69-
description: |
70-
Earth Mover Distance (EMD), also known as the Wasserstein metric, measures the difference
71-
between two probability distributions.
72-
73-
Here, EMD is used to compare marker expression distributions between paired samples from the same donor
74-
quantified across two different batches.
75-
For each paired sample, cell type, and marker, the marker expression values are first converted into
76-
probability distributions.
77-
This is done by binning the expression values into a range from -100 to 100 with a bin width of 0.1.
78-
The `wasserstein_distance` function from SciPy is then used to calculate the EMD between the two
79-
probability distributions belonging to the same cell type, marker, and a given paired samples.
80-
This is then repeated for every cell type, marker, and paired sample.
81-
Finally, the maximum of all these EMD values is computed and reported as the metric score.
82-
83-
EMD Max CT score reflects the largest difference in marker expression distributions across all cell types,
84-
markers, and paired samples.
85-
A high score indicates that at least one marker, cell type, or sample pair has a large difference in
86-
distribution after batch integration.
87-
A low score means that even the most poorly corrected marker expression is well integrated across batches.
88-
references:
89-
doi:
90-
- 10.1023/A:1026543900054
91-
links:
92-
# URL to the documentation for this metric (required).
93-
documentation: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.wasserstein_distance.html
94-
# URL to the code repository for this metric (required).
95-
repository: https://github.com/scipy/scipy
96-
# The minimum possible value for this metric (required)
97-
min: 0
98-
# The maximum possible value for this metric (required)
99-
max: .inf
100-
# Whether a higher value represents a 'better' solution (required)
101-
maximize: false
10258

10359
# A unique identifier for your metric (required).
10460
# Can contain only lowercase letters or underscores.
@@ -140,47 +96,6 @@ info:
14096
max: .inf
14197
# Whether a higher value represents a 'better' solution (required)
14298
maximize: false
143-
144-
# A unique identifier for your metric (required).
145-
# Can contain only lowercase letters or underscores.
146-
- name: emd_max_ct_vert
147-
# A relatively short label, used when rendering visualisarions (required)
148-
label: EMD Max CT Vertical
149-
# A one sentence summary of how this metric works (required). Used when
150-
# rendering summary tables.
151-
summary: "Max Earth Mover Distance across batch corrected samples, cell types, and markers."
152-
# A multi-line description of how this component works (required). Used
153-
# when rendering reference documentation.
154-
description: |
155-
Earth Mover Distance (EMD), also known as the Wasserstein metric, measures the difference
156-
between two probability distributions.
157-
158-
Here, EMD is used to compare marker expression distributions between all integrated
159-
samples from the same group.
160-
For each pair of samples, cell type, and marker, the marker expression values are first converted into
161-
probability distributions.
162-
This is done by binning the expression values into a range from -100 to 100 with a bin width of 0.1.
163-
The `wasserstein_distance` function from SciPy is then used to calculate the EMD between the two
164-
probability distributions belonging to the same cell type, marker, and a given paired samples.
165-
This is then repeated for every cell type, marker, and paired sample.
166-
Finally, the maximum of all these EMD values is computed and reported as the metric score.
167-
168-
A high score indicates there is a pair of samples and marker which show large difference in distribution after batch integration.
169-
A low score means that, the worst integrated pair of samples and marker are well integrated.
170-
references:
171-
doi:
172-
- 10.1023/A:1026543900054
173-
links:
174-
# URL to the documentation for this metric (required).
175-
documentation: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.wasserstein_distance.html
176-
# URL to the code repository for this metric (required).
177-
repository: https://github.com/scipy/scipy
178-
# The minimum possible value for this metric (required)
179-
min: 0
180-
# The maximum possible value for this metric (required)
181-
max: .inf
182-
# Whether a higher value represents a 'better' solution (required)
183-
maximize: false
18499

185100
# Resources required to run the component
186101
resources:
@@ -203,4 +118,4 @@ runners:
203118
# Allows turning the component into a Nextflow module / pipeline.
204119
- type: nextflow
205120
directives:
206-
label: [midtime,midmem,midcpu]
121+
label: [lowtime,lowmem,lowcpu]

src/metrics/emd/helper.py

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from scipy.stats import wasserstein_distance
77

88
KEY_MEAN_EMD_CT = "mean_emd_ct"
9-
KEY_MAX_EMD_CT = "max_emd_ct"
109
KEY_EMD_VERT_MAT_split1 = "emd_vert_mat_split1"
1110
KEY_EMD_VERT_MAT_split2 = "emd_vert_mat_split2"
1211
KEY_EMD_HORZ_PER_DONOR = "emd_horz_per_donor"
@@ -27,13 +26,14 @@ def calculate_vertical_emd(
2726
dict: a dictionary containing the following elements.
2827
"mean_emd_ct": np.float32: mean emd value computed from a flattened data frame containing
2928
mean emd computed for every marker and cell type across all pairing two samples from the same group.
30-
"max_emd_ct": np.float32: max emd value computed from a flattened data frame containing
31-
max emd computed for every marker and cell type across all pairing two samples from the same group.
32-
"emd_wide_dfs": dict: each key is a marker. A value is yet another dictionary which value is
33-
a 2d matrix where each row/column is a pair of sample and a cell contains
34-
emd value computed for the sample pair for either a given cell type
35-
or global. The key for this dictionary then is either a given cell type
36-
or global, depending on what the 2d matrix represents.
29+
"emd_split1_long": pd.DataFrame or np.nan: a long format dataframe where each row is a combination of
30+
first_sample, second_sample, cell_type, and markers.
31+
Value is the EMD computed for that combination.
32+
If the input data does not have at least 2 samples per group, then return np.nan.
33+
"emd_split2_long": pd.DataFrame or np.nan: a long format dataframe where each row is a combination of
34+
first_sample, second_sample, cell_type, and markers.
35+
Value is the EMD computed for that combination.
36+
If the input data does not have at least 2 samples per group, then return np.nan.
3737
"""
3838

3939
print("Calculating vertical EMD for split 1", flush=True)
@@ -48,9 +48,8 @@ def calculate_vertical_emd(
4848

4949
# safeguard
5050
mean_emd_ct = np.nan
51-
max_emd_ct = np.nan
5251

53-
print("Computing mean and max vertical EMD", flush=True)
52+
print("Computing mean vertical EMD", flush=True)
5453

5554
# compute these only if we can.
5655
emd_long = []
@@ -71,15 +70,9 @@ def calculate_vertical_emd(
7170
.to_numpy()
7271
.flatten()
7372
)
74-
max_emd_ct = np.nanmax(
75-
emd_long.drop(columns=["cell_type", "first_sample", "second_sample"])
76-
.to_numpy()
77-
.flatten()
78-
)
7973

8074
return {
8175
KEY_MEAN_EMD_CT: mean_emd_ct,
82-
KEY_MAX_EMD_CT: max_emd_ct,
8376
KEY_EMD_VERT_MAT_split1: emd_split1_long,
8477
KEY_EMD_VERT_MAT_split2: emd_split2_long,
8578
}
@@ -94,9 +87,10 @@ def get_vert_emd_for_integrated_adata(i_adata: ad.AnnData, markers_to_assess: li
9487
markers_to_assess (list): list of markers to compute EMD for.
9588
9689
Returns:
97-
emd_dfs_ct: EMD per cell type,
98-
emd_dfs_global: EMD per donor,
99-
emd_wide_dfs: the break down of EMD per donor and cell type.
90+
emd_vals (pd.DataFrame or np.nan): a long format dataframe where each row is a combination of
91+
first_sample, second_sample, cell_type, and markers.
92+
Value is the EMD computed for that combination.
93+
If the input data does not have at least 2 samples per group, then return np.nan.
10094
"""
10195

10296
print("Determining samples per group", flush=True)
@@ -278,9 +272,6 @@ def calculate_horizontal_emd(
278272
mean_emd_ct = np.nanmean(
279273
emd_per_donor_per_ct.drop(columns=["cell_type", "donor"]).values
280274
)
281-
max_emd_ct = np.nanmax(
282-
emd_per_donor_per_ct.drop(columns=["cell_type", "donor"]).values
283-
)
284275

285276
# concatenate the global and cell type emd
286277
emd_per_donor_per_ct.columns = emd_per_donor_per_ct.columns.str.replace(
@@ -289,7 +280,6 @@ def calculate_horizontal_emd(
289280

290281
return {
291282
KEY_MEAN_EMD_CT: mean_emd_ct,
292-
KEY_MAX_EMD_CT: max_emd_ct,
293283
KEY_EMD_HORZ_PER_DONOR: emd_per_donor_per_ct,
294284
}
295285

src/metrics/emd/script.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,11 @@
9999
"method_id": method_id,
100100
"metric_ids": [
101101
"emd_mean_ct_horiz",
102-
"emd_max_ct_horiz",
103102
"emd_mean_ct_vert",
104-
"emd_max_ct_vert",
105103
],
106104
"metric_values": [
107105
emd_horz[emd_helper.KEY_MEAN_EMD_CT],
108-
emd_horz[emd_helper.KEY_MAX_EMD_CT],
109106
emd_vert[emd_helper.KEY_MEAN_EMD_CT],
110-
emd_vert[emd_helper.KEY_MAX_EMD_CT],
111107
],
112108
"emd_values": {
113109
"emd_values_horiz": emd_horz[emd_helper.KEY_EMD_HORZ_PER_DONOR],

0 commit comments

Comments
 (0)