Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clevar/catalog/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,8 @@ def __getitem__(self, item):
kwargs["mt_input"] = self.mt_input[item]
if self.members is not None and isinstance(item, (list, np.ndarray)):
cl_mask = np.zeros(self.size, dtype=bool)
cl_mask[item] = True
if len(item) > 0:
cl_mask[item] = True
kwargs["members"] = self.members[cl_mask[self.members["ind_cl"]]]
return self._getitem_base(DataType=ClCatalog, **kwargs)

Expand Down
75 changes: 57 additions & 18 deletions clevar/match/parent.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _set_unique_matching_function(self, preference, **kwargs):
raise NotImplementedError

def _init_matching_extra_cols(self, cat1, cat2, preference):
if preference == "shared_member_fraction":
if self.type == "Membership":
cat1["mt_frac_self"] = np.zeros(cat1.size)
cat2["mt_frac_other"] = np.zeros(cat2.size)
if "mt_frac_other" not in cat1.colnames:
Expand Down Expand Up @@ -136,7 +136,8 @@ def set_unique(*args):
set_unique = self._set_unique_matching_function(
preference, minimum_share_fraction=minimum_share_fraction
)
self._init_matching_extra_cols(cat1, cat2, preference)

self._init_matching_extra_cols(cat1, cat2, preference)

# Run matching
print(f"Unique Matches ({cat1.name})")
Expand Down Expand Up @@ -176,6 +177,40 @@ def match_from_config(self, cat1, cat2, match_config, cosmo=None):
"""
raise NotImplementedError

def _link_matched_pairs(self, cat1, cat2, ind1, ind2, shared_frac=None):
"""
Sets mt_* columns for a given matched pair.

Parameters
----------
cat1: clevar.ClCatalog
ClCatalog 1
cat2: clevar.ClCatalog
ClCatalog 2
ind1: int
Index of the cluster from cat1
ind2: int
Index of the cluster from cat2 corresponding to cat1[ind1]
shared_frac: float, None
Richness shared fraction of clusters. If None and membership
matching is used, it is computed from cat1.mt_input columns.

Note
----
Also adds share fraction to preference!=shared_member_fraction cases
when membership matching is used.
"""
cat1["mt_self"][ind1] = cat2["id"][ind2]
cat2["mt_other"][ind2] = cat1["id"][ind1]

if shared_frac is None and "share_mems" in cat1.mt_input.colnames:
id2 = cat2["id"][ind2]
shared_frac = cat1.mt_input["share_mems"][ind1][id2] / cat1.mt_input["nmem"][ind1]

if shared_frac is not None:
cat1["mt_frac_self"][ind1] = shared_frac
cat2["mt_frac_other"][ind2] = shared_frac

def _match_mpref(self, cat1, ind1, cat2):
"""
Make the unique match by mass preference
Expand All @@ -198,8 +233,7 @@ def _match_mpref(self, cat1, ind1, cat2):
if len(inds2) > 0:
for ind2 in self._sorted2[np.isin(self._sorted2, inds2)]:
if cat2["mt_other"][ind2] is None:
cat1["mt_self"][ind1] = cat2["id"][ind2]
cat2["mt_other"][ind2] = cat1["id"][ind1]
self._link_matched_pairs(cat1, cat2, ind1, ind2)
return True
return False

Expand All @@ -224,20 +258,24 @@ def _match_apref(self, cat1, ind1, cat2, match_pref):
Tells if the cluster was matched
"""
inds2 = cat2.ids2inds(cat1["mt_multi_self"][ind1])
dists = self._get_dist_mt(cat1[ind1], cat2[inds2], match_pref)

dists = self._get_dist_mt(cat1.raw()[ind1], cat2.raw()[inds2], match_pref)
sort_d = np.argsort(dists)
for dist, ind2 in zip(dists[sort_d], inds2[sort_d]):
i1_replace = cat1.id_dict[cat2["mt_other"][ind2]] if cat2["mt_other"][ind2] else None
if i1_replace is None:
cat1["mt_self"][ind1] = cat2["id"][ind2]
cat2["mt_other"][ind2] = cat1["id"][ind1]
return True
if dist < self._get_dist_mt(cat1[i1_replace], cat2[ind2], match_pref):
cat1["mt_self"][ind1] = cat2["id"][ind2]
cat2["mt_other"][ind2] = cat1["id"][ind1]
cat1["mt_self"][i1_replace] = None
self._match_apref(cat1, i1_replace, cat2, match_pref)

_do_match = True
if i1_replace is not None:
_do_match = dist < self._get_dist_mt(
cat1.raw()[i1_replace], cat2.raw()[ind2], match_pref
)

if _do_match:
self._link_matched_pairs(cat1, cat2, ind1, ind2)
if i1_replace is not None:
cat1["mt_self"][i1_replace] = None
return True

return False

def _match_sharepref(self, cat1, ind1, cat2, minimum_share_fraction=0):
Expand Down Expand Up @@ -282,14 +320,15 @@ def _match_sharepref(self, cat1, ind1, cat2, minimum_share_fraction=0):
and cat1["mass"][ind1] <= cat1["mass"][i1_replace]
):
return False
cat1["mt_self"][ind1] = id2
cat1["mt_frac_self"][ind1] = shared_frac
cat2["mt_other"][ind2] = id1
cat2["mt_frac_other"][ind2] = shared_frac

self._link_matched_pairs(cat1, cat2, ind1, ind2, shared_frac)

# try to rematch other candidate that lost the counterpart
if i1_replace is not None:
cat1["mt_self"][i1_replace] = None
cat1["mt_frac_other"][i1_replace] = 0
self._match_sharepref(cat1, i1_replace, cat2, minimum_share_fraction)

return True
return False

Expand Down
2 changes: 1 addition & 1 deletion clevar/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Version of ClEvaR"""

__version__ = "0.18.1"
__version__ = "0.18.2"
19 changes: 19 additions & 0 deletions tests/test_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ def get_test_data_mem():
input1 = {
"id": [f"CL{i}" for i in range(ncl)],
"mass": [30 + i for i in range(ncl)],
"ra": np.arange(ncl),
"dec": np.zeros(ncl),
"z": np.ones(ncl),
}
input2 = {k: v[:-1] for k, v in input1.items()}
# members
Expand Down Expand Up @@ -459,6 +462,22 @@ def test_membership():
print(cat1.members)
print(cat2.members)

# Test shared fracthion is computed with other preferences
for pref in (
"more_massive",
"angular_proximity",
"redshift_proximity",
"shared_member_fraction",
):
cat1, cat2 = get_test_data_mem()
mt.match_members(cat1.members, cat2.members, method="id")
mt.fill_shared_members(cat1, cat2)
mt.multiple(cat1, cat2)
mt.multiple(cat2, cat1)
mt.unique(cat1, cat2, pref)
assert cat1["mt_frac_self"].max() > 0
assert cat2["mt_frac_other"].max() > 0


def test_membership_cfg(CosmoClass):
cat1, cat2 = get_test_data_mem()
Expand Down
Loading