triskele/python/triskele/Triskele.py

93 lines
3.2 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# \file Triskele.py
# \brief TODO
# \author Florent Guiotte <florent.guiotte@gmail.com>
# \version 0.1
# \date 22 mars 2018
#
# TODO details
import os
import subprocess
from pathlib import Path
import numpy as np
from .CreaTIFF import read, write
class Triskele:
def __init__(self, raster, dtype=np.uint8, cache_dir='/tmp', verbose=True):
self.verbose = verbose
self.triskele_bin = Path(os.path.dirname(os.path.realpath(__file__))\
+ '/../../build/out/apGenerator')
self.cache_dir = Path(cache_dir)
if not self.triskele_bin.exists():
raise EnvironmentError ('TRISKELE bin not found: {}'.format(self.triskele_bin))
if not self.cache_dir.exists():
raise EnvironmentError ('Cache directory not found: {}'.format(self.cache_dir))
self.infile = self.cache_dir.joinpath('infile.tif')
self.outfile = self.cache_dir.joinpath('outfile.tif')
self.areafile = self.cache_dir.joinpath('areafile.txt')
self.sdfile = self.cache_dir.joinpath('sdfile.txt')
self.moifile = self.cache_dir.joinpath('moifile.txt')
self._write_infile(raster, dtype)
def filter(self, tree='max-tree', area=None, standard_deviation=None, moment_of_inertia=None, feature='weight'):
self._setup(tree, area, standard_deviation, moment_of_inertia, feature)
self._run()
return self._read_outfile()
def _read_outfile(self):
return read(self.outfile)
def _write_infile(self, rasters, dtype):
## Expand if rasters is 2D
if len(rasters.shape) < 3:
rasters = np.expand_dims(rasters, 2)
## Scale to new dtype
rep = np.iinfo(dtype)
rasters = rasters.astype(np.float64)
## Channel independant scale
for i in range(rasters.shape[2]):
rasters[:,:,i] -= rasters[:,:,i].min() - rep.min
rasters[:,:,i] *= (rep.max - rep.min) / (rasters[:,:,i].max() - rasters[:,:,i].min())
rasters = rasters.astype(dtype)
write(self.infile, rasters)
def _setup(self, tree, area, standard_deviation, moment_of_inertia, feature):
self.process = [self.triskele_bin,
'-i', '{}'.format(self.infile),
'-o', '{}'.format(self.outfile),
'--{}'.format(tree),
'--f-{}'.format(feature)]
if area is not None:
np.savetxt(self.areafile, area, fmt='%d')
self.process.extend(['--area', '{}'.format(self.areafile)])
if standard_deviation is not None:
np.savetxt(self.sdfile, standard_deviation, fmt='%f')
self.process.extend(['--standard-deviation', '{}'.format(self.sdfile)])
if moment_of_inertia is not None:
np.savetxt(self.moifile, moment_of_inertia, fmt='%f')
self.process.extend(['--moment-of-inertia', '{}'.format(self.moifile)])
def _run(self):
tryskele = subprocess.Popen(self.process, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
tryskele.wait()
if self.verbose:
print('STDOUT:\n' + tryskele.stdout.read().decode() + \
'\nSTDERR:\n' + tryskele.stderr.read().decode())