def transfer(self, new_region_slug):
        """
            Transfer the image
        """
        return self.get_data(
            "images/%s/actions/" % self.id,
            type=POST,
            params={"type": "transfer", "region": new_region_slug}
        )

def transfer ( self , new_region_slug ) : return self . get_data ( "images/%s/actions/" % self . id , type = POST , params = { "type" : "transfer" , "region" : new_region_slug } )


def rename(self, new_name):
        """
            Rename an image
        """
        return self.get_data(
            "images/%s" % self.id,
            type=PUT,
            params={"name": new_name}
        )

def rename ( self , new_name ) : return self . get_data ( "images/%s" % self . id , type = PUT , params = { "name" : new_name } )


def convert_convtranspose(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert transposed convolution layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting transposed convolution ...')

    if names == 'short':
        tf_name = 'C' + random_string(7)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    bias_name = '{0}.bias'.format(w_name)
    weights_name = '{0}.weight'.format(w_name)

    if len(weights[weights_name].numpy().shape) == 4:
        W = weights[weights_name].numpy().transpose(2, 3, 1, 0)
        height, width, n_filters, channels = W.shape

        n_groups = params['group']
        if n_groups > 1:
            raise AssertionError('Cannot convert conv1d with groups != 1')

        if params['dilations'][0] > 1:
            raise AssertionError('Cannot convert conv1d with dilation_rate != 1')

        if bias_name in weights:
            biases = weights[bias_name].numpy()
            has_bias = True
        else:
            biases = None
            has_bias = False

        input_name = inputs[0]

        if has_bias:
            weights = [W, biases]
        else:
            weights = [W]

        conv = keras.layers.Conv2DTranspose(
            filters=n_filters,
            kernel_size=(height, width),
            strides=(params['strides'][0], params['strides'][1]),
            padding='valid',
            output_padding=0,
            weights=weights,
            use_bias=has_bias,
            activation=None,
            dilation_rate=params['dilations'][0],
            bias_initializer='zeros', kernel_initializer='zeros',
            name=tf_name
        )

        layers[scope_name] = conv(layers[input_name])

        # Magic ad-hoc.
        # See the Keras issue: https://github.com/keras-team/keras/issues/6777
        layers[scope_name].set_shape(layers[scope_name]._keras_shape)

        pads = params['pads']
        if pads[0] > 0:
            assert(len(pads) == 2 or (pads[2] == pads[0] and pads[3] == pads[1]))

            crop = keras.layers.Cropping2D(
                pads[:2],
                name=tf_name + '_crop'
            )
            layers[scope_name] = crop(layers[scope_name])
    else:
        raise AssertionError('Layer is not supported for now')


def convert_sum(
    params, w_name, scope_name, inputs, layers, weights, names
):
    """
    Convert sum.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting Sum ...')

    def target_layer(x):
        import keras.backend as K
        return K.sum(x)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_sum
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting Sum ...'
)
def
target_layer
(
x
)
:
import
keras
.
backend
as
K
return
K
.
sum
(
x
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_reduce_sum(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert reduce_sum layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting reduce_sum ...')

    keepdims = params['keepdims'] > 0
    axis = params['axes']

    def target_layer(x, keepdims=keepdims, axis=axis):
        import keras.backend as K
        return K.sum(x, keepdims=keepdims, axis=axis)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_reduce_sum
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting reduce_sum ...'
)
keepdims
=
params
[
'keepdims'
]
>
0
axis
=
params
[
'axes'
]
def
target_layer
(
x
,
keepdims
=
keepdims
,
axis
=
axis
)
:
import
keras
.
backend
as
K
return
K
.
sum
(
x
,
keepdims
=
keepdims
,
axis
=
axis
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_concat(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert concatenation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting concat ...')
    concat_nodes = [layers[i] for i in inputs]

    if len(concat_nodes) == 1:
        # no-op
        layers[scope_name] = concat_nodes[0]
        return

    if names == 'short':
        tf_name = 'CAT' + random_string(5)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    cat = keras.layers.Concatenate(name=tf_name, axis=params['axis'])
    layers[scope_name] = cat(concat_nodes)

def
convert_concat
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting concat ...'
)
concat_nodes
=
[
layers
[
i
]
for
i
in
inputs
]
if
len
(
concat_nodes
)
==
1
:
layers
[
scope_name
]
=
concat_nodes
[
0
]
return
if
names
==
'short'
:
tf_name
=
'CAT'
+
random_string
(
5
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
cat
=
keras
.
layers
.
Concatenate
(
name
=
tf_name
,
axis
=
params
[
'axis'
]
)
layers
[
scope_name
]
=
cat
(
concat_nodes
)


def convert_slice(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert slice operation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting slice ...')

    if len(params['axes']) > 1:
        raise AssertionError('Cannot convert slice by multiple dimensions')

    if params['axes'][0] not in [0, 1, 2, 3]:
        raise AssertionError('Slice by dimension more than 3 or less than 0 is not supported')

    def target_layer(x, axis=int(params['axes'][0]), start=int(params['starts'][0]), end=int(params['ends'][0])):
        if axis == 0:
            return x[start:end]
        elif axis == 1:
            return x[:, start:end]
        elif axis == 2:
            return x[:, :, start:end]
        elif axis == 3:
            return x[:, :, :, start:end]

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])


def convert_clip(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert clip operation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting clip ...')

    if params['min'] == 0:
        print("using ReLU({0})".format(params['max']))
        layer = keras.layers.ReLU(max_value=params['max'])
    else:
        def target_layer(x, vmin=params['min'], vmax=params['max']):
            import tensorflow as tf
            return tf.clip_by_value(x, vmin, vmax)
        layer = keras.layers.Lambda(target_layer)

    layers[scope_name] = layer(layers[inputs[0]])

def
convert_clip
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting clip ...'
)
if
params
[
'min'
]
==
0
:
print
(
"using ReLU({0})"
.
format
(
params
[
'max'
]
)
)
layer
=
keras
.
layers
.
ReLU
(
max_value
=
params
[
'max'
]
)
else
:
def
target_layer
(
x
,
vmin
=
params
[
'min'
]
,
vmax
=
params
[
'max'
]
)
:
import
tensorflow
as
tf
return
tf
.
clip_by_value
(
x
,
vmin
,
vmax
)
layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
layer
(
layers
[
inputs
[
0
]
]
)


def convert_elementwise_add(
    params, w_name, scope_name, inputs, layers, weights, names
):
    """
    Convert elementwise addition.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting elementwise_add ...')
    if 'broadcast' in params:
        model0 = layers[inputs[0]]
        model1 = layers[inputs[1]]

        if names == 'short':
            tf_name = 'A' + random_string(7)
        elif names == 'keep':
            tf_name = w_name
        else:
            tf_name = w_name + str(random.random())

        def target_layer(x):
            layer = tf.add(x[0], x[1])
            return layer

        lambda_layer = keras.layers.Lambda(target_layer, name=tf_name)
        layers[scope_name] = lambda_layer([layers[inputs[0]], layers[inputs[1]]])
    else:
        model0 = layers[inputs[0]]
        model1 = layers[inputs[1]]

        if names == 'short':
            tf_name = 'A' + random_string(7)
        elif names == 'keep':
            tf_name = w_name
        else:
            tf_name = w_name + str(random.random())

        add = keras.layers.Add(name=tf_name)
        layers[scope_name] = add([model0, model1])

def
convert_elementwise_add
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting elementwise_add ...'
)
if
'broadcast'
in
params
:
model0
=
layers
[
inputs
[
0
]
]
model1
=
layers
[
inputs
[
1
]
]
if
names
==
'short'
:
tf_name
=
'A'
+
random_string
(
7
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
def
target_layer
(
x
)
:
layer
=
tf
.
add
(
x
[
0
]
,
x
[
1
]
)
return
layer
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
,
name
=
tf_name
)
layers
[
scope_name
]
=
lambda_layer
(
[
layers
[
inputs
[
0
]
]
,
layers
[
inputs
[
1
]
]
]
)
else
:
model0
=
layers
[
inputs
[
0
]
]
model1
=
layers
[
inputs
[
1
]
]
if
names
==
'short'
:
tf_name
=
'A'
+
random_string
(
7
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
add
=
keras
.
layers
.
Add
(
name
=
tf_name
)
layers
[
scope_name
]
=
add
(
[
model0
,
model1
]
)


def convert_elementwise_sub(
    params, w_name, scope_name, inputs, layers, weights, names
):
    """
    Convert elementwise subtraction.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting elementwise_sub ...')
    model0 = layers[inputs[0]]
    model1 = layers[inputs[1]]

    if names == 'short':
        tf_name = 'S' + random_string(7)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    sub = keras.layers.Subtract(name=tf_name)
    layers[scope_name] = sub([model0, model1])

def
convert_elementwise_sub
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting elementwise_sub ...'
)
model0
=
layers
[
inputs
[
0
]
]
model1
=
layers
[
inputs
[
1
]
]
if
names
==
'short'
:
tf_name
=
'S'
+
random_string
(
7
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
sub
=
keras
.
layers
.
Subtract
(
name
=
tf_name
)
layers
[
scope_name
]
=
sub
(
[
model0
,
model1
]
)


def convert_gemm(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert Linear.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting Linear ...')

    if names == 'short':
        tf_name = 'FC' + random_string(6)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    bias_name = '{0}.bias'.format(w_name)
    weights_name = '{0}.weight'.format(w_name)

    W = weights[weights_name].numpy().transpose()
    input_channels, output_channels = W.shape

    keras_weights = [W]
    has_bias = False
    if bias_name in weights:
        bias = weights[bias_name].numpy()
        keras_weights = [W, bias]
        has_bias = True

    dense = keras.layers.Dense(
        output_channels,
        weights=keras_weights, use_bias=has_bias, name=tf_name, bias_initializer='zeros', kernel_initializer='zeros',
    )

    layers[scope_name] = dense(layers[inputs[0]])

def
convert_gemm
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting Linear ...'
)
if
names
==
'short'
:
tf_name
=
'FC'
+
random_string
(
6
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
bias_name
=
'{0}.bias'
.
format
(
w_name
)
weights_name
=
'{0}.weight'
.
format
(
w_name
)
W
=
weights
[
weights_name
]
.
numpy
(
)
.
transpose
(
)
input_channels
,
output_channels
=
W
.
shape
keras_weights
=
[
W
]
has_bias
=
False
if
bias_name
in
weights
:
bias
=
weights
[
bias_name
]
.
numpy
(
)
keras_weights
=
[
W
,
bias
]
has_bias
=
True
dense
=
keras
.
layers
.
Dense
(
output_channels
,
weights
=
keras_weights
,
use_bias
=
has_bias
,
name
=
tf_name
,
bias_initializer
=
'zeros'
,
kernel_initializer
=
'zeros'
,
)
layers
[
scope_name
]
=
dense
(
layers
[
inputs
[
0
]
]
)


def convert_matmul(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert matmul layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting matmul ...')

    if names == 'short':
        tf_name = 'MMUL' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    if len(inputs) == 1:
        weights_name = '{0}.weight'.format(w_name)

        W = weights[weights_name].numpy().transpose()
        input_channels, output_channels = W.shape

        keras_weights = [W]

        dense = keras.layers.Dense(
            output_channels,
            weights=keras_weights, use_bias=False, name=tf_name, bias_initializer='zeros', kernel_initializer='zeros',
        )
        layers[scope_name] = dense(layers[inputs[0]])
    elif len(inputs) == 2:
        weights_name = '{0}.weight'.format(w_name)

        W = weights[weights_name].numpy().transpose()
        input_channels, output_channels = W.shape

        keras_weights = [W]

        dense = keras.layers.Dense(
            output_channels,
            weights=keras_weights, use_bias=False, name=tf_name, bias_initializer='zeros', kernel_initializer='zeros',
        )
        layers[scope_name] = dense(layers[inputs[0]])
    else:
        raise AssertionError('Cannot convert matmul layer')

def
convert_matmul
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting matmul ...'
)
if
names
==
'short'
:
tf_name
=
'MMUL'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
if
len
(
inputs
)
==
1
:
weights_name
=
'{0}.weight'
.
format
(
w_name
)
W
=
weights
[
weights_name
]
.
numpy
(
)
.
transpose
(
)
input_channels
,
output_channels
=
W
.
shape
keras_weights
=
[
W
]
dense
=
keras
.
layers
.
Dense
(
output_channels
,
weights
=
keras_weights
,
use_bias
=
False
,
name
=
tf_name
,
bias_initializer
=
'zeros'
,
kernel_initializer
=
'zeros'
,
)
layers
[
scope_name
]
=
dense
(
layers
[
inputs
[
0
]
]
)
elif
len
(
inputs
)
==
2
:
weights_name
=
'{0}.weight'
.
format
(
w_name
)
W
=
weights
[
weights_name
]
.
numpy
(
)
.
transpose
(
)
input_channels
,
output_channels
=
W
.
shape
keras_weights
=
[
W
]
dense
=
keras
.
layers
.
Dense
(
output_channels
,
weights
=
keras_weights
,
use_bias
=
False
,
name
=
tf_name
,
bias_initializer
=
'zeros'
,
kernel_initializer
=
'zeros'
,
)
layers
[
scope_name
]
=
dense
(
layers
[
inputs
[
0
]
]
)
else
:
raise
AssertionError
(
'Cannot convert matmul layer'
)


def convert_constant(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert constant layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting constant ...')

    params_list = params['value'].numpy()

    def target_layer(x, value=params_list):
        return tf.constant(value.tolist(), shape=value.shape)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name + '_np'] = params_list  # ad-hoc
    layers[scope_name] = lambda_layer(layers[list(layers.keys())[0]])

def
convert_constant
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting constant ...'
)
params_list
=
params
[
'value'
]
.
numpy
(
)
def
target_layer
(
x
,
value
=
params_list
)
:
return
tf
.
constant
(
value
.
tolist
(
)
,
shape
=
value
.
shape
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
+
'_np'
]
=
params_list
layers
[
scope_name
]
=
lambda_layer
(
layers
[
list
(
layers
.
keys
(
)
)
[
0
]
]
)


def convert_transpose(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert transpose layer.

   Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting transpose ...')
    if params['perm'][0] != 0:
        if inputs[0] in layers:
            print('!!! Cannot permute batch dimension. Result may be wrong !!!')
            layers[scope_name] = layers[inputs[0]]
        else:
            print('Skip weight matrix transpose, result may be wrong.')
    else:
        if names:
            tf_name = 'PERM' + random_string(4)
        else:
            tf_name = w_name + str(random.random())
        permute = keras.layers.Permute(params['perm'][1:], name=tf_name)
        layers[scope_name] = permute(layers[inputs[0]])


def convert_reshape(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert reshape layer.

   Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting reshape ...')
    if names == 'short':
        tf_name = 'RESH' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    if len(inputs) > 1:
        if layers[inputs[1]][0] == -1:
            print('Cannot deduct batch size! It will be omitted, but result may be wrong.')

        reshape = keras.layers.Reshape(layers[inputs[1] + '_np'], name=tf_name)
        layers[scope_name] = reshape(layers[inputs[0]])
    else:
        if inputs[0] in layers:
            reshape = keras.layers.Reshape(params['shape'][1:], name=tf_name)
            layers[scope_name] = reshape(layers[inputs[0]])
        else:
            print('Skip weight matrix transpose, but result may be wrong.')


def convert_squeeze(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert squeeze operation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting squeeze ...')

    if len(params['axes']) > 1:
        raise AssertionError('Cannot convert squeeze by multiple dimensions')

    def target_layer(x, axis=int(params['axes'][0])):
        import tensorflow as tf
        return tf.squeeze(x, axis=axis)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])


def convert_unsqueeze(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert unsqueeze operation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting unsqueeze ...')

    if names == 'short':
        tf_name = 'UNSQ' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    def target_layer(x):
        import keras
        return keras.backend.expand_dims(x)

    lambda_layer = keras.layers.Lambda(target_layer, name=tf_name + 'E')
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_unsqueeze
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting unsqueeze ...'
)
if
names
==
'short'
:
tf_name
=
'UNSQ'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
def
target_layer
(
x
)
:
import
keras
return
keras
.
backend
.
expand_dims
(
x
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
,
name
=
tf_name
+
'E'
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_shape(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert shape operation.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting shape ...')

    def target_layer(x):
        import tensorflow as tf
        return tf.shape(x)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_shape
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting shape ...'
)
def
target_layer
(
x
)
:
import
tensorflow
as
tf
return
tf
.
shape
(
x
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_avgpool(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert Average pooling.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting pooling ...')

    if names == 'short':
        tf_name = 'P' + random_string(7)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    if 'kernel_shape' in params:
        height, width = params['kernel_shape']
    else:
        height, width = params['kernel_size']

    if 'strides' in params:
        stride_height, stride_width = params['strides']
    else:
        stride_height, stride_width = params['stride']

    if 'pads' in params:
        padding_h, padding_w, _, _ = params['pads']
    else:
        padding_h, padding_w = params['padding']

    input_name = inputs[0]
    pad = 'valid'

    if height % 2 == 1 and width % 2 == 1 and \
       height // 2 == padding_h and width // 2 == padding_w and \
       stride_height == 1 and stride_width == 1:
        pad = 'same'
    else:
        padding_name = tf_name + '_pad'
        padding_layer = keras.layers.ZeroPadding2D(
            padding=(padding_h, padding_w),
            name=padding_name
        )
        layers[padding_name] = padding_layer(layers[inputs[0]])
        input_name = padding_name

    # Pooling type AveragePooling2D
    pooling = keras.layers.AveragePooling2D(
        pool_size=(height, width),
        strides=(stride_height, stride_width),
        padding=pad,
        name=tf_name,
        data_format='channels_first'
    )

    layers[scope_name] = pooling(layers[input_name])

def
convert_avgpool
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting pooling ...'
)
if
names
==
'short'
:
tf_name
=
'P'
+
random_string
(
7
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
if
'kernel_shape'
in
params
:
height
,
width
=
params
[
'kernel_shape'
]
else
:
height
,
width
=
params
[
'kernel_size'
]
if
'strides'
in
params
:
stride_height
,
stride_width
=
params
[
'strides'
]
else
:
stride_height
,
stride_width
=
params
[
'stride'
]
if
'pads'
in
params
:
padding_h
,
padding_w
,
_
,
_
=
params
[
'pads'
]
else
:
padding_h
,
padding_w
=
params
[
'padding'
]
input_name
=
inputs
[
0
]
pad
=
'valid'
if
height
%
2
==
1
and
width
%
2
==
1
and
height
//
2
==
padding_h
and
width
//
2
==
padding_w
and
stride_height
==
1
and
stride_width
==
1
:
pad
=
'same'
else
:
padding_name
=
tf_name
+
'_pad'
padding_layer
=
keras
.
layers
.
ZeroPadding2D
(
padding
=
(
padding_h
,
padding_w
)
,
name
=
padding_name
)
layers
[
padding_name
]
=
padding_layer
(
layers
[
inputs
[
0
]
]
)
input_name
=
padding_name
pooling
=
keras
.
layers
.
AveragePooling2D
(
pool_size
=
(
height
,
width
)
,
strides
=
(
stride_height
,
stride_width
)
,
padding
=
pad
,
name
=
tf_name
,
data_format
=
'channels_first'
)
layers
[
scope_name
]
=
pooling
(
layers
[
input_name
]
)


def convert_maxpool3(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert 3d Max pooling.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """

    print('Converting pooling ...')

    if names == 'short':
        tf_name = 'P' + random_string(7)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    if 'kernel_shape' in params:
        height, width, depth = params['kernel_shape']
    else:
        height, width, depth = params['kernel_size']

    if 'strides' in params:
        stride_height, stride_width, stride_depth = params['strides']
    else:
        stride_height, stride_width, stride_depth = params['stride']

    if 'pads' in params:
        padding_h, padding_w, padding_d, _, _ = params['pads']
    else:
        padding_h, padding_w, padding_d = params['padding']

    input_name = inputs[0]
    if padding_h > 0 and padding_w > 0 and padding_d > 0:
        padding_name = tf_name + '_pad'
        padding_layer = keras.layers.ZeroPadding3D(
            padding=(padding_h, padding_w, padding_d),
            name=padding_name
        )
        layers[padding_name] = padding_layer(layers[inputs[0]])
        input_name = padding_name

    # Pooling type
    pooling = keras.layers.MaxPooling3D(
        pool_size=(height, width, depth),
        strides=(stride_height, stride_width, stride_depth),
        padding='valid',
        name=tf_name
    )

    layers[scope_name] = pooling(layers[input_name])

def
convert_maxpool3
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting pooling ...'
)
if
names
==
'short'
:
tf_name
=
'P'
+
random_string
(
7
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
if
'kernel_shape'
in
params
:
height
,
width
,
depth
=
params
[
'kernel_shape'
]
else
:
height
,
width
,
depth
=
params
[
'kernel_size'
]
if
'strides'
in
params
:
stride_height
,
stride_width
,
stride_depth
=
params
[
'strides'
]
else
:
stride_height
,
stride_width
,
stride_depth
=
params
[
'stride'
]
if
'pads'
in
params
:
padding_h
,
padding_w
,
padding_d
,
_
,
_
=
params
[
'pads'
]
else
:
padding_h
,
padding_w
,
padding_d
=
params
[
'padding'
]
input_name
=
inputs
[
0
]
if
padding_h
>
0
and
padding_w
>
0
and
padding_d
>
0
:
padding_name
=
tf_name
+
'_pad'
padding_layer
=
keras
.
layers
.
ZeroPadding3D
(
padding
=
(
padding_h
,
padding_w
,
padding_d
)
,
name
=
padding_name
)
layers
[
padding_name
]
=
padding_layer
(
layers
[
inputs
[
0
]
]
)
input_name
=
padding_name
pooling
=
keras
.
layers
.
MaxPooling3D
(
pool_size
=
(
height
,
width
,
depth
)
,
strides
=
(
stride_height
,
stride_width
,
stride_depth
)
,
padding
=
'valid'
,
name
=
tf_name
)
layers
[
scope_name
]
=
pooling
(
layers
[
input_name
]
)


def convert_adaptive_max_pool2d(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert convert_adaptive_max_pool2d layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting adaptive_avg_pool2d...')

    if names == 'short':
        tf_name = 'APOL' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    global_pool = keras.layers.GlobalMaxPooling2D(data_format='channels_first', name=tf_name)
    layers[scope_name] = global_pool(layers[inputs[0]])

    def target_layer(x):
        import keras
        return keras.backend.expand_dims(x)

    lambda_layer = keras.layers.Lambda(target_layer, name=tf_name + 'E')
    layers[scope_name] = lambda_layer(layers[scope_name])  # double expand dims
    layers[scope_name] = lambda_layer(layers[scope_name])

def
convert_adaptive_max_pool2d
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting adaptive_avg_pool2d...'
)
if
names
==
'short'
:
tf_name
=
'APOL'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
global_pool
=
keras
.
layers
.
GlobalMaxPooling2D
(
data_format
=
'channels_first'
,
name
=
tf_name
)
layers
[
scope_name
]
=
global_pool
(
layers
[
inputs
[
0
]
]
)
def
target_layer
(
x
)
:
import
keras
return
keras
.
backend
.
expand_dims
(
x
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
,
name
=
tf_name
+
'E'
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
scope_name
]
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
scope_name
]
)

