@@ -56,8 +56,9 @@ def make_montage(filename, fnames, orientation='h', colorbar=None,
56
56
fnames : list of str | list of array
57
57
The images to make the montage of. Can be a list of filenames
58
58
or a list of image data arrays.
59
- orientation : 'h' | 'v'
60
- The orientation of the montage: horizontal or vertical
59
+ orientation : 'h' | 'v' | list
60
+ The orientation of the montage: horizontal, vertical, or a nested
61
+ list of int (indexes into fnames).
61
62
colorbar : None | list of int
62
63
If None remove colorbars, else keep the ones whose index
63
64
is present.
@@ -102,13 +103,21 @@ def make_montage(filename, fnames, orientation='h', colorbar=None,
102
103
# box = (left, top, width, height)
103
104
boxes .append ([s [1 ].start - border_size , s [0 ].start - border_size ,
104
105
s [1 ].stop + border_size , s [0 ].stop + border_size ])
105
- if orientation == 'v' :
106
+ # convert orientation to nested list of int
107
+ if orientation == 'h' :
108
+ orientation = [range (len (images ))]
109
+ elif orientation == 'v' :
110
+ orientation = [[i ] for i in range (len (images ))]
111
+ # find bounding box
112
+ n_rows = len (orientation )
113
+ n_cols = max (len (row ) for row in orientation )
114
+ if n_rows > 1 :
106
115
min_left = min (box [0 ] for box in boxes )
107
116
max_width = max (box [2 ] for box in boxes )
108
117
for box in boxes :
109
118
box [0 ] = min_left
110
119
box [2 ] = max_width
111
- else :
120
+ if n_cols > 1 :
112
121
min_top = min (box [1 ] for box in boxes )
113
122
max_height = max (box [3 ] for box in boxes )
114
123
for box in boxes :
@@ -120,22 +129,21 @@ def make_montage(filename, fnames, orientation='h', colorbar=None,
120
129
cropped_images .append (im .crop (box ))
121
130
images = cropped_images
122
131
# Get full image size
123
- if orientation == 'h' :
124
- w = sum (i .size [0 ] for i in images )
125
- h = max (i .size [1 ] for i in images )
126
- else :
127
- h = sum (i .size [1 ] for i in images )
128
- w = max (i .size [0 ] for i in images )
129
- new = Image .new ("RGBA" , (w , h ))
130
- x = 0
131
- for i in images :
132
- if orientation == 'h' :
133
- pos = (x , 0 )
134
- x += i .size [0 ]
135
- else :
136
- pos = (0 , x )
137
- x += i .size [1 ]
138
- new .paste (i , pos )
132
+ row_w = [sum (images [i ].size [0 ] for i in row ) for row in orientation ]
133
+ row_h = [max (images [i ].size [1 ] for i in row ) for row in orientation ]
134
+ out_w = max (row_w )
135
+ out_h = sum (row_h )
136
+ # compose image
137
+ new = Image .new ("RGBA" , (out_w , out_h ))
138
+ y = 0
139
+ for row , h in zip (orientation , row_h ):
140
+ x = 0
141
+ for i in row :
142
+ im = images [i ]
143
+ pos = (x , y )
144
+ new .paste (im , pos )
145
+ x += im .size [0 ]
146
+ y += h
139
147
if filename is not None :
140
148
try :
141
149
new .save (filename )
@@ -1881,9 +1889,12 @@ def save_montage(self, filename, order=['lat', 'ven', 'med'],
1881
1889
filename: string | None
1882
1890
path to final image. If None, the image will not be saved.
1883
1891
order: list
1884
- order of views to build montage
1892
+ list of views: order of views to build montage (default ['lat',
1893
+ 'ven', 'med']; nested list of views to specify views in a
1894
+ 2-dimensional grid (e.g, [['lat', 'ven'], ['med', 'fro']])
1885
1895
orientation: {'h' | 'v'}
1886
- montage image orientation (horizontal of vertical alignment)
1896
+ montage image orientation (horizontal of vertical alignment; only
1897
+ applies if ``order`` is a flat list)
1887
1898
border_size: int
1888
1899
Size of image border (more or less space between images)
1889
1900
colorbar: None | 'auto' | [int], optional
@@ -1900,9 +1911,25 @@ def save_montage(self, filename, order=['lat', 'ven', 'med'],
1900
1911
out : array
1901
1912
The montage image, useable with matplotlib.imshow().
1902
1913
"""
1914
+ # find flat list of views and nested list of view indexes
1903
1915
assert orientation in ['h' , 'v' ]
1916
+ if all (isinstance (x , (str , dict )) for x in order ):
1917
+ views = order
1918
+ else :
1919
+ views = []
1920
+ orientation = []
1921
+ for row_order in order :
1922
+ if isinstance (row_order , (str , dict )):
1923
+ orientation .append ([len (views )])
1924
+ views .append (row_order )
1925
+ else :
1926
+ orientation .append ([])
1927
+ for view in row_order :
1928
+ orientation [- 1 ].append (len (views ))
1929
+ views .append (view )
1930
+
1904
1931
if colorbar == 'auto' :
1905
- colorbar = [len (order ) // 2 ]
1932
+ colorbar = [len (views ) // 2 ]
1906
1933
brain = self .brain_matrix [row , col ]
1907
1934
1908
1935
# store current view + colorbar visibility
@@ -1912,8 +1939,8 @@ def save_montage(self, filename, order=['lat', 'ven', 'med'],
1912
1939
for cb in colorbars :
1913
1940
colorbars_visibility [cb ] = cb .visible
1914
1941
1915
- images = self .save_imageset (None , order , colorbar = colorbar ,
1916
- row = row , col = col )
1942
+ images = self .save_imageset (None , views , colorbar = colorbar , row = row ,
1943
+ col = col )
1917
1944
out = make_montage (filename , images , orientation , colorbar ,
1918
1945
border_size )
1919
1946
0 commit comments