Skip to content

Commit 1c3300a

Browse files
Carole SudreCarole Sudre
authored andcommitted
Update to empty dataframe instead of None and removing reliance on pkg_resources
1 parent ebf9ba6 commit 1c3300a

8 files changed

Lines changed: 201 additions & 54 deletions

File tree

MetricsReloaded/metrics/pairwise_measures.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ def confusion_matrix(self):
201201
"""
202202
one_hot_pred = one_hot_encode(self.pred, len(self.list_values))
203203
one_hot_ref = one_hot_encode(self.ref, len(self.list_values))
204+
print(one_hot_ref.shape, one_hot_pred.shape)
204205
confusion_matrix = np.matmul(one_hot_pred.T, one_hot_ref)
205206
return confusion_matrix
206207

MetricsReloaded/processes/mixed_measures_processes.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def detection_quality(self):
153153

154154
def panoptic_quality(self):
155155
"""
156-
Calculates the panopitic quality defined as the production between
156+
Calculates the panopitic quality defined as the product between
157157
detection quality and segmentation quality
158158
159159
Alexander Kirillov, Kaiming He, Ross Girshick, Carsten Rother, and Piotr Dollár. 2019. Panoptic segmentation. In
@@ -248,7 +248,7 @@ def __init__(
248248
pixdim=[],
249249
empty=False,
250250
assignment="Greedy_IoU",
251-
localization="iou",
251+
localization="mask_iou",
252252
thresh=0.5,
253253
flag_fp_in=True,
254254
dict_args={},
@@ -476,7 +476,7 @@ def per_label_dict(self):
476476
list_mt.append(res_mt)
477477
self.matching = pd.concat(self.matching)
478478
if len(list_seg) == 0:
479-
df_seg = None
479+
df_seg = pd.DataFrame()
480480
else:
481481
df_seg = pd.concat(list_seg)
482482
return (
@@ -541,8 +541,8 @@ def __init__(
541541
self.names = names
542542
self.pixdim = pixdim
543543
self.flag_fp_in = flag_fp_in
544-
if len(self.names) < len(self.ref):
545-
self.names = range(len(self.ref))
544+
if len(self.names) < len(self.ref_class):
545+
self.names = range(len(self.ref_class))
546546
self.flag_valid_proba = True
547547
if pred_prob is None or pred_prob[0] is None:
548548
self.flag_valid_proba=False
@@ -556,6 +556,7 @@ def per_label_dict(self):
556556
list_det = []
557557
list_mt = []
558558
for lab in self.list_values:
559+
print('Taking care of label %d in OD process'%lab)
559560
list_pred = []
560561
list_ref = []
561562
list_prob = []
@@ -566,8 +567,9 @@ def per_label_dict(self):
566567
ind_ref = np.where(ref_arr == lab)
567568
pred_loc_tmp = [self.pred_loc[case][f] for f in ind_pred[0]]
568569
ref_loc_tmp = [self.ref_loc[case][f] for f in ind_ref[0]]
570+
print(self.pred_prob[case].shape)
569571
if self.flag_valid_proba:
570-
pred_prob_tmp = [self.pred_prob[case][lab,f] for f in ind_pred[0]]
572+
pred_prob_tmp = [self.pred_prob[case][f,lab] for f in ind_pred[0]]
571573
else:
572574
pred_prob_tmp = None
573575
AS = AssignmentMapping(
@@ -581,6 +583,9 @@ def per_label_dict(self):
581583
pixdim=self.pixdim
582584
)
583585
df_matching = AS.df_matching
586+
if df_matching is None:
587+
warnings.warn('Issue with the processing due to incorrect choices and/or input - output will be none')
588+
return None, None
584589
pred_tmp_fin = np.asarray(df_matching["pred"])
585590
pred_tmp_fin = np.where(
586591
pred_tmp_fin > -1,
@@ -910,12 +915,12 @@ def multi_label_res(self):
910915
list_mcc.append(dict_mcc)
911916
pd_mcc = pd.DataFrame.from_dict(list_mcc)
912917
else:
913-
pd_mcc = None
918+
pd_mcc = pd.DataFrame()
914919
if len(self.measures_calibration) > 0 and overall_prob is not None:
915920
CM = CalibrationMeasures(overall_prob, overall_ref,measures=self.measures_calibration)
916921
dict_cal = CM.to_dict_meas()
917922
list_cal.append(dict_cal)
918923
pd_cal = pd.DataFrame.from_dict(list_cal)
919924
else:
920-
pd_cal = None
925+
pd_cal = pd.DataFrame()
921926
return pd_mcc, pd_cal

MetricsReloaded/processes/overall_process.py

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def __init__(
357357
self.pixdim = pixdim
358358
if self.flag_valid:
359359
self.process_data()
360-
if 'ref_missing' in self.data.keys():
360+
if 'ref_missing_pred' in self.data.keys():
361361
self.complete_missing_cases()
362362
if 'weights_labels' in self.data.keys():
363363
self.weights_labels = self.data['weights_labels']
@@ -428,11 +428,11 @@ def process_data(self):
428428
429429
"""
430430
data = self.data
431-
df_resdet = None
432-
df_resseg = None
433-
df_resmt = None
434-
df_resmcc = None
435-
df_rescal = None
431+
df_resdet = pd.DataFrame()
432+
df_resseg = pd.DataFrame()
433+
df_resmt = pd.DataFrame()
434+
df_resmcc = pd.DataFrame()
435+
df_rescal = pd.DataFrame()
436436
if self.category == "InS":
437437
MLLS = MultiLabelLocSegPairwiseMeasure(
438438
pred_loc=data["pred_loc"],
@@ -475,7 +475,7 @@ def process_data(self):
475475

476476
)
477477
df_resdet, df_resmt = MLDT.per_label_dict()
478-
df_resseg = None
478+
df_resseg = pd.DataFrame()
479479
elif self.category in ["ImLC", "SemS"]:
480480
if 'names' in data.keys():
481481
list_names=data['names']
@@ -504,12 +504,12 @@ def process_data(self):
504504
# print(df_cal, 'CAL')
505505
if self.category == "ImLC":
506506
df_resdet = df_bin
507-
df_resseg = None
507+
df_resseg = pd.DataFrame()
508508
df_resmt = df_mt
509509
df_resmcc = df_mcc
510510
df_rescal = df_cal
511511
else:
512-
df_resdet = None
512+
df_resdet = pd.DataFrame()
513513
df_resseg = df_bin
514514
df_resmt = df_mt
515515
df_resmcc = df_mcc
@@ -518,12 +518,14 @@ def process_data(self):
518518
self.resmt = df_resmt
519519
self.resmcc = df_resmcc
520520
self.rescal = df_rescal
521-
self.create_mapping_column_nan_replaced_seg()
521+
print('After process state of resdet', self.resdet, ' and resseg ',self.resseg)
522+
if self.category == 'SemS':
523+
self.create_mapping_column_nan_replaced_seg()
522524
return
523525

524526
def create_mapping_column_nan_replaced_seg(self):
525527
"""
526-
For each measure (segmentation) for which nan are possible
528+
For each measure (semantic segmentation) for which nan are possible
527529
creates an additional column in which nans are replaced by value (worse or best according to situation
528530
"""
529531
list_to_map = []
@@ -547,8 +549,6 @@ def create_mapping_column_nan_replaced_seg(self):
547549

548550
return
549551

550-
551-
552552

553553
def identify_empty_ref(self):
554554
"""
@@ -650,37 +650,50 @@ def label_aggregation(self, option='average',dict_args={}):
650650
# print('DET', self.resdet,'CAL',self.rescal, 'SEG',self.resseg,'MT', self.resmt,'MCC', self.resmcc)
651651
df_grouped_all = merge_list_df([self.resdet, self.resseg, self.resmt,self.resmcc, self.rescal])
652652
return df_grouped_all
653-
df_all_labels = merge_list_df([self.resdet, self.resseg, self.resmt], on=['label','case'])
654-
df_all_labels['weights_labels'] = 1
655-
df_all_labels['prevalence_labels'] = 1
656-
for k in self.weights_labels.keys():
657-
df_all_labels['weights_labels'] = np.where(df_all_labels['label']==k,self.weights_labels[k],df_all_labels['weights_labels'])
658-
for (c,rc) in enumerate(self.data['ref_class']):
659-
values,counts = np.unique(rc, return_counts=True)
660-
for (v,co) in zip(values,counts):
661-
df_all_labels['prevalence_labels'] = np.where(np.logical_and(df_all_labels['case']==c, df_all_labels['label']==v),co,df_all_labels['prevalence_labels'])
662-
wm = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)), weights=df_all_labels.loc[x.index, "prevalence_labels"])
663-
wm2 = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)), weights=df_all_labels.loc[x.index, "weights_labels"])
664-
wm3 = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)))
665-
list_measures = self.measures_boundary + self.measures_overlap + self.measures_detseg + self.measures_pcc + self.measures_mt
666-
dict_measures = {k:[('prevalence',wm),('weights',wm2),('average',wm3)] for k in list_measures}
667-
df_grouped_lab = df_all_labels.groupby('case',as_index=False).agg(dict_measures).reset_index()
668-
df_grouped_lab.columns = ['_'.join(col).rstrip('_') for col in df_grouped_lab.columns.values]
653+
if self.category == 'ImLC':
654+
print(self.resdet, self.resmt, self.rescal, self.resmcc)
655+
df_all_labels = merge_list_df([self.resdet, self.resmt, self.rescal], on='label')
656+
657+
else:
658+
df_all_labels = merge_list_df([self.resdet, self.resseg, self.resmt], on=['label','case'])
659+
if df_all_labels is not None:
660+
df_all_labels['weights_labels'] = 1
661+
df_all_labels['prevalence_labels'] = 1
662+
for k in self.weights_labels.keys():
663+
df_all_labels['weights_labels'] = np.where(df_all_labels['label']==k,self.weights_labels[k],df_all_labels['weights_labels'])
664+
for (c,rc) in enumerate(self.data['ref_class']):
665+
values,counts = np.unique(rc, return_counts=True)
666+
for (v,co) in zip(values,counts):
667+
df_all_labels['prevalence_labels'] = np.where(np.logical_and(df_all_labels['case']==c, df_all_labels['label']==v),co,df_all_labels['prevalence_labels'])
668+
wm = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)), weights=df_all_labels.loc[x.index, "prevalence_labels"])
669+
wm2 = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)), weights=df_all_labels.loc[x.index, "weights_labels"])
670+
wm3 = lambda x: np.ma.average(np.ma.masked_array(x,np.isnan(x)))
671+
list_measures = self.measures_boundary + self.measures_overlap + self.measures_detseg + self.measures_pcc + self.measures_mt
672+
dict_measures = {k:[('prevalence',wm),('weights',wm2),('average',wm3)] for k in list_measures}
673+
df_grouped_lab = df_all_labels.groupby('case',as_index=False).agg(dict_measures).reset_index()
674+
df_grouped_lab.columns = ['_'.join(col).rstrip('_') for col in df_grouped_lab.columns.values]
669675

