@tensorflow/tfjs-layers
Version:
TensorFlow layers API in JavaScript
140 lines • 24.1 kB
JavaScript
/**
* @license
* Copyright 2018 Google LLC
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
* =============================================================================
*/
/**
* TensorFlow.js Layers: Depthwise Convolutional Layers
*/
import * as tfc from '@tensorflow/tfjs-core';
import { serialization, tidy } from '@tensorflow/tfjs-core';
import { imageDataFormat } from '../backend/common';
import * as K from '../backend/tfjs_backend';
import { checkDataFormat } from '../common';
import { getConstraint, serializeConstraint } from '../constraints';
import { ValueError } from '../errors';
import { getInitializer, serializeInitializer } from '../initializers';
import { getRegularizer, serializeRegularizer } from '../regularizers';
import { convOutputLength } from '../utils/conv_utils';
import { getExactlyOneShape, getExactlyOneTensor } from '../utils/types_utils';
import { BaseConv, preprocessConv2DInput } from './convolutional';
/**
* 2D convolution with separable filters.
* @param x Input tensor.
* @param depthwiseKernel Convolution kernel for depthwise convolution.
* @param strides Strides (Array of two integers).
* @param padding Padding model.
* @param dataFormat Data format.
* @param dilationRate Array of two integers, dilation rates for the separable
* convolution.
* @returns Output tensor.
* @throws ValueError If depthwiseKernel is not a 4D array.
*/
export function depthwiseConv2d(x, depthwiseKernel, strides = [1, 1], padding = 'valid', dataFormat, dilationRate) {
return tidy(() => {
if (dataFormat == null) {
dataFormat = imageDataFormat();
}
checkDataFormat(dataFormat);
let y = preprocessConv2DInput(x, dataFormat);
if (x.rank !== 4) {
throw new ValueError(`Input for depthwiseConv2d is required to be 4-D, but is instead ` +
`${x.rank}-D`);
}
if (depthwiseKernel.rank !== 4) {
throw new ValueError(`depthwiseKernel is required to be 4-D, but is instead ` +
`${depthwiseKernel.rank}-D`);
}
y = tfc.depthwiseConv2d(y, depthwiseKernel, strides, padding === 'same' ? 'same' : 'valid', 'NHWC', dilationRate);
if (dataFormat === 'channelsFirst') {
y = tfc.transpose(y, [0, 3, 1, 2]);
}
return y;
});
}
class DepthwiseConv2D extends BaseConv {
constructor(args) {
super(2, args);
this.depthwiseKernel = null;
this.depthMultiplier =
args.depthMultiplier == null ? 1 : args.depthMultiplier;
this.depthwiseInitializer = getInitializer(args.depthwiseInitializer || this.DEFAULT_KERNEL_INITIALIZER);
this.depthwiseConstraint = getConstraint(args.depthwiseConstraint);
this.depthwiseRegularizer = getRegularizer(args.depthwiseRegularizer);
}
build(inputShape) {
inputShape = getExactlyOneShape(inputShape);
if (inputShape.length < 4) {
throw new ValueError(`Inputs to DepthwiseConv2D should have rank 4. ` +
`Received input shape: ${JSON.stringify(inputShape)}.`);
}
const channelAxis = this.dataFormat === 'channelsFirst' ? 1 : 3;
if (inputShape[channelAxis] == null || inputShape[channelAxis] < 0) {
throw new ValueError('The channel dimension of the inputs to DepthwiseConv2D should ' +
`be defined, but is not (${inputShape[channelAxis]}).`);
}
const inputDim = inputShape[channelAxis];
const depthwiseKernelShape = [
this.kernelSize[0], this.kernelSize[1], inputDim, this.depthMultiplier
];
this.depthwiseKernel = this.addWeight('depthwise_kernel', depthwiseKernelShape, null, this.depthwiseInitializer, this.depthwiseRegularizer, true, this.depthwiseConstraint);
if (this.useBias) {
this.bias = this.addWeight('bias', [inputDim * this.depthMultiplier], null, this.biasInitializer, this.biasRegularizer, true, this.biasConstraint);
}
else {
this.bias = null;
}
this.built = true;
}
call(inputs, kwargs) {
return tidy(() => {
inputs = getExactlyOneTensor(inputs);
let outputs = depthwiseConv2d(inputs, this.depthwiseKernel.read(), this.strides, this.padding, this.dataFormat, null);
// TODO(cais): Add support for dilation.
if (this.useBias) {
outputs = K.biasAdd(outputs, this.bias.read(), this.dataFormat);
}
if (this.activation != null) {
outputs = this.activation.apply(outputs);
}
return outputs;
});
}
computeOutputShape(inputShape) {
inputShape = getExactlyOneShape(inputShape);
const rows = this.dataFormat === 'channelsFirst' ? inputShape[2] : inputShape[1];
const cols = this.dataFormat === 'channelsFirst' ? inputShape[3] : inputShape[2];
const outFilters = this.dataFormat === 'channelsFirst' ?
inputShape[1] * this.depthMultiplier :
inputShape[3] * this.depthMultiplier;
const outRows = convOutputLength(rows, this.kernelSize[0], this.padding, this.strides[0]);
const outCols = convOutputLength(cols, this.kernelSize[1], this.padding, this.strides[1]);
if (this.dataFormat === 'channelsFirst') {
return [inputShape[0], outFilters, outRows, outCols];
}
else {
// In this case, assume 'channelsLast'.
return [inputShape[0], outRows, outCols, outFilters];
}
}
getConfig() {
const config = super.getConfig();
config['depthMultiplier'] = this.depthMultiplier;
config['depthwiseInitializer'] =
serializeInitializer(this.depthwiseInitializer);
config['depthwiseRegularizer'] =
serializeRegularizer(this.depthwiseRegularizer);
config['depthwiseConstraint'] =
serializeConstraint(this.depthwiseRegularizer);
return config;
}
}
/** @nocollapse */
DepthwiseConv2D.className = 'DepthwiseConv2D';
export { DepthwiseConv2D };
serialization.registerClass(DepthwiseConv2D);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udm9sdXRpb25hbF9kZXB0aHdpc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWxheWVycy9zcmMvbGF5ZXJzL2NvbnZvbHV0aW9uYWxfZGVwdGh3aXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUg7O0dBRUc7QUFFSCxPQUFPLEtBQUssR0FBRyxNQUFNLHVCQUF1QixDQUFDO0FBQzdDLE9BQU8sRUFBQyxhQUFhLEVBQW9CLElBQUksRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRTVFLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssQ0FBQyxNQUFNLHlCQUF5QixDQUFDO0FBQzdDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDMUMsT0FBTyxFQUFtQyxhQUFhLEVBQUUsbUJBQW1CLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sRUFBQyxjQUFjLEVBQXNDLG9CQUFvQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFekcsT0FBTyxFQUFDLGNBQWMsRUFBc0Msb0JBQW9CLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUV6RyxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUUsbUJBQW1CLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUc3RSxPQUFPLEVBQUMsUUFBUSxFQUFvQyxxQkFBcUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxHOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDM0IsQ0FBUyxFQUFFLGVBQXVCLEVBQUUsVUFBNEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ3RFLE9BQU8sR0FBRyxPQUFPLEVB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VUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdELElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxlQUFlLEVBQUU7WUFDdkMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1NBQ3REO2FBQU07WUFDTCx1Q0FBdUM7WUFDdkMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1NBQ3REO0lBQ0gsQ0FBQztJQUVRLFNBQVM7UUFDaEIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDakQsTUFBTSxDQUFDLHNCQUFzQixDQUFDO1lBQzFCLG9CQUFvQixDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQztZQUMxQixvQkFBb0IsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNwRCxNQUFNLENBQUMscUJBQXFCLENBQUM7WUFDekIsbUJBQW1CLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDbkQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQzs7QUFuR0Qsa0JBQWtCO0FBQ1gseUJBQVMsR0FBRyxpQkFBaUIsQUFBcEIsQ0FBcUI7U0FGMUIsZUFBZTtBQXNHNUIsYUFBYSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE4IEdvb2dsZSBMTENcbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGVcbiAqIGxpY2Vuc2UgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBvciBhdFxuICogaHR0cHM6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVQuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8qKlxuICogVGVuc29yRmxvdy5qcyBMYXllcnM6IERlcHRod2lzZSBDb252b2x1dGlvbmFsIExheWVyc1xuICovXG5cbmltcG9ydCAqIGFzIHRmYyBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuaW1wb3J0IHtzZXJpYWxpemF0aW9uLCBUZW5zb3IsIFRlbnNvcjRELCB0aWR5fSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge2ltYWdlRGF0YUZvcm1hdH0gZnJvbSAnLi4vYmFja2VuZC9jb21tb24nO1xuaW1wb3J0ICogYXMgSyBmcm9tICcuLi9iYWNrZW5kL3RmanNfYmFja2VuZCc7XG5pbXBvcnQge2NoZWNrRGF0YUZvcm1hdH0gZnJvbSAnLi4vY29tbW9uJztcbmltcG9ydCB7Q29uc3RyYWludCwgQ29uc3RyYWludElkZW50aWZpZXIsIGdldENvbnN0cmFpbnQsIHNlcmlhbGl6ZUNvbnN0cmFpbnR9IGZyb20gJy4uL2NvbnN0cmFpbnRzJztcbmltcG9ydCB7VmFsdWVFcnJvcn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7Z2V0SW5pdGlhbGl6ZXIsIEluaXRpYWxpemVyLCBJbml0aWFsaXplcklkZW50aWZpZXIsIHNlcmlhbGl6ZUluaXRpYWxpemVyfSBmcm9tICcuLi9pbml0aWFsaXplcnMnO1xuaW1wb3J0IHtEYXRhRm9ybWF0LCBTaGFwZX0gZnJvbSAnLi4va2VyYXNfZm9ybWF0L2NvbW1vbic7XG5pbXBvcnQge2dldFJlZ3VsYXJpemVyLCBSZWd1bGFyaXplciwgUmVndWxhcml6ZXJJZGVudGlmaWVyLCBzZXJpYWxpemVSZWd1bGFyaXplcn0gZnJvbSAnLi4vcmVndWxhcml6ZXJzJztcbmltcG9ydCB7S3dhcmdzfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2NvbnZPdXRwdXRMZW5ndGh9IGZyb20gJy4uL3V0aWxzL2NvbnZfdXRpbHMnO1xuaW1wb3J0IHtnZXRFeGFjdGx5T25lU2hhcGUsIGdldEV4YWN0bHlPbmVUZW5zb3J9IGZyb20gJy4uL3V0aWxzL3R5cGVzX3V0aWxzJztcbmltcG9ydCB7TGF5ZXJWYXJpYWJsZX0gZnJvbSAnLi4vdmFyaWFibGVzJztcblxuaW1wb3J0IHtCYXNlQ29udiwgQmFzZUNvbnZMYXllckFyZ3MsIENvbnZMYXllckFyZ3MsIHByZXByb2Nlc3NDb252MkRJbnB1dH0gZnJvbSAnLi9jb252b2x1dGlvbmFsJztcblxuLyoqXG4gKiAyRCBjb252b2x1dGlvbiB3aXRoIHNlcGFyYWJsZSBmaWx0ZXJzLlxuICogQHBhcmFtIHggSW5wdXQgdGVuc29yLlxuICogQHBhcmFtIGRlcHRod2lzZUtlcm5lbCBDb252b2x1dGlvbiBrZXJuZWwgZm9yIGRlcHRod2lzZSBjb252b2x1dGlvbi5cbiAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZXMgKEFycmF5IG9mIHR3byBpbnRlZ2VycykuXG4gKiBAcGFyYW0gcGFkZGluZyBQYWRkaW5nIG1vZGVsLlxuICogQHBhcmFtIGRhdGFGb3JtYXQgRGF0YSBmb3JtYXQuXG4gKiBAcGFyYW0gZGlsYXRpb25SYXRlIEFycmF5IG9mIHR3byBpbnRlZ2VycywgZGlsYXRpb24gcmF0ZXMgZm9yIHRoZSBzZXBhcmFibGVcbiAqICAgY29udm9sdXRpb24uXG4gKiBAcmV0dXJucyBPdXRwdXQgdGVuc29yLlxuICogQHRocm93cyBWYWx1ZUVycm9yIElmIGRlcHRod2lzZUtlcm5lbCBpcyBub3QgYSA0RCBhcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlcHRod2lzZUNvbnYyZChcbiAgICB4OiBUZW5zb3IsIGRlcHRod2lzZUtlcm5lbDogVGVuc29yLCBzdHJpZGVzOiBbbnVtYmVyLCBudW1iZXJdID0gWzEsIDFdLFxuICAgIHBhZGRpbmcgPSAndmFsaWQnLCBkYXRhRm9ybWF0PzogRGF0YUZvcm1hdCxcbiAgICBkaWxhdGlvblJhdGU/OiBbbnVtYmVyLCBudW1iZXJdKTogVGVuc29yIHtcbiAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgIGlmIChkYXRhRm9ybWF0ID09IG51bGwpIHtcbiAgICAgIGRhdGFGb3JtYXQgPSBpbWFnZURhdGFGb3JtYXQoKTtcbiAgICB9XG4gICAgY2hlY2tEYXRhRm9ybWF0KGRhdGFGb3JtYXQpO1xuICAgIGxldCB5ID0gcHJlcHJvY2Vzc0NvbnYyRElucHV0KHgsIGRhdGFGb3JtYXQpO1xuICAgIGlmICh4LnJhbmsgIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgIGBJbnB1dCBmb3IgZGVwdGh3aXNlQ29udjJkIGlzIHJlcXVpcmVkIHRvIGJlIDQtRCwgYnV0IGlzIGluc3RlYWQgYCArXG4gICAgICAgICAgYCR7eC5yYW5rfS1EYCk7XG4gICAgfVxuICAgIGlmIChkZXB0aHdpc2VLZXJuZWwucmFuayAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgYGRlcHRod2lzZUtlcm5lbCBpcyByZXF1aXJlZCB0byBiZSA0LUQsIGJ1dCBpcyBpbnN0ZWFkIGAgK1xuICAgICAgICAgIGAke2RlcHRod2lzZUtlcm5lbC5yYW5rfS1EYCk7XG4gICAgfVxuICAgIHkgPSB0ZmMuZGVwdGh3aXNlQ29udjJkKFxuICAgICAgICB5IGFzIFRlbnNvcjRELCBkZXB0aHdpc2VLZXJuZWwgYXMgVGVuc29yNEQsIHN0cmlkZXMsXG4gICAgICAgIHBhZGRpbmcgPT09ICdzYW1lJyA/ICdzYW1lJyA6ICd2YWxpZCcsICdOSFdDJywgZGlsYXRpb25SYXRlKTtcbiAgICBpZiAoZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnKSB7XG4gICAgICB5ID0gdGZjLnRyYW5zcG9zZSh5LCBbMCwgMywgMSwgMl0pO1xuICAgIH1cbiAgICByZXR1cm4geTtcbiAgfSk7XG59XG5cbmV4cG9ydCBkZWNsYXJlIGludGVyZmFjZSBEZXB0aHdpc2VDb252MkRMYXllckFyZ3MgZXh0ZW5kcyBCYXNlQ29udkxheWVyQXJncyB7XG4gIC8qKlxuICAgKiBBbiBpbnRlZ2VyIG9yIEFycmF5IG9mIDIgaW50ZWdlcnMsIHNwZWNpZnlpbmcgdGhlIHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlXG4gICAqIDJEIGNvbnZvbHV0aW9uIHdpbmRvdy4gQ2FuIGJlIGEgc2luZ2xlIGludGVnZXIgdG8gc3BlY2lmeSB0aGUgc2FtZSB2YWx1ZVxuICAgKiBmb3IgYWxsIHNwYXRpYWwgZGltZW5zaW9ucy5cbiAgICovXG4gIGtlcm5lbFNpemU6IG51bWJlcnxbbnVtYmVyLCBudW1iZXJdO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGRlcHRod2lzZSBjb252b2x1dGlvbiBvdXRwdXQgY2hhbm5lbHMgZm9yIGVhY2ggaW5wdXRcbiAgICogY2hhbm5lbC5cbiAgICogVGhlIHRvdGFsIG51bWJlciBvZiBkZXB0aHdpc2UgY29udm9sdXRpb24gb3V0cHV0IGNoYW5uZWxzIHdpbGwgYmUgZXF1YWwgdG9cbiAgICogYGZpbHRlcnNJbiAqIGRlcHRoTXVsdGlwbGllcmAuXG4gICAqIERlZmF1bHQ6IDEuXG4gICAqL1xuICBkZXB0aE11bHRpcGxpZXI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVyIGZvciB0aGUgZGVwdGh3aXNlIGtlcm5lbCBtYXRyaXguXG4gICAqIERlZmF1bHQ6IEdsb3JvdE5vcm1hbC5cbiAgICovXG4gIGRlcHRod2lzZUluaXRpYWxpemVyPzogSW5pdGlhbGl6ZXJJZGVudGlmaWVyfEluaXRpYWxpemVyO1xuXG4gIC8qKlxuICAgKiBDb25zdHJhaW50IGZvciB0aGUgZGVwdGh3aXNlIGtlcm5lbCBtYXRyaXguXG4gICAqL1xuICBkZXB0aHdpc2VDb25zdHJhaW50PzogQ29uc3RyYWludElkZW50aWZpZXJ8Q29uc3RyYWludDtcblxuICAvKipcbiAgICogUmVndWxhcml6ZXIgZnVuY3Rpb24gZm9yIHRoZSBkZXB0aHdpc2Uga2VybmVsIG1hdHJpeC5cbiAgICovXG4gIGRlcHRod2lzZVJlZ3VsYXJpemVyPzogUmVndWxhcml6ZXJJZGVudGlmaWVyfFJlZ3VsYXJpemVyO1xufVxuXG5leHBvcnQgY2xhc3MgRGVwdGh3aXNlQ29udjJEIGV4dGVuZHMgQmFzZUNvbnYge1xuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIGNsYXNzTmFtZSA9ICdEZXB0aHdpc2VDb252MkQnO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlcHRoTXVsdGlwbGllcjogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlcHRod2lzZUluaXRpYWxpemVyOiBJbml0aWFsaXplcjtcbiAgcHJpdmF0ZSByZWFkb25seSBkZXB0aHdpc2VDb25zdHJhaW50OiBDb25zdHJhaW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGRlcHRod2lzZVJlZ3VsYXJpemVyOiBSZWd1bGFyaXplcjtcblxuICBwcml2YXRlIGRlcHRod2lzZUtlcm5lbDogTGF5ZXJWYXJpYWJsZSA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoYXJnczogRGVwdGh3aXNlQ29udjJETGF5ZXJBcmdzKSB7XG4gICAgc3VwZXIoMiwgYXJncyBhcyBDb252TGF5ZXJBcmdzKTtcbiAgICB0aGlzLmRlcHRoTXVsdGlwbGllciA9XG4gICAgICAgIGFyZ3MuZGVwdGhNdWx0aXBsaWVyID09IG51bGwgPyAxIDogYXJncy5kZXB0aE11bHRpcGxpZXI7XG4gICAgdGhpcy5kZXB0aHdpc2VJbml0aWFsaXplciA9IGdldEluaXRpYWxpemVyKFxuICAgICAgICBhcmdzLmRlcHRod2lzZUluaXRpYWxpemVyIHx8IHRoaXMuREVGQVVMVF9LRVJORUxfSU5JVElBTElaRVIpO1xuICAgIHRoaXMuZGVwdGh3aXNlQ29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5kZXB0aHdpc2VDb25zdHJhaW50KTtcbiAgICB0aGlzLmRlcHRod2lzZVJlZ3VsYXJpemVyID0gZ2V0UmVndWxhcml6ZXIoYXJncy5kZXB0aHdpc2VSZWd1bGFyaXplcik7XG4gIH1cblxuICBvdmVycmlkZSBidWlsZChpbnB1dFNoYXBlOiBTaGFwZXxTaGFwZVtdKTogdm9pZCB7XG4gICAgaW5wdXRTaGFwZSA9IGdldEV4YWN0bHlPbmVTaGFwZShpbnB1dFNoYXBlKTtcbiAgICBpZiAoaW5wdXRTaGFwZS5sZW5ndGggPCA0KSB7XG4gICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICBgSW5wdXRzIHRvIERlcHRod2lzZUNvbnYyRCBzaG91bGQgaGF2ZSByYW5rIDQuIGAgK1xuICAgICAgICAgIGBSZWNlaXZlZCBpbnB1dCBzaGFwZTogJHtKU09OLnN0cmluZ2lmeShpbnB1dFNoYXBlKX0uYCk7XG4gICAgfVxuICAgIGNvbnN0IGNoYW5uZWxBeGlzID0gdGhpcy5kYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNGaXJzdCcgPyAxIDogMztcbiAgICBpZiAoaW5wdXRTaGFwZVtjaGFubmVsQXhpc10gPT0gbnVsbCB8fCBpbnB1dFNoYXBlW2NoYW5uZWxBeGlzXSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgICdUaGUgY2hhbm5lbCBkaW1lbnNpb24gb2YgdGhlIGlucHV0cyB0byBEZXB0aHdpc2VDb252MkQgc2hvdWxkICcgK1xuICAgICAgICAgIGBiZSBkZWZpbmVkLCBidXQgaXMgbm90ICgke2lucHV0U2hhcGVbY2hhbm5lbEF4aXNdfSkuYCk7XG4gICAgfVxuICAgIGNvbnN0IGlucHV0RGltID0gaW5wdXRTaGFwZVtjaGFubmVsQXhpc107XG4gICAgY29uc3QgZGVwdGh3aXNlS2VybmVsU2hhcGU6IFNoYXBlID0gW1xuICAgICAgdGhpcy5rZXJuZWxTaXplWzBdLCB0aGlzLmtlcm5lbFNpemVbMV0sIGlucHV0RGltLCB0aGlzLmRlcHRoTXVsdGlwbGllclxuICAgIF07XG5cbiAgICB0aGlzLmRlcHRod2lzZUtlcm5lbCA9IHRoaXMuYWRkV2VpZ2h0KFxuICAgICAgICAnZGVwdGh3aXNlX2tlcm5lbCcsIGRlcHRod2lzZUtlcm5lbFNoYXBlLCBudWxsLFxuICAgICAgICB0aGlzLmRlcHRod2lzZUluaXRpYWxpemVyLCB0aGlzLmRlcHRod2lzZVJlZ3VsYXJpemVyLCB0cnVlLFxuICAgICAgICB0aGlzLmRlcHRod2lzZUNvbnN0cmFpbnQpO1xuICAgIGlmICh0aGlzLnVzZUJpYXMpIHtcbiAgICAgIHRoaXMuYmlhcyA9IHRoaXMuYWRkV2VpZ2h0KFxuICAgICAgICAgICdiaWFzJywgW2lucHV0RGltICogdGhpcy5kZXB0aE11bHRpcGxpZXJdLCBudWxsLCB0aGlzLmJpYXNJbml0aWFsaXplcixcbiAgICAgICAgICB0aGlzLmJpYXNSZWd1bGFyaXplciwgdHJ1ZSwgdGhpcy5iaWFzQ29uc3RyYWludCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYmlhcyA9IG51bGw7XG4gICAgfVxuICAgIHRoaXMuYnVpbHQgPSB0cnVlO1xuICB9XG5cbiAgb3ZlcnJpZGUgY2FsbChpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXSwga3dhcmdzOiBLd2FyZ3MpOiBUZW5zb3J8VGVuc29yW10ge1xuICAgIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICAgIGlucHV0cyA9IGdldEV4YWN0bHlPbmVUZW5zb3IoaW5wdXRzKTtcbiAgICAgIGxldCBvdXRwdXRzID0gZGVwdGh3aXNlQ29udjJkKFxuICAgICAgICAgIGlucHV0cywgdGhpcy5kZXB0aHdpc2VLZXJuZWwucmVhZCgpLCB0aGlzLnN0cmlkZXMgYXMgW251bWJlciwgbnVtYmVyXSxcbiAgICAgICAgICB0aGlzLnBhZGRpbmcsIHRoaXMuZGF0YUZvcm1hdCwgbnVsbCk7XG4gICAgICAvLyBUT0RPKGNhaXMpOiBBZGQgc3VwcG9ydCBmb3IgZGlsYXRpb24uXG4gICAgICBpZiAodGhpcy51c2VCaWFzKSB7XG4gICAgICAgIG91dHB1dHMgPSBLLmJpYXNBZGQob3V0cHV0cywgdGhpcy5iaWFzLnJlYWQoKSwgdGhpcy5kYXRhRm9ybWF0KTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmFjdGl2YXRpb24gIT0gbnVsbCkge1xuICAgICAgICBvdXRwdXRzID0gdGhpcy5hY3RpdmF0aW9uLmFwcGx5KG91dHB1dHMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG91dHB1dHM7XG4gICAgfSk7XG4gIH1cblxuICBvdmVycmlkZSBjb21wdXRlT3V0cHV0U2hhcGUoaW5wdXRTaGFwZTogU2hhcGV8U2hhcGVbXSk6IFNoYXBlfFNoYXBlW10ge1xuICAgIGlucHV0U2hhcGUgPSBnZXRFeGFjdGx5T25lU2hhcGUoaW5wdXRTaGFwZSk7XG4gICAgY29uc3Qgcm93cyA9XG4gICAgICAgIHRoaXMuZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnID8gaW5wdXRTaGFwZVsyXSA6IGlucHV0U2hhcGVbMV07XG4gICAgY29uc3QgY29scyA9XG4gICAgICAgIHRoaXMuZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnID8gaW5wdXRTaGFwZVszXSA6IGlucHV0U2hhcGVbMl07XG4gICAgY29uc3Qgb3V0RmlsdGVycyA9IHRoaXMuZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnID9cbiAgICAgICAgaW5wdXRTaGFwZVsxXSAqIHRoaXMuZGVwdGhNdWx0aXBsaWVyIDpcbiAgICAgICAgaW5wdXRTaGFwZVszXSAqIHRoaXMuZGVwdGhNdWx0aXBsaWVyO1xuICAgIGNvbnN0IG91dFJvd3MgPSBjb252T3V0cHV0TGVuZ3RoKFxuICAgICAgICByb3dzLCB0aGlzLmtlcm5lbFNpemVbMF0sIHRoaXMucGFkZGluZywgdGhpcy5zdHJpZGVzWzBdKTtcbiAgICBjb25zdCBvdXRDb2xzID0gY29udk91dHB1dExlbmd0aChcbiAgICAgICAgY29scywgdGhpcy5rZXJuZWxTaXplWzFdLCB0aGlzLnBhZGRpbmcsIHRoaXMuc3RyaWRlc1sxXSk7XG4gICAgaWYgKHRoaXMuZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnKSB7XG4gICAgICByZXR1cm4gW2lucHV0U2hhcGVbMF0sIG91dEZpbHRlcnMsIG91dFJvd3MsIG91dENvbHNdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJbiB0aGlzIGNhc2UsIGFzc3VtZSAnY2hhbm5lbHNMYXN0Jy5cbiAgICAgIHJldHVybiBbaW5wdXRTaGFwZVswXSwgb3V0Um93cywgb3V0Q29scywgb3V0RmlsdGVyc107XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0Q29uZmlnKCk6IHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdCB7XG4gICAgY29uc3QgY29uZmlnID0gc3VwZXIuZ2V0Q29uZmlnKCk7XG4gICAgY29uZmlnWydkZXB0aE11bHRpcGxpZXInXSA9IHRoaXMuZGVwdGhNdWx0aXBsaWVyO1xuICAgIGNvbmZpZ1snZGVwdGh3aXNlSW5pdGlhbGl6ZXInXSA9XG4gICAgICAgIHNlcmlhbGl6ZUluaXRpYWxpemVyKHRoaXMuZGVwdGh3aXNlSW5pdGlhbGl6ZXIpO1xuICAgIGNvbmZpZ1snZGVwdGh3aXNlUmVndWxhcml6ZXInXSA9XG4gICAgICAgIHNlcmlhbGl6ZVJlZ3VsYXJpemVyKHRoaXMuZGVwdGh3aXNlUmVndWxhcml6ZXIpO1xuICAgIGNvbmZpZ1snZGVwdGh3aXNlQ29uc3RyYWludCddID1cbiAgICAgICAgc2VyaWFsaXplQ29uc3RyYWludCh0aGlzLmRlcHRod2lzZVJlZ3VsYXJpemVyKTtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG59XG5zZXJpYWxpemF0aW9uLnJlZ2lzdGVyQ2xhc3MoRGVwdGh3aXNlQ29udjJEKTtcbiJdfQ==