# Copyright (c) 2011, Enthought, Ltd.
# Author: Pietro Berkes <pberkes@enthought.com>
# License: Modified BSD license (2-clause)
from traits.has_traits import HasTraits, on_trait_change
from traits.trait_numeric import Array
from traits.trait_types import Enum, Button, Instance, Int, Str, Float
from traitsui.group import VGroup, HGroup
from traitsui.item import Item, Spring
from traitsui.message import message
from traitsui.view import View
import numpy as np
import pyanno.measures as measures
from pyanno.plots.matrix_plot import MatrixPlot
import logging
logger = logging.getLogger(__name__)
# statistical measures for pairs of annotators
from pyanno.util import PyannoValueError
PAIRWISE_STATS = {
"Scott's Pi": measures.scotts_pi,
"Cohen's Kappa": measures.cohens_kappa,
"Cohen's weighted Kappa": measures.cohens_weighted_kappa,
"Pearson's Rho": measures.pearsons_rho,
"Spearman's Rho": measures.spearmans_rho
}
# statistical measures for all annotators
GLOBAL_STATS = {
"Fleiss' Kappa": measures.fleiss_kappa,
"Krippendorff's Kappa": measures.krippendorffs_alpha,
"Cronbach's Alpha": measures.cronbachs_alpha
}
ALL_STATS_NAMES = PAIRWISE_STATS.keys() + GLOBAL_STATS.keys()
class _SingleStatView(HasTraits):
value = Float
name = Str
txt = Str
@on_trait_change('value')
def _update_txt(self):
txt = "{name} = {val:.4}".format(
name = self.name,
val = self.value
)
self.txt = txt
traits_view = View(
Item('txt', style='readonly', show_label=False)
)
[docs]class AnnotationsStatisticsView(HasTraits):
statistics_name = Enum(ALL_STATS_NAMES)
annotations = Array
nclasses = Int
info_button = Button("Info...")
stats_view = Instance(HasTraits)
def _info_button_fired(self):
"""Open dialog with description of statistics."""
if self.statistics_name in GLOBAL_STATS:
stat_func = GLOBAL_STATS[self.statistics_name]
else:
stat_func = PAIRWISE_STATS[self.statistics_name]
message(message = stat_func.__doc__, title='Statistics info')
@on_trait_change('statistics_name')
def _update_stats_view(self):
if self.statistics_name in GLOBAL_STATS:
stat_func = GLOBAL_STATS[self.statistics_name]
try:
res = stat_func(self.annotations, nclasses=self.nclasses)
except PyannoValueError as e:
logger.info(e)
res = np.nan
self.stats_view = _SingleStatView(value=res,
name=self.statistics_name)
else:
stat_func = PAIRWISE_STATS[self.statistics_name]
try:
res = measures.pairwise_matrix(stat_func, self.annotations,
nclasses=self.nclasses)
except PyannoValueError as e:
logger.info(e)
nannotators = self.annotations.shape[1]
res = np.empty((nannotators, nannotators))
res.fill(np.nan)
self.stats_view = MatrixPlot(matrix=res,
colormap_low=-1.0,
colormap_high=1.0,
title=self.statistics_name)
[docs] def traits_view(self):
self.statistics_name = "Cohen's Kappa"
traits_view = View(
VGroup(
HGroup(
Item("statistics_name", show_label=False),
Item("info_button", show_label=False)
),
Spring(),
HGroup(
Spring(),
Item("stats_view",
style="custom",
show_label=False,
width=300,
resizable=False),
Spring()
),
),
width=400,
resizable = True
)
return traits_view
#### Testing and debugging ####################################################
[docs]def main():
""" Entry point for standalone testing/debugging. """
from pyanno.modelBt_loopdesign import ModelBtLoopDesign
model = ModelBtLoopDesign.create_initial_state(5)
annotations = model.generate_annotations(20)
stats_view = AnnotationsStatisticsView(annotations=annotations, nclasses=5)
stats_view.configure_traits()
return model, annotations, stats_view
if __name__ == '__main__':
m, a, sv = main()