def get_color(self, forecast=False): if forecast: color = self.forecast_color else: color = self.historical_color if color: return color if forecast and self.historical_color: color = Color(self.historical_color) else: color = Color(GHG_MAIN_SECTOR_COLORS[self.graph.sector_name]) if self.luminance_change: luminance = color.get_luminance() if self.luminance_change < 0: luminance = luminance * (1 + self.luminance_change) else: luminance = luminance + (1 - luminance) * self.luminance_change color.set_luminance(luminance) if forecast: # Lighten forecast series by 30 % luminance = color.get_luminance() luminance = luminance + (1 - color.get_luminance()) * .3 color.set_luminance(luminance) return color.hex
def is_bright(self, color: Color): if color.get_saturation() == 0 \ and color.get_luminance() == 1: return True if color.get_luminance() > 0.7: return True if color.get_saturation() >= 0.3 \ and color.get_luminance() >= 0.3: return True return False
def rgb_color_picker(obj, min_luminance=None, max_luminance=None): """Modified version of colour.RGB_color_picker""" color_value = (int.from_bytes( hashlib.md5(str(obj).encode("utf-8")).digest(), "little") % 0xFFFFFF) color = Color(f"#{color_value:06x}") if min_luminance and color.get_luminance() < min_luminance: color.set_luminance(min_luminance) elif max_luminance and color.get_luminance() > max_luminance: color.set_luminance(max_luminance) return color
def rgb_color_picker(obj, min_luminance=None, max_luminance=None): """Modified version of colour.RGB_color_picker""" color_value = int.from_bytes( hashlib.md5(str(obj).encode('utf-8')).digest(), 'little', ) % 0xffffff color = Color(f'#{color_value:06x}') if min_luminance and color.get_luminance() < min_luminance: color.set_luminance(min_luminance) elif max_luminance and color.get_luminance() > max_luminance: color.set_luminance(max_luminance) return color
def generate_color_scale(base_color, n): change = 0.2 color = Color(base_color) lum = color.get_luminance() if lum <= 0.6 and lum >= 0.4: go_down = n // 2 go_up = n - go_down - 1 elif lum > 0.6: go_down = n go_up = 0 else: go_up = n go_down = 0 out = [] for i in range(0, go_down): lum = lum + (0 - lum) * change color.set_luminance(lum) out.insert(0, color.hex) out.append(base_color) for i in range(0, go_up): lum = lum + (1 - lum) * change color.set_luminance(lum) out.append(color.hex) return out
def to_serializer_format(cls, labels, created): existing_shortkeys = { (label.suffix_key, label.prefix_key) for label in created.values() } serializer_labels = [] for label in sorted(labels): serializer_label = {"text": label} shortkey = cls.get_shortkey(label, existing_shortkeys) if shortkey: serializer_label["suffix_key"] = shortkey[0] serializer_label["prefix_key"] = shortkey[1] existing_shortkeys.add(shortkey) 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) return serializer_labels
def SetOneLed(self, idx: int, color: Color, smooth=False): if not smooth: super().SetOneLed(idx, color, smooth) else: lum = self._leds[idx].get_luminance() num_steps = round(lum / self._SMOOTH_STEP) if lum > 0.1: for i in range(num_steps): lum -= self._SMOOTH_STEP self._leds[idx].set_luminance(lum) self.redrawLed(idx) self.PreUpdate() pygame.display.update() time.sleep(0.01) new_lum = 0 num_steps = round(color.get_luminance() / self._SMOOTH_STEP) for i in range(num_steps - 1): # we start with a non-zero value new_lum += self._SMOOTH_STEP color.set_luminance(new_lum) self._leds[idx] = color self.redrawLed(idx) self.PreUpdate() pygame.display.update() time.sleep(0.01) super().SetOneLed(idx, color)
def dynamic_label_color(color): """ calculates the luminance of a color and determines if a black or white label will be more contrasting """ color = Color(color) if color.get_luminance() < 0.5: return '#FFFFFF' return '#000000'
def get_play_colors(play): """ Return two colors (in hex) for a given play: the main color and the color to use as a font color :return: """ # TODO: Check the if the picked color is (almost) white. We can't see a white edge on the graph picked_color = Color(pick_for=play) play_font_color = "#000000" if picked_color.get_luminance( ) > 0.6 else "#ffffff" return picked_color.get_hex_l(), play_font_color
def pick_font_color(rgb_tuple: tuple, luminance_threshold: float = 0.5) -> tuple: """ Given a background color, determine whether a font should be black or white based on calculated luminance :param color_str: Color string such as hex, RGB, etc :param luminance_threshold: Luminances above this threshold return 'black', below returns 'white' :return: 'black' or 'white' """ c = Color() c.rgb = rgb_tuple lum = c.get_luminance() if lum >= luminance_threshold: return [0, 0, 0, 1] else: return [1, 1, 1, 1]
def generateColorSwatch( baseColor, levels, alphaOffset=(.1, .9), lumaOffset=(.1, 1), ): colorsList = [None] * levels for i in range(levels): c = Color(baseColor) baseLum = lumaOffset[1] - c.get_luminance() lumLevel = (baseLum - ((lumaOffset[1]-baseLum)/levels * i)) + (lumaOffset[0]) c.set_luminance(lumLevel) rgb = c.get_rgb() alphaLevel = alphaOffset[0] + ((alphaOffset[1]-alphaOffset[0]) * i/levels) colorsList[i] = (rgb[0], rgb[1], rgb[2], alphaLevel) return colorsList
def startSubdiagram(id, label, **kwargs): attrs = kwargs attrs.setdefault('label', label) attrs['id'] = id or Helper.cluster_counter Helper.cluster_counter += 1 attrs.setdefault('fillcolor', '#FFFFFF') fillcolor_dark = Color(attrs.get('fillcolor')) fillcolor_dark.set_luminance(fillcolor_dark.get_luminance() * 0.5) attrs.setdefault('fillcolor_dark', fillcolor_dark.get_web()) #TODO: support fillcolor and other attributes return """ <node id="sub_{id}" yfiles.foldertype="group"> <data key="d0"> <y:ProxyAutoBoundsNode> <y:Realizers active="0"> <y:GroupNode> <y:Geometry height="289.6015625" width="240.0" x="1170.0" y="-1579.6015625"/> <y:Fill color="{fillcolor}" transparent="false"/> <y:BorderStyle color="#000000" type="line" width="1.0"/> <y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="{fillcolor_dark}" borderDistance="0.0" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasLineColor="false" height="23.6015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="240.0" x="0.0" xml:space="preserve" y="0.0">{label}</y:NodeLabel> <y:Shape type="rectangle3d"/> <y:State closed="false" closedHeight="90.0" closedWidth="180.0" innerGraphDisplayEnabled="true"/> <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/> <y:BorderInsets bottom="28" bottomF="28.298828125" left="29" leftF="29.2978515625" right="29" rightF="29.2978515625" top="24" topF="24.298828125"/> </y:GroupNode> <y:GroupNode> <y:Geometry height="90.0" width="180.0" x="1170.0" y="-1579.6015625"/> <y:Fill color="{fillcolor}" transparent="false"/> <y:BorderStyle color="#000000" type="line" width="1.0"/> <y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="{fillcolor_dark}" borderDistance="0.0" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasLineColor="false" height="23.6015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#FFFFFF" verticalTextPosition="bottom" visible="true" width="100.0" x="0.0" xml:space="preserve" y="0.0">{label}</y:NodeLabel> <y:Shape type="rectangle3d"/> <y:State closed="true" closedHeight="90.0" closedWidth="180.0" innerGraphDisplayEnabled="true"/> <y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/> <y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph id="{id}" edgedefault="directed" > """.format(**attrs)
def get_random_background(size: Size) -> Image.Image: """ Creates a background with random color and gradient Parameters ---------- :param size: size of the output image :return: random background image """ start_col = Color(rgb=(random(), random(), random())) # get random color for the background end_col = Color(start_col) end_col.set_luminance(start_col.get_luminance() * 0.5) # set luminance for the gradient gradient = list(start_col.range_to( end_col, size[0])) # we preliminary simulate shadows with gradient row = np.array([list(color.get_rgb()) for color in gradient]) bg = np.repeat(row[None, ...], size[1], axis=0) n_rotations = randint(0, 3) bg = np.rot90(bg, n_rotations) # random gradient bg = Image.fromarray((bg * 255).astype('uint8')) return bg
def to_serializer_format(cls, labels, created): existing_shortkeys = {(label.suffix_key, label.prefix_key) for label in created.values()} serializer_labels = [] for label in sorted(labels): serializer_label = {'text': label} shortkey = cls.get_shortkey(label, existing_shortkeys) if shortkey: serializer_label['suffix_key'] = shortkey[0] serializer_label['prefix_key'] = shortkey[1] existing_shortkeys.add(shortkey) 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) return serializer_labels
def match(self, color: Color, ansi=False) -> ColorPoint: lum = map_interval(0, 1, .3, .9, color.get_luminance()) color.set_luminance(lum) sat = map_interval(0, 1, .2, .9, color.get_saturation()) color.set_saturation(sat) return super().match(color)
def _marks_to_excel(data): """ :type discipline: students.models.Discipline :type group: students.models.Group """ from students.models.group import Group # data = json.loads(json.loads(DisciplineMarksCache.get(discipline.pk, group.pk))) lessons = data['lessons'] students = data['students'] mark_types = data['mark_types'] lesson_types = data['lesson_types'] group = None if len(students) > 0: group = Group.objects.filter(pk=students[0]['group']).first() else: return '' students.sort(key=lambda s: s['sum'], reverse=True) # Create an in-memory output file for the new workbook. output = io.BytesIO() workbook = xlsxwriter.Workbook(output, {'in_memory': True}) frmt_student = workbook.add_format() frmt_student.set_border() frmt_student.set_align('center') frmt_student.set_align('vcenter') frmt_student.set_rotation(90) frmt_student.set_text_wrap() frmt_header = workbook.add_format() frmt_header.set_border() frmt_header.set_align('center') frmt_header.set_align('vcenter') frmt_header.set_text_wrap() worksheet = workbook.add_worksheet(u"{}".format(group.title if group else u'студенты')) bg_colors = { # Mark.MARK_ABSENT: "#ffeeee", Mark.MARK_NORMAL: "#aef28c", Mark.MARK_GOOD: "#aef28c", Mark.MARK_EXCELLENT: "#4bb814", Mark.MARK_AWESOME: "#388a0f", Mark.MARK_FANTASTIC: "#255c0a", Mark.MARK_INCREDIBLE: "#3a4408", Mark.MARK_BLACK_HOLE: "black", Mark.MARK_SHINING: "yellow", } mark_formats = {} lesson_formts = {} # Подготовка стилей for lt in lesson_types: frmt = workbook.add_format() frmt.set_align('center') frmt.set_align('vcenter') frmt.set_text_wrap() frmt.set_border() if lt['id'] >= 2: bg_color = Color(bg_colors[Mark.MARK_NORMAL]) bg_color.set_hue({ 2: 0.15, 3: 0.5, 4: 0.6, 5: 0.8 }.get(lt['id'], bg_color.get_hue())) frmt.set_bg_color(bg_color.get_hex_l()) lesson_formts[lt['id']] = frmt for mt in mark_types: if mark_formats.get(lt['id']) is None: mark_formats[lt['id']] = {} frmt = workbook.add_format() frmt.set_align('center') frmt.set_align('vcenter') frmt.set_border() bg_color = bg_colors.get(mt['k'], 'white') color = { Mark.MARK_BLACK_HOLE: 'white', Mark.MARK_AWESOME: 'white', Mark.MARK_EXCELLENT: 'white', Mark.MARK_FANTASTIC: 'white', Mark.MARK_INCREDIBLE: 'white', }.get(mt['k'], 'black') bg_color = Color(bg_color) color = Color(color) if mt['k'] > 0: if lt['id'] == 2: bg_color.set_hue(0.15) bg_color.set_luminance(min(bg_color.get_luminance() * 1.4, 0.9)) elif lt['id'] == 3: bg_color.set_hue(0.5) bg_color.set_luminance(min(bg_color.get_luminance() * 1.1, 0.9)) elif lt['id'] == 4: bg_color.set_hue(0.6) bg_color.set_luminance(min(bg_color.get_luminance() * 1.1, 0.9)) elif lt['id'] == 5: bg_color.set_hue(0.8) bg_color.set_luminance(min(bg_color.get_luminance() * 1.1, 0.9)) else: bg_color.set_hue(0.25) bg_color = { Mark.MARK_SHINING: Color(bg_colors[Mark.MARK_SHINING]), Mark.MARK_BLACK_HOLE: Color(bg_colors[Mark.MARK_BLACK_HOLE]), }.get(mt['k'], bg_color) frmt.set_bg_color(bg_color.get_hex_l()) frmt.set_color(color.get_hex_l()) mark_formats[lt['id']][mt['k']] = frmt # заполнение строки занятий worksheet.set_row(0, 90) for r, l in enumerate(lessons, 2): worksheet.write(r, 0, l['dn_raw'].strip(), lesson_formts[l['lt']]) h = 20 * max(1, l['dn_raw'].strip().count("\n") + 1) worksheet.set_row(r, h) # заполнение таблицы оценок max_width = 1 for c, s in enumerate(students, 1): name = "%s %s" % (s['second_name'], s['name']) score = Discipline.compute_percents(s['marks'], lessons=lessons) score = "{score} / {percents}%".format(**{ 'percents': int(score * 100), 'score': s['sum'], }) # ячейка имени worksheet.write(0, c, name, frmt_student) worksheet.write(1, c, score, frmt_header) # заполняем оценки marks = s['marks'] for r, m in enumerate(marks, 2): if m['m'] is not None: if abs(m['m']) > Mark.MARK_SPECIAL: mark = { Mark.MARK_BLACK_HOLE: u'∅', Mark.MARK_SHINING: u'∞', Mark.MARK_MERCY: u'○', Mark.MARK_KEEP: u'=', }.get(m['m'], '') else: mark = u'н' if m['m'] == -2 else m['m'] else: mark = '' lt = lessons[r - 2]['lt'] worksheet.write(r, c, mark, mark_formats[lt].get(0 if m['m'] is None else m['m'], None)) if len(name) > max_width: max_width = len(name) # декоративные улучшения worksheet.set_column(0, 0, max_width) worksheet.merge_range('A1:A2', group.title, frmt_header) # print setup if len(lessons) < len(students): worksheet.set_landscape() worksheet.fit_to_pages(1, 1) # Close the workbook before streaming the data. workbook.close() # Rewind the buffer. output.seek(0) return output
def put_char_at_random_pos(bg: Image.Image, char: str, font_list: List[str], size_interval: Tuple[int, int], free_region: Tuple[int, int, int, int] = None, angle: float = 0) -> Tuple[Image.Image, np.ndarray]: """ Puts a char at a random position Parameters ---------- :param angle: the angle of rotation of the character :param bg: background to put the char on :param char: the char we want to put on the background :param font_list: list of fonts we want to choose from :param size_interval: the intervals we choose the size of the font from :param free_region: the region where the character can be put on the image given as (left, top, right, bottom). None means the whole image :return: (im, bbox) im: the image with the char drawn on bbox: [x, y (left upper), w, h] """ height, width = bg.height, bg.width # get width and height of the picture font_size = size_interval[0] + int( random() * (size_interval[1] + 1 - size_interval[0])) # get random font size font = font_list[int(random() * len(font_list))] # random font box_size = ImageFont.truetype(font, font_size).getsize( char) # size of font [width, height] if free_region is None: position = (int(random() * (width - box_size[0] + 1)), int(random() * (height - box_size[1] + 1)) ) # random position else: region_width = free_region[2] - free_region[0] region_height = free_region[3] - free_region[1] position = (int(random() * (region_width - box_size[0] + 1)) + free_region[0], int(random() * (region_height - box_size[1] + 1)) + free_region[1]) bbox = np.array([ position[0] + box_size[0] / 2, position[1] + box_size[1] / 2, box_size[0], box_size[1], angle ]) # get luminance of the background to make contrast between he caracter and the background pixpos = (min(max(0, position[1]), bg.width), min(max(0, position[1]), bg.height)) pixel = bg.getpixel(pixpos) box_color = Color(rgb=tuple(c / 255. for c in pixel)) box_luminance = box_color.get_luminance() white = (1, 1, 1) black = (0, 0, 0) char_color = black if box_luminance > 0.9 else white if box_luminance < 0.1 else [ black, white ][randint(0, 1)] char_color = tuple(c * 255 for c in char_color) im = put_char_on_bg(bg, char, font, font_size, char_color, position=position, angle=angle) return im, bbox
def asciiArt(image_file, output_file, scale=0, bg=(0, 0, 0)): # Covnert bg to color object bg = Color(rgb=bg) # Open file img = Image.open(image_file) img.load() # Scale if scale == 0: scale = 36 / img.size[0] # Array of chars from dense to sparse chars = numpy.asarray( list( '$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,"^`\'. ' )) # Compute aspect ratio of font width/height font = ImageFont.load_default() font_width, font_height = font.getsize('X') # Resize image to match font aspect ratio letter_width = round(img.size[0] * scale * (font_height / font_width)) letter_height = round(img.size[1] * scale) img = img.resize((letter_width, letter_height)) # Convert image to RGB img.convert('RGBA') temp = img.copy() img = Image.new('RGB', temp.size, tuple(round(i * 255) for i in bg.get_rgb())) alpha = temp.convert('RGBA').split()[-1] img.paste(temp, mask=alpha) # Get a normalized grayscale version img_grayscale = img.convert(mode='L') img_grayscale = ImageOps.autocontrast(img_grayscale) # Invert if bg is near black if bg.get_luminance() < 0.5: img_grayscale = ImageOps.invert(img_grayscale) # Remap values to 0 to chars.size - 1 img_grayscale = ImageMath.eval("a * factor / 255", { 'a': img_grayscale, 'factor': chars.size - 1 }) # Generate ascii art rows = chunks(list(img_grayscale.getdata()), img_grayscale.size[0]) rows = [''.join(chars[row]) for row in rows] # Create blank image and drawer newimg = Image.new( "RGB", (letter_width * font_width, letter_height * font_height), tuple(round(i * 255) for i in bg.get_rgb())) drawer = ImageDraw.Draw(newimg) color_generator = (i for i in img.getdata()) y = 0 for row in rows: x = 0 for c in row: color = tuple(next(color_generator)) drawer.text((x, y), c, color, font=font) x += font_width # print(c, end='') y += font_height # print() # print("Showing newimg") # newimg.show() newimg.save(output_file) return rows
def box_plot( periods, stat, swing, imperial_units ): mi2km = 1.609344 box_per_axis = 14 max_boxes = box_per_axis * 2 box_fill = SWING_COLORS[swing] color = Color(box_fill) color.set_luminance(max(0.,color.get_luminance()-0.2)) box_border = color.get_web() color = Color(box_fill) color.set_luminance(max(0.,color.get_luminance()-0.3)) box_median = color.get_web() data = [] data_labels = [] upperLabels = [] ngroups = periods.count() if ngroups > max_boxes: all_periods = periods.all()[ngroups-max_boxes:] ngroups = max_boxes else: all_periods = periods.all() for period in all_periods: vals = period.shots.filter(data__swing_type=swing).values_list('data__'+stat) #vals = np.zeros(50) vals = np.array(vals).flatten() if stat in ['swing_speed', 'ball_speed'] and imperial_units: vals /= mi2km data_labels.append(str(period)) data.append(np.abs(vals)) upperLabels.append('({})'.format(len(vals))) naxes = ngroups//box_per_axis + (ngroups%box_per_axis > 0) fig, axes = plt.subplots(nrows=naxes, ncols=1, squeeze=False,figsize=(6,4*naxes)) #fig.subplots_adjust(hspace=0.4) y_min = 20 y_max = 160 if imperial_units: y_min = 10 y_max = 100 if swing == 'SE': if imperial_units: y_min = 50 y_max = 140 else: y_min = 80 y_max = 220 if stat == 'swing_speed': if imperial_units: y_label = 'Swing Speed (mi/h)' else: y_label = 'Swing Speed (km/h)' elif stat == 'ball_speed': if imperial_units: y_label = 'Ball Speed (mi/h)' else: y_label = 'Ball Speed (km/h)' elif stat == 'ball_spin': y_label = 'Ball Spin (abs)' y_min = 0 y_max = 10 y_lim = (y_min,y_max) y_pos = y_min+0.05*(y_max-y_min) for iax, ax in enumerate(axes.flatten()): igroup = iax*box_per_axis if iax==0: pass #ax.set_title(title_) bp = ax.boxplot(data[igroup:min(ngroups,igroup+box_per_axis)], labels=data_labels[igroup:min(ngroups,igroup+box_per_axis)], patch_artist=True) ax.set_ylim(y_lim) ax.set_ylabel(y_label) ax.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.75) plt.setp(ax.get_xticklabels(), rotation=30, fontsize=9, ha='right') if naxes > 1: ax.set_xlim(0.5,box_per_axis+0.5) pos = np.arange(box_per_axis) + 1 weights = 'semibold' for tick, label in enumerate(ax.get_xticklabels()): k = tick % 2 ax.text(pos[tick], y_pos, upperLabels[tick], horizontalalignment='center', size='x-small')#, weight=weights) for box in bp['boxes']: box.set(color=box_border, linewidth=1.5) box.set(facecolor=box_fill) for whisker in bp['whiskers']: whisker.set(color=box_border, linewidth=1.5) for cap in bp['caps']: cap.set(color=box_border, linewidth=1.5) for median in bp['medians']: median.set(color=box_median, linewidth=1.5) for flier in bp['fliers']: flier.set(marker='o', alpha=0.25) flier.set_markersize(5) flier.set_markeredgecolor(box_fill) flier.set_markerfacecolor(box_fill) fig.tight_layout() tmp=io.BytesIO() fig.savefig(tmp,format='svg') #return base64.b64encode(tmp.getvalue()).decode("utf-8") #return tmp.getvalue().decode("utf-8") return base64.b64encode(tmp.getvalue())
def match(self, color: Color, ansi=False) -> ColorPoint: lum = map_interval(0, 1, .2, 1, color.get_luminance()) color.set_luminance(lum) return super().match(color)