Skip to content

Instantly share code, notes, and snippets.

@Yu-AnChen
Created July 27, 2018 17:06
Show Gist options
  • Save Yu-AnChen/8b0fd24d10906dc6a128e30809f17313 to your computer and use it in GitHub Desktop.
Save Yu-AnChen/8b0fd24d10906dc6a128e30809f17313 to your computer and use it in GitHub Desktop.
import re
share_link = 'https://omero.hms.harvard.edu/webgateway/img_detail/559116/?c=-1|3000:45000$0000FF,-2|3000:30000$00FF00,-3|3000:30000$FFFFFF,-4|3000:30000$FF0000,-5|0:65535$0000FF,-6|2000:12000$00FF00,-7|3000:30000$FFFFFF,-8|3000:45000$FF0000,-9|3000:50000$0000FF,-10|2500:10000$00FF00,-11|500:9000$FFFFFF,-12|1500:8000$FF0000,-13|4500:45000$0000FF,-14|1500:10000$00FF00,-15|1000:4500$FFFFFF,-16|2000:10000$FF0000,17|0:65535$0000FF,18|2000:10000$00FF00,19|1500:20000$FFFFFF,20|1500:4500$FF0000,21|0:65535$0000FF,22|1500:30000$00FF00,23|3000:45000$FFFFFF,24|3000:45000$FF0000,-25|4500:55000$0000FF,-26|3000:50000$00FF00,-27|1500:45000$FFFFFF,-28|2500:25000$FF0000,-29|5000:50000$0000FF,-30|1500:4500$00FF00,-31|1000:3000$FFFFFF,-32|1500:9000$FF0000,-33|0:65535$0000FF,-34|3000:30000$00FF00,-35|2000:25000$FFFFFF,-36|3000:25000$FF0000&m=c&p=normal&ia=0&q=0.9&t=1&z=1&zm=3.1291772997934135&x=8244.978640776699&y=5880.1398058252435&maps=[{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}},{"inverted":{"enabled":false}}]'
marker_names_string = 'Hoechst1, A488, A555, A647, Hoechst2, pAKT, empty, 5hmC, Hoechst3, Ki67, pCTD2, p21, Hoechst4, pERK, CD45, pS6_235, Hoechst5, EGFR, VEGFR, HER2, Hoechst6, E-Caderin, Keratin, Vimentin, Hoechst7, PCNA, PD-L1(?), Beta-Catenin, Hoechst8, MET, CD4, NGFR, Hoechst9, Mitotracker, ActinRed, HCSred'
"Hoechst1, A488, A555, A647, Hoechst2, pAKT, empty, 5hmC, Hoechst3, Ki67, pCTD2, p21, Hoechst4, pERK, CD45, pS6_235, Hoechst5, EGFR, VEGFR, HER2, Hoechst6, E-Caderin, Keratin, Vimentin, Hoechst7, PCNA, PD-L1(?), Beta-Catenin, Hoechst8, MET, CD4, NGFR, Hoechst9, Mitotracker, ActinRed, HCSred"
share_link.split('|')
def parseChannelsInfos(shareLinkString, markersNamesString):
markersNamesList = markersNames.split(', ')
channelsInfos = []
for text in shareLinkString.split('|'):
m = re.match(r"(\d+):(\d+)", text)
if m:
ms = m.group(0).split(':')
channelsInfos.append({'start': ms[0], 'end': ms[1]})
for idx, marker in enumerate(markersNamesList):
channelsInfos[idx].update({ 'label': marker })
return channelsInfos
channels_infos = parseChannelsInfos(share_link, marker_names_string)
# channels_infos
import sys
import itertools
try:
import pathlib
except ImportError:
import pathlib2 as pathlib
import json
import numpy as np
import pytiff
from PIL import Image
def composite_channel(target, image, color, range_min, range_max):
''' Render _image_ in pseudocolor and composite into _target_
Args:
target: Numpy float32 array containing composition target image
image: Numpy uint16 array of image to render and composite
color: Color as r, g, b float array, 0-1
range_min: Threshhold range minimum, 0-65535
range_max: Threshhold range maximum, 0-65535
'''
f_image = (image.astype('float32') - range_min) / (range_max - range_min)
### clip before composition
f_image = f_image.clip(0,1, out=f_image)
for i, component in enumerate(color):
target[:, :, i] += f_image * component
TILE_SIZE = 1024
EXT = 'jpg'
# List markers as: green, white, red
RENDER_GROUPS = [list(range(36))[i*4:(i+1)*4] for i in range(9)]
COLORS = [
[0, 0, 1], # blue
[0, 1, 0], # green
[1, 1, 1], # white
[1, 0, 0], # red
]
input_file_path = pathlib.Path('TMA0809.ome.tif')
output_path = pathlib.Path('./')
tiff = pytiff.Tiff(str(input_file_path))
num_channels = len(channels_infos)
assert tiff.number_of_pages % num_channels == 0, "Pyramid/channel mismatch"
num_levels = tiff.number_of_pages // num_channels
for level in range(num_levels):
# for level in range(num_levels)[4:]:
page_base = level * num_channels
tiff.set_page(page_base)
ny = int(np.ceil(tiff.shape[0] / TILE_SIZE))
nx = int(np.ceil(tiff.shape[1] / TILE_SIZE))
print(f"level {level} ({ny} x {nx})")
for ty, tx in itertools.product(range(0, ny), range(0, nx)):
iy = ty * TILE_SIZE
ix = tx * TILE_SIZE
filename = f'{level}_{tx}_{ty}.{EXT}'
# print(f" {filename}")
for idx, marker_list in enumerate(RENDER_GROUPS):
group_dir = pathlib.Path('---'.join(
str(x) + '___' + channels_infos[x]['label'] for x in marker_list
))
(output_path / group_dir).mkdir(exist_ok=True)
# print(f" {group_dir}")
for i, (marker, color) in enumerate(zip(marker_list, COLORS)):
ch_info = channels_infos[marker]
tiff.set_page(page_base + marker)
tile = tiff[iy:iy+TILE_SIZE, ix:ix+TILE_SIZE]
if i == 0:
target = np.zeros(tile.shape + (3,), np.float32)
composite_channel(
target, tile, color, float(ch_info['start']), float(ch_info['end'])
)
np.clip(target, 0, 1, out=target)
### I think we don't need this
# np.power(target, 1/2.2, out=target)
target_u8 = (target * 255).astype(np.uint8)
img = Image.frombytes('RGB', target.T.shape[1:], target_u8.tobytes())
img.save(str(output_path / group_dir / filename), quality=85)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment