diff --git a/app/api/tests/test_utils.py b/app/api/tests/test_utils.py index 34d0e9ac..e12a0917 100644 --- a/app/api/tests/test_utils.py +++ b/app/api/tests/test_utils.py @@ -6,26 +6,7 @@ from seqeval.metrics.sequence_labeling import get_entities from ..models import Label, Document from ..utils import BaseStorage, ClassificationStorage, SequenceLabelingStorage, Seq2seqStorage, CoNLLParser -from ..utils import Color, iterable_to_io - - -class TestColor(TestCase): - def test_random_color(self): - color = Color.random() - self.assertTrue(0 <= color.red <= 255) - self.assertTrue(0 <= color.green <= 255) - self.assertTrue(0 <= color.blue <= 255) - - def test_hex(self): - color = Color(red=255, green=192, blue=203) - self.assertEqual(color.hex, '#ffc0cb') - - def test_contrast_color(self): - color = Color(red=255, green=192, blue=203) - self.assertEqual(color.contrast_color.hex, '#000000') - - color = Color(red=199, green=21, blue=133) - self.assertEqual(color.contrast_color.hex, '#ffffff') +from ..utils import iterable_to_io class TestBaseStorage(TestCase): @@ -48,15 +29,14 @@ class TestBaseStorage(TestCase): labels = ['positive'] created = {} - actual = BaseStorage.to_serializer_format(labels, created, random_seed=123) + actual = BaseStorage.to_serializer_format(labels, created) - self.assertEqual(actual, [{ - 'text': 'positive', - 'prefix_key': None, - 'suffix_key': 'p', - 'background_color': '#0d1668', - 'text_color': '#ffffff', - }]) + self.assertEqual(len(actual), 1) + self.assertEqual(actual[0]['text'], 'positive') + self.assertIsNone(actual[0]['prefix_key']) + self.assertEqual(actual[0]['suffix_key'], 'p') + self.assertIsNotNone(actual[0]['background_color']) + self.assertIsNotNone(actual[0]['text_color']) def test_get_shortkey_without_existing_shortkey(self): label = 'positive' diff --git a/app/api/utils.py b/app/api/utils.py index 267e0b8f..396a66b4 100644 --- a/app/api/utils.py +++ b/app/api/utils.py @@ -4,12 +4,12 @@ import itertools import json import re from collections import defaultdict -from random import Random import conllu from chardet import UniversalDetector from django.db import transaction from django.conf import settings +from colour import Color import pyexcel from rest_framework.renderers import JSONRenderer from seqeval.metrics.sequence_labeling import get_entities @@ -66,7 +66,7 @@ class BaseStorage(object): return [label for label in labels if label not in created] @classmethod - def to_serializer_format(cls, labels, created, random_seed=None): + def to_serializer_format(cls, labels, created): existing_shortkeys = {(label.suffix_key, label.prefix_key) for label in created.values()} @@ -81,9 +81,10 @@ class BaseStorage(object): serializer_label['prefix_key'] = shortkey[1] existing_shortkeys.add(shortkey) - color = Color.random(seed=random_seed) - serializer_label['background_color'] = color.hex - serializer_label['text_color'] = color.contrast_color.hex + background_color = Color(pick_for=label) + text_color = Color('white') if background_color.get_luminance() < 0.5 else Color('black') + serializer_label['background_color'] = background_color.hex + serializer_label['text_color'] = text_color.hex serializer_labels.append(serializer_label) @@ -450,47 +451,6 @@ class CSVPainter(JSONPainter): return res -class Color: - def __init__(self, red, green, blue): - self.red = red - self.green = green - self.blue = blue - - @property - def contrast_color(self): - """Generate black or white color. - - Ensure that text and background color combinations provide - sufficient contrast when viewed by someone having color deficits or - when viewed on a black and white screen. - - Algorithm from w3c: - * https://www.w3.org/TR/AERT/#color-contrast - """ - return Color.white() if self.brightness < 128 else Color.black() - - @property - def brightness(self): - return ((self.red * 299) + (self.green * 587) + (self.blue * 114)) / 1000 - - @property - def hex(self): - return '#{:02x}{:02x}{:02x}'.format(self.red, self.green, self.blue) - - @classmethod - def white(cls): - return cls(red=255, green=255, blue=255) - - @classmethod - def black(cls): - return cls(red=0, green=0, blue=0) - - @classmethod - def random(cls, seed=None): - rgb = Random(seed).choices(range(256), k=3) - return cls(*rgb) - - def iterable_to_io(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE): """See https://stackoverflow.com/a/20260030/3817588.""" class IterStream(io.RawIOBase): diff --git a/requirements.txt b/requirements.txt index 1981b52b..cf6e008a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ apache-libcloud==2.4.0 applicationinsights==0.11.7 +colour==0.1.5 chardet==3.0.4 coverage==4.5.3 dj-database-url==0.5.0