Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement/Replace Color class with colour library #393

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 8 additions & 28 deletions app/api/tests/test_utils.py
Expand Up @@ -6,26 +6,7 @@

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):
Expand All @@ -48,15 +29,14 @@ def test_to_serializer_format(self):
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'
Expand Down
52 changes: 6 additions & 46 deletions app/api/utils.py
Expand Up @@ -4,12 +4,12 @@
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
Expand Down Expand Up @@ -66,7 +66,7 @@ def exclude_created_labels(cls, labels, created):
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()}

Expand All @@ -81,9 +81,10 @@ def to_serializer_format(cls, labels, created, random_seed=None):
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)

Expand Down Expand Up @@ -450,47 +451,6 @@ def paint(self, documents):
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):
Expand Down
1 change: 1 addition & 0 deletions 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
Expand Down