670676
# print(df_grouped_lab, " grouped lab ")
671-
df_grouped_all = merge_list_df([df_grouped_lab.reset_index(), self.resmcc, self.rescal], on=['case'])
672-
# print(df_grouped_all, 'grouped all')
677+
df_grouped_all = merge_list_df([df_grouped_lab.reset_index(), self.resmcc, self.rescal], on=['case'])
678+
else:
679+
df_grouped_all = merge_list_df([self.rescal,self.resmcc],on=['case'])
680+
print(df_grouped_all, 'grouped all')
673681
return df_grouped_all
674682

675683
def get_stats_res(self):
676684
"""
677685
Create summary statistics overall and per label available in self.stats_lab and self.stats_all
678686
"""
679687
df_stats_all = self.grouped_lab.describe()
688+
self.stats_all = df_stats_all
689+
print(self.resdet, self.resseg)
690+
if len(self.resdet.index)==0 and len(self.resseg.index)==0:
691+
return
692+
680693
df_all_labels = merge_list_df([self.resdet, self.resseg, self.resmt], on=['label','case'])
681694
df_stats_lab = df_all_labels.groupby('label').describe()
682695
self.stats_lab = df_stats_lab
683-
self.stats_all = df_stats_all
696+
684697
return
685698

686699

MetricsReloaded/utility/assignment_localization.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ def __init__(
123123

124124
dim = 0
125125
print(all_input)
126-
if all_input.shape[0] > 0:
126+
if np.asarray(all_input).size > 0:
127+
#if all_input.shape[0] > 0:
127128
input = guess_input_style(all_input)
128129
if input == 'mask':
129130
dim = all_input.ndim
@@ -132,7 +133,7 @@ def __init__(
132133
dim = int(np.size(all_input)/2)
133134
else:
134135
dim = np.size(all_input)
135-
print(input, dim)
136+
print(input, dim)
136137
if dim > 0:
137138
self.pixdim = np.ones([dim])
138139

@@ -168,13 +169,13 @@ def __init__(
168169
elif localization == "com_dist":
169170
self.matrix = self.pairwise_pointcomdist()
170171
else:
171-
print(' not valid localisation ')
172+
print(' not valid localisation with ', localization)
172173
self.flag_usable = False
173174
self.df_matching = None
174175
self.valid = None
175176
warnings.warn("No adequate localization strategy chosen - not going ahead")
176177
else:
177-
print(' not valid localisation ')
178+
print(' not valid localisation with void entries')
178179
self.flag_usable = False
179180
self.df_matching = None
180181
self.valid = None
@@ -627,6 +628,8 @@ def resolve_ambiguities_matching(self):
627628
):
628629
print("No ambiguity in matching")
629630
df_matching_all = pd.concat([df_matching, df_fp, df_fn])
631+
if df_matching_all.shape[0] == 0:
632+
df_matching_all =pd.DataFrame(columns = ['pred','ref','pred_prob','performance'])
630633
return df_matching_all, list_valid
631634
else:
632635
if self.assignment == "hungarian":
@@ -696,6 +699,8 @@ def resolve_ambiguities_matching(self):
696699
df_matching_all = pd.concat([df_ordered2, df_fn_all, df_fp, df_fp_new])
697700
else:
698701
df_matching_all = pd.concat([df_ordered2, df_fp, df_fn_all])
702+
if df_matching_all.shape[0] == 0:
703+
df_matching_all =pd.DataFrame(columns = ['pred','ref','pred_prob','performance'])
699704
return df_matching_all, list_valid
700705

701706
def matching_ref_predseg(self):

MetricsReloaded/utility/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,9 +521,9 @@ def combine_df(df1,df2):
521521
if df1 is None or df1.shape[0]==0:
522522
print('Nothing in first')
523523
if df2 is None:
524-
return None
524+
return pd.DataFrame()
525525
elif df2.shape[0] == 0:
526-
return None
526+
return pd.DataFrame()
527527
else:
528528
return df2
529529
elif df2 is None or df2.shape[0]==0:

setup.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import os
55
from glob import glob
66

7-
from pkg_resources import parse_requirements
7+
#from pkg_resources import parse_requirements
8+
from packaging.requirements import Requirement
89
from setuptools import find_packages
910
from setuptools import setup
1011

@@ -17,7 +18,7 @@
1718

1819
# read install requirements from requirements.txt
1920
with open(os.path.join(source_dir, "requirements.txt")) as o:
20-
requirements = [str(r) for r in parse_requirements(o.read())]
21+
requirements = [str(r) for r in Requirement(o.read())]
2122

2223
setup(
2324
name="MetricsReloaded",
@@ -46,6 +47,10 @@
4647
"Programming Language :: Python :: 3.8",
4748
"Programming Language :: Python :: 3.9",
4849
"Programming Language :: Python :: 3.10",
50+
"Programming Language :: Python :: 3.11",
51+
"Programming Language :: Python :: 3.12",
52+
"Programming Language :: Python :: 3.13",
53+
"Programming Language :: Python :: 3.14",
4954
"Topic :: Scientific/Engineering",
5055
],
5156
project_urls={

0 commit comments

Comments
 (0)