Convert convert_adaptive_max_pool2d layer .


def convert_padding(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert padding layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting padding...')

    if params['mode'] == 'constant':
        # raise AssertionError('Cannot convert non-constant padding')

        if params['value'] != 0.0:
            raise AssertionError('Cannot convert non-zero padding')

        if names:
            tf_name = 'PADD' + random_string(4)
        else:
            tf_name = w_name + str(random.random())

        # Magic ordering
        padding_name = tf_name
        padding_layer = keras.layers.ZeroPadding2D(
            padding=((params['pads'][2], params['pads'][6]), (params['pads'][3], params['pads'][7])),
            name=padding_name
        )

        layers[scope_name] = padding_layer(layers[inputs[0]])
    elif params['mode'] == 'reflect':

        def target_layer(x, pads=params['pads']):
            # x = tf.transpose(x, [0, 2, 3, 1])
            layer = tf.pad(x, [[0, 0], [0, 0], [pads[2], pads[6]], [pads[3], pads[7]]], 'REFLECT')
            # layer = tf.transpose(layer, [0, 3, 1, 2])
            return layer

        lambda_layer = keras.layers.Lambda(target_layer)
        layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_padding
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting padding...'
)
if
params
[
'mode'
]
==
'constant'
:
if
params
[
'value'
]
!=
0.0
:
raise
AssertionError
(
'Cannot convert non-zero padding'
)
if
names
:
tf_name
=
'PADD'
+
random_string
(
4
)
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
padding_name
=
tf_name
padding_layer
=
keras
.
layers
.
ZeroPadding2D
(
padding
=
(
(
params
[
'pads'
]
[
2
]
,
params
[
'pads'
]
[
6
]
)
,
(
params
[
'pads'
]
[
3
]
,
params
[
'pads'
]
[
7
]
)
)
,
name
=
padding_name
)
layers
[
scope_name
]
=
padding_layer
(
layers
[
inputs
[
0
]
]
)
elif
params
[
'mode'
]
==
'reflect'
:
def
target_layer
(
x
,
pads
=
params
[
'pads'
]
)
:
layer
=
tf
.
pad
(
x
,
[
[
0
,
0
]
,
[
0
,
0
]
,
[
pads
[
2
]
,
pads
[
6
]
]
,
[
pads
[
3
]
,
pads
[
7
]
]
]
,
'REFLECT'
)
return
layer
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_batchnorm(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert batch normalization layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting batchnorm ...')

    if names == 'short':
        tf_name = 'BN' + random_string(6)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    bias_name = '{0}.bias'.format(w_name)
    weights_name = '{0}.weight'.format(w_name)
    mean_name = '{0}.running_mean'.format(w_name)
    var_name = '{0}.running_var'.format(w_name)

    if bias_name in weights:
        beta = weights[bias_name].numpy()

    if weights_name in weights:
        gamma = weights[weights_name].numpy()

    mean = weights[mean_name].numpy()
    variance = weights[var_name].numpy()

    eps = params['epsilon']
    momentum = params['momentum']

    if weights_name not in weights:
        bn = keras.layers.BatchNormalization(
            axis=1, momentum=momentum, epsilon=eps,
            center=False, scale=False,
            weights=[mean, variance],
            name=tf_name
        )
    else:
        bn = keras.layers.BatchNormalization(
            axis=1, momentum=momentum, epsilon=eps,
            weights=[gamma, beta, mean, variance],
            name=tf_name
        )
    layers[scope_name] = bn(layers[inputs[0]])

def
convert_batchnorm
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting batchnorm ...'
)
if
names
==
'short'
:
tf_name
=
'BN'
+
random_string
(
6
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
bias_name
=
'{0}.bias'
.
format
(
w_name
)
weights_name
=
'{0}.weight'
.
format
(
w_name
)
mean_name
=
'{0}.running_mean'
.
format
(
w_name
)
var_name
=
'{0}.running_var'
.
format
(
w_name
)
if
bias_name
in
weights
:
beta
=
weights
[
bias_name
]
.
numpy
(
)
if
weights_name
in
weights
:
gamma
=
weights
[
weights_name
]
.
numpy
(
)
mean
=
weights
[
mean_name
]
.
numpy
(
)
variance
=
weights
[
var_name
]
.
numpy
(
)
eps
=
params
[
'epsilon'
]
momentum
=
params
[
'momentum'
]
if
weights_name
not
in
weights
:
bn
=
keras
.
layers
.
BatchNormalization
(
axis
=
1
,
momentum
=
momentum
,
epsilon
=
eps
,
center
=
False
,
scale
=
False
,
weights
=
[
mean
,
variance
]
,
name
=
tf_name
)
else
:
bn
=
keras
.
layers
.
BatchNormalization
(
axis
=
1
,
momentum
=
momentum
,
epsilon
=
eps
,
weights
=
[
gamma
,
beta
,
mean
,
variance
]
,
name
=
tf_name
)
layers
[
scope_name
]
=
bn
(
layers
[
inputs
[
0
]
]
)


def convert_instancenorm(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert instance normalization layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting instancenorm ...')

    if names == 'short':
        tf_name = 'IN' + random_string(6)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    assert(len(inputs) == 3)

    bias_name = '{0}.bias'.format(w_name)
    weights_name = '{0}.weight'.format(w_name)

    # Use previously taken constants
    if inputs[-2] + '_np' in layers:
        gamma = layers[inputs[-2] + '_np']
    else:
        gamma = weights[weights_name].numpy()

    if inputs[-1] + '_np' in layers:
        beta = layers[inputs[-1] + '_np']
    else:
        beta = weights[bias_name].numpy()

    def target_layer(x, epsilon=params['epsilon'], gamma=gamma, beta=beta):
        layer = tf.contrib.layers.instance_norm(
            x,
            param_initializers={'beta': tf.constant_initializer(beta), 'gamma': tf.constant_initializer(gamma)},
            epsilon=epsilon, data_format='NCHW',
            trainable=False
        )
        return layer

    lambda_layer = keras.layers.Lambda(target_layer, name=tf_name)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_instancenorm
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting instancenorm ...'
)
if
names
==
'short'
:
tf_name
=
'IN'
+
random_string
(
6
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
assert
(
len
(
inputs
)
==
3
)
bias_name
=
'{0}.bias'
.
format
(
w_name
)
weights_name
=
'{0}.weight'
.
format
(
w_name
)
if
inputs
[
2
]
+
'_np'
in
layers
:
gamma
=
layers
[
inputs
[
2
]
+
'_np'
]
else
:
gamma
=
weights
[
weights_name
]
.
numpy
(
)
if
inputs
[
1
]
+
'_np'
in
layers
:
beta
=
layers
[
inputs
[
1
]
+
'_np'
]
else
:
beta
=
weights
[
bias_name
]
.
numpy
(
)
def
target_layer
(
x
,
epsilon
=
params
[
'epsilon'
]
,
gamma
=
gamma
,
beta
=
beta
)
:
layer
=
tf
.
contrib
.
layers
.
instance_norm
(
x
,
param_initializers
=
{
'beta'
:
tf
.
constant_initializer
(
beta
)
,
'gamma'
:
tf
.
constant_initializer
(
gamma
)
}
,
epsilon
=
epsilon
,
data_format
=
'NCHW'
,
trainable
=
False
)
return
layer
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
,
name
=
tf_name
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_dropout(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert dropout.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting dropout ...')

    if names == 'short':
        tf_name = 'DO' + random_string(6)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    dropout = keras.layers.Dropout(rate=params['ratio'], name=tf_name)
    layers[scope_name] = dropout(layers[inputs[0]])

def
convert_dropout
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting dropout ...'
)
if
names
==
'short'
:
tf_name
=
'DO'
+
random_string
(
6
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
dropout
=
keras
.
layers
.
Dropout
(
rate
=
params
[
'ratio'
]
,
name
=
tf_name
)
layers
[
scope_name
]
=
dropout
(
layers
[
inputs
[
0
]
]
)


def convert_relu(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert relu layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting relu ...')

    if names == 'short':
        tf_name = 'RELU' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    relu = keras.layers.Activation('relu', name=tf_name)
    layers[scope_name] = relu(layers[inputs[0]])

def
convert_relu
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting relu ...'
)
if
names
==
'short'
:
tf_name
=
'RELU'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
relu
=
keras
.
layers
.
Activation
(
'relu'
,
name
=
tf_name
)
layers
[
scope_name
]
=
relu
(
layers
[
inputs
[
0
]
]
)


def convert_lrelu(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert leaky relu layer.

   Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting lrelu ...')

    if names == 'short':
        tf_name = 'lRELU' + random_string(3)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    leakyrelu = \
        keras.layers.LeakyReLU(alpha=params['alpha'], name=tf_name)
    layers[scope_name] = leakyrelu(layers[inputs[0]])

def
convert_lrelu
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting lrelu ...'
)
if
names
==
'short'
:
tf_name
=
'lRELU'
+
random_string
(
3
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
leakyrelu
=
keras
.
layers
.
LeakyReLU
(
alpha
=
params
[
'alpha'
]
,
name
=
tf_name
)
layers
[
scope_name
]
=
leakyrelu
(
layers
[
inputs
[
0
]
]
)


def convert_sigmoid(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert sigmoid layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting sigmoid ...')

    if names == 'short':
        tf_name = 'SIGM' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    sigmoid = keras.layers.Activation('sigmoid', name=tf_name)
    layers[scope_name] = sigmoid(layers[inputs[0]])

def
convert_sigmoid
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting sigmoid ...'
)
if
names
==
'short'
:
tf_name
=
'SIGM'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
sigmoid
=
keras
.
layers
.
Activation
(
'sigmoid'
,
name
=
tf_name
)
layers
[
scope_name
]
=
sigmoid
(
layers
[
inputs
[
0
]
]
)


def convert_softmax(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert softmax layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting softmax ...')

    if names == 'short':
        tf_name = 'SMAX' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    def target_layer(x, dim=params['dim']):
        import keras
        return keras.activations.softmax(x, axis=dim)

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_softmax
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting softmax ...'
)
if
names
==
'short'
:
tf_name
=
'SMAX'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
def
target_layer
(
x
,
dim
=
params
[
'dim'
]
)
:
import
keras
return
keras
.
activations
.
softmax
(
x
,
axis
=
dim
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_tanh(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert tanh layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting tanh ...')

    if names == 'short':
        tf_name = 'TANH' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    tanh = keras.layers.Activation('tanh', name=tf_name)
    layers[scope_name] = tanh(layers[inputs[0]])

def
convert_tanh
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting tanh ...'
)
if
names
==
'short'
:
tf_name
=
'TANH'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
tanh
=
keras
.
layers
.
Activation
(
'tanh'
,
name
=
tf_name
)
layers
[
scope_name
]
=
tanh
(
layers
[
inputs
[
0
]
]
)


def convert_hardtanh(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert hardtanh layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting hardtanh (clip) ...')

    def target_layer(x, max_val=float(params['max_val']), min_val=float(params['min_val'])):
        return tf.minimum(max_val, tf.maximum(min_val, x))

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_hardtanh
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting hardtanh (clip) ...'
)
def
target_layer
(
x
,
max_val
=
float
(
params
[
'max_val'
]
)
,
min_val
=
float
(
params
[
'min_val'
]
)
)
:
return
tf
.
minimum
(
max_val
,
tf
.
maximum
(
min_val
,
x
)
)
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_selu(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert selu layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting selu ...')

    if names == 'short':
        tf_name = 'SELU' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    selu = keras.layers.Activation('selu', name=tf_name)
    layers[scope_name] = selu(layers[inputs[0]])

def
convert_selu
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting selu ...'
)
if
names
==
'short'
:
tf_name
=
'SELU'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
selu
=
keras
.
layers
.
Activation
(
'selu'
,
name
=
tf_name
)
layers
[
scope_name
]
=
selu
(
layers
[
inputs
[
0
]
]
)


def convert_upsample_bilinear(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert upsample_bilinear2d layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting upsample...')

    if names == 'short':
        tf_name = 'UPSL' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    output_size = params['output_size']
    align_corners = params['align_corners'] > 0

    def target_layer(x, size=output_size, align_corners=align_corners):
        import tensorflow as tf
        x = tf.transpose(x, [0, 2, 3, 1])
        x = tf.image.resize_images(x, size, align_corners=align_corners)
        x = tf.transpose(x, [0, 3, 1, 2])
        return x

    lambda_layer = keras.layers.Lambda(target_layer)
    layers[scope_name] = lambda_layer(layers[inputs[0]])

def
convert_upsample_bilinear
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting upsample...'
)
if
names
==
'short'
:
tf_name
=
'UPSL'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
output_size
=
params
[
'output_size'
]
align_corners
=
params
[
'align_corners'
]
>
0
def
target_layer
(
x
,
size
=
output_size
,
align_corners
=
align_corners
)
:
import
tensorflow
as
tf
x
=
tf
.
transpose
(
x
,
[
0
,
2
,
3
,
1
]
)
x
=
tf
.
image
.
resize_images
(
x
,
size
,
align_corners
=
align_corners
)
x
=
tf
.
transpose
(
x
,
[
0
,
3
,
1
,
2
]
)
return
x
lambda_layer
=
keras
.
layers
.
Lambda
(
target_layer
)
layers
[
scope_name
]
=
lambda_layer
(
layers
[
inputs
[
0
]
]
)


def convert_upsample(params, w_name, scope_name, inputs, layers, weights, names):
    """
    Convert nearest upsampling layer.

    Args:
        params: dictionary with layer parameters
        w_name: name prefix in state_dict
        scope_name: pytorch scope name
        inputs: pytorch node inputs
        layers: dictionary with keras tensors
        weights: pytorch state_dict
        names: use short names for keras layers
    """
    print('Converting upsample...')

    if params['mode'] != 'nearest':
        raise AssertionError('Cannot convert non-nearest upsampling')

    if names == 'short':
        tf_name = 'UPSL' + random_string(4)
    elif names == 'keep':
        tf_name = w_name
    else:
        tf_name = w_name + str(random.random())

    if 'height_scale' in params:
        scale = (params['height_scale'], params['width_scale'])
    elif len(inputs) == 2:
        scale = layers[inputs[-1] + '_np'][-2:]

    upsampling = keras.layers.UpSampling2D(
        size=scale, name=tf_name
    )
    layers[scope_name] = upsampling(layers[inputs[0]])

def
convert_upsample
(
params
,
w_name
,
scope_name
,
inputs
,
layers
,
weights
,
names
)
:
print
(
'Converting upsample...'
)
if
params
[
'mode'
]
!=
'nearest'
:
raise
AssertionError
(
'Cannot convert non-nearest upsampling'
)
if
names
==
'short'
:
tf_name
=
'UPSL'
+
random_string
(
4
)
elif
names
==
'keep'
:
tf_name
=
w_name
else
:
tf_name
=
w_name
+
str
(
random
.
random
(
)
)
if
'height_scale'
in
params
:
scale
=
(
params
[
'height_scale'
]
,
params
[
'width_scale'
]
)
elif
len
(
inputs
)
==
2
:
scale
=
layers
[
inputs
[
1
]
+
'_np'
]
[
2
:
]
upsampling
=
keras
.
layers
.
UpSampling2D
(
size
=
scale
,
name
=
tf_name
)
layers
[
scope_name
]
=
upsampling
(
layers
[
inputs
[
0
]
]
)


def set_training(model, mode):
    """
    A context manager to temporarily set the training mode of 'model'
    to 'mode', resetting it when we exit the with-block.  A no-op if
    mode is None.
    """
    if mode is None:
        yield
        return
    old_mode = model.training
    if old_mode != mode:
        model.train(mode)
    try:
        yield
    finally:
        if old_mode != mode:
            model.train(old_mode)

def set_training ( model , mode ) : if mode is None : yield return old_mode = model . training if old_mode != mode : model . train ( mode ) try : yield finally : if old_mode != mode : model . train ( old_mode )

A context manager to temporarily set the training mode of model to mode resetting it when we exit the with - block . A no - op if mode is None .


def get_platform_pwm(**keywords):
    """Attempt to return a PWM instance for the platform which the code is being
    executed on.  Currently supports only the Raspberry Pi using the RPi.GPIO
    library and Beaglebone Black using the Adafruit_BBIO library.  Will throw an
    exception if a PWM instance can't be created for the current platform.  The
    returned PWM object has the same interface as the RPi_PWM_Adapter and
    BBIO_PWM_Adapter classes.
    """
    plat = Platform.platform_detect()
    if plat == Platform.RASPBERRY_PI:
        import RPi.GPIO
        return RPi_PWM_Adapter(RPi.GPIO, **keywords)
    elif plat == Platform.BEAGLEBONE_BLACK:
        import Adafruit_BBIO.PWM
        return BBIO_PWM_Adapter(Adafruit_BBIO.PWM, **keywords)
    elif plat == Platform.UNKNOWN:
        raise RuntimeError('Could not determine platform.')

def
get_platform_pwm
(
**
keywords
)
:
plat
=
Platform
.
platform_detect
(
)
if
plat
==
Platform
.
RASPBERRY_PI
:
import
RPi
.
GPIO
return
RPi_PWM_Adapter
(
RPi
.
GPIO
,
**
keywords
)
elif
plat
==
Platform
.
BEAGLEBONE_BLACK
:
import
Adafruit_BBIO
.
PWM
return
BBIO_PWM_Adapter
(
Adafruit_BBIO
.
PWM
,
**
keywords
)
elif
plat
==
Platform
.
UNKNOWN
:
raise
RuntimeError
(
'Could not determine platform.'
)

Attempt to return a PWM instance for the platform which the code is being executed on . Currently supports only the Raspberry Pi using the RPi . GPIO library and Beaglebone Black using the Adafruit_BBIO library . Will throw an exception if a PWM instance can t be created for the current platform . The returned PWM object has the same interface as the RPi_PWM_Adapter and BBIO_PWM_Adapter classes .


def stop(self, pin):
        """Stop PWM output on specified pin."""
        if pin not in self.pwm:
            raise ValueError('Pin {0} is not configured as a PWM.  Make sure to first call start for the pin.'.format(pin))
        self.pwm[pin].stop()
        del self.pwm[pin]


def platform_detect():
    """Detect if running on the Raspberry Pi or Beaglebone Black and return the
    platform type.  Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN."""
    # Handle Raspberry Pi
    pi = pi_version()
    if pi is not None:
        return RASPBERRY_PI

    # Handle Beaglebone Black
    # TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading
    # the platform.
    plat = platform.platform()
    if plat.lower().find('armv7l-with-debian') > -1:
        return BEAGLEBONE_BLACK
    elif plat.lower().find('armv7l-with-ubuntu') > -1:
        return BEAGLEBONE_BLACK
    elif plat.lower().find('armv7l-with-glibc2.4') > -1:
        return BEAGLEBONE_BLACK
    elif plat.lower().find('tegra-aarch64-with-ubuntu') > -1:
        return JETSON_NANO

    # Handle Minnowboard
    # Assumption is that mraa is installed
    try:
        import mraa
        if mraa.getPlatformName()=='MinnowBoard MAX':
            return MINNOWBOARD
    except ImportError:
        pass

    # Couldn't figure out the platform, just return unknown.
    return UNKNOWN

def
platform_detect
(
)
:
pi
=
pi_version
(
)
if
pi
is
not
:
return
RASPBERRY_PI
plat
=
platform
.
platform
(
)
if
plat
.
lower
(
)
.
find
(
'armv7l-with-debian'
)
>
1
:
return
BEAGLEBONE_BLACK
elif
plat
.
lower
(
)
.
find
(
'armv7l-with-ubuntu'
)
>
1
:
return
BEAGLEBONE_BLACK
elif
plat
.
lower
(
)
.
find
(
'armv7l-with-glibc2.4'
)
>
1
:
return
BEAGLEBONE_BLACK
elif
plat
.
lower
(
)
.
find
(
'tegra-aarch64-with-ubuntu'
)
>
1
:
return
JETSON_NANO
try
:
import
mraa
if
mraa
.
getPlatformName
(
)
==
'MinnowBoard MAX'
:
return
MINNOWBOARD
except
ImportError
:
pass
return
UNKNOWN

Detect if running on the Raspberry Pi or Beaglebone Black and return the platform type . Will return RASPBERRY_PI BEAGLEBONE_BLACK or UNKNOWN .


def write(self, data, assert_ss=True, deassert_ss=True):
        """Half-duplex SPI write.  If assert_ss is True, the SS line will be
        asserted low, the specified bytes will be clocked out the MOSI line, and
        if deassert_ss is True the SS line be put back high.
        """
        # Fail MOSI is not specified.
        if self._mosi is None:
            raise RuntimeError('Write attempted with no MOSI pin specified.')
        if assert_ss and self._ss is not None:
            self._gpio.set_low(self._ss)
        for byte in data:
            for i in range(8):
                # Write bit to MOSI.
                if self._write_shift(byte, i) & self._mask:
                    self._gpio.set_high(self._mosi)
                else:
                    self._gpio.set_low(self._mosi)
                # Flip clock off base.
                self._gpio.output(self._sclk, not self._clock_base)
                # Return clock to base.
                self._gpio.output(self._sclk, self._clock_base)
        if deassert_ss and self._ss is not None:
            self._gpio.set_high(self._ss)

Half - duplex SPI write . If assert_ss is True the SS line will be asserted low the specified bytes will be clocked out the MOSI line and if deassert_ss is True the SS line be put back high .


def read(self, length, assert_ss=True, deassert_ss=True):
        """Half-duplex SPI read.  If assert_ss is true, the SS line will be
        asserted low, the specified length of bytes will be clocked in the MISO
        line, and if deassert_ss is true the SS line will be put back high.
        Bytes which are read will be returned as a bytearray object.
        """
        if self._miso is None:
            raise RuntimeError('Read attempted with no MISO pin specified.')
        if assert_ss and self._ss is not None:
            self._gpio.set_low(self._ss)
        result = bytearray(length)
        for i in range(length):
            for j in range(8):
                # Flip clock off base.
                self._gpio.output(self._sclk, not self._clock_base)
                # Handle read on leading edge of clock.
                if self._read_leading:
                    if self._gpio.is_high(self._miso):
                        # Set bit to 1 at appropriate location.
                        result[i] |= self._read_shift(self._mask, j)
                    else:
                        # Set bit to 0 at appropriate location.
                        result[i] &= ~self._read_shift(self._mask, j)
                # Return clock to base.
                self._gpio.output(self._sclk, self._clock_base)
                # Handle read on trailing edge of clock.
                if not self._read_leading:
                    if self._gpio.is_high(self._miso):
                        # Set bit to 1 at appropriate location.
                        result[i] |= self._read_shift(self._mask, j)
                    else:
                        # Set bit to 0 at appropriate location.
                        result[i] &= ~self._read_shift(self._mask, j)
        if deassert_ss and self._ss is not None:
            self._gpio.set_high(self._ss)
        return result

Half - duplex SPI read . If assert_ss is true the SS line will be asserted low the specified length of bytes will be clocked in the MISO line and if deassert_ss is true the SS line will be put back high . Bytes which are read will be returned as a bytearray object .


def transfer(self, data, assert_ss=True, deassert_ss=True):
        """Full-duplex SPI read and write.  If assert_ss is true, the SS line
        will be asserted low, the specified bytes will be clocked out the MOSI
        line while bytes will also be read from the MISO line, and if
        deassert_ss is true the SS line will be put back high.  Bytes which are
        read will be returned as a bytearray object.
        """
        if self._mosi is None:
            raise RuntimeError('Write attempted with no MOSI pin specified.')
        if self._miso is None:
            raise RuntimeError('Read attempted with no MISO pin specified.')
        if assert_ss and self._ss is not None:
            self._gpio.set_low(self._ss)
        result = bytearray(len(data))
        for i in range(len(data)):
            for j in range(8):
                # Write bit to MOSI.
                if self._write_shift(data[i], j) & self._mask:
                    self._gpio.set_high(self._mosi)
                else:
                    self._gpio.set_low(self._mosi)
                # Flip clock off base.
                self._gpio.output(self._sclk, not self._clock_base)
                # Handle read on leading edge of clock.
                if self._read_leading:
                    if self._gpio.is_high(self._miso):
                        # Set bit to 1 at appropriate location.
                        result[i] |= self._read_shift(self._mask, j)
                    else:
                        # Set bit to 0 at appropriate location.
                        result[i] &= ~self._read_shift(self._mask, j)
                # Return clock to base.
                self._gpio.output(self._sclk, self._clock_base)
                # Handle read on trailing edge of clock.
                if not self._read_leading:
                    if self._gpio.is_high(self._miso):
                        # Set bit to 1 at appropriate location.
                        result[i] |= self._read_shift(self._mask, j)
                    else:
                        # Set bit to 0 at appropriate location.
                        result[i] &= ~self._read_shift(self._mask, j)
        if deassert_ss and self._ss is not None:
            self._gpio.set_high(self._ss)
        return result

Full - duplex SPI read and write . If assert_ss is true the SS line will be asserted low the specified bytes will be clocked out the MOSI line while bytes will also be read from the MISO line and if deassert_ss is true the SS line will be put back high . Bytes which are read will be returned as a bytearray object .


def setup(self, pin, value):
        """Set the input or output mode for a specified pin.  Mode should be
        either GPIO.OUT or GPIO.IN.
        """
        self._validate_pin(pin)
        # Set bit to 1 for input or 0 for output.
        if value == GPIO.IN:
            self.iodir[int(pin/8)] |= 1 << (int(pin%8))
        elif value == GPIO.OUT:
            self.iodir[int(pin/8)] &= ~(1 << (int(pin%8)))
        else:
            raise ValueError('Unexpected value.  Must be GPIO.IN or GPIO.OUT.')
        self.write_iodir()

Set the input or output mode for a specified pin . Mode should be either GPIO . OUT or GPIO . IN .


def pullup(self, pin, enabled):
        """Turn on the pull-up resistor for the specified pin if enabled is True,
        otherwise turn off the pull-up resistor.
        """
        self._validate_pin(pin)
        if enabled:
            self.gppu[int(pin/8)] |= 1 << (int(pin%8))
        else:
            self.gppu[int(pin/8)] &= ~(1 << (int(pin%8)))
        self.write_gppu()

def pullup ( self , pin , enabled ) : self . _validate_pin ( pin ) if enabled : self . gppu [ int ( pin / 8 ) ] |= 1 << ( int ( pin % 8 ) ) else : self . gppu [ int ( pin / 8 ) ] &= ~ ( 1 << ( int ( pin % 8 ) ) ) self . write_gppu ( )

Turn on the pull - up resistor for the specified pin if enabled is True otherwise turn off the pull - up resistor .


def write_gpio(self, gpio=None):
        """Write the specified byte value to the GPIO registor.  If no value
        specified the current buffered value will be written.
        """
        if gpio is not None:
            self.gpio = gpio
        self._device.writeList(self.GPIO, self.gpio)

def write_gpio ( self , gpio = None ) : if gpio is not None : self . gpio = gpio self . _device . writeList ( self . GPIO , self . gpio )

Write the specified byte value to the GPIO registor . If no value specified the current buffered value will be written .


def write_iodir(self, iodir=None):
        """Write the specified byte value to the IODIR registor.  If no value
        specified the current buffered value will be written.
        """
        if iodir is not None:
            self.iodir = iodir
        self._device.writeList(self.IODIR, self.iodir)

def write_iodir ( self , iodir = None ) : if iodir is not None : self . iodir = iodir self . _device . writeList ( self . IODIR , self . iodir )

Write the specified byte value to the IODIR registor . If no value specified the current buffered value will be written .


def write_gppu(self, gppu=None):
        """Write the specified byte value to the GPPU registor.  If no value
        specified the current buffered value will be written.
        """
        if gppu is not None:
            self.gppu = gppu
        self._device.writeList(self.GPPU, self.gppu)

def write_gppu ( self , gppu = None ) : if gppu is not None : self . gppu = gppu self . _device . writeList ( self . GPPU , self . gppu )

Write the specified byte value to the GPPU registor . If no value specified the current buffered value will be written .


def disable_FTDI_driver():
    """Disable the FTDI drivers for the current platform.  This is necessary
    because they will conflict with libftdi and accessing the FT232H.  Note you
    can enable the FTDI drivers again by calling enable_FTDI_driver.
    """
    logger.debug('Disabling FTDI driver.')
    if sys.platform == 'darwin':
        logger.debug('Detected Mac OSX')
        # Mac OS commands to disable FTDI driver.
        _check_running_as_root()
        subprocess.call('kextunload -b com.apple.driver.AppleUSBFTDI', shell=True)
        subprocess.call('kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext', shell=True)
    elif sys.platform.startswith('linux'):
        logger.debug('Detected Linux')
        # Linux commands to disable FTDI driver.
        _check_running_as_root()
        subprocess.call('modprobe -r -q ftdi_sio', shell=True)
        subprocess.call('modprobe -r -q usbserial', shell=True)

Disable the FTDI drivers for the current platform . This is necessary because they will conflict with libftdi and accessing the FT232H . Note you can enable the FTDI drivers again by calling enable_FTDI_driver .


def enable_FTDI_driver():
    """Re-enable the FTDI drivers for the current platform."""
    logger.debug('Enabling FTDI driver.')
    if sys.platform == 'darwin':
        logger.debug('Detected Mac OSX')
        # Mac OS commands to enable FTDI driver.
        _check_running_as_root()
        subprocess.check_call('kextload -b com.apple.driver.AppleUSBFTDI', shell=True)
        subprocess.check_call('kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext', shell=True)
    elif sys.platform.startswith('linux'):
        logger.debug('Detected Linux')
        # Linux commands to enable FTDI driver.
        _check_running_as_root()
        subprocess.check_call('modprobe -q ftdi_sio', shell=True)
        subprocess.check_call('modprobe -q usbserial', shell=True)

Re - enable the FTDI drivers for the current platform .


def enumerate_device_serials(vid=FT232H_VID, pid=FT232H_PID):
    """Return a list of all FT232H device serial numbers connected to the
    machine.  You can use these serial numbers to open a specific FT232H device
    by passing it to the FT232H initializer's serial parameter.
    """
    try:
        # Create a libftdi context.
        ctx = None
        ctx = ftdi.new()
        # Enumerate FTDI devices.
        device_list = None
        count, device_list = ftdi.usb_find_all(ctx, vid, pid)
        if count < 0:
            raise RuntimeError('ftdi_usb_find_all returned error {0}: {1}'.format(count, ftdi.get_error_string(self._ctx)))
        # Walk through list of devices and assemble list of serial numbers.
        devices = []
        while device_list is not None:
            # Get USB device strings and add serial to list of devices.
            ret, manufacturer, description, serial = ftdi.usb_get_strings(ctx, device_list.dev, 256, 256, 256)
            if serial is not None:
                devices.append(serial)
            device_list = device_list.next
        return devices
    finally:
        # Make sure to clean up list and context when done.
        if device_list is not None:
            ftdi.list_free(device_list)
        if ctx is not None:
            ftdi.free(ctx)

Return a list of all FT232H device serial numbers connected to the machine . You can use these serial numbers to open a specific FT232H device by passing it to the FT232H initializer s serial parameter .


def close(self):
        """Close the FTDI device.  Will be automatically called when the program ends."""
        if self._ctx is not None:
            ftdi.free(self._ctx)
        self._ctx = None

def close ( self ) : if self . _ctx is not None : ftdi . free ( self . _ctx ) self . _ctx = None

Close the FTDI device . Will be automatically called when the program ends .


def _write(self, string):
        """Helper function to call write_data on the provided FTDI device and
        verify it succeeds.
        """
        # Get modem status. Useful to enable for debugging.
        #ret, status = ftdi.poll_modem_status(self._ctx)
        #if ret == 0:
        #	logger.debug('Modem status {0:02X}'.format(status))
        #else:
        #	logger.debug('Modem status error {0}'.format(ret))
        length = len(string)
        try:
            ret = ftdi.write_data(self._ctx, string, length)
        except TypeError:
            ret = ftdi.write_data(self._ctx, string); #compatible with libFtdi 1.3
        # Log the string that was written in a python hex string format using a very
        # ugly one-liner list comprehension for brevity.
        #logger.debug('Wrote {0}'.format(''.join(['\\x{0:02X}'.format(ord(x)) for x in string])))
        if ret < 0:
            raise RuntimeError('ftdi_write_data failed with error {0}: {1}'.format(ret, ftdi.get_error_string(self._ctx)))
        if ret != length:
            raise RuntimeError('ftdi_write_data expected to write {0} bytes but actually wrote {1}!'.format(length, ret))

Helper function to call write_data on the provided FTDI device and verify it succeeds .


def _check(self, command, *args):
        """Helper function to call the provided command on the FTDI device and
        verify the response matches the expected value.
        """
        ret = command(self._ctx, *args)
        logger.debug('Called ftdi_{0} and got response {1}.'.format(command.__name__, ret))
        if ret != 0:
            raise RuntimeError('ftdi_{0} failed with error {1}: {2}'.format(command.__name__, ret, ftdi.get_error_string(self._ctx)))

def
_check
(
self
,
command
,
*
args
)
:
ret
=
command
(
self
.
_ctx
,
*
args
)
logger
.
debug
(
'Called ftdi_{0} and got response {1}.'
.
format
(
command
.
__name__
,
ret
)
)
if
ret
!=
0
:
raise
RuntimeError
(
'ftdi_{0} failed with error {1}: {2}'
.
format
(
command
.
__name__
,
ret
,
ftdi
.
get_error_string
(
self
.
_ctx
)
)
)

Helper function to call the provided command on the FTDI device and verify the response matches the expected value .


def _poll_read(self, expected, timeout_s=5.0):
        """Helper function to continuously poll reads on the FTDI device until an
        expected number of bytes are returned.  Will throw a timeout error if no
        data is received within the specified number of timeout seconds.  Returns
        the read data as a string if successful, otherwise raises an execption.
        """
        start = time.time()
        # Start with an empty response buffer.
        response = bytearray(expected)
        index = 0
        # Loop calling read until the response buffer is full or a timeout occurs.
        while time.time() - start <= timeout_s:
            ret, data = ftdi.read_data(self._ctx, expected - index)
            # Fail if there was an error reading data.
            if ret < 0:
                raise RuntimeError('ftdi_read_data failed with error code {0}.'.format(ret))
            # Add returned data to the buffer.
            response[index:index+ret] = data[:ret]
            index += ret
            # Buffer is full, return the result data.
            if index >= expected:
                return str(response)
            time.sleep(0.01)
        raise RuntimeError('Timeout while polling ftdi_read_data for {0} bytes!'.format(expected))

Helper function to continuously poll reads on the FTDI device until an expected number of bytes are returned . Will throw a timeout error if no data is received within the specified number of timeout seconds . Returns the read data as a string if successful otherwise raises an execption .


def _mpsse_enable(self):
        """Enable MPSSE mode on the FTDI device."""
        # Reset MPSSE by sending mask = 0 and mode = 0
        self._check(ftdi.set_bitmode, 0, 0)
        # Enable MPSSE by sending mask = 0 and mode = 2
        self._check(ftdi.set_bitmode, 0, 2)

def _mpsse_enable ( self ) : self . _check ( ftdi . set_bitmode , 0 , 0 ) self . _check ( ftdi . set_bitmode , 0 , 2 )


def _mpsse_sync(self, max_retries=10):
        """Synchronize buffers with MPSSE by sending bad opcode and reading expected
        error response.  Should be called once after enabling MPSSE."""
        # Send a bad/unknown command (0xAB), then read buffer until bad command
        # response is found.
        self._write('\xAB')
        # Keep reading until bad command response (0xFA 0xAB) is returned.
        # Fail if too many read attempts are made to prevent sticking in a loop.
        tries = 0
        sync = False
        while not sync:
            data = self._poll_read(2)
            if data == '\xFA\xAB':
                sync = True
            tries += 1
            if tries >= max_retries:
                raise RuntimeError('Could not synchronize with FT232H!')

def
_mpsse_sync
(
self
,
max_retries
=
10
)
:
self
.
_write
(
'\xAB'
)
tries
=
0
sync
=
False
while
not
sync
:
data
=
self
.
_poll_read
(
2
)
if
data
==
'\xFA\xAB'
:
sync
=
True
tries
+=
1
if
tries
>=
max_retries
:
raise
RuntimeError
(
'Could not synchronize with FT232H!'
)

Synchronize buffers with MPSSE by sending bad opcode and reading expected error response . Should be called once after enabling MPSSE .


def mpsse_set_clock(self, clock_hz, adaptive=False, three_phase=False):
        """Set the clock speed of the MPSSE engine.  Can be any value from 450hz
        to 30mhz and will pick that speed or the closest speed below it.
        """
        # Disable clock divisor by 5 to enable faster speeds on FT232H.
        self._write('\x8A')
        # Turn on/off adaptive clocking.
        if adaptive:
            self._write('\x96')
        else:
            self._write('\x97')
        # Turn on/off three phase clock (needed for I2C).
        # Also adjust the frequency for three-phase clocking as specified in section 2.2.4
        # of this document:
        #   http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
        if three_phase:
            self._write('\x8C')
        else:
            self._write('\x8D')
        # Compute divisor for requested clock.
        # Use equation from section 3.8.1 of:
        #  http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
        # Note equation is using 60mhz master clock instead of 12mhz.
        divisor = int(math.ceil((30000000.0-float(clock_hz))/float(clock_hz))) & 0xFFFF
        if three_phase:
            divisor = int(divisor*(2.0/3.0))
        logger.debug('Setting clockspeed with divisor value {0}'.format(divisor))
        # Send command to set divisor from low and high byte values.
        self._write(str(bytearray((0x86, divisor & 0xFF, (divisor >> 8) & 0xFF))))

Set the clock speed of the MPSSE engine . Can be any value from 450hz to 30mhz and will pick that speed or the closest speed below it .


def mpsse_read_gpio(self):
        """Read both GPIO bus states and return a 16 bit value with their state.
        D0-D7 are the lower 8 bits and C0-C7 are the upper 8 bits.
        """
        # Send command to read low byte and high byte.
        self._write('\x81\x83')
        # Wait for 2 byte response.
        data = self._poll_read(2)
        # Assemble response into 16 bit value.
        low_byte = ord(data[0])
        high_byte = ord(data[1])
        logger.debug('Read MPSSE GPIO low byte = {0:02X} and high byte = {1:02X}'.format(low_byte, high_byte))
        return (high_byte << 8) | low_byte

Read both GPIO bus states and return a 16 bit value with their state . D0 - D7 are the lower 8 bits and C0 - C7 are the upper 8 bits .


def mpsse_gpio(self):
        """Return command to update the MPSSE GPIO state to the current direction
        and level.
        """
        level_low  = chr(self._level & 0xFF)
        level_high = chr((self._level >> 8) & 0xFF)
        dir_low  = chr(self._direction & 0xFF)
        dir_high = chr((self._direction >> 8) & 0xFF)
        return str(bytearray((0x80, level_low, dir_low, 0x82, level_high, dir_high)))

def mpsse_gpio ( self ) : level_low = chr ( self . _level & 0xFF ) level_high = chr ( ( self . _level >> 8 ) & 0xFF ) dir_low = chr ( self . _direction & 0xFF ) dir_high = chr ( ( self . _direction >> 8 ) & 0xFF ) return str ( bytearray ( ( 0x80 , level_low , dir_low , 0x82 , level_high , dir_high ) ) )

Return command to update the MPSSE GPIO state to the current direction and level .


def setup(self, pin, mode):
        """Set the input or output mode for a specified pin.  Mode should be
        either OUT or IN."""
        self._setup_pin(pin, mode)
        self.mpsse_write_gpio()

def setup ( self , pin , mode ) : self . _setup_pin ( pin , mode ) self . mpsse_write_gpio ( )

Set the input or output mode for a specified pin . Mode should be either OUT or IN .


def write(self, data):
        """Half-duplex SPI write.  The specified array of bytes will be clocked
        out the MOSI line.
        """
        #check for hardware limit of FT232H and similar MPSSE chips
        if (len(data) > 65536):
            print('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!')
            print('use for loops for larger reads')
            exit(1)
        # Build command to write SPI data.
        command = 0x10 | (self.lsbfirst << 3) | self.write_clock_ve
        logger.debug('SPI write with command {0:2X}.'.format(command))
        # Compute length low and high bytes.
        # NOTE: Must actually send length minus one because the MPSSE engine
        # considers 0 a length of 1 and FFFF a length of 65536
	# splitting into two lists for two commands to prevent buffer errors
	data1 = data[:len(data)/2]
	data2 = data[len(data)/2:]
        len_low1  = (len(data1) - 1) & 0xFF
        len_high1 = ((len(data1) - 1) >> 8) & 0xFF
	len_low2  = (len(data2) - 1) & 0xFF
        len_high2 = ((len(data2) - 1) >> 8) & 0xFF
        self._assert_cs()
        # Send command and length, then data, split into two commands, handle for length 1
	if len(data1) > 0:
            self._ft232h._write(str(bytearray((command, len_low1, len_high1))))
            self._ft232h._write(str(bytearray(data1)))
        if len(data2) > 0:
	    self._ft232h._write(str(bytearray((command, len_low2, len_high2))))
	    self._ft232h._write(str(bytearray(data2)))
        self._deassert_cs()

Half - duplex SPI write . The specified array of bytes will be clocked out the MOSI line .


def read(self, length):
        """Half-duplex SPI read.  The specified length of bytes will be clocked
        in the MISO line and returned as a bytearray object.
        """
        #check for hardware limit of FT232H and similar MPSSE chips
        if (1 > length > 65536):
            print('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!')
            print('use for loops for larger reads')
            exit(1)
        # Build command to read SPI data.
        command = 0x20 | (self.lsbfirst << 3) | (self.read_clock_ve << 2)
        logger.debug('SPI read with command {0:2X}.'.format(command))
        # Compute length low and high bytes.
        # NOTE: Must actually send length minus one because the MPSSE engine
        # considers 0 a length of 1 and FFFF a length of 65536
	#force odd numbers to round up instead of down
	lengthR = length
	if length % 2 == 1:
	    lengthR += 1
	lengthR = lengthR/2
	#when odd length requested, get the remainder instead of the same number
	lenremain = length - lengthR
        len_low  = (lengthR - 1) & 0xFF
        len_high = ((lengthR - 1) >> 8) & 0xFF
        self._assert_cs()
        # Send command and length.
        # Perform twice to prevent error from hardware defect/limits
        self._ft232h._write(str(bytearray((command, len_low, len_high))))
        payload1 = self._ft232h._poll_read(lengthR)
        self._ft232h._write(str(bytearray((command, len_low, len_high))))
        payload2 = self._ft232h._poll_read(lenremain)
        self._deassert_cs()
        # Read response bytes
        return bytearray(payload1 + payload2)

Half - duplex SPI read . The specified length of bytes will be clocked in the MISO line and returned as a bytearray object .


def bulkread(self, data = [], lengthR = 'None', readmode = 1):
        """Half-duplex SPI write then read. Send command and payload to slave as bytearray
            then consequently read out response from the slave for length in bytes.
        Designed for use with NOR or NAND flash chips, and possibly SD cards...etc...
        Read command is cut in half and performed twice in series to prevent single byte errors.
        Hardware limits per command are enforced before doing anything.
        Read length is an optional argument, so that it can function similar to transfer
            but still half-duplex.
        For reading without writing, one can send a blank array or skip that argument.
        """
        #check for hardware limit of FT232H and similar MPSSE chips
        if (1 > lengthR > 65536)|(len(data) > 65536):
            print('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!')
            print('use for loops for larger reads')
            exit(1)
        #default mode is to act like `transfer` but half-duplex
        if (lengthR == 'None')&(readmode == 1):
            lengthR = len(data)
        #command parameters definition and math
        #MPSSE engine sees length 0 as 1 byte, so - 1 lengths
        commandW = 0x10 | (self.lsbfirst << 3) | self.write_clock_ve
        lengthW = len(data) - 1
        len_lowW  = (lengthW) & 0xFF
        len_highW = ((lengthW) >> 8) & 0xFF
        commandR = 0x20 | (self.lsbfirst << 3) | (self.read_clock_ve << 2)
        #force odd numbers to round up instead of down
	length = lengthR
	if lengthR % 2 == 1:
	    length += 1
	length = length/2
        #when odd length requested, get the remainder instead of the same number
	lenremain = lengthR - length
        len_lowR  = (length - 1) & 0xFF
        len_highR = ((length - 1) >> 8) & 0xFF
        #logger debug info
        logger.debug('SPI bulkread with write command {0:2X}.'.format(commandW))
        logger.debug('and read command {0:2X}.'.format(commandR))
        #begin command set
        self._assert_cs()
        #write command, these have to be separated due to TypeError
        self._ft232h._write(str(bytearray((commandW, len_lowW, len_highW))))
        self._ft232h._write(str(bytearray(data)))
        #read command, which is divided into two commands
        self._ft232h._write(str(bytearray((commandR, len_lowR, len_highR))))
        payload1 = self._ft232h._poll_read(length)
        self._ft232h._write(str(bytearray((commandR, len_lowR, len_highR))))
        payload2 = self._ft232h._poll_read(lenremain)
        self._deassert_cs()
        #end command set
        # Read response bytes
        return bytearray(payload1 + payload2)

Half - duplex SPI write then read . Send command and payload to slave as bytearray then consequently read out response from the slave for length in bytes . Designed for use with NOR or NAND flash chips and possibly SD cards ... etc ... Read command is cut in half and performed twice in series to prevent single byte errors . Hardware limits per command are enforced before doing anything . Read length is an optional argument so that it can function similar to transfer but still half - duplex . For reading without writing one can send a blank array or skip that argument .


def transfer(self, data):
        """Full-duplex SPI read and write.  The specified array of bytes will be
        clocked out the MOSI line, while simultaneously bytes will be read from
        the MISO line.  Read bytes will be returned as a bytearray object.
        """
        #check for hardware limit of FT232H and similar MPSSE chips
        if (len(data) > 65536):
            print('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!')
            print('use for loops for larger reads')
            exit(1)
        # Build command to read and write SPI data.
        command = 0x30 | (self.lsbfirst << 3) | (self.read_clock_ve << 2) | self.write_clock_ve
        logger.debug('SPI transfer with command {0:2X}.'.format(command))
        # Compute length low and high bytes.
        # NOTE: Must actually send length minus one because the MPSSE engine
        # considers 0 a length of 1 and FFFF a length of 65536
        data1 = data[:len(data)/2]
	data2 = data[len(data)/2:]
	len_low1  = (len(data1) - 1) & 0xFF
        len_high1 = ((len(data1) - 1) >> 8) & 0xFF
	len_low2  = (len(data2) - 1) & 0xFF
        len_high2 = ((len(data2) - 1) >> 8) & 0xFF
	payload1 = ''
	payload2 = ''
	#start command set
        self._assert_cs()
        # Perform twice to prevent error from hardware defect/limits
	# Send command and length, then data, split into two commands, handle for length 1
	if len(data1) > 0:
	    self._ft232h._write(str(bytearray((command, len_low1, len_high1))))
	    self._ft232h._write(str(bytearray(data1)))
	    payload1 = self._ft232h._poll_read(len(data1))
	if len(data2) > 0:
	    self._ft232h._write(str(bytearray((command, len_low2, len_high2))))
	    self._ft232h._write(str(bytearray(data2)))
	    payload2 = self._ft232h._poll_read(len(data2))
        #self._ft232h._write('\x87')
        self._deassert_cs()
        # Read response bytes.
        return bytearray(payload1 + payload2)

Full - duplex SPI read and write . The specified array of bytes will be clocked out the MOSI line while simultaneously bytes will be read from the MISO line . Read bytes will be returned as a bytearray object .


def _idle(self):
        """Put I2C lines into idle state."""
        # Put the I2C lines into an idle state with SCL and SDA high.
        self._ft232h.setup_pins({0: GPIO.OUT, 1: GPIO.OUT, 2: GPIO.IN},
                                {0: GPIO.HIGH, 1: GPIO.HIGH})

def _idle ( self ) : self . _ft232h . setup_pins ( { 0 : GPIO . OUT , 1 : GPIO . OUT , 2 : GPIO . IN } , { 0 : GPIO . HIGH , 1 : GPIO . HIGH } )


def _transaction_end(self):
        """End I2C transaction and get response bytes, including ACKs."""
        # Ask to return response bytes immediately.
        self._command.append('\x87')
        # Send the entire command to the MPSSE.
        self._ft232h._write(''.join(self._command))
        # Read response bytes and return them.
        return bytearray(self._ft232h._poll_read(self._expected))

def _transaction_end ( self ) : self . _command . append ( '\x87' ) self . _ft232h . _write ( '' . join ( self . _command ) ) return bytearray ( self . _ft232h . _poll_read ( self . _expected ) )

End I2C transaction and get response bytes including ACKs .


def _i2c_write_bytes(self, data):
        """Write the specified number of bytes to the chip."""
        for byte in data:
            # Write byte.
            self._command.append(str(bytearray((0x11, 0x00, 0x00, byte))))
            # Make sure pins are back in idle state with clock low and data high.
            self._ft232h.output_pins({0: GPIO.LOW, 1: GPIO.HIGH}, write=False)
            self._command.append(self._ft232h.mpsse_gpio() * _REPEAT_DELAY)
            # Read bit for ACK/NAK.
            self._command.append('\x22\x00')
        # Increase expected response bytes.
        self._expected += len(data)

def _i2c_write_bytes ( self , data ) : for byte in data : self . _command . append ( str ( bytearray ( ( 0x11 , 0x00 , 0x00 , byte ) ) ) ) self . _ft232h . output_pins ( { 0 : GPIO . LOW , 1 : GPIO . HIGH } , write = False ) self . _command . append ( self . _ft232h . mpsse_gpio ( ) * _REPEAT_DELAY ) self . _command . append ( '\x22\x00' ) self . _expected += len ( data )

Write the specified number of bytes to the chip .


def ping(self):
        """Attempt to detect if a device at this address is present on the I2C
        bus.  Will send out the device's address for writing and verify an ACK
        is received.  Returns true if the ACK is received, and false if not.
        """
        self._idle()
        self._transaction_start()
        self._i2c_start()
        self._i2c_write_bytes([self._address_byte(False)])
        self._i2c_stop()
        response = self._transaction_end()
        if len(response) != 1:
            raise RuntimeError('Expected 1 response byte but received {0} byte(s).'.format(len(response)))
        return ((response[0] & 0x01) == 0x00)

Attempt to detect if a device at this address is present on the I2C bus . Will send out the device s address for writing and verify an ACK is received . Returns true if the ACK is received and false if not .


def readS8(self, register):
        """Read a signed byte from the specified register."""
        result = self.readU8(register)
        if result > 127:
            result -= 256
        return result

def readS8 ( self , register ) : result = self . readU8 ( register ) if result > 127 : result -= 256 return result

Read a signed byte from the specified register .


def get_i2c_device(address, busnum=None, i2c_interface=None, **kwargs):
    """Return an I2C device for the specified address and on the specified bus.
    If busnum isn't specified, the default I2C bus for the platform will attempt
    to be detected.
    """
    if busnum is None:
        busnum = get_default_bus()
    return Device(address, busnum, i2c_interface, **kwargs)

def get_i2c_device ( address , busnum = None , i2c_interface = None , ** kwargs ) : if busnum is None : busnum = get_default_bus ( ) return Device ( address , busnum , i2c_interface , ** kwargs )

Return an I2C device for the specified address and on the specified bus . If busnum isn t specified the default I2C bus for the platform will attempt to be detected .


def write8(self, register, value):
        """Write an 8-bit value to the specified register."""
        value = value & 0xFF
        self._bus.write_byte_data(self._address, register, value)
        self._logger.debug("Wrote 0x%02X to register 0x%02X",
                     value, register)

def
write8
(
self
,
register
,
value
)
:
value
=
value
&
0xFF
self
.
_bus
.
write_byte_data
(
self
.
_address
,
register
,
value
)
self
.
_logger
.
debug
(
"Wrote 0x%02X to register 0x%02X"
,
value
,
register
)

Write an 8 - bit value to the specified register .


def readU8(self, register):
        """Read an unsigned byte from the specified register."""
        result = self._bus.read_byte_data(self._address, register) & 0xFF
        self._logger.debug("Read 0x%02X from register 0x%02X",
                     result, register)
        return result

def
readU8
(
self
,
register
)
:
result
=
self
.
_bus
.
read_byte_data
(
self
.
_address
,
register
)
&
0xFF
self
.
_logger
.
debug
(
"Read 0x%02X from register 0x%02X"
,
result
,
register
)
return
result

Read an unsigned byte from the specified register .


def get_platform_gpio(**keywords):
    """Attempt to return a GPIO instance for the platform which the code is being
    executed on.  Currently supports only the Raspberry Pi using the RPi.GPIO
    library and Beaglebone Black using the Adafruit_BBIO library.  Will throw an
    exception if a GPIO instance can't be created for the current platform.  The
    returned GPIO object is an instance of BaseGPIO.
    """
    plat = Platform.platform_detect()
    if plat == Platform.RASPBERRY_PI:
        import RPi.GPIO
        return RPiGPIOAdapter(RPi.GPIO, **keywords)
    elif plat == Platform.BEAGLEBONE_BLACK:
        import Adafruit_BBIO.GPIO
        return AdafruitBBIOAdapter(Adafruit_BBIO.GPIO, **keywords)
    elif plat == Platform.MINNOWBOARD:
        import mraa
        return AdafruitMinnowAdapter(mraa, **keywords)
    elif plat == Platform.JETSON_NANO:
        import Jetson.GPIO
        return RPiGPIOAdapter(Jetson.GPIO, **keywords)
    elif plat == Platform.UNKNOWN:
        raise RuntimeError('Could not determine platform.')

def
get_platform_gpio
(
**
keywords
)
:
plat
=
Platform
.
platform_detect
(
)
if
plat
==
Platform
.
RASPBERRY_PI
:
import
RPi
.
GPIO
return
RPiGPIOAdapter
(
RPi
.
GPIO
,
**
keywords
)
elif
plat
==
Platform
.
BEAGLEBONE_BLACK
:
import
Adafruit_BBIO
.
GPIO
return
AdafruitBBIOAdapter
(
Adafruit_BBIO
.
GPIO
,
**
keywords
)
elif
plat
==
Platform
.
MINNOWBOARD
:
import
mraa
return
AdafruitMinnowAdapter
(
mraa
,
**
keywords
)
elif
plat
==
Platform
.
JETSON_NANO
:
import
Jetson
.
GPIO
return
RPiGPIOAdapter
(
Jetson
.
GPIO
,
**
keywords
)
elif
plat
==
Platform
.
UNKNOWN
:
raise
RuntimeError
(
'Could not determine platform.'
)

Attempt to return a GPIO instance for the platform which the code is being executed on . Currently supports only the Raspberry Pi using the RPi . GPIO library and Beaglebone Black using the Adafruit_BBIO library . Will throw an exception if a GPIO instance can t be created for the current platform . The returned GPIO object is an instance of BaseGPIO .


def setup(self, pin, mode, pull_up_down=PUD_OFF):
        """Set the input or output mode for a specified pin.  Mode should be
        either OUTPUT or INPUT.
        """
        self.rpi_gpio.setup(pin, self._dir_mapping[mode],
                            pull_up_down=self._pud_mapping[pull_up_down])

def setup ( self , pin , mode , pull_up_down = PUD_OFF ) : self . rpi_gpio . setup ( pin , self . _dir_mapping [ mode ] , pull_up_down = self . _pud_mapping [ pull_up_down ] )

Set the input or output mode for a specified pin . Mode should be either OUTPUT or INPUT .


def setup(self,pin,mode):
        """Set the input or output mode for a specified pin.  Mode should be
        either DIR_IN or DIR_OUT.
        """
        self.mraa_gpio.Gpio.dir(self.mraa_gpio.Gpio(pin),self._dir_mapping[mode])

def setup ( self , pin , mode ) : self . mraa_gpio . Gpio . dir ( self . mraa_gpio . Gpio ( pin ) , self . _dir_mapping [ mode ] )

Set the input or output mode for a specified pin . Mode should be either DIR_IN or DIR_OUT .


def remove_event_detect(self, pin):
        """Remove edge detection for a particular GPIO channel.  Pin should be
        type IN.
        """
        self.mraa_gpio.Gpio.isrExit(self.mraa_gpio.Gpio(pin))

def remove_event_detect ( self , pin ) : self . mraa_gpio . Gpio . isrExit ( self . mraa_gpio . Gpio ( pin ) )

Remove edge detection for a particular GPIO channel . Pin should be type IN .


def all_info_files(self) :
        'Returns a generator of "Path"s'
        try :
            for info_file in list_files_in_dir(self.info_dir):
                if not os.path.basename(info_file).endswith('.trashinfo') :
                    self.on_non_trashinfo_found()
                else :
                    yield info_file
        except OSError: # when directory does not exist
            pass

def
all_info_files
(
self
)
:
'Returns a generator of "Path"s'
try
:
for
info_file
in
list_files_in_dir
(
self
.
info_dir
)
:
if
not
os
.
path
.
basename
(
info_file
)
.
endswith
(
'.trashinfo'
)
:
self
.
on_non_trashinfo_found
(
)
else
:
yield
info_file
except
OSError
:
pass