Commit fa6d0484 authored by inhuszar's avatar inhuszar
Browse files

Updated histology_to_block with the library functions.

parent 17f40a8c
......@@ -80,5 +80,6 @@ setup(name="tirl",
"tirl/transformations/linear",
"tirl/transformations/nonlinear",
"tirl/usermodules"],
scripts=["tirl/tirl"]
scripts=["tirl/tirl",
"tirl/tirlvision/sliceview.py"]
)
No preview for this file type
......@@ -29,6 +29,6 @@ The package includes the following modules:
"""
from tirl.scripts.mnd import io
from tirl.scripts.mnd import inout
from tirl.scripts.mnd import image
from tirl.scripts.mnd import general
\ No newline at end of file
......@@ -5,47 +5,54 @@
"author": "Istvan N Huszar"
},
"general": {
"name": "histology_to_block",
"direction": "h2b",
"system": "linux",
"verbosity": "debug",
"logfile": null,
"outdir": "/Users/inhuszar/temp/histo_to_block/4La/reg_svs_automask",
"outputdir": "/mnt/rio/temp/histreg/histo_to_block/4La/reg",
"stages": ["rotation", "rigid", "affine", "nonlinear"],
"warnings": false
},
"histology": {
"file": "/Users/inhuszar/temp/histo_to_block/4La/NP140-14-4La-2-PLP.svs",
"alternative": null,
"file": "/mnt/rio/temp/histreg/histo_to_block/4La/NP140-14-4La-2-PLP.svs",
"storage": "mem",
"dtype": "<f4",
"resolution": 0.008,
"mask": {
"file": null,
"function": null,
"normalise": false
},
"automask": {
"thr": 0,
"uthr": 1
"normalise": true,
"function": "labkmeans",
"automask": {
"thr": 0,
"uthr": 1
}
},
"resolution": 0.008,
"preview": false,
"actions": ["resample_histology", "labkmeans", "histology_preproc"]
"export": true,
"snapshot": true
},
"block": {
"file": "/Users/inhuszar/temp/histo_to_block/4La/block_4La_sup_seg.tif",
"file": "/mnt/rio/temp/histreg/histo_to_block/4La/block_4La_sup_seg.tif",
"storage": "mem",
"dtype": "<f4",
"resolution": 0.050,
"mask": {
"file": null,
"normalise": true,
"function": null,
"normalise": false
},
"automask": {
"thr": 0,
"uthr": 1
"automask": {
"thr": 0,
"uthr": 1
}
},
"resolution": 0.050,
"preview": false,
"actions": ["block_preproc"]
"export": false,
"snapshot": false
},
"preprocessing": {
"histology": ["match_block_resolution", "histology_preprocessing"],
"block": ["block_preprocessing"]
},
"regparams": {
"init": {
......@@ -96,7 +103,7 @@
"scaling": [20, 10, 5, 2],
"smoothing": [0, 0, 0, 0],
"xtol_rel": 0.01,
"xtol_abs": [0.001, 0.001, 0.1, 0.001, 0.001, 0.1],
"xtol_abs": [0.001, 0.1, 0.1, 0.1, 0.001, 0.1],
"opt_step": [0.01, 0.01, 1, 0.01, 0.01, 1],
"visualise": false
},
......
......@@ -159,14 +159,14 @@ def run_stage(target, source, stage_no, counter, scope, config):
# Export stage result as TImage
ext = ts.EXTENSIONS["TImage"]
scr.io.export(target, q.export.timage, default=os.path.join(
scr.inout.export(target, q.export.timage, default=os.path.join(
p.general.outputdir, f"{counter}_stage{stage_no}.{ext}"))
# Create snapshot showing end-stage alignment
snpfile = os.path.join(
p.general.outputdir, f"{counter}_stage{stage_no}.{SNAPSHOT_EXT}")
scr.io.snapshot(source.evaluate(target.domain), q.export.snapshot,
default=snpfile)
scr.inout.snapshot(source.evaluate(target.domain), q.export.snapshot,
default=snpfile)
# Save mask if requested
if target.tmask() is not None:
......@@ -175,14 +175,14 @@ def run_stage(target, source, stage_no, counter, scope, config):
targetmaskfile = os.path.join(
p.general.outputdir,
f"{counter}_stage{stage_no}_targetmask.{SNAPSHOT_EXT}")
scr.io.snapshot(mask, q.export.target_mask, default=targetmaskfile)
scr.inout.snapshot(mask, q.export.target_mask, default=targetmaskfile)
if source.tmask() is not None:
from tirl.timage import TImage
mask = TImage.fromTField(target.tmask())
sourcemaskfile = os.path.join(
p.general.outputdir,
f"{counter}_stage{stage_no}_sourcemask.{SNAPSHOT_EXT}")
scr.io.snapshot(mask, q.export.source_mask, default=sourcemaskfile)
scr.inout.snapshot(mask, q.export.source_mask, default=sourcemaskfile)
# Visualise end-stage alignment
if q.visualise:
......
This diff is collapsed.
......@@ -171,6 +171,37 @@ def perform_image_operations(img, *actions, scope=None, other=None):
return lastimg
def flip_x(img, **kwargs):
"""
Flips the image along the vertical axis.
"""
img.data[...] = img.data[::-1, ...]
if img.tmask() is not None:
img.mask[...] = img.mask[::-1]
def flip_y(img, **kwargs):
"""
Flips the image along the horizontal axis.
"""
img.data[...] = img.data[:, ::-1, ...]
if img.tmask() is not None:
img.mask[...] = img.mask[:, ::-1]
def rgb2yiq(timg):
"""
Convert RGB to YIQ, or leave as grayscale.
"""
from tirl.operations.tensor import TensorOperator
if timg.tsize >= 3:
mat = np.asarray([[ 0.299, 0.587, 0.114],
[0.5959, -0.2746, -0.3213],
[0.2115, -0.5227, 0.3112]])
return TensorOperator(lambda t: np.einsum("ij,...j", mat, t))(timg)
else:
return timg
\ No newline at end of file
......@@ -135,6 +135,87 @@ def snapshot(timg, exportattr, default=None):
raise TypeError(f"Invalid export attribute: {exportattr}")
def load_histology(**imageinputmodule):
"""
Loads histology slide from file as TImage.
:param q: configurations related to the histology input
:type q: AttrMap
"""
# Inintialise import parameters
q = DEFAULT_IMAGEINPUT_MODULE.copy()
q.update(imageinputmodule)
q = AttrMap(q)
import os
from tirl.timage import TImage
# Load image
if q.file is None:
raise FileNotFoundError("No histology image file was specified.")
elif isinstance(q.file, str):
if not os.path.isfile(q.file):
raise FileNotFoundError(
f"Histology image file does not exist: {q.file}")
if q.file.lower().endswith(
(ts.EXTENSIONS["TImage"], ts.EXTENSIONS["TIRLObject"])):
img = load_timage(q.file)
logger.info(f"Loaded histology image from {q.file}: {img}")
return img
elif q.file.lower().endswith(".svs"):
import tirl.loader
img = TImage.fromfile(q.file, storage=q.storage, dtype=q.dtype,
loader=tirl.loader.OpenSlideLoader,
loader_kwargs={"level": 2})
logger.info(f"Loaded histology image from {q.file}: {img}")
else:
try:
img = TImage.fromfile(q.file, storage=q.storage, dtype=q.dtype)
logger.info(f"Loaded histology image from {q.file}: {img}")
except Exception as exc:
logger.error(exc.args)
logger.error("Error while trying to load {}.")
raise
else:
raise TypeError(f"Invalid image file specification: {q.file}")
# ------------------------------------------------------------------------ #
# The operations below are only carried out if the image was loaded from
# an "ordinary" image file, not a TImage file.
# ------------------------------------------------------------------------ #
# Set resolution based on user input
img.resolution = q.resolution
logger.info(f"Pixel size of the histology image was set per user "
f"specification to {q.resolution} [a.u./px].")
# Set mask
from tirl.scripts.mnd.image import set_mask
set_mask(img, scope=dict(q).get("scope", globals()), **q.mask)
# Perform operations
from tirl.scripts.mnd.image import perform_image_operations
perform_image_operations(img, *q.actions,
scope=dict(q).get("scope", globals()), other=None)
# Preview
if q.preview is True:
img.preview()
# Export
export(img, q.export, default=None)
# Snapshot
snapshot(img, q.snapshot, default=None)
return img
def load_image(**imageinputmodule):
"""
Loads 2D image as a TImage. If the input is a TImage file, it is loaded as
......@@ -178,7 +259,7 @@ def load_image(**imageinputmodule):
raise
else:
raise TypeError(f"Invalid volume file specification: {q.file}")
raise TypeError(f"Invalid image file specification: {q.file}")
# ------------------------------------------------------------------------ #
# The operations below are only carried out if the image was loaded from
......
......@@ -126,11 +126,11 @@ def run(cnf=None, **options):
if p.slice.export is True:
ext = ts.EXTENSIONS["TImage"]
p.slice.export = os.path.join(p.general.outputdir, f"slice.{ext}")
slice_ = scr.io.load_image(**p.slice)
slice_ = scr.inout.load_image(**p.slice)
if p.volume.export is True:
ext = ts.EXTENSIONS["TImage"]
p.volume.export = os.path.join(p.general.outputdir, f"volume.{ext}")
volume = scr.io.load_volume(**p.volume)
volume = scr.inout.load_volume(**p.volume)
# Having loaded both images, perform actions on the brain slice photo prior
# to registration, unless it was loaded from an alternative source.
......
......@@ -25,6 +25,7 @@ Part of the FMRIB Software Library (FSL)
Author: Istvan N. Huszar
Available options:
home displays the installation directory
version displays the library version
config [text editor] modify library-wide constants
info <file> display information about a TIRL file
......@@ -56,6 +57,15 @@ def version(*args):
print(tirl.__version__)
def home(*args):
"""
Displays the directory where TIRL is installed.
"""
import tirl
print(tirl.home())
def config(*args):
"""
TIRL config utility. Allows the user to edit the settings.py file of
......@@ -77,7 +87,6 @@ def info(*args):
Displays the ASCII header of a TIRL file using pretty formatting.
"""
# TODO: Make this feature compatible with TIRL v2.0
from tirl.tirlfile import info
if args:
info(args[0])
......@@ -142,6 +151,7 @@ def _module_add(src, *args):
f"You need write permission in the directory {pkgdir} to "
f"change the active TIRL installation.")
# Copy the module source to the requested package directory
src = str(src) + ".py" if not str(src).lower().endswith(".py") else str(src)
shutil.copy2(src, os.path.join(pkgdir, os.path.basename(src)))
......@@ -152,15 +162,23 @@ def _module_edit(src, *args):
module path with respect to the main TIRL package.
"""
import os
import tirl
import subprocess
if str(src).lower().endswith(".py"):
src = str(src)[:-3]
if "." not in src:
src = "usermodules." + src
module_file = tirl.home(*src.split(".")) + ".py"
if not os.path.isfile(module_file):
raise FileNotFoundError(f"Module file does not exist: {module_file}")
editor = "vim" if not args else args[0]
confirm = f"Do you wish to EDIT {module_file}? [y/n] ".lower()
while True:
ans = input(confirm)
if ans in ("y", "yes", "ye"):
subprocess.run([editor, module_file])
return
elif ans in ("n", "no"):
break
else:
......@@ -175,6 +193,8 @@ def _module_remove(src):
"""
import os
import tirl
if str(src).endswith(".py"):
src = str(src)[:-3]
target = tirl.home("usermodules", *src.split("."))
if not os.path.isdir(target):
target += ".py"
......@@ -186,6 +206,7 @@ def _module_remove(src):
if ans in ("y", "yes", "ye"):
try:
os.remove(target)
return
except:
raise PermissionError(
f"You need elevated permissions to remove {target}.")
......
......@@ -420,6 +420,30 @@ def load(fname):
return object_dump
def header(fname):
""" Returns the header of a TIRLFile. """
with open(fname, "rb") as fp:
fp.seek(len(MAGIC) + 2 * UINT8.nbytes)
hdrsize = bytes2int(fp.read(UINT64.nbytes), UINT64)
hdr = fp.read(hdrsize)
return json.loads(hdr.decode())
def info(fname):
"""
Prints the formatted file header without parsing the binary part of the
file.
"""
from pygments import highlight, lexers, formatters
hdr = header(fname)
formatted_json = json.dumps(hdr, indent=4)
colorful_json = highlight(formatted_json.encode("UTF-8"),
lexers.JsonLexer(),
formatters.TerminalFormatter())
print(colorful_json)
def encode(node):
"""
Recursive function that traverses an object dump and replaces
......
#!/usr/bin/env python
#!/usr/bin/env fslpython
# -*- coding: utf-8 -*-
import tirl
# _______ _____ _____ _
# |__ __| |_ _| | __ \ | |
# | | | | | |__) | | |
# | | | | | _ / | |
# | | _| |_ | | \ \ | |____
# |_| |_____| |_| \_\ |______|
#
# Copyright (C) 2018-2020 University of Oxford
# Part of the FMRIB Software Library (FSL)
# Author: Istvan N. Huszar
# Date: 23 June 2020
# SHBASECOPYRIGHT
__version__ = "2020.6.0"
# DEPENDENCIES
import sys
import argparse
import numpy as np
from mayavi import mlab
from scipy.spatial import Delaunay
# TIRL IMPORTS
import tirl
# IMPLEMENTATION
def sliceview():
"""
Main program code.
"""
def surfvis():
images = [
......@@ -43,6 +81,28 @@ def volslicer(fig):
mlab.show()
def create_cli():
"""
Creates command-line interface.
"""
usage = """./sliceview --slice """
parser = argparse.ArgumentParser(
prog="sliceview", usage=usage, description=descr)
def main(*args):
""" Main program code. """
parser = create_cli()
if args:
sliceview(parser.parse_args(args))
else:
parser.print_help()
if __name__ == "__main__":
fig = surfvis()
volslicer(fig)
main(*sys.argv)
......@@ -16,6 +16,7 @@ dependencies:
- imagecodecs-lite
- imageio
- joblib
- mayavi
- matplotlib
- nibabel
- nlopt
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment