forked from Pymol-Scripts/Pymol-script-repo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
load_img_stack.py
108 lines (79 loc) · 2.64 KB
/
load_img_stack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
'''
http://pymolwiki.org/index.php/load_img_stack
PyMOL image stack loading module
(c) Thomas Holder, Schrodinger, Inc.
'''
from pymol import cmd, CmdException
def imgframeiter(img):
'''
Iterate over frames of a multi-frame image (like tiff)
'''
import itertools
try:
for i in itertools.count():
img.seek(i)
yield img
except EOFError:
raise StopIteration
def load_img_stack(pattern, name='', grid=1.0, channel=0, normalize=1,
extent=None, quiet=1, _self=cmd):
'''
DESCRIPTION
Load a stack of images as a map
ARGUMENTS
pattern = str: image filename or pattern
name = str: map object name to create
grid = float: grid spacing in Angstrom {default: 1.0}
channel = int: color channel for RGB images {default: 0}
normalize = 0 or 1: normalize data {default: 1}
extent = 3-float: (a,b,c) edge lengths in Angstrom, overwrites "grid"
arguments if given {default: }
EXAMPLES
load_img_stack img*.tif, extent=(21.0, 14.5, 18.2)
'''
import glob
import numpy
from chempy.brick import Brick
try:
from PIL import Image
except ImportError:
import Image
channel, normalize, quiet = int(channel), int(normalize), int(quiet)
if not name:
name = _self.get_unused_name('map')
if isinstance(grid, str):
grid = _self.safe_eval(grid)
if not isinstance(grid, (tuple, list)):
grid = (grid,) * 3
stack = []
size = None
filenames = glob.glob(_self.exp_path(pattern))
if not filenames:
raise CmdException('no such files')
for filename in sorted(filenames):
img = Image.open(filename)
if size is None:
size = img.size
for img in imgframeiter(img):
if img.size != size:
if not quiet:
print('Image size mismatch: %s != %s' % (img.size, size))
continue
a = numpy.reshape(img, (size[0], size[1], -1))
stack.append(a[..., channel])
stack = numpy.asfarray(stack)
stack = stack.swapaxes(0, 2)[:, ::-1, ::-1]
if min(stack.shape) < 2:
raise CmdException('insufficient grid dimensions: ' + str(stack.shape))
if normalize:
stack -= stack.mean()
stack /= stack.std()
if extent:
if isinstance(extent, str):
extent = _self.safe_eval(extent)
grid = [(float(e) / (s - 1)) for (e, s) in zip(extent, stack.shape)]
if not quiet:
print(' Setting grid = ' + str(grid))
brick = Brick.from_numpy(stack, grid)
_self.load_brick(brick, name)
cmd.extend('load_img_stack', load_img_stack)