Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
4e1cc8a
- Added parameter for setting control pane height from settings-local.py
arikpoz Sep 11, 2017
5d8fd0a
- Added parameter for setting control pane height from settings-local.py
arikpoz Sep 11, 2017
baee354
Merge remote-tracking branch 'origin-arik/master' into master-arik
arikpoz Sep 15, 2017
6bd2ab3
- added new parameters in settings:
arikpoz Sep 15, 2017
eff49e3
- moved functions def get_files_from_directory, get_files_from_image_…
arikpoz Sep 15, 2017
432ef1d
- revised find_max_acts.py and max_tracker.py, and subsequently crop_…
arikpoz Sep 15, 2017
cde627f
- made max_tracker more generic
arikpoz Sep 15, 2017
9956160
fixed bug in backprop image generation
arikpoz Sep 15, 2017
bc83b8c
disabled generation of some of the outsputs by default
arikpoz Sep 15, 2017
a5b869d
added conversion of layer name to top name in max search
arikpoz Sep 15, 2017
db6d833
- added support for loading offline visualization in the format which…
arikpoz Sep 15, 2017
d3ca852
fixed crash when trying to deconv or backprop from invalid layers
arikpoz Sep 15, 2017
de2273f
fixed so that current deconv shows only selected image deconvolution
arikpoz Sep 15, 2017
5d374bf
- slight change in optimizer to be able to optimize over a Siamese ne…
arikpoz Sep 15, 2017
6c96738
added support for camera mode in siamese network
arikpoz Sep 15, 2017
813564f
- added keyboard binding which will be used to change siamese input m…
arikpoz Sep 15, 2017
c0d6041
- added support for SiameseInputMode.FIRST_IMAGE, SECOND_IMAGE, BOTH_…
arikpoz Sep 16, 2017
6aa65d9
moved caffe dependency to local function in caffevis_helper.py
arikpoz Sep 16, 2017
792e796
- added code to automatically go over all the channels of the given l…
arikpoz Sep 16, 2017
cee2221
- fixed import modules issues in find_max and optimizer
arikpoz Sep 16, 2017
57e9112
- fixed some layer/blob confusion in optimizer
arikpoz Sep 16, 2017
6a901cd
added support for running on multiple layers in optimizer
arikpoz Sep 16, 2017
3f2a35d
added option to skip small files generation
arikpoz Sep 16, 2017
f1abd5b
- added multiple max_iter per layer
arikpoz Sep 16, 2017
95fde69
- added batch support to optimize_image.py
arikpoz Sep 16, 2017
f9a6d87
added support for skipping files for units which were already generated
arikpoz Sep 16, 2017
925f952
- added option to show maximal input images as patterns
arikpoz Sep 16, 2017
05bcbb0
- added debug code to show calculation of network result
arikpoz Sep 16, 2017
007b007
fixed crash when max tracker working on fc
arikpoz Sep 16, 2017
0f1d809
- added more info to progress printouts
arikpoz Sep 16, 2017
dcd9e1a
- added function get_top_to_layer_dict
arikpoz Sep 19, 2017
5866383
added parameter channelwise_mean to transform a mean file into per ch…
arikpoz Sep 19, 2017
7ae647a
refactor mean setting
arikpoz Sep 19, 2017
671feb7
fixed image loading in max tracker for a single network
arikpoz Sep 19, 2017
04172a0
added batch support to find_max_acts
arikpoz Sep 19, 2017
1b423cb
added empty implementation to avoid crash when patterns view with max…
arikpoz Sep 19, 2017
7195e35
added 'B' key binding to back cycle backprop options in the UI
arikpoz Sep 19, 2017
b7e28b6
added support for loading Siamese networks when Siamese is implemente…
arikpoz Sep 19, 2017
697f140
- added support for maximal input histograms for each neuron. the bas…
arikpoz Sep 19, 2017
3077e30
fixed crush due to old file format
arikpoz Sep 19, 2017
cc22193
fix some other crash in case input file is invalid
arikpoz Sep 19, 2017
bab2f1c
added progress report to histogram calculation
arikpoz Sep 19, 2017
f1fe6d3
- fixed size of selected activation
arikpoz Sep 19, 2017
912e52a
- cleared images with 0 max value
arikpoz Sep 19, 2017
2b63b16
- added weights histogram view
arikpoz Sep 19, 2017
4408a57
- added proof of concept for web ui
arikpoz Sep 19, 2017
cc7ccc4
- extracted new method: _add_label_or_score_overlay to simplified cod…
arikpoz Sep 19, 2017
563bced
- extracted new function _display_pane_based_on_zoom_mode to organize…
arikpoz Sep 19, 2017
f091e94
- improved weights histogram loading time by caching the 2d results i…
arikpoz Sep 19, 2017
67e1616
fixed crash when info.txt is missing
arikpoz Sep 19, 2017
93e6c5c
- fixed bug when cache folder doesn't exist
arikpoz Sep 19, 2017
008f40f
added assertion
arikpoz Sep 20, 2017
fa95dd9
changed default batch size for optimize_image to 1
arikpoz Sep 20, 2017
4e4abc0
- replaced use of cv2.resize with image_misc.resize_without_fit which…
arikpoz Sep 20, 2017
86659f1
- added option to overlay activation/gradient over original image
arikpoz Sep 20, 2017
fdb4cc5
added user settings file which contains model_to_load and gpu settings
arikpoz Sep 20, 2017
2952df5
- fixed bug: when moving between layers and siamese mode is first or …
arikpoz Sep 20, 2017
34bb15f
adjusted optimize_image script for siamese networks in "siamese_batch…
arikpoz Sep 20, 2017
e6a987d
- added parameter to deconv to select between running "Zeiler & Fergu…
arikpoz Sep 20, 2017
7aff139
added softmax raw view option, and histogram view option
arikpoz Sep 20, 2017
751298f
organized a little the help screen
arikpoz Sep 20, 2017
44943e0
added settings_model_selector.py
arikpoz Sep 20, 2017
b25cc29
fixed bug when data_mean is empty
arikpoz Sep 20, 2017
497349e
added support for grayscale models
arikpoz Sep 20, 2017
2a83546
- fixed bug when input images list is too short for max tracker
arikpoz Sep 20, 2017
cd35999
added caffevis_clear_negative_activations which is False by default t…
arikpoz Sep 20, 2017
fc78c73
- fixed bug in backprop when using siamese view, first image only
arikpoz Sep 20, 2017
7514d3f
fixed missing field in info file
arikpoz Sep 20, 2017
234c35c
added color maps options
arikpoz Sep 20, 2017
e7bb793
added option to select deconv target layer
arikpoz Sep 23, 2017
4a93916
moved some code
arikpoz Sep 23, 2017
1ab937b
handle missing inputs in max tracker
arikpoz Sep 23, 2017
d87afa1
fixed bug related to missing layer name to top name conversion
arikpoz Sep 23, 2017
e5149ca
added support for siamese_input_mode to be 'concat_along_width', exis…
arikpoz Sep 23, 2017
84975ca
- implemented unique deconv
arikpoz Sep 26, 2017
1b27aef
- make camera feature work again
arikpoz Sep 26, 2017
f6fdb50
removed softmax raw view option leftovers from the code
arikpoz Sep 27, 2017
7a3f17c
refactor loading method of network settings file
arikpoz Sep 27, 2017
d4985d3
added code to support replacing of max_tracker_layers_list with autom…
arikpoz Sep 27, 2017
220c0d6
- use RegionComputer.convert_region_dag in get_max_data_extent() and …
arikpoz Sep 27, 2017
8d5e995
added progress reports when loading images and calculating histograms
arikpoz Sep 27, 2017
0abe730
- removed get_layer_info function
arikpoz Sep 27, 2017
4433092
- added function to handle missing force_backwards and to upgrade net…
arikpoz Sep 27, 2017
f0c742a
- when caffevis_jpgvis_layers is None (which is now the default) we t…
arikpoz Sep 27, 2017
93b5506
- replaced max_tracker_layers_to_output, layers_for_max_tracker and o…
arikpoz Sep 27, 2017
e0951a3
- removed caffevis_maximum_activation_histogram_data_file
arikpoz Sep 28, 2017
1625261
- removed siamese_network_format, replaced with layer based informati…
arikpoz Sep 28, 2017
8a7188a
- added layer size and receptive field to status line
arikpoz Sep 28, 2017
d8b86fd
make control pane height be determined automatically
arikpoz Sep 29, 2017
9185e2c
- made get_receptive_field implementation lazy, to speed up loading o…
arikpoz Sep 29, 2017
683b0fa
- removed use of check_force_backward_true
arikpoz Sep 29, 2017
2c7bdbe
- added visualization of activation correlation
arikpoz Sep 29, 2017
fa1dd3d
- moved get_receptive_field to settings_misc
arikpoz Sep 29, 2017
5fbc347
fixed dead relu count for maxout based networks
arikpoz Sep 29, 2017
50b7a8f
fixed missing cache when folder doesn't exist
arikpoz Sep 29, 2017
98f1078
- added mouse support when clicking layer or channel
arikpoz Sep 29, 2017
f2bf6aa
added error handling in case of missing input
arikpoz Sep 29, 2017
8324b03
added option to generate input images which minimize activations
arikpoz Sep 29, 2017
872aebb
- added caffe as submodule
arikpoz Sep 29, 2017
ec482fe
moved model settings files into single model_settings folder
arikpoz Oct 1, 2017
b8ae04b
updated settings for googlenet and squeezenet
arikpoz Oct 1, 2017
c11f278
updated installation instructions in README.md
arikpoz Oct 16, 2017
d737a09
fixed bug: crash due to use of invalid cache
arikpoz Nov 18, 2017
b084d77
fix caffe build to make install easier
arikpoz Apr 7, 2018
286fecd
removed unneeded dependency
arikpoz Apr 7, 2018
7d4dce0
updated readme
arikpoz Apr 7, 2018
f47371a
fixed typos in readme
arikpoz Apr 8, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
settings_local.py
settings.py.templatec
*.pyc
*.DS_Store
.idea
settings_user.py

