80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
from pathlib import Path
|
|
import sys
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
import numpy as np
|
|
from tools import check_if_app
|
|
import logging
|
|
|
|
logger = logging.getLogger(f"submissions.{__name__}")
|
|
|
|
def make_plate_map(sample_list:list) -> Image:
|
|
"""
|
|
Makes a pillow image of a plate from hitpicks
|
|
|
|
Args:
|
|
sample_list (list): list of positive sample dictionaries from the hitpicks
|
|
|
|
Returns:
|
|
Image: Image of the 96 well plate with positive samples in red.
|
|
"""
|
|
# If we can't get a plate number, do nothing
|
|
try:
|
|
plate_num = sample_list[0]['plate_name']
|
|
except IndexError as e:
|
|
logger.error(f"Couldn't get a plate number. Will not make plate.")
|
|
return None
|
|
except TypeError as e:
|
|
logger.error(f"No samples for this plate. Nothing to do.")
|
|
return None
|
|
# Make a 8 row, 12 column, 3 color ints array, filled with white by default
|
|
grid = np.full((8,12,3),255, dtype=np.uint8)
|
|
# Go through samples and change its row/column to red
|
|
for sample in sample_list:
|
|
grid[int(sample['row'])-1][int(sample['column'])-1] = [255,0,0]
|
|
# Create image from the grid
|
|
img = Image.fromarray(grid).resize((1200, 800), resample=Image.NEAREST)
|
|
# create a drawer over the image
|
|
draw = ImageDraw.Draw(img)
|
|
# draw grid over the image
|
|
y_start = 0
|
|
y_end = img.height
|
|
step_size = int(img.width / 12)
|
|
for x in range(0, img.width, step_size):
|
|
line = ((x, y_start), (x, y_end))
|
|
draw.line(line, fill=128)
|
|
x_start = 0
|
|
x_end = img.width
|
|
step_size = int(img.height / 8)
|
|
for y in range(0, img.height, step_size):
|
|
line = ((x_start, y), (x_end, y))
|
|
draw.line(line, fill=128)
|
|
del draw
|
|
old_size = img.size
|
|
new_size = (1300, 900)
|
|
# create a new, larger white image to hold the annotations
|
|
new_img = Image.new("RGB", new_size, "White")
|
|
box = tuple((n - o) // 2 for n, o in zip(new_size, old_size))
|
|
# paste plate map into the new image
|
|
new_img.paste(img, box)
|
|
# create drawer over the new image
|
|
draw = ImageDraw.Draw(new_img)
|
|
# font = ImageFont.truetype("sans-serif.ttf", 16)
|
|
if check_if_app():
|
|
font_path = Path(sys._MEIPASS).joinpath("files", "resources")
|
|
else:
|
|
font_path = Path(__file__).parents[2].joinpath('resources').absolute()
|
|
logger.debug(f"Font path: {font_path}")
|
|
font = ImageFont.truetype(font_path.joinpath('arial.ttf').__str__(), 32)
|
|
row_dict = ["A", "B", "C", "D", "E", "F", "G", "H"]
|
|
# write the plate number on the image
|
|
draw.text((100, 850),plate_num,(0,0,0),font=font)
|
|
# write column numbers
|
|
for num in range(1,13):
|
|
x = (num * 100) - 10
|
|
draw.text((x, 0), str(num), (0,0,0),font=font)
|
|
# write row letters
|
|
for num in range(1,9):
|
|
letter = row_dict[num-1]
|
|
y = (num * 100) - 10
|
|
draw.text((10, y), letter, (0,0,0),font=font)
|
|
return new_img |