function Plot() {
	var options;
	var nargs;
	var keys;
	var self;
	var opts;
	var key;
	var i;

	nargs = arguments.length;
	if ( !(this instanceof Plot) ) {
		if ( nargs === 0 ) {
			return new Plot();
		}
		if ( nargs === 1 ) {
			return new Plot( arguments[0] );
		}
		if ( nargs === 2 ) {
			return new Plot( arguments[0], arguments[1] );
		}
		return new Plot( arguments[0], arguments[1], arguments[2] );
	}
	self = this;

	opts = defaults();
	if ( nargs === 0 ) {
		options = {};
	} else if ( nargs === 1 ) {
		options = arguments[ 0 ];
		if ( !isObject( options ) ) {
			throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) );
		}
	} else if ( nargs === 2 ) {
		options = {
			'x': arguments[ 0 ],
			'y': arguments[ 1 ]
		};
	} else if ( nargs > 2 ) {
		if ( !isObject( arguments[2] ) ) {
			throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', arguments[2] ) );
		}
		options = copy( arguments[2] ); // avoid mutation
		options.x = arguments[ 0 ];
		options.y = arguments[ 1 ];
	}
	opts = merge( opts, options );

	debug( 'Creating an instance with the following configuration: %s.', JSON.stringify( opts ) );
	EventEmitter.call( this );

	for ( i = 0; i < PRIVATE_PROPS.length; i++ ) {
		defineProperty( this, PRIVATE_PROPS[i], {
			'configurable': false,
			'enumerable': false,
			'writable': true,
			'value': null
		});
	}
	// Set a clipping path id:
	defineProperty( this, '_clipPathId', {
		'configurable': false,
		'enumerable': false,
		'writable': false,
		'value': minstd().toString() // TODO: uuid
	});

	// Initialize an internal cache for renderers...
	defineProperty( this, '$', {
		'configurable': false,
		'enumerable': false,
		'writable': false,
		'value': {}
	});
	defineProperty( this.$, 'svg', {
		'configurable': false,
		'enumerable': false,
		'writable': false,
		'value': {}
	});

	// Set options...
	keys = objectKeys( opts );
	for ( i = 0; i < keys.length; i++ ) {
		key = keys[ i ];
		this[ key ] = opts[ key ];
	}

	// Add event listeners:
	this.on( 'change', onChange );
	this.on( 'render', onRender );

	return this;

	/**
	* Callback invoked upon receiving a change event.
	*
	* @private
	*/
	function onChange() {
		/* eslint-disable no-underscore-dangle */
		debug( 'Received a change event.' );
		if ( self._autoRender ) {
			self.render();
		}
	}

	/**
	* Callback invoked upon receiving a render event.
	*
	* @private
	* @param {*} plot - rendered plot
	*/
	function onRender( plot ) {
		/* eslint-disable no-underscore-dangle */
		debug( 'Received a render event.' );
		if ( self._autoView ) {
			debug( 'Viewer: %s.', self._viewer );
			debug( 'Generating view...' );
			view( self, self._viewer, plot );
		}
	}
}
Plot constructor.

@constructor
@param {Array} [x] - x-values
@param {Array} [y] - y-values
@param {Options} [options] - constructor options
@param {boolean} [options.autoRender=false] - indicates whether to re-render on a change event
@param {boolean} [options.autoView=false] - indicates whether to generate an updated view on a render event
@param {(string|StringArray)} [options.colors='category10'] - data colors
@param {string} [options.description=''] - plot description
@param {string} [options.engine='svg'] - plot engine
@param {PositiveNumber} [options.height=400] - plot height
@param {Function} [options.isDefined] - accessor indicating whether a datum is defined
@param {(StringArray|EmptyArray)} [options.labels] - data labels
@param {(number|NumberArray)} [options.lineOpacity=0.9] - data line opacity
@param {(string|StringArray)} [options.lineStyle='-'] - data line style(s)
@param {(NonNegativeInteger|Array<NonNegativeInteger>)} [options.lineWidth=2] - data line width(s)
@param {NonNegativeInteger} [options.paddingBottom=80] - bottom padding
@param {NonNegativeInteger} [options.paddingLeft=90] - left padding
@param {NonNegativeInteger} [options.paddingRight=20] - right padding
@param {NonNegativeInteger} [options.paddingTop=80] - top padding
@param {string} [options.renderFormat='vdom'] - plot render format
@param {(string|StringArray)} [options.symbols='none'] - data symbols
@param {(number|NumberArray)} [options.symbolsOpacity=0.9] - symbols opacity
@param {(NonNegativeInteger|Array<NonNegativeInteger>)} [options.symbolsSize=6] - symbols size
@param {string} [options.title=''] - plot title
@param {string} [options.viewer='none'] - plot viewer
@param {PositiveNumber} [options.width=400] - plot width
@param {Array} [options.x=[]] - x-values
@param {string} [options.xAxisOrient='bottom'] - x-axis orientation
@param {string} [options.xLabel='x'] - x-axis label
@param {(Date|FiniteNumber|null)} [options.xMax=null] - maximum value of x-axis domain
@param {(Date|FiniteNumber|null)} [options.xMin=null] - minimum value of x-axis domain
@param {(NonNegativeInteger|null)} [options.xNumTicks=5] - number of x-axis tick marks
@param {(boolean|BooleanArray)} [options.xRug=false] - indicates whether to render a rug plot along the x-axis
@param {(string|StringArray)} [options.xRugOrient='bottom'] - x-axis rug orientation
@param {(number|NumberArray)} [options.xRugOpacity=0.1] - x-axis rug opacity
@param {(NonNegativeInteger|Array<NonNegativeInteger>)} [options.xRugSize=6] - x-axis rug tick (tassel) size
@param {string} [options.xScale='linear'] - x-axis scale
@param {(string|null)} [options.xTickFormat=null] - x-axis tick format
@param {Array} [options.y=[]] - y-values
@param {string} [options.yAxisOrient='left'] - y-axis orientation
@param {string} [options.yLabel='y'] - y-axis label
@param {(FiniteNumber|null)} [options.yMax=null] - maximum value of y-axis domain
@param {(FiniteNumber|null)} [options.yMin=null] - minimum value of y-axis domain
@param {(NonNegativeInteger|null)} [options.yNumTicks=5] - number of y-axis tick marks
@param {(boolean|BooleanArray)} [options.yRug=false] - indicates whether to render a rug plot along the y-axis
@param {(string|StringArray)} [options.yRugOrient='left'] - y-axis rug orientation
@param {(number|NumberArray)} [options.yRugOpacity=0.1] - y-axis rug opacity
@param {(NonNegativeInteger|Array<NonNegativeInteger>)} [options.yRugSize=6] - y-axis rug tick (tassel) size
@param {string} [options.yScale='linear'] - y-axis scale
@param {(string|null)} [options.yTickFormat=null] - y-axis tick format
@throws {TypeError} must provide valid options
@returns {Plot} Plot instance

@example
var plot = new Plot();