# **************************************************************************
# *
# * Authors: J.M. De la Rosa Trevin (jmdelarosa@cnb.csic.es)
# * Laura del Cano (ldelcano@cnb.csic.es)
# *
# * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307 USA
# *
# * All comments concerning this program package may be sent to the
# * e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
"""
This module contains utils functions for Xmipp protocols
"""
from os.path import join, basename, isfile
import numpy as np
import math
from pyworkflow import Config
import pyworkflow.utils as pwutils
from pwem import emlib
from pyworkflow.object import Object
[docs]def validateXmippGpuBins():
pass
BAD_IMPORT_TENSORFLOW_KERAS_MSG = '''
Error, tensorflow/keras is probably not installed. Install it with:\n ./scipion installb deepLearningToolkit
If gpu version of tensorflow desired, install cuda 8.0 or cuda 9.0
We will try to automatically install cudnn, if unsucesfully, install cudnn and add to LD_LIBRARY_PATH
add to {0}
CUDA = True
CUDA_VERSION = 8.0 or 9.0
CUDA_HOME = /path/to/cuda-%(CUDA_VERSION)s
CUDA_BIN = %(CUDA_HOME)s/bin
CUDA_LIB = %(CUDA_HOME)s/lib64
CUDNN_VERSION = 6 or 7
'''.format(Config.SCIPION_CONFIG)
[docs]def writeImageFromArray(array, fn):
img = emlib.Image()
img.setData(array)
img.write(fn)
[docs]def readImage(fn):
img = emlib.Image()
img.read(fn)
return img
[docs]def rotation(imag, angle, shape, P):
'''Rotate a np.array and return also the transformation matrix
#imag: np.array
#angle: angle in degrees
#shape: output shape
#P: transform matrix (further transformation in addition to the rotation)'''
(hsrc, wsrc) = imag.shape
angle *= math.pi / 180
T = np.asarray([[1, 0, -wsrc / 2], [0, 1, -hsrc / 2], [0, 0, 1]])
R = np.asarray([[math.cos(angle), math.sin(angle), 0], [-math.sin(angle), math.cos(angle), 0], [0, 0, 1]])
M = np.matmul(np.matmul(np.linalg.inv(T), np.matmul(R, T)), P)
transformed = applyTransform(imag, M, shape)
return transformed, M
[docs]def flipYImage(inFn, outFn=None, outDir=None):
'''Flips an image in the Y axis'''
if outFn == None:
if not '_flipped' in basename(inFn):
ext = pwutils.getExt(inFn)
outFn = inFn.replace(ext, '_flipped' + ext)
else:
outFn = inFn.replace('_flipped', '')
if outDir != None:
outFn = outDir + '/' + basename(outFn)
if isfile(outFn):
return outFn
gainImg = readImage(inFn)
imag_array = np.asarray(gainImg.getData(), dtype=np.float64)
# Flipped Y matrix
M, angle = np.asarray([[1, 0, 0], [0, -1, imag_array.shape[0]], [0, 0, 1]]), 0
flipped_array, M = rotation(imag_array, angle, imag_array.shape, M)
writeImageFromArray(flipped_array, outFn)
return outFn
[docs]def copy_image(imag):
''' Return a copy of a xmipp_image
'''
new_imag = emlib.Image()
new_imag.setData(imag.getData())
return new_imag
[docs]def matmul_serie(mat_list, size=4):
'''Return the matmul of several numpy arrays'''
# Return the identity matrix if te list is empty
if len(mat_list) > 0:
res = np.identity(len(mat_list[0]))
for i in range(len(mat_list)):
res = np.matmul(res, mat_list[i])
else:
res = np.identity(size)
return res
[docs]def normalize_array(ar):
'''Normalize values in an array with mean 0 and std deviation 1
'''
ar -= np.mean(ar)
ar /= np.std(ar)
return ar
[docs]def surrounding_values(a, ii, jj, depth=1):
'''Return a list with the surrounding elements, given the indexs of the center, from an 2D numpy array
'''
values = []
for i in range(ii - depth, ii + depth + 1):
for j in range(jj - depth, jj + depth + 1):
if i >= 0 and j >= 0 and i < a.shape[0] and j < a.shape[1]:
if i != ii or j != jj:
values += [a[i][j]]
return values
[docs]class Point:
""" Return x, y 2d coordinates and some other properties
such as weight and state.
"""
# Selection states
DISCARDED = -1
NORMAL = 0
SELECTED = 1
def __init__(self, pointId, data, weight, state=0):
self._id = pointId
self._data = data
self._weight = weight
self._state = state
self._container = None
[docs] def getId(self):
return self._id
[docs] def getX(self):
return self._data[self._container.XIND]
[docs] def setX(self, value):
self._data[self._container.XIND] = value
[docs] def getY(self):
return self._data[self._container.YIND]
[docs] def setY(self, value):
self._data[self._container.YIND] = value
[docs] def getZ(self):
return self._data[self._container.ZIND]
[docs] def setZ(self, value):
self._data[self._container.ZIND] = value
[docs] def getWeight(self):
return self._weight
[docs] def getState(self):
return self._state
[docs] def setState(self, newState):
self._state = newState
[docs] def eval(self, expression):
localDict = {}
for i, x in enumerate(self._data):
localDict['x%d' % (i + 1)] = x
return eval(expression, {"__builtins__": None}, localDict)
[docs] def setSelected(self):
self.setState(Point.SELECTED)
[docs] def isSelected(self):
return self.getState() == Point.SELECTED
[docs] def setDiscarded(self):
self.setState(Point.DISCARDED)
[docs] def isDiscarded(self):
return self.getState() == Point.DISCARDED
[docs] def getData(self):
return self._data
[docs]class Data():
""" Store data points. """
def __init__(self, **kwargs):
# Indexes of data
self._dim = kwargs.get('dim') # The points dimensions
self.clear()
[docs] def addPoint(self, point, position=None):
point._container = self
if position is None:
self._points.append(point)
else:
self._points.insert(position, point)
[docs] def getPoint(self, index):
return self._points[index]
def __iter__(self):
for point in self._points:
if not point.isDiscarded():
yield point
[docs] def iterAll(self):
""" Iterate over all points, including the discarded ones."""
return iter(self._points)
[docs] def getXData(self):
return [p.getX() for p in self]
[docs] def getYData(self):
return [p.getY() for p in self]
[docs] def getZData(self):
return [p.getZ() for p in self]
[docs] def getWeights(self):
return [p.getWeight() for p in self]
[docs] def getSize(self):
return len(self._points)
[docs] def getSelectedSize(self):
return len([p for p in self if p.isSelected()])
[docs] def getDiscardedSize(self):
return len([p for p in self.iterAll() if p.isDiscarded()])
[docs] def clear(self):
self.XIND = 0
self.YIND = 1
self.ZIND = 2
self._points = []
[docs]class PathData(Data):
""" Just contains two list of x and y coordinates. """
def __init__(self, **kwargs):
Data.__init__(self, **kwargs)
[docs] def splitLongestSegment(self):
""" Split the longest segment by adding the midpoint. """
maxDist = 0
n = self.getSize()
# Find the longest segment and its index
for i in range(n - 1):
p1 = self.getPoint(i)
x1, y1 = p1.getX(), p1.getY()
p2 = self.getPoint(i + 1)
x2, y2 = p2.getX(), p2.getY()
dist = (x1 - x2) ** 2 + (y1 - y2) ** 2
if dist > maxDist:
maxDist = dist
maxIndex = i + 1
midX = (x1 + x2) / 2
midY = (y1 + y2) / 2
# Add a midpoint to it
point = self.createEmptyPoint()
point.setX(midX)
point.setY(midY)
self.addPoint(point, position=maxIndex)
[docs] def createEmptyPoint(self):
data = [0.] * self._dim # create 0, 0...0 point
point = Point(0, data, 0)
point._container = self
return point
[docs] def removeLastPoint(self):
del self._points[-1]