# Path: sklearn/utils/validation.py
# def check_array(array, accept_sparse=None, dtype=None, order=None, copy=False,
#                 force_all_finite=True, ensure_2d=True, allow_nd=False):
#     """Input validation on an array, list, sparse matrix or similar.
# 
#     By default, the input is converted to an at least 2nd numpy array.
# 
#     Parameters
#     ----------
#     array : object
#         Input object to check / convert.
# 
#     accept_sparse : string, list of string or None (default=None)
#         String[s] representing allowed sparse matrix formats, such as 'csc',
#         'csr', etc.  None means that sparse matrix input will raise an error.
#         If the input is sparse but not in the allowed format, it will be
#         converted to the first listed format.
# 
#     dtype : string, type or None (default=none)
#         Data type of result. If None, the dtype of the input is preserved.
# 
#     order : 'F', 'C' or None (default=None)
#         Whether an array will be forced to be fortran or c-style.
# 
#     copy : boolean (default=False)
#         Whether a forced copy will be triggered. If copy=False, a copy might
#         be triggered by a conversion.
# 
#     force_all_finite : boolean (default=True)
#         Whether to raise an error on np.inf and np.nan in X.
# 
#     ensure_2d : boolean (default=True)
#         Whether to make X at least 2d.
# 
#     allow_nd : boolean (default=False)
#         Whether to allow X.ndim > 2.
# 
#     Returns
#     -------
#     X_converted : object
#         The converted and validated X.
#     """
#     if isinstance(accept_sparse, str):
#         accept_sparse = [accept_sparse]
# 
#     if sp.issparse(array):
#         array = _ensure_sparse_format(array, accept_sparse, dtype, order,
#                                       copy, force_all_finite)
#     else:
#         if ensure_2d:
#             array = np.atleast_2d(array)
#         array = np.array(array, dtype=dtype, order=order, copy=copy)
#         if not allow_nd and array.ndim >= 3:
#             raise ValueError("Found array with dim %d. Expected <= 2" %
#                              array.ndim)
#         if force_all_finite:
#             _assert_all_finite(array)
# 
#     return array


from heapq import heapify, heappop, heappush, heappushpop
from scipy import sparse
from ..base import BaseEstimator, ClusterMixin
from ..externals.joblib import Memory
from ..externals import six
from ..metrics.pairwise import paired_distances, pairwise_distances
from ..utils import check_array
from ..utils.sparsetools import connected_components
from . import _hierarchical
from ._feature_agglomeration import AgglomerationTransform
from ..utils.fast_dict import IntFloatDict
        from scipy.cluster import hierarchy     # imports PIL
        from scipy.cluster import hierarchy     # imports PIL
import warnings
import sys
import numpy as np
        The children of each non-leaf node. Values less than `n_features`
        correspond to leaves of the tree which are the original samples.
        A node `i` greater than or equal to `n_features` is a non-leaf
        node and has children `children_[i - n_features]`. Alternatively
        at the i-th iteration, children[i][0] and children[i][1]
        are merged to form node `n_features + i`

    labels_ : array [n_features]
        cluster labels for each feature

    n_leaves_ : int
        Number of leaves in the hierarchical tree.

    n_components_ : int
        The estimated number of connected components in the graph.

    """

    def fit(self, X, y=None, **params):
        """Fit the hierarchical clustering on the data

        Parameters
        ----------
        X : array-like, shape = [n_samples, n_features]
            The data

        Returns
        -------
        self
        """

# Path: sklearn/utils/validation.py
# def check_array(array, accept_sparse=None, dtype=None, order=None, copy=False,
#                 force_all_finite=True, ensure_2d=True, allow_nd=False):
#     """Input validation on an array, list, sparse matrix or similar.
# 
#     By default, the input is converted to an at least 2nd numpy array.
# 
#     Parameters
#     ----------
#     array : object
#         Input object to check / convert.
# 
#     accept_sparse : string, list of string or None (default=None)
#         String[s] representing allowed sparse matrix formats, such as 'csc',
#         'csr', etc.  None means that sparse matrix input will raise an error.
#         If the input is sparse but not in the allowed format, it will be
#         converted to the first listed format.
# 
#     dtype : string, type or None (default=none)
#         Data type of result. If None, the dtype of the input is preserved.
# 
#     order : 'F', 'C' or None (default=None)
#         Whether an array will be forced to be fortran or c-style.
# 
#     copy : boolean (default=False)
#         Whether a forced copy will be triggered. If copy=False, a copy might
#         be triggered by a conversion.
# 
#     force_all_finite : boolean (default=True)
#         Whether to raise an error on np.inf and np.nan in X.
# 
#     ensure_2d : boolean (default=True)
#         Whether to make X at least 2d.
# 
#     allow_nd : boolean (default=False)
#         Whether to allow X.ndim > 2.
# 
#     Returns
#     -------
#     X_converted : object
#         The converted and validated X.
#     """
#     if isinstance(accept_sparse, str):
#         accept_sparse = [accept_sparse]
# 
#     if sp.issparse(array):
#         array = _ensure_sparse_format(array, accept_sparse, dtype, order,
#                                       copy, force_all_finite)
#     else:
#         if ensure_2d:
#             array = np.atleast_2d(array)
#         array = np.array(array, dtype=dtype, order=order, copy=copy)
#         if not allow_nd and array.ndim >= 3:
#             raise ValueError("Found array with dim %d. Expected <= 2" %
#                              array.ndim)
#         if force_all_finite:
#             _assert_all_finite(array)
# 
#     return array


# Path: sklearn/cluster/hierarchical.py
from heapq import heapify, heappop, heappush, heappushpop
from scipy import sparse
from ..base import BaseEstimator, ClusterMixin
from ..externals.joblib import Memory
from ..externals import six
from ..metrics.pairwise import paired_distances, pairwise_distances
from ..utils import check_array
from ..utils.sparsetools import connected_components
from . import _hierarchical
from ._feature_agglomeration import AgglomerationTransform
from ..utils.fast_dict import IntFloatDict
        from scipy.cluster import hierarchy     # imports PIL
        from scipy.cluster import hierarchy     # imports PIL
import warnings
import sys
import numpy as np

        The children of each non-leaf node. Values less than `n_features`
        correspond to leaves of the tree which are the original samples.
        A node `i` greater than or equal to `n_features` is a non-leaf
        node and has children `children_[i - n_features]`. Alternatively
        at the i-th iteration, children[i][0] and children[i][1]
        are merged to form node `n_features + i`

    labels_ : array [n_features]
        cluster labels for each feature

    n_leaves_ : int
        Number of leaves in the hierarchical tree.

    n_components_ : int
        The estimated number of connected components in the graph.

    """

    def fit(self, X, y=None, **params):
        """Fit the hierarchical clustering on the data

        Parameters
        ----------
        X : array-like, shape = [n_samples, n_features]
            The data

        Returns
        -------
        self
        """

        X = check_array(X)