3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "caffe"]
path = caffe
url = https://github.com/arikpoz/caffe.git
193 changes: 79 additions & 114 deletions README.md

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions app_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ class BaseApp(object):
def __init__(self, settings, key_bindings):
self.debug_level = 0

def handle_input(self, input_image, panes):
def handle_input(self, input_image, input_label, input_filename, panes):
pass

def handle_key(self, key, panes):
'''Handle key and return either key (to let someone downstream handle it) or None (if this app handled it)'''
pass

def handle_mouse_left_click(self, x, y, flags, param, panes):
'''Handle mouse events'''
pass

def redraw_needed(self, key, panes):
'''App should return whether or not its internal state has
been updated (perhaps in response to handle_key, handle_input,
Expand All @@ -28,7 +32,7 @@ def draw_help(self, panes):
'''Tells the app to draw its help screen in the given pane. No return necessary.'''
pass

def start(self):
def start(self, live_vis):
'''Notify app to start, possibly creating any necessary threads'''
pass

Expand Down
37 changes: 29 additions & 8 deletions bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,29 @@ def get_key_help(self, tag):

_.add('zoom_mode', 'z',
'Cycle zooming through {currently selected unit, backprop results, none}')
_.add('pattern_mode', 's',
'Toggle overlay of preferred input pattern (regularized optimized images)')
_.add('next_pattern_mode', 's',
'Cycle channels overlay (max opt, max input, weights hist, max hist, correlation, off)')
_.add('prev_pattern_mode', 'S',
'Cycle patterns overlay (max opt, max input, weights hist, max hist, correlation, off)')
_.add('pattern_first_only', '1',
'Toggle pattern loading first image only or loading all available images')

_.add('ez_back_mode_loop', 'b',
'Cycle through a few common backprop/deconv modes')
_.add('next_ez_back_mode_loop', 'b',
'Cycle through backprop modes (grad, deconv zf, deconv gb, off)')
_.add('prev_ez_back_mode_loop', 'B',
'Cycle through backprop modes (grad, deconv zf, deconv gb, off)')
_.add('freeze_back_unit', 'd',
'Freeze the bprop/deconv origin to be the currently selected unit')
_.add('show_back', 'a',
'Toggle between showing forward activations and back/deconv diffs')
_.add('back_mode', 'n',
'(expert) Change back mode directly.')
_.add('back_filt_mode', 'm',
'(expert) Change back output filter directly.')
_.add('next_back_view_option', 'n',
'Cycle through backprop view options (raw, gray, norm, normblur, sum>0, histogram)')
_.add('prev_back_view_option', 'N',
'Cycle through backprop view options (raw, gray, norm, normblur, sum>0, histogram)')
_.add('next_color_map', 'm',
'Cycle through colormaps options (grayscale, jet, plasma)')
_.add('prev_color_map', 'M',
'Cycle through colormaps options (grayscale, jet, plasma)')

_.add('boost_gamma', 't',
'Boost contrast using gamma correction')
Expand All @@ -124,4 +134,15 @@ def get_key_help(self, tag):
_.add('toggle_unit_jpgs', '9',
'Turn on or off display of loaded jpg visualization')

_.add('siamese_view_mode', 'v',
'Cycle between siamese view modes {first image, second image, both images}')

_.add('toggle_maximal_score', 'r',
'Toggle showing maximal score overlays {on, off}')
_.add('next_input_overlay', 'y',
'Cycle input overlay {off, over active, over inactive}')
_.add('prev_input_overlay', 'Y',
'Cycle input overlay {off, over active, over inactive}')


bindings = _
12 changes: 12 additions & 0 deletions build_default.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
cd caffe
# fix issue with caffe build from source in ubuntu, see more details here: https://github.com/BVLC/caffe/issues/2347
find . -type f -exec sed -i -e 's^"hdf5.h"^"hdf5/serial/hdf5.h"^g' -e 's^"hdf5_hl.h"^"hdf5/serial/hdf5_hl.h"^g' '{}' \;

# if Makefile.config has already existed, then don't overwrite it
if [ ! -e Makefile.config ]; then
cp Makefile.config.example Makefile.config
fi
make all pycaffe
cd ..
cp settings_user.py.example settings_user.py
1 change: 1 addition & 0 deletions caffe
Submodule caffe added at 7fec25
265 changes: 265 additions & 0 deletions caffe_misc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
#! /usr/bin/env python

import skimage.io
import numpy as np
from image_misc import norm01c


def shownet(net):
'''Print some stats about a net and its activations'''

print '%-41s%-31s%s' % ('', 'acts', 'act diffs')
print '%-45s%-31s%s' % ('', 'params', 'param diffs')
for k, v in net.blobs.items():
if k in net.params:
params = net.params[k]
for pp, blob in enumerate(params):
if pp == 0:
print ' ', 'P: %-5s'%k,
else:
print ' ' * 11,
print '%-32s' % repr(blob.data.shape),
print '%-30s' % ('(%g, %g)' % (blob.data.min(), blob.data.max())),
print '(%g, %g)' % (blob.diff.min(), blob.diff.max())
print '%-5s'%k, '%-34s' % repr(v.data.shape),
print '%-30s' % ('(%g, %g)' % (v.data.min(), v.data.max())),
print '(%g, %g)' % (v.diff.min(), v.diff.max())


class RegionComputer(object):
'''Computes regions of possible influcence from higher layers to lower layers.'''

@staticmethod
def region_converter(top_slice, filter_width=(1, 1), stride=(1, 1), pad=(0, 0)):
'''
Works for conv or pool

vector<int> ConvolutionLayer<Dtype>::JBY_region_of_influence(const vector<int>& slice) {
+ CHECK_EQ(slice.size(), 4) << "slice must have length 4 (ii_start, ii_end, jj_start, jj_end)";
+ // Crop region to output size
+ vector<int> sl = vector<int>(slice);
+ sl[0] = max(0, min(height_out_, slice[0]));
+ sl[1] = max(0, min(height_out_, slice[1]));
+ sl[2] = max(0, min(width_out_, slice[2]));
+ sl[3] = max(0, min(width_out_, slice[3]));
+ vector<int> roi;
+ roi.resize(4);
+ roi[0] = sl[0] * stride_h_ - pad_h_;
+ roi[1] = (sl[1]-1) * stride_h_ + kernel_h_ - pad_h_;
+ roi[2] = sl[2] * stride_w_ - pad_w_;
+ roi[3] = (sl[3]-1) * stride_w_ + kernel_w_ - pad_w_;
+ return roi;
+}
'''
assert len(top_slice) == 4
assert len(filter_width) == 2
assert len(stride) == 2
assert len(pad) == 2

# Crop top slice to allowable region
top_slice = [ss for ss in top_slice] # Copy list or array -> list

bot_slice = [-123] * 4

bot_slice[0] = top_slice[0] * stride[0] - pad[0]
bot_slice[1] = top_slice[1] * stride[0] - pad[0] + filter_width[0] - 1
bot_slice[2] = top_slice[2] * stride[1] - pad[1]
bot_slice[3] = top_slice[3] * stride[1] - pad[1] + filter_width[1] - 1

return bot_slice


@staticmethod
def merge_regions(region1, region2):

region1_x_start, region1_x_end, region1_y_start, region1_y_end = region1
region2_x_start, region2_x_end, region2_y_start, region2_y_end = region2

merged_x_start = min(region1_x_start, region2_x_start)
merged_x_end = max(region1_x_end, region2_x_end)
merged_y_start = min(region1_y_start, region2_y_start)
merged_y_end = max(region1_y_end, region2_y_end)

merged_region = (merged_x_start, merged_x_end, merged_y_start, merged_y_end)

return merged_region


@staticmethod
def convert_region_dag(settings, from_layer, to_layer, region):

step_region = None

layer_def = settings._layer_name_to_record[from_layer] if from_layer in settings._layer_name_to_record else None

# do single step to convert according to from_layer
if not layer_def:
# fallback to doing nothing
step_region = region

else:

if layer_def.type in ['Convolution', 'Pooling']:
step_region = RegionComputer.region_converter(region, layer_def.filter, layer_def.stride, layer_def.pad)

else:
# fallback to doing nothing
step_region = region

if from_layer == to_layer:
return step_region

# handle the rest
total_region = None

if layer_def is not None:
for parent_layer in layer_def.parents:

# skip inplace layers
if len(parent_layer.tops) == 1 and len(parent_layer.bottoms) == 1 and parent_layer.tops[0] == parent_layer.bottoms[0]:
continue

# calculate convert_region_dag on each one
current_region = RegionComputer.convert_region_dag(settings, parent_layer.name, to_layer, step_region)

# aggregate results
if total_region is None:
total_region = current_region
else:
total_region = RegionComputer.merge_regions(total_region, current_region)

if total_region is None:
return step_region

return total_region


def save_caffe_image(img, filename, autoscale = True, autoscale_center = None):
'''Takes an image in caffe format (01) or (c01, BGR) and saves it to a file'''
if len(img.shape) == 2:
# upsample grayscale 01 -> 01c
img = np.tile(img[:,:,np.newaxis], (1,1,3))
else:
img = img[::-1].transpose((1,2,0))
if autoscale_center is not None:
img = norm01c(img, autoscale_center)
elif autoscale:
img = img.copy()
img -= img.min()
img *= 1.0 / (img.max() + 1e-10)
skimage.io.imsave(filename, img)


def layer_name_to_top_name(net, layer_name):

if net.top_names.has_key(layer_name) and len(net.top_names[layer_name]) >= 1:
return net.top_names[layer_name][0]

else:
return None

def get_max_data_extent(net, settings, layer_name, is_spatial):
'''Gets the maximum size of the data layer that can influence a unit on layer.'''

data_size = net.blobs['data'].data.shape[2:4] # e.g. (227,227) for fc6,fc7,fc8,prop

if is_spatial:
top_name = layer_name_to_top_name(net, layer_name)
conv_size = net.blobs[top_name].data.shape[2:4] # e.g. (13,13) for conv5
layer_slice_middle = (conv_size[0]/2,conv_size[0]/2+1, conv_size[1]/2,conv_size[1]/2+1) # e.g. (6,7,6,7,), the single center unit
data_slice = RegionComputer.convert_region_dag(settings, layer_name, 'input', layer_slice_middle)
data_slice_size = data_slice[1]-data_slice[0], data_slice[3]-data_slice[2] # e.g. (163, 163) for conv5
# crop data slice size to data size
data_slice_size = min(data_slice_size[0], data_size[0]), min(data_slice_size[1], data_size[1])
return data_slice_size
else:
# Whole data region
return data_size


def compute_data_layer_focus_area(is_spatial, ii, jj, settings, layer_name, size_ii, size_jj, data_size_ii, data_size_jj):

if is_spatial:

# Compute the focus area of the data layer
layer_indices = (ii, ii + 1, jj, jj + 1)

data_indices = RegionComputer.convert_region_dag(settings, layer_name, 'input', layer_indices)
data_ii_start, data_ii_end, data_jj_start, data_jj_end = data_indices

# safe guard edges
data_ii_start = max(data_ii_start, 0)
data_jj_start = max(data_jj_start, 0)
data_ii_end = min(data_ii_end, data_size_ii)
data_jj_end = min(data_jj_end, data_size_jj)

touching_imin = (data_ii_start == 0)
touching_jmin = (data_jj_start == 0)

# Compute how much of the data slice falls outside the actual data [0,max] range
ii_outside = size_ii - (data_ii_end - data_ii_start) # possibly 0
jj_outside = size_jj - (data_jj_end - data_jj_start) # possibly 0

if touching_imin:
out_ii_start = ii_outside
out_ii_end = size_ii
else:
out_ii_start = 0
out_ii_end = size_ii - ii_outside
if touching_jmin:
out_jj_start = jj_outside
out_jj_end = size_jj
else:
out_jj_start = 0
out_jj_end = size_jj - jj_outside

else:
data_ii_start, out_ii_start, data_jj_start, out_jj_start = 0, 0, 0, 0
data_ii_end, out_ii_end, data_jj_end, out_jj_end = size_ii, size_ii, size_jj, size_jj

return [out_ii_start, out_ii_end, out_jj_start, out_jj_end, data_ii_start, data_ii_end, data_jj_start, data_jj_end]


def extract_patch_from_image(data, net, selected_input_index, settings,
data_ii_end, data_ii_start, data_jj_end, data_jj_start,
out_ii_end, out_ii_start, out_jj_end, out_jj_start, size_ii, size_jj):
if settings.is_siamese:

# input is first image so select first 3 channels
if selected_input_index == 0:

out_arr = np.zeros((3, size_ii, size_jj), dtype='float32')
out_arr[:, out_ii_start:out_ii_end, out_jj_start:out_jj_end] = data[0:3,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]
# input is second image so select second 3 channels
elif selected_input_index == 1:
out_arr = np.zeros((3, size_ii, size_jj), dtype='float32')
out_arr[:, out_ii_start:out_ii_end, out_jj_start:out_jj_end] = data[3:6,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]
# input is both images so select concatenate data horizontally
elif selected_input_index == -1:

if settings.siamese_input_mode == 'concat_channelwise':
out_arr = np.zeros((3, size_ii, size_jj * 2), dtype='float32')
out_arr[:, out_ii_start:out_ii_end, (0 + out_jj_start):(0 + out_jj_end)] = data[0:3,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]
out_arr[:, out_ii_start:out_ii_end, (size_jj + out_jj_start):(size_jj + out_jj_end)] = data[3:6,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]
elif settings.siamese_input_mode == 'concat_along_width':
out_arr = np.zeros((3, size_ii, size_jj), dtype='float32')
out_arr[:, out_ii_start:out_ii_end, out_jj_start:out_jj_end] = data[:,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]

else:
print "Error: invalid value for selected_input_index (", selected_input_index, ")"
else:
out_arr = np.zeros((3, size_ii, size_jj), dtype='float32')
out_arr[:, out_ii_start:out_ii_end, out_jj_start:out_jj_end] = data[:,
data_ii_start:data_ii_end,
data_jj_start:data_jj_end]
return out_arr
Loading