# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------

"""Compute minibatch blobs for training a Fast R-CNN network."""

import numpy as np
import numpy.random as npr
import cv2
from fast_rcnn.config import cfg
from utils.blob import prep_im_for_blob, im_list_to_blob
from utils.model import last_conv_size
from roi_data_layer.roidb import prepare_one_roidb_rpn, prepare_one_roidb_frcnn
from roidb import clear_one_roidb

def get_minibatch(roidb, num_classes, bbox_means, bbox_stds, proposal_file):
    """Given a roidb, construct a minibatch sampled from it."""
    num_images = len(roidb)
    # Sample random scales to use for each image in this batch
    random_scale_inds = npr.randint(0, high=len(cfg.TRAIN.SCALES),
                                    size=num_images)
    assert(cfg.TRAIN.BATCH_SIZE % num_images == 0), \
        'num_images ({}) must divide BATCH_SIZE ({})'. \
        format(num_images, cfg.TRAIN.BATCH_SIZE)
    rois_per_image = cfg.TRAIN.BATCH_SIZE / num_images
    fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image)

    # Get the input image blob, formatted for caffe
    im_blob, im_scales, processed_ims = _get_image_blob(roidb, random_scale_inds)

    if 'model_to_use' in roidb[0] and roidb[0]['model_to_use'] == 'rpn':

        conv_h, scale_h = last_conv_size(im_blob.shape[2], cfg.MODEL_NAME)
        conv_w, scale_w = last_conv_size(im_blob.shape[3], cfg.MODEL_NAME)

        # Now, build the region of interest and label blobs
        rois_blob = np.zeros((0, 5), dtype=np.float32)
        labels_blob = np.zeros((0, 9, conv_h, conv_w), dtype=np.float32)
        bbox_targets_blob = np.zeros((0, 36, conv_h, conv_w), dtype=np.float32)
        bbox_loss_blob = np.zeros(bbox_targets_blob.shape, dtype=np.float32)
        all_overlaps = []
        for im_i in xrange(num_images):

            if cfg.TRAIN.LAZY_PREPARING_ROIDB:
                prepare_one_roidb_rpn(roidb[im_i],
                                      processed_ims[im_i].shape[0],
                                      processed_ims[im_i].shape[1],
                                      im_scales[im_i])

            # Normalize bbox_targets
            if cfg.TRAIN.NORMALIZE_BBOX:
                bbox_targets = roidb[im_i]['bbox_targets']
                cls_inds = np.where(bbox_targets[:, 0] > 0)[0]
                if cls_inds.size > 0:
                    bbox_targets[cls_inds, 1:] -= bbox_means[0, :]
                    bbox_targets[cls_inds, 1:] /= bbox_stds[0, :]

            labels, overlaps, im_rois, bbox_targets, bbox_loss \
                = _sample_rois_rpn(roidb[im_i], fg_rois_per_image, rois_per_image,
                               num_classes, conv_h, conv_w)

            # Add to RoIs blob
            if im_rois != None:
                batch_ind = im_i * np.ones((im_rois.shape[0], 1))
                rois_blob_this_image = np.hstack((batch_ind, im_rois))
                rois_blob = np.vstack((rois_blob, rois_blob_this_image))

            # Add to labels, bbox targets, and bbox loss blobs
            labels_blob = np.vstack((labels_blob, labels))
            bbox_targets_blob = np.vstack((bbox_targets_blob, bbox_targets))
            bbox_loss_blob = np.vstack((bbox_loss_blob, bbox_loss))

        # For debug visualizations
        #_vis_minibatch_rpn(im_blob, conv_h, conv_w, rois_blob, labels_blob, roidb, bbox_targets_blob, bbox_loss_blob)

        blobs = {'data': im_blob,
                 'labels': labels_blob}
    else:
        # Now, build the region of interest and label blobs
        rois_blob = np.zeros((0, 5), dtype=np.float32)
        labels_blob = np.zeros((0), dtype=np.float32)
        bbox_targets_blob = np.zeros((0, 4 * num_classes), dtype=np.float32)
        bbox_loss_blob = np.zeros(bbox_targets_blob.shape, dtype=np.float32)
        all_overlaps = []
        for im_i in xrange(num_images):

            if cfg.TRAIN.LAZY_PREPARING_ROIDB:
                prepare_one_roidb_frcnn(roidb[im_i], proposal_file, num_classes)

            # Normalize bbox_targets
            if cfg.TRAIN.NORMALIZE_BBOX:
                bbox_targets = roidb[im_i]['bbox_targets']
                for cls in xrange(1, num_classes):
                    cls_inds = np.where(bbox_targets[:, 0] == cls)[0]
                    bbox_targets[cls_inds, 1:] -= bbox_means[cls, :]
                    bbox_targets[cls_inds, 1:] /= bbox_stds[cls, :]

            labels, overlaps, im_rois, bbox_targets, bbox_loss \
                = _sample_rois(roidb[im_i], fg_rois_per_image, rois_per_image,
                               num_classes)

            # Add to RoIs blob
            rois = _project_im_rois(im_rois, im_scales[im_i])
            batch_ind = im_i * np.ones((rois.shape[0], 1))
            rois_blob_this_image = np.hstack((batch_ind, rois))
            rois_blob = np.vstack((rois_blob, rois_blob_this_image))

            # Add to labels, bbox targets, and bbox loss blobs
            labels_blob = np.hstack((labels_blob, labels))
            bbox_targets_blob = np.vstack((bbox_targets_blob, bbox_targets))
            bbox_loss_blob = np.vstack((bbox_loss_blob, bbox_loss))
            #all_overlaps = np.hstack((all_overlaps, overlaps))

        # For debug visualizations
        #_vis_minibatch(im_blob, rois_blob, labels_blob, all_overlaps)

        blobs = {'data': im_blob,
                 'rois': rois_blob,
                 'labels': labels_blob}

    if cfg.TRAIN.BBOX_REG:
        blobs['bbox_targets'] = bbox_targets_blob
        blobs['bbox_loss_weights'] = bbox_loss_blob

    return blobs

def clear_minibatch(roidb):
    num_images = len(roidb)
    for im_i in xrange(num_images):
        clear_one_roidb(roidb[im_i])

def _sample_rois(roidb, fg_rois_per_image, rois_per_image, num_classes):
    """Generate a random sample of RoIs comprising foreground and background
    examples.
    """
    # label = class RoI has max overlap with
    labels = roidb['max_classes']
    overlaps = roidb['max_overlaps']
    rois = roidb['boxes']

    # Select foreground RoIs as those with >= FG_THRESH overlap
    fg_inds = np.where(overlaps >= cfg.TRAIN.FG_THRESH)[0]
    # Guard against the case when an image has fewer than fg_rois_per_image
    # foreground RoIs
    fg_rois_per_this_image = np.minimum(fg_rois_per_image, fg_inds.size)
    # Sample foreground regions without replacement
    if fg_inds.size > 0:
        fg_inds = npr.choice(fg_inds, size=fg_rois_per_this_image,
                             replace=False)

    # Select background RoIs as those within [BG_THRESH_LO, BG_THRESH_HI)
    bg_inds = np.where((overlaps < cfg.TRAIN.BG_THRESH_HI) &
                       (overlaps >= cfg.TRAIN.BG_THRESH_LO))[0]
    # Compute number of background RoIs to take from this image (guarding
    # against there being fewer than desired)
    bg_rois_per_this_image = rois_per_image - fg_rois_per_this_image
    bg_rois_per_this_image = np.minimum(bg_rois_per_this_image,
                                        bg_inds.size)
    # Sample foreground regions without replacement
    if bg_inds.size > 0:
        bg_inds = npr.choice(bg_inds, size=bg_rois_per_this_image,
                             replace=False)

    # The indices that we're selecting (both fg and bg)
    keep_inds = np.append(fg_inds, bg_inds)
    # Select sampled values from various arrays:
    labels = labels[keep_inds]
    # Clamp labels for the background RoIs to 0
    labels[fg_rois_per_this_image:] = 0
    overlaps = overlaps[keep_inds]
    rois = rois[keep_inds]

    bbox_targets, bbox_loss_weights = \
            _get_bbox_regression_labels(roidb['bbox_targets'][keep_inds, :],
                                        num_classes)

    return labels, overlaps, rois, bbox_targets, bbox_loss_weights

def get_img_rect(img_height, img_width, conv_height, conv_width, axis1, axis2, axis3):

    anchors = np.array([[128*2, 128*1], [128*1, 128*1], [128*1, 128*2],
                       [256*2, 256*1], [256*1, 256*1], [256*1, 256*2],
                       [512*2, 512*1], [512*1, 512*1], [512*1, 512*2]])

    scale_width = img_width / conv_width
    scale_height = img_height / conv_height

    img_center_x = img_width * axis3 / conv_width + scale_width / 2
    img_center_y = img_height * axis2 / conv_height + scale_height / 2
    anchor_size = anchors[axis1]
    img_x1 = img_center_x - anchor_size[0] / 2
    img_x2 = img_center_x + anchor_size[0] / 2
    img_y1 = img_center_y - anchor_size[1] / 2
    img_y2 = img_center_y + anchor_size[1] / 2

    return [img_x1, img_y1, img_x2, img_y2]

def _sample_rois_rpn(roidb, fg_rois_per_image, rois_per_image, num_classes,
                 union_conv_height, union_conv_width):
    """Generate a random sample of RoIs comprising foreground and background
    examples.
    """
    # label = class RoI has max overlap with
    labels = roidb['max_classes']
    new_labels = np.zeros(labels.shape, dtype=np.int16)
    new_labels.fill(-1)
    bbox_target = roidb['bbox_targets']
    new_bbox_target = np.zeros(bbox_target.shape, dtype=np.float32)

    conv_width = roidb['conv_width']
    conv_height = roidb['conv_height']

    # Select foreground RoIs as those with >= FG_THRESH overlap
    fg_inds = np.where(labels > 0)[0]
    # Guard against the case when an image has fewer than fg_rois_per_image
    # foreground RoIs
    fg_rois_per_this_image = np.minimum(fg_rois_per_image, fg_inds.size)

    # Sample foreground regions without replacement
    if fg_inds.size > 0:
        fg_inds = npr.choice(fg_inds, size=fg_rois_per_this_image,
                             replace=False)

    # Select background RoIs as those within [BG_THRESH_LO, BG_THRESH_HI)
    bg_inds = np.where(labels == 0)[0]

    # Compute number of background RoIs to take from this image (guarding
    # against there being fewer than desired)
    bg_rois_per_this_image = rois_per_image - fg_rois_per_this_image
    bg_rois_per_this_image = np.minimum(bg_rois_per_this_image,
                                        bg_inds.size)
    # Sample foreground regions without replacement
    if bg_inds.size > 0:
        bg_inds = npr.choice(bg_inds, size=bg_rois_per_this_image,
                             replace=False)

    new_labels[fg_inds] = 1
    new_labels[bg_inds] = 0

    if 'rois' in roidb:
        rois = roidb['rois'][fg_inds]
    else:
        rois = None

    """
    print 'labels.shape %s' % labels.shape
    print 'bbox_target.shape %s' % (bbox_target.shape, )

    for fg_ind in fg_inds:
        print 'label : %s ' % labels[fg_ind]
        print 'bbox_target : %s ' % bbox_target[fg_ind]

        axis1 = fg_ind / conv_height / conv_width
        axis2 = fg_ind / conv_width % conv_height
        axis3 = fg_ind % conv_width

        im = cv2.imread(roidb['image'])
        target_size = cfg.TRAIN.SCALES[0]
        im, im_scale = prep_im_for_blob(im, 0, target_size,
                                        cfg.TRAIN.MAX_SIZE,
                                        cfg.TRAIN.MIN_SIZE)

        img_height = im.shape[2]
        img_width = im.shape[3]
        proposal_rects = get_img_rect(img_height, img_width, conv_height, conv_width, axis1, axis2, axis3)

        for proposal_rect in proposal_rects:

            plt.imshow(im)
            for ground_rect in ground_rects:
                plt.gca().add_patch(
                    plt.Rectangle((ground_rect[0], ground_rect[1]), ground_rect[2] - ground_rect[0],
                                  ground_rect[3] - ground_rect[1], fill=False,
                                  edgecolor='b', linewidth=3)
                    )
            plt.gca().add_patch(
                plt.Rectangle((proposal_rect[0], proposal_rect[1]), proposal_rect[2] - proposal_rect[0],
                              proposal_rect[3] - proposal_rect[1], fill=False,
                              edgecolor='g', linewidth=3)
                )
            plt.gca().add_patch(
                plt.Rectangle((pred_rect[0], pred_rect[1]), pred_rect[2] - pred_rect[0],
                              pred_rect[3] - pred_rect[1], fill=False,
                              edgecolor='r', linewidth=3)
                )

            plt.show(block=False)
            raw_input("")
            plt.close()
    """

    new_bbox_target[fg_inds] = bbox_target[fg_inds]

    new_bbox_target, bbox_loss_weights = \
            _get_bbox_regression_labels_rpn(new_bbox_target,
                                        num_classes, labels)

    """
    print 'label no 1 : %s' % len(np.where(new_labels == 1)[0])
    print 'new_bbox_target no 1 : %s' % len(np.where(new_bbox_target != 0)[0])
    print 'bbox_loss_weights no 1 : %s' % len(np.where(bbox_loss_weights > 0)[0])
    """

    new_labels = new_labels.reshape((1, 9, conv_height, conv_width))

    new_bbox_target = new_bbox_target.reshape((1, 9, conv_height, conv_width, 4))
    new_bbox_target = new_bbox_target.transpose(0, 1, 4, 2, 3)
    new_bbox_target = new_bbox_target.reshape((1, 36, conv_height, conv_width))

    bbox_loss_weights = bbox_loss_weights.reshape((1, 9, conv_height, conv_width, 4))
    bbox_loss_weights = bbox_loss_weights.transpose(0, 1, 4, 2, 3)
    bbox_loss_weights = bbox_loss_weights.reshape((1, 36, conv_height, conv_width))

    output_labels = np.zeros((1, 9, union_conv_height, union_conv_width))
    output_bbox_targets = np.zeros((1, 36, union_conv_height, union_conv_width))
    output_bbox_loss_weights = np.zeros((1, 36, union_conv_height, union_conv_width))

    output_labels.fill(-1)
    output_labels[:, :, 0:conv_height, 0:conv_width] = new_labels
    output_bbox_targets[:, :, 0:conv_height, 0:conv_width] = new_bbox_target
    output_bbox_loss_weights[:, :, 0:conv_height, 0:conv_width] = bbox_loss_weights

    """
    for fg_ind in fg_inds:
        if fg_ind == 6510:
            axis1 = fg_ind / conv_height / conv_width
            axis2 = fg_ind / conv_width % conv_height
            axis3 = fg_ind % conv_width
            print ''
            print 'conv_size : %s, %s' % (conv_height, conv_width)
            print 'axis : %s, %s, %s' % (axis1, axis2, axis3)
            print 'output_labels[%s] : %s' % (fg_ind, output_labels[0, axis1, axis2, axis3])
            print 'output_bbox_targets[%s] : %s' % (fg_ind, output_bbox_targets[0, axis1*4:axis1*4+4, axis2, axis3])
            print 'output_bbox_loss_weights[%s] : %s' % (fg_ind, output_bbox_loss_weights[0, axis1*4:axis1*4+4, axis2, axis3])
    """

    """
    # Generate positive rois based on index for debugging
    anchors = [[128*2, 128*1], [128*1, 128*1], [128*1, 128*2],
               [256*2, 256*1], [256*1, 256*1], [256*1, 256*2],
               [512*2, 512*1], [512*1, 512*1], [512*1, 512*2]]

    conv_scale_width = roidb['conv_scale_width']
    conv_scale_height = roidb['conv_scale_height']

    rois = np.zeros((len(fg_inds), 4), dtype=np.int16)
    for i, fg_ind in enumerate(fg_inds):
        center_x = fg_ind % conv_width
        center_y = (fg_ind - center_x) / conv_width % conv_height
        anchor = fg_ind / conv_height / conv_width

        anchor_w = anchors[anchor][0]
        anchor_h = anchors[anchor][1]

        x1 = center_x * conv_scale_width - anchor_w / 2
        y1 = center_y * conv_scale_height - anchor_h / 2
        x2 = x1 + anchor_w
        y2 = y1 + anchor_h

        rois[i, :] = x1, y1, x2, y2
    """

    """
    pos_labels = np.where(new_labels == 1)

    i = 0
    for d0, d1, d2, d3 in zip(pos_labels[0], pos_labels[1], pos_labels[2], pos_labels[3]):
        print '[%s] label : %s, bbox_target : %s, bbox_loss_weights : %s' % (i, new_labels[d0, d1, d2, d3],
                                                     new_bbox_target[d0, d1*4 : d1*4+4, d2, d3],
                                                     bbox_loss_weights[d0, d1*4 : d1*4+4, d2, d3])
        i += 1
    """

    """
    print 'label no 2 : %s' % len(np.where(output_labels == 1)[0])
    print 'new_bbox_target no 2 : %s' % len(np.where(output_bbox_targets != 0)[0])
    print 'bbox_loss_weights no 2 : %s' % len(np.where(output_bbox_loss_weights > 0)[0])
    """

    return output_labels, None, rois, output_bbox_targets, output_bbox_loss_weights

def _get_image_blob(roidb, scale_inds):
    """Builds an input blob from the images in the roidb at the specified
    scales.
    """
    num_images = len(roidb)
    processed_ims = []
    im_scales = []
    for i in xrange(num_images):
        im = cv2.imread(roidb[i]['image'])
        if roidb[i]['flipped']:
            im = im[:, ::-1, :]
        target_size = cfg.TRAIN.SCALES[scale_inds[i]]
        im, im_scale = prep_im_for_blob(im, cfg.PIXEL_MEANS, target_size,
                                        cfg.TRAIN.MAX_SIZE,
                                        cfg.TRAIN.MIN_SIZE)
        im_scales.append(im_scale)
        processed_ims.append(im)

    # Create a blob to hold the input images
    blob = im_list_to_blob(processed_ims)

    return blob, im_scales, processed_ims

def _project_im_rois(im_rois, im_scale_factor):
    """Project image RoIs into the rescaled training image."""
    rois = im_rois * im_scale_factor
    return rois

def _get_bbox_regression_labels(bbox_target_data, num_classes):
    """Bounding-box regression targets are stored in a compact form in the
    roidb.

    This function expands those targets into the 4-of-4*K representation used
    by the network (i.e. only one class has non-zero targets). The loss weights
    are similarly expanded.

    Returns:
        bbox_target_data (ndarray): N x 4K blob of regression targets
        bbox_loss_weights (ndarray): N x 4K blob of loss weights
    """
    clss = bbox_target_data[:, 0]

    bbox_targets = np.zeros((clss.size, 4 * num_classes), dtype=np.float32)
    bbox_loss_weights = np.zeros(bbox_targets.shape, dtype=np.float32)
    inds = np.where(clss > 0)[0]
    for ind in inds:
        cls = clss[ind]
        start = 4 * cls
        end = start + 4
        bbox_targets[ind, start:end] = bbox_target_data[ind, 1:]
        bbox_loss_weights[ind, start:end] = [1., 1., 1., 1.]

    return bbox_targets, bbox_loss_weights

def _get_bbox_regression_labels_rpn(bbox_target_data, num_classes, labels):
    """Bounding-box regression targets are stored in a compact form in the
    roidb.

    This function expands those targets into the 4-of-4*K representation used
    by the network (i.e. only one class has non-zero targets). The loss weights
    are similarly expanded.

    Returns:
        bbox_target_data (ndarray): N x 4K blob of regression targets
        bbox_loss_weights (ndarray): N x 4K blob of loss weights
    """
    clss = bbox_target_data[:, 0]

    bbox_targets = np.zeros((clss.size, 4), dtype=np.float32)
    bbox_loss_weights = np.zeros(bbox_targets.shape, dtype=np.float32)
    inds = np.where(clss > 0)[0]

    #print ''
    #print 'len(inds) : %s' % len(inds)

    for ind in inds:
        bbox_targets[ind, :] = bbox_target_data[ind, 1:]
        bbox_loss_weights[ind, :] = [1., 1., 1., 1.]

        #print 'bbox_targets[ind, :] : %s - %s ' % (bbox_target_data[ind, 0], bbox_targets[ind, :])

    return bbox_targets, bbox_loss_weights

def _vis_minibatch(im_blob, rois_blob, labels_blob, overlaps):
    """Visualize a mini-batch for debugging."""
    import matplotlib.pyplot as plt
    for i in xrange(rois_blob.shape[0]):
        rois = rois_blob[i, :]
        im_ind = rois[0]
        roi = rois[1:]
        im = im_blob[im_ind, :, :, :].transpose((1, 2, 0)).copy()
        im += cfg.PIXEL_MEANS
        im = im[:, :, (2, 1, 0)]
        im = im.astype(np.uint8)
        cls = labels_blob[i]
        plt.imshow(im)
        print 'class: ', cls, ' overlap: ', overlaps[i]
        plt.gca().add_patch(
            plt.Rectangle((roi[0], roi[1]), roi[2] - roi[0],
                          roi[3] - roi[1], fill=False,
                          edgecolor='r', linewidth=3)
            )
        plt.show()

def _vis_minibatch_rpn(im_blob, conv_h, conv_w, rois_blob, labels_blob, roidb, bbox_targets_blob, bbox_loss_blob):
    """Visualize a mini-batch for debugging."""
    import matplotlib.pyplot as plt
    for i in xrange(len(roidb)):

        # DJDJ
        #if roidb[i]['image'].endswith('000009.jpg') == False:
        #    continue

        print 'image : %s' % roidb[i]['image']

        resized_gt_boxes = roidb[int(i)]['resized_gt_boxes']
        im = im_blob[i, :, :, :].transpose((1, 2, 0)).copy()
        im += cfg.PIXEL_MEANS
        im = im[:, :, (2, 1, 0)]
        im = im.astype(np.uint8)

        for j in range(9):
            for k in range(labels_blob.shape[2]):
                for l in range(labels_blob.shape[3]):
                    label = labels_blob[i][j][k][l]

                    if label == -1:
                        continue
                    elif label == 1:
                        color = 'g'
                    elif label == 0:
                        #color = 'y'
                        continue

                    plt.imshow(im)

                    for resized_gt_box in resized_gt_boxes:
                        resized_gt_box = resized_gt_box.astype(np.int)
                        plt.gca().add_patch(
                            plt.Rectangle((resized_gt_box[0], resized_gt_box[1]), resized_gt_box[2] - resized_gt_box[0],
                                          resized_gt_box[3] - resized_gt_box[1], fill=False,
                                          edgecolor='b', linewidth=3)
                            )

                    proposal_rects = get_img_rect(im.shape[0], im.shape[1], conv_h, conv_w, j, k, l)
                    plt.gca().add_patch(
                        plt.Rectangle((proposal_rects[0], proposal_rects[1]), proposal_rects[2] - proposal_rects[0],
                                      proposal_rects[3] - proposal_rects[1], fill=False,
                                      edgecolor=color, linewidth=3)
                    )
                    plt.show(block=False)
                    raw_input("")
                    plt.close()


"""MCMC example for transit fitting."""

import matplotlib.pyplot as pl
from everest import Everest, TransitModel
import numpy as np
import emcee
from tqdm import tqdm
from corner import corner

def lnprior(x):
    """Return the log prior given parameter vector `x`."""
    per, t0, b = x
    if b < -1 or b > 1:
        return -np.inf
    elif per < 7 or per > 10:
        return -np.inf
    elif t0 < 1978 or t0 > 1979:
        return -np.inf
    else:
        return 0.

def lnlike(x, star):
    """Return the log likelihood given parameter vector `x`."""
    ll = lnprior(x)
    if np.isinf(ll):
        return ll, (np.nan, np.nan)
    per, t0, b = x
    model = TransitModel('b', per=per, t0=t0, b=b, rhos=10.)(star.time)
    like, d, vard = star.lnlike(model, full_output=True)
    ll += like
    return ll, (d,)

# Initialize the everest model
star = Everest(201635569)

# Set up the MCMC sampler
params = ['Period (days)', r't$_0$ (BJD - 2456811)', 'Impact parameter']
blobs = ['Depth (%)']
nsteps = 1000
nburn = 300
nwalk = 10
ndim = len(params)
nblobs = len(blobs)
sampler = emcee.EnsembleSampler(nwalk, ndim, lnlike, args=[star])
x0 = [[8.368 + 0.01 * np.random.randn(),
       1978.4513 + 0.01 * np.random.randn(),
       0. + 0.1 * np.random.randn()] for k in range(nwalk)]
blobs0 = [[0.] for k in range(nwalk)]

# Run!
for i in tqdm(sampler.sample(x0, iterations=nsteps, blobs0=blobs0),
              total=nsteps):
        pass

# Add the blobs to the chain for plotting
chain = np.concatenate((sampler.chain,
                        np.array(sampler.blobs).swapaxes(0, 1)), axis=2)

# Re-scale the transit time for prettier axes labels
chain[:, :, 1] -= 1978.

# Take the absolute value of the impact parameter for plotting
chain[:, :, 2] = np.abs(chain[:, :, 2])

# Re-scale the transit depth as a percentage
chain[:, :, 3] *= 100.

# Plot the chains
fig1, ax = pl.subplots(ndim + nblobs, figsize=(6, 7))
fig1.suptitle("K2-14b", fontsize=16, fontweight='bold')
ax[-1].set_xlabel("Iteration", fontsize=14)
for n in range(ndim + nblobs):
    for k in range(nwalk):
        ax[n].plot(chain[k, :, n], alpha=0.3, lw=1)
    ax[n].set_ylabel((params + blobs)[n], fontsize=9)
    ax[n].margins(0, None)
    ax[n].axvline(nburn, color='b', alpha=0.5, lw=1, ls='--')
fig1.savefig("k2-14b_chains.png", bbox_inches='tight')

# Plot the posterior distributions
samples = chain[:, nburn:, :].reshape(-1, ndim + nblobs)
fig2 = corner(samples, labels=params + blobs)
fig2.suptitle("K2-14b", fontsize=16, fontweight='bold')
fig2.set_size_inches(6, 6)
for ax in fig2.axes:
    for tick in ax.get_xticklabels() + ax.get_yticklabels():
        tick.set_fontsize(7)
fig2.savefig("k2-14b_corner.png", bbox_inches='tight')


#
#  Copyright (C) 2012, 2015, 2016, 2019
#            Smithsonian Astrophysical Observatory
#
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License along
#  with this program; if not, write to the Free Software Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

"""
Image-specific Crates routines.

At present there is only one routine - imextent.

"""

from pytransform import LINEAR2DTransform

__all__ = ('imextent', )

def imextent(img, xmin, xmax, ymin, ymax, limits='center'):
    """Create a linear transform for the image axes.

    Returns a 2D linear transform object that represents the
    mapping from "pixel" units (e.g. logical values) to
    a linearly scaled system (offset and scale change, no
    rotation). One use of this is to mimic the extent
    argument from matplotlib's imshow command, as discussed
    in the examples below.

    Parameters
    ----------
    img : 2D NumPy array
    xmin, xmax, ymin, ymax : float
        The coordinates of the lower-left and upper-right
        corners of the image in the transformed (non-logical)
        system.
    limits : {'center', 'edge'}
        Do the coordinates (xmin, ..., ymax) refer to the
        center of the pixels, or their edges. In FITS convention,
        the bottom-left pixel is centered on 1,1 and the top-right
        pixel is nx,ny (for a nx by ny grid). With limits='center'
        xmin,xmax refers to the center of the lower-left pixel
        (i.e. 1,1 in FITS terminology) whereas with limits='edge'
        it refers to the bottom-left corner (0.5,0.5 in FITS).

    Returns
    -------
    tr : pytransform.LINEAR2DTransform
        The transform object containing the coordinate mapping.

    Notes
    -----
    The logical coordinate system follows the FITS standard, so the
    first pixel is (1,1) and not (0,0), and the X axis values are
    given first.

    Examples
    --------

    The following example creates a 40 pixel wide by 20 pixel high
    image, zi, where the X axis goes from 40 to 60 and the Y
    axis 10 to 20. The imextent call creates a transform object.

    >>> yi, xi = np.mgrid[10:20:20j, 40:60:40j]
    >>> zi = 100.0 / np.sqrt((xi - 45.62) ** 2 + (yi - 14.7) ** 2)
    >>> tr = imextent(zi, 40, 60, 10, 20)

    The transform object can be used to convert between logical
    coordinates (where 1,1 refers to the center of the lower-left
    pixel) and the data coordinates:

    >>> print(tr.apply([[1,1], [40,20]]))
    [[40 10]
     [60 20]]

    and the invert method goes from data to logical coordinates:

    >>> print(tr.invert([[45.0, 15.0]]))
    [[ 10.75  10.5 ]]

    The following examples use a 4 pixel by 3 pixel image:

    >>> img = np.arange(0, 12).reshape(3, 4)

    The default value for the limits argument is 'center', which
    means that the given coordinates - in this case 10,-10 and
    13,-6 - refer to the center of the bottom-left and top-right
    pixels:

    >>> tr_cen = imextent(img, 10, 13, -10, -6, limits='center')

    The alternative is limits='edge', where 10,-10 refers to the
    bottom-left corner of the image and 13,-6 refers to the
    top-right corner:

    >>> tr_edge = imextent(img, 10, 13, -10, -6, limits='edge')

    >>> print(tr_cen.apply([[1.0, 1.0]]))
    [[ 10. -10.]]
    >>> print(tr_edge.apply([[1.0, 1.0]]))
    [[ 10.375       -9.33333333]]

    """

    try:
        (ny, nx) = img.shape
    except AttributeError:
        raise ValueError("First argument has no shape attribute.")

    dx = (xmax - xmin) * 1.0
    dy = (ymax - ymin) * 1.0

    if limits == 'center':
        dx /= (nx - 1.0)
        dy /= (ny - 1.0)
        x0 = xmin - dx
        y0 = ymin - dy

    elif limits == 'edge':
        dx /= nx
        dy /= ny
        x0 = xmin - dx / 2.0
        y0 = ymin - dy / 2.0

    else:
        raise ValueError("limits must be 'center' or 'edge', not '{}'".format(limits))

    tr = LINEAR2DTransform()

    tr.get_parameter('ROTATION').set_value(0.0)
    tr.get_parameter('SCALE').set_value([dx, dy])
    tr.get_parameter('OFFSET').set_value([x0, y0])

    return tr


# Sebastian Raschka, 2015 (http://sebastianraschka.com)
# Python Machine Learning - Code Examples
#
# Chapter 5 - Compressing Data via Dimensionality Reduction
#
# S. Raschka. Python Machine Learning. Packt Publishing Ltd., 2015.
# GitHub Repo: https://github.com/rasbt/python-machine-learning-book
#
# License: MIT
# https://github.com/rasbt/python-machine-learning-book/blob/master/LICENSE.txt

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.linear_model import LogisticRegression
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.datasets import make_moons
from sklearn.datasets import make_circles
from sklearn.decomposition import KernelPCA
from scipy.spatial.distance import pdist, squareform
from scipy import exp
from scipy.linalg import eigh
from matplotlib.ticker import FormatStrFormatter

# for sklearn 0.18's alternative syntax
from distutils.version import LooseVersion as Version
from sklearn import __version__ as sklearn_version
if Version(sklearn_version) < '0.18':
    from sklearn.grid_search import train_test_split
    from sklearn.lda import LDA
else:
    from sklearn.model_selection import train_test_split
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

#############################################################################
print(50 * '=')
print('Section: Unsupervised dimensionality reduction'
      ' via principal component analysis')
print(50 * '-')

df_wine = pd.read_csv('https://archive.ics.uci.edu/ml/'
                      'machine-learning-databases/wine/wine.data',
                      header=None)

df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                   'Alcalinity of ash', 'Magnesium', 'Total phenols',
                   'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                   'Color intensity', 'Hue',
                   'OD280/OD315 of diluted wines', 'Proline']

print('Wine data excerpt:\n\n:', df_wine.head())

X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values

X_train, X_test, y_train, y_test = \
    train_test_split(X, y, test_size=0.3, random_state=0)

sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)

cov_mat = np.cov(X_train_std.T)
eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)

print('\nEigenvalues \n%s' % eigen_vals)

#############################################################################
print(50 * '=')
print('Section: Total and explained variance')
print(50 * '-')

tot = sum(eigen_vals)
var_exp = [(i / tot) for i in sorted(eigen_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)

plt.bar(range(1, 14), var_exp, alpha=0.5, align='center',
        label='individual explained variance')
plt.step(range(1, 14), cum_var_exp, where='mid',
         label='cumulative explained variance')
plt.ylabel('Explained variance ratio')
plt.xlabel('Principal components')
plt.legend(loc='best')
# plt.tight_layout()
# plt.savefig('./figures/pca1.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: Feature Transformation')
print(50 * '-')

# Make a list of (eigenvalue, eigenvector) tuples
eigen_pairs = [(np.abs(eigen_vals[i]), eigen_vecs[:, i])
               for i in range(len(eigen_vals))]

# Sort the (eigenvalue, eigenvector) tuples from high to low
eigen_pairs.sort(reverse=True)

w = np.hstack((eigen_pairs[0][1][:, np.newaxis],
               eigen_pairs[1][1][:, np.newaxis]))
print('Matrix W:\n', w)

X_train_pca = X_train_std.dot(w)
colors = ['r', 'b', 'g']
markers = ['s', 'x', 'o']

for l, c, m in zip(np.unique(y_train), colors, markers):
    plt.scatter(X_train_pca[y_train == l, 0],
                X_train_pca[y_train == l, 1],
                c=c, label=l, marker=m)

plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.legend(loc='lower left')
# plt.tight_layout()
# plt.savefig('./figures/pca2.png', dpi=300)
plt.show()

print('Dot product:\n', X_train_std[0].dot(w))

#############################################################################
print(50 * '=')
print('Section: Principal component analysis in scikit-learn')
print(50 * '-')

pca = PCA()
X_train_pca = pca.fit_transform(X_train_std)
print('Variance explained ratio:\n', pca.explained_variance_ratio_)

plt.bar(range(1, 14), pca.explained_variance_ratio_, alpha=0.5, align='center')
plt.step(range(1, 14), np.cumsum(pca.explained_variance_ratio_), where='mid')
plt.ylabel('Explained variance ratio')
plt.xlabel('Principal components')
plt.show()

pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train_std)
X_test_pca = pca.transform(X_test_std)

plt.scatter(X_train_pca[:, 0], X_train_pca[:, 1])
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.show()

def plot_decision_regions(X, y, classifier, resolution=0.02):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    # plot class samples
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
                    alpha=0.8, c=cmap(idx),
                    marker=markers[idx], label=cl)

lr = LogisticRegression()
lr = lr.fit(X_train_pca, y_train)

plot_decision_regions(X_train_pca, y_train, classifier=lr)
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.legend(loc='lower left')
# plt.tight_layout()
# plt.savefig('./figures/pca3.png', dpi=300)
plt.show()

plot_decision_regions(X_test_pca, y_test, classifier=lr)
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.legend(loc='lower left')
# plt.tight_layout()
# plt.savefig('./figures/pca4.png', dpi=300)
plt.show()

pca = PCA(n_components=None)
X_train_pca = pca.fit_transform(X_train_std)
print('Explaind variance ratio:\n', pca.explained_variance_ratio_)

#############################################################################
print(50 * '=')
print('Section: Supervised data compression via linear discriminant analysis'
      ' - Computing the scatter matrices')
print(50 * '-')

np.set_printoptions(precision=4)

mean_vecs = []
for label in range(1, 4):
    mean_vecs.append(np.mean(X_train_std[y_train == label], axis=0))
    print('MV %s: %s\n' % (label, mean_vecs[label - 1]))

d = 13  # number of features
S_W = np.zeros((d, d))
for label, mv in zip(range(1, 4), mean_vecs):
    class_scatter = np.zeros((d, d))  # scatter matrix for each class
    for row in X_train_std[y_train == label]:
        row, mv = row.reshape(d, 1), mv.reshape(d, 1)  # make column vectors
        class_scatter += (row - mv).dot((row - mv).T)
    S_W += class_scatter                          # sum class scatter matrices

print('Within-class scatter matrix: %sx%s' % (S_W.shape[0], S_W.shape[1]))

print('Class label distribution: %s'
      % np.bincount(y_train)[1:])

d = 13  # number of features
S_W = np.zeros((d, d))
for label, mv in zip(range(1, 4), mean_vecs):
    class_scatter = np.cov(X_train_std[y_train == label].T)
    S_W += class_scatter
print('Scaled within-class scatter matrix: %sx%s' % (S_W.shape[0],
                                                     S_W.shape[1]))

mean_overall = np.mean(X_train_std, axis=0)
d = 13  # number of features
S_B = np.zeros((d, d))
for i, mean_vec in enumerate(mean_vecs):
    n = X_train[y_train == i + 1, :].shape[0]
    mean_vec = mean_vec.reshape(d, 1)  # make column vector
    mean_overall = mean_overall.reshape(d, 1)  # make column vector
    S_B += n * (mean_vec - mean_overall).dot((mean_vec - mean_overall).T)

print('Between-class scatter matrix: %sx%s' % (S_B.shape[0], S_B.shape[1]))

#############################################################################
print(50 * '=')
print('Section: Selecting linear discriminants for the new feature subspace')
print(50 * '-')

eigen_vals, eigen_vecs = np.linalg.eig(np.linalg.inv(S_W).dot(S_B))

# Make a list of (eigenvalue, eigenvector) tuples
eigen_pairs = [(np.abs(eigen_vals[i]), eigen_vecs[:, i])
               for i in range(len(eigen_vals))]

# Sort the (eigenvalue, eigenvector) tuples from high to low
eigen_pairs = sorted(eigen_pairs, key=lambda k: k[0], reverse=True)

# Visually confirm that the list is correctly sorted by decreasing eigenvalues

print('Eigenvalues in decreasing order:\n')
for eigen_val in eigen_pairs:
    print(eigen_val[0])

tot = sum(eigen_vals.real)
discr = [(i / tot) for i in sorted(eigen_vals.real, reverse=True)]
cum_discr = np.cumsum(discr)

plt.bar(range(1, 14), discr, alpha=0.5, align='center',
        label='individual "discriminability"')
plt.step(range(1, 14), cum_discr, where='mid',
         label='cumulative "discriminability"')
plt.ylabel('"discriminability" ratio')
plt.xlabel('Linear Discriminants')
plt.ylim([-0.1, 1.1])
plt.legend(loc='best')
# plt.tight_layout()
# plt.savefig('./figures/lda1.png', dpi=300)
plt.show()

w = np.hstack((eigen_pairs[0][1][:, np.newaxis].real,
              eigen_pairs[1][1][:, np.newaxis].real))
print('Matrix W:\n', w)

#############################################################################
print(50 * '=')
print('Section: Projecting samples onto the new feature space')
print(50 * '-')

X_train_lda = X_train_std.dot(w)
colors = ['r', 'b', 'g']
markers = ['s', 'x', 'o']

for l, c, m in zip(np.unique(y_train), colors, markers):
    plt.scatter(X_train_lda[y_train == l, 0] * (-1),
                X_train_lda[y_train == l, 1] * (-1),
                c=c, label=l, marker=m)

plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower right')
# plt.tight_layout()
# plt.savefig('./figures/lda2.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: LDA via scikit-learn')
print(50 * '-')

lda = LDA(n_components=2)
X_train_lda = lda.fit_transform(X_train_std, y_train)

lr = LogisticRegression()
lr = lr.fit(X_train_lda, y_train)

plot_decision_regions(X_train_lda, y_train, classifier=lr)
plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower left')
# plt.tight_layout()
# plt.savefig('./images/lda3.png', dpi=300)
plt.show()

X_test_lda = lda.transform(X_test_std)

plot_decision_regions(X_test_lda, y_test, classifier=lr)
plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower left')
# plt.tight_layout()
# plt.savefig('./images/lda4.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: Implementing a kernel principal component analysis in Python')
print(50 * '-')

def rbf_kernel_pca(X, gamma, n_components):
    """
    RBF kernel PCA implementation.

    Parameters
    ------------
    X: {NumPy ndarray}, shape = [n_samples, n_features]

    gamma: float
      Tuning parameter of the RBF kernel

    n_components: int
      Number of principal components to return

    Returns
    ------------
     X_pc: {NumPy ndarray}, shape = [n_samples, k_features]
       Projected dataset

    """
    # Calculate pairwise squared Euclidean distances
    # in the MxN dimensional dataset.
    sq_dists = pdist(X, 'sqeuclidean')

    # Convert pairwise distances into a square matrix.
    mat_sq_dists = squareform(sq_dists)

    # Compute the symmetric kernel matrix.
    K = exp(-gamma * mat_sq_dists)

    # Center the kernel matrix.
    N = K.shape[0]
    one_n = np.ones((N, N)) / N
    K = K - one_n.dot(K) - K.dot(one_n) + one_n.dot(K).dot(one_n)

    # Obtaining eigenpairs from the centered kernel matrix
    # numpy.eigh returns them in sorted order
    eigvals, eigvecs = eigh(K)

    # Collect the top k eigenvectors (projected samples)
    X_pc = np.column_stack((eigvecs[:, -i]
                            for i in range(1, n_components + 1)))

    return X_pc

#############################################################################
print(50 * '=')
print('Section: Example 1: Separating half-moon shapes')
print(50 * '-')

X, y = make_moons(n_samples=100, random_state=123)

plt.scatter(X[y == 0, 0], X[y == 0, 1], color='red', marker='^', alpha=0.5)
plt.scatter(X[y == 1, 0], X[y == 1, 1], color='blue', marker='o', alpha=0.5)

# plt.tight_layout()
# plt.savefig('./figures/half_moon_1.png', dpi=300)
plt.show()

scikit_pca = PCA(n_components=2)
X_spca = scikit_pca.fit_transform(X)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))

ax[0].scatter(X_spca[y == 0, 0], X_spca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_spca[y == 1, 0], X_spca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_spca[y == 0, 0], np.zeros((50, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_spca[y == 1, 0], np.zeros((50, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')

# plt.tight_layout()
# plt.savefig('./figures/half_moon_2.png', dpi=300)
plt.show()

X_kpca = rbf_kernel_pca(X, gamma=15, n_components=2)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))
ax[0].scatter(X_kpca[y == 0, 0], X_kpca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_kpca[y == 1, 0], X_kpca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_kpca[y == 0, 0], np.zeros((50, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_kpca[y == 1, 0], np.zeros((50, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')
ax[0].xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
ax[1].xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))

# plt.tight_layout()
# plt.savefig('./figures/half_moon_3.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: Example 2: Separating concentric circles')
print(50 * '-')

X, y = make_circles(n_samples=1000, random_state=123, noise=0.1, factor=0.2)

plt.scatter(X[y == 0, 0], X[y == 0, 1], color='red', marker='^', alpha=0.5)
plt.scatter(X[y == 1, 0], X[y == 1, 1], color='blue', marker='o', alpha=0.5)

# plt.tight_layout()
# plt.savefig('./figures/circles_1.png', dpi=300)
plt.show()

scikit_pca = PCA(n_components=2)
X_spca = scikit_pca.fit_transform(X)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))

ax[0].scatter(X_spca[y == 0, 0], X_spca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_spca[y == 1, 0], X_spca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_spca[y == 0, 0], np.zeros((500, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_spca[y == 1, 0], np.zeros((500, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')

# plt.tight_layout()
# plt.savefig('./figures/circles_2.png', dpi=300)
plt.show()

X_kpca = rbf_kernel_pca(X, gamma=15, n_components=2)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))
ax[0].scatter(X_kpca[y == 0, 0], X_kpca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_kpca[y == 1, 0], X_kpca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_kpca[y == 0, 0], np.zeros((500, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_kpca[y == 1, 0], np.zeros((500, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')

# plt.tight_layout()
# plt.savefig('./figures/circles_3.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: Projecting new data points')
print(50 * '-')

def rbf_kernel_pca(X, gamma, n_components):
    """
    RBF kernel PCA implementation.

    Parameters
    ------------
    X: {NumPy ndarray}, shape = [n_samples, n_features]

    gamma: float
      Tuning parameter of the RBF kernel

    n_components: int
      Number of principal components to return

    Returns
    ------------
     X_pc: {NumPy ndarray}, shape = [n_samples, k_features]
       Projected dataset

     lambdas: list
       Eigenvalues

    """
    # Calculate pairwise squared Euclidean distances
    # in the MxN dimensional dataset.
    sq_dists = pdist(X, 'sqeuclidean')

    # Convert pairwise distances into a square matrix.
    mat_sq_dists = squareform(sq_dists)

    # Compute the symmetric kernel matrix.
    K = exp(-gamma * mat_sq_dists)

    # Center the kernel matrix.
    N = K.shape[0]
    one_n = np.ones((N, N)) / N
    K = K - one_n.dot(K) - K.dot(one_n) + one_n.dot(K).dot(one_n)

    # Obtaining eigenpairs from the centered kernel matrix
    # numpy.eigh returns them in sorted order
    eigvals, eigvecs = eigh(K)

    # Collect the top k eigenvectors (projected samples)
    alphas = np.column_stack((eigvecs[:, -i]
                              for i in range(1, n_components + 1)))

    # Collect the corresponding eigenvalues
    lambdas = [eigvals[-i] for i in range(1, n_components + 1)]

    return alphas, lambdas

X, y = make_moons(n_samples=100, random_state=123)
alphas, lambdas = rbf_kernel_pca(X, gamma=15, n_components=1)

x_new = X[25]
print('New data point x_new:', x_new)

x_proj = alphas[25]  # original projection
print('Original projection x_proj:', x_proj)

def project_x(x_new, X, gamma, alphas, lambdas):
    pair_dist = np.array([np.sum((x_new - row)**2) for row in X])
    k = np.exp(-gamma * pair_dist)
    return k.dot(alphas / lambdas)

# projection of the "new" datapoint
x_reproj = project_x(x_new, X, gamma=15, alphas=alphas, lambdas=lambdas)
print('Reprojection x_reproj:', x_reproj)

plt.scatter(alphas[y == 0, 0], np.zeros((50)),
            color='red', marker='^', alpha=0.5)
plt.scatter(alphas[y == 1, 0], np.zeros((50)),
            color='blue', marker='o', alpha=0.5)
plt.scatter(x_proj, 0, color='black',
            label='original projection of point X[25]', marker='^', s=100)
plt.scatter(x_reproj, 0, color='green',
            label='remapped point X[25]', marker='x', s=500)
plt.legend(scatterpoints=1)

# plt.tight_layout()
# plt.savefig('./figures/reproject.png', dpi=300)
plt.show()

#############################################################################
print(50 * '=')
print('Section: Kernel principal component analysis in scikit-learn')
print(50 * '-')

X, y = make_moons(n_samples=100, random_state=123)
scikit_kpca = KernelPCA(n_components=2, kernel='rbf', gamma=15)
X_skernpca = scikit_kpca.fit_transform(X)

plt.scatter(X_skernpca[y == 0, 0], X_skernpca[y == 0, 1],
            color='red', marker='^', alpha=0.5)
plt.scatter(X_skernpca[y == 1, 0], X_skernpca[y == 1, 1],
            color='blue', marker='o', alpha=0.5)

plt.xlabel('PC1')
plt.ylabel('PC2')
# plt.tight_layout()
# plt.savefig('./figures/scikit_kpca.png', dpi=300)
plt.show()


import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import SGDClassifier
from sklearn.datasets.samples_generator import make_blobs

def plot_sgd_separator():
    # we create 50 separable points
    X, Y = make_blobs(n_samples=50, centers=2,
                      random_state=0, cluster_std=0.60)

    # fit the model
    clf = SGDClassifier(loss="hinge", alpha=0.01,
                        n_iter=200, fit_intercept=True)
    clf.fit(X, Y)

    # plot the line, the points, and the nearest vectors to the plane
    xx = np.linspace(-1, 5, 10)
    yy = np.linspace(-1, 5, 10)

    X1, X2 = np.meshgrid(xx, yy)
    Z = np.empty(X1.shape)
    for (i, j), val in np.ndenumerate(X1):
        x1 = val
        x2 = X2[i, j]
        p = clf.decision_function([x1, x2])
        Z[i, j] = p[0]
    levels = [-1.0, 0.0, 1.0]
    linestyles = ['dashed', 'solid', 'dashed']
    colors = 'k'

    ax = plt.axes()
    ax.contour(X1, X2, Z, levels, colors=colors, linestyles=linestyles)
    ax.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)

    ax.axis('tight')

if __name__ == '__main__':
    plot_sgd_separator()
    plt.show()


""" A minimal application using the ZMQ-based terminal IPython frontend.

This is not a complete console app, as subprocess will not be able to receive
input, there is no real readline support, among other limitations.

Authors:

* Min RK
* Paul Ivanov

"""

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import signal
import sys
import time

from IPython.frontend.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags

from IPython.utils.traitlets import (
    Dict, List, Unicode, Int, CaselessStrEnum, CBool, Any
)
from IPython.utils.warn import warn,error

from IPython.zmq.ipkernel import IPKernelApp
from IPython.zmq.session import Session, default_secure
from IPython.zmq.zmqshell import ZMQInteractiveShell
from IPython.frontend.consoleapp import (
        IPythonConsoleApp, app_aliases, app_flags, aliases, app_aliases, flags
    )

from IPython.frontend.terminal.console.interactiveshell import ZMQTerminalInteractiveShell

#-----------------------------------------------------------------------------
# Globals
#-----------------------------------------------------------------------------

_examples = """
ipython console # start the ZMQ-based console
ipython console --existing # connect to an existing ipython session
"""

#-----------------------------------------------------------------------------
# Flags and Aliases
#-----------------------------------------------------------------------------

# copy flags from mixin:
flags = dict(flags)
# start with mixin frontend flags:
frontend_flags = dict(app_flags)
# add TerminalIPApp flags:
frontend_flags.update(term_flags)
# disable quick startup, as it won't propagate to the kernel anyway
frontend_flags.pop('quick')
# update full dict with frontend flags:
flags.update(frontend_flags)

# copy flags from mixin
aliases = dict(aliases)
# start with mixin frontend flags
frontend_aliases = dict(app_aliases)
# load updated frontend flags into full dict
aliases.update(frontend_aliases)

# get flags&aliases into sets, and remove a couple that
# shouldn't be scrubbed from backend flags:
frontend_aliases = set(frontend_aliases.keys())
frontend_flags = set(frontend_flags.keys())

#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------

class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
    name = "ipython-console"
    """Start a terminal frontend to the IPython zmq kernel."""

    description = """
        The IPython terminal-based Console.

        This launches a Console application inside a terminal.

        The Console supports various extra features beyond the traditional
        single-process Terminal IPython shell, such as connecting to an
        existing ipython session, via:

            ipython console --existing

        where the previous session could have been created by another ipython
        console, an ipython qtconsole, or by opening an ipython notebook.

    """
    examples = _examples

    classes = [ZMQTerminalInteractiveShell] + IPythonConsoleApp.classes
    flags = Dict(flags)
    aliases = Dict(aliases)
    frontend_aliases = Any(frontend_aliases)
    frontend_flags = Any(frontend_flags)

    subcommands = Dict()

    def parse_command_line(self, argv=None):
        super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
        self.build_kernel_argv(argv)

    def init_shell(self):
        IPythonConsoleApp.initialize(self)
        # relay sigint to kernel
        signal.signal(signal.SIGINT, self.handle_sigint)
        self.shell = ZMQTerminalInteractiveShell.instance(config=self.config,
                        display_banner=False, profile_dir=self.profile_dir,
                        ipython_dir=self.ipython_dir, kernel_manager=self.kernel_manager)

    def init_gui_pylab(self):
        # no-op, because we don't want to import matplotlib in the frontend.
        pass

    def handle_sigint(self, *args):
        if self.shell._executing:
            if self.kernel_manager.has_kernel:
                # interrupt already gets passed to subprocess by signal handler.
                # Only if we prevent that should we need to explicitly call
                # interrupt_kernel, until which time, this would result in a
                # double-interrupt:
                # self.kernel_manager.interrupt_kernel()
                pass
            else:
                self.shell.write_err('\n')
                error("Cannot interrupt kernels we didn't start.\n")
        else:
            # raise the KeyboardInterrupt if we aren't waiting for execution,
            # so that the interact loop advances, and prompt is redrawn, etc.
            raise KeyboardInterrupt

    def init_code(self):
        # no-op in the frontend, code gets run in the backend
        pass

def launch_new_instance():
    """Create and run a full blown IPython instance"""
    app = ZMQTerminalIPythonApp.instance()
    app.initialize()
    app.start()

if __name__ == '__main__':
    launch_new_instance()


"""Isomap for manifold learning"""

# Author: Jake Vanderplas  -- <vanderplas@astro.washington.edu>
# License: BSD 3 clause (C) 2011

import numpy as np
from ..base import BaseEstimator, TransformerMixin
from ..neighbors import NearestNeighbors, kneighbors_graph
from ..utils import check_array
from ..utils.graph import graph_shortest_path
from ..decomposition import KernelPCA
from ..preprocessing import KernelCenterer

class Isomap(BaseEstimator, TransformerMixin):
    """Isomap Embedding

    Non-linear dimensionality reduction through Isometric Mapping

    Read more in the :ref:`User Guide <isomap>`.

    Parameters
    ----------
    n_neighbors : integer
        number of neighbors to consider for each point.

    n_components : integer
        number of coordinates for the manifold

    eigen_solver : ['auto'|'arpack'|'dense']
        'auto' : Attempt to choose the most efficient solver
        for the given problem.

        'arpack' : Use Arnoldi decomposition to find the eigenvalues
        and eigenvectors.

        'dense' : Use a direct solver (i.e. LAPACK)
        for the eigenvalue decomposition.

    tol : float
        Convergence tolerance passed to arpack or lobpcg.
        not used if eigen_solver == 'dense'.

    max_iter : integer
        Maximum number of iterations for the arpack solver.
        not used if eigen_solver == 'dense'.

    path_method : string ['auto'|'FW'|'D']
        Method to use in finding shortest path.

        'auto' : attempt to choose the best algorithm automatically.

        'FW' : Floyd-Warshall algorithm.

        'D' : Dijkstra's algorithm.

    neighbors_algorithm : string ['auto'|'brute'|'kd_tree'|'ball_tree']
        Algorithm to use for nearest neighbors search,
        passed to neighbors.NearestNeighbors instance.

    Attributes
    ----------
    embedding_ : array-like, shape (n_samples, n_components)
        Stores the embedding vectors.

    kernel_pca_ : object
        `KernelPCA` object used to implement the embedding.

    training_data_ : array-like, shape (n_samples, n_features)
        Stores the training data.

    nbrs_ : sklearn.neighbors.NearestNeighbors instance
        Stores nearest neighbors instance, including BallTree or KDtree
        if applicable.

    dist_matrix_ : array-like, shape (n_samples, n_samples)
        Stores the geodesic distance matrix of training data.

    References
    ----------

    .. [1] Tenenbaum, J.B.; De Silva, V.; & Langford, J.C. A global geometric
           framework for nonlinear dimensionality reduction. Science 290 (5500)
    """

    def __init__(self, n_neighbors=5, n_components=2, eigen_solver='auto',
                 tol=0, max_iter=None, path_method='auto',
                 neighbors_algorithm='auto'):

        self.n_neighbors = n_neighbors
        self.n_components = n_components
        self.eigen_solver = eigen_solver
        self.tol = tol
        self.max_iter = max_iter
        self.path_method = path_method
        self.neighbors_algorithm = neighbors_algorithm
        self.nbrs_ = NearestNeighbors(n_neighbors=n_neighbors,
                                      algorithm=neighbors_algorithm)

    def _fit_transform(self, X):
        X = check_array(X)
        self.nbrs_.fit(X)
        self.training_data_ = self.nbrs_._fit_X
        self.kernel_pca_ = KernelPCA(n_components=self.n_components,
                                     kernel="precomputed",
                                     eigen_solver=self.eigen_solver,
                                     tol=self.tol, max_iter=self.max_iter)

        kng = kneighbors_graph(self.nbrs_, self.n_neighbors,
                               mode='distance')

        self.dist_matrix_ = graph_shortest_path(kng,
                                                method=self.path_method,
                                                directed=False)
        G = self.dist_matrix_ ** 2
        G *= -0.5

        self.embedding_ = self.kernel_pca_.fit_transform(G)

    def reconstruction_error(self):
        """Compute the reconstruction error for the embedding.

        Returns
        -------
        reconstruction_error : float

        Notes
        -------
        The cost function of an isomap embedding is

        ``E = frobenius_norm[K(D) - K(D_fit)] / n_samples``

        Where D is the matrix of distances for the input data X,
        D_fit is the matrix of distances for the output embedding X_fit,
        and K is the isomap kernel:

        ``K(D) = -0.5 * (I - 1/n_samples) * D^2 * (I - 1/n_samples)``
        """
        G = -0.5 * self.dist_matrix_ ** 2
        G_center = KernelCenterer().fit_transform(G)
        evals = self.kernel_pca_.lambdas_
        return np.sqrt(np.sum(G_center ** 2) - np.sum(evals ** 2)) / G.shape[0]

    def fit(self, X, y=None):
        """Compute the embedding vectors for data X

        Parameters
        ----------
        X : {array-like, sparse matrix, BallTree, KDTree, NearestNeighbors}
            Sample data, shape = (n_samples, n_features), in the form of a
            numpy array, precomputed tree, or NearestNeighbors
            object.

        Returns
        -------
        self : returns an instance of self.
        """
        self._fit_transform(X)
        return self

    def fit_transform(self, X, y=None):
        """Fit the model from data in X and transform X.

        Parameters
        ----------
        X: {array-like, sparse matrix, BallTree, KDTree}
            Training vector, where n_samples in the number of samples
            and n_features is the number of features.

        Returns
        -------
        X_new: array-like, shape (n_samples, n_components)
        """
        self._fit_transform(X)
        return self.embedding_

    def transform(self, X):
        """Transform X.

        This is implemented by linking the points X into the graph of geodesic
        distances of the training data. First the `n_neighbors` nearest
        neighbors of X are found in the training data, and from these the
        shortest geodesic distances from each point in X to each point in
        the training data are computed in order to construct the kernel.
        The embedding of X is the projection of this kernel onto the
        embedding vectors of the training set.

        Parameters
        ----------
        X: array-like, shape (n_samples, n_features)

        Returns
        -------
        X_new: array-like, shape (n_samples, n_components)
        """
        X = check_array(X)
        distances, indices = self.nbrs_.kneighbors(X, return_distance=True)

        #Create the graph of shortest distances from X to self.training_data_
        # via the nearest neighbors of X.
        #This can be done as a single array operation, but it potentially
        # takes a lot of memory.  To avoid that, use a loop:
        G_X = np.zeros((X.shape[0], self.training_data_.shape[0]))
        for i in range(X.shape[0]):
            G_X[i] = np.min((self.dist_matrix_[indices[i]]
                             + distances[i][:, None]), 0)

        G_X **= 2
        G_X *= -0.5

        return self.kernel_pca_.transform(G_X)


# -*- coding: utf-8 -*-

from __future__ import unicode_literals
import os
import sys
import shutil
import pytz
import nose
from nose.tools import assert_equal, raises, assert_true, assert_false, assert_not_equal
from datetime import datetime, date
from xlwings import Application, Workbook, Sheet, Range, Chart, ChartType, RgbColor, Calculation

# Mac imports
if sys.platform.startswith('darwin'):
    from appscript import k as kw
    # TODO: uncomment the desired Excel installation or set to None for default installation
    APP_TARGET = None
    # APP_TARGET = '/Applications/Microsoft Office 2011/Microsoft Excel'
else:
    APP_TARGET = None

# Optional dependencies
try:
    import numpy as np
    from numpy.testing import assert_array_equal
except ImportError:
    np = None
try:
    import pandas as pd
    from pandas import DataFrame, Series
    from pandas.util.testing import assert_frame_equal, assert_series_equal
except ImportError:
    pd = None

# Test data
data = [[1, 2.222, 3.333],
        ['Test1', None, 'éöà'],
        [datetime(1962, 11, 3), datetime(2020, 12, 31, 12, 12, 20), 9.999]]

test_date_1 = datetime(1962, 11, 3)
test_date_2 = datetime(2020, 12, 31, 12, 12, 20)

list_row_1d = [1.1, None, 3.3]
list_row_2d = [[1.1, None, 3.3]]
list_col = [[1.1], [None], [3.3]]
chart_data = [['one', 'two'], [1.1, 2.2]]

if np is not None:
    array_1d = np.array([1.1, 2.2, np.nan, -4.4])
    array_2d = np.array([[1.1, 2.2, 3.3], [-4.4, 5.5, np.nan]])

if pd is not None:
    series_1 = pd.Series([1.1, 3.3, 5., np.nan, 6., 8.])

    rng = pd.date_range('1/1/2012', periods=10, freq='D')
    timeseries_1 = pd.Series(np.arange(len(rng)) + 0.1, rng)
    timeseries_1[1] = np.nan

    df_1 = pd.DataFrame([[1, 'test1'],
                         [2, 'test2'],
                         [np.nan, None],
                         [3.3, 'test3']], columns=['a', 'b'])

    df_2 = pd.DataFrame([1, 3, 5, np.nan, 6, 8], columns=['col1'])

    df_dateindex = pd.DataFrame(np.arange(50).reshape(10,5) + 0.1, index=rng)

    # MultiIndex (Index)
    tuples = list(zip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
                        ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'],
                        ['x', 'x', 'x', 'x', 'y', 'y', 'y', 'y']]))
    index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second', 'third'])
    df_multiindex = pd.DataFrame([[1.1, 2.2], [3.3, 4.4], [5.5, 6.6], [7.7, 8.8], [9.9, 10.10],
                                  [11.11, 12.12],[13.13, 14.14], [15.15, 16.16]], index=index)

    # MultiIndex (Header)
    header = [['Foo', 'Foo', 'Bar', 'Bar', 'Baz'], ['A', 'B', 'C', 'D', 'E']]

    df_multiheader = pd.DataFrame([[0.0, 1.0, 2.0, 3.0, 4.0],
                                   [0.0, 1.0, 2.0, 3.0, 4.0],
                                   [0.0, 1.0, 2.0, 3.0, 4.0],
                                   [0.0, 1.0, 2.0, 3.0, 4.0],
                                   [0.0, 1.0, 2.0, 3.0, 4.0],
                                   [0.0, 1.0, 2.0, 3.0, 4.0]], columns=pd.MultiIndex.from_arrays(header))

# Test skips and fixtures
def _skip_if_no_numpy():
    if np is None:
        raise nose.SkipTest('numpy missing')

def _skip_if_no_pandas():
    if pd is None:
        raise nose.SkipTest('pandas missing')

def _skip_if_not_default_xl():
    if APP_TARGET is not None:
        raise nose.SkipTest('not Excel default')

def class_teardown(wb):
    wb.close()
    if sys.platform.startswith('win'):
        Application(wb).quit()

class TestApplication:
    def setUp(self):
        # Connect to test file and make Sheet1 the active sheet
        xl_file1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_workbook_1.xlsx')
        self.wb = Workbook(xl_file1, app_visible=False, app_target=APP_TARGET)
        Sheet('Sheet1').activate()

    def tearDown(self):
        class_teardown(self.wb)

    def test_screen_updating(self):
        Application(wkb=self.wb).screen_updating = False
        assert_equal(Application(wkb=self.wb).screen_updating, False)

        Application(wkb=self.wb).screen_updating = True
        assert_equal(Application(wkb=self.wb).screen_updating, True)

    def test_calculation(self):
        Range('A1').value = 2
        Range('B1').formula = '=A1 * 2'

        app = Application(wkb=self.wb)

        app.calculation = Calculation.xlCalculationManual
        Range('A1').value = 4
        assert_equal(Range('B1').value, 4)

        app.calculation = Calculation.xlCalculationAutomatic
        app.calculate()  # This is needed on Mac Excel 2016 but not on Mac Excel 2011 (changed behaviour)
        assert_equal(Range('B1').value, 8)

        Range('A1').value = 2
        assert_equal(Range('B1').value, 4)

class TestWorkbook:
    def setUp(self):
        # Connect to test file and make Sheet1 the active sheet
        xl_file1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_workbook_1.xlsx')
        self.wb = Workbook(xl_file1, app_visible=False, app_target=APP_TARGET)
        Sheet('Sheet1').activate()

    def tearDown(self):
        class_teardown(self.wb)

    def test_name(self):
        assert_equal(self.wb.name, 'test_workbook_1.xlsx')

    def test_active_sheet(self):
        assert_equal(self.wb.active_sheet.name, 'Sheet1')

    def test_current(self):
        assert_equal(self.wb.xl_workbook, Workbook.current().xl_workbook)

    def test_set_current(self):
        wb2 = Workbook(app_visible=False, app_target=APP_TARGET)
        assert_equal(Workbook.current().xl_workbook, wb2.xl_workbook)
        self.wb.set_current()
        assert_equal(Workbook.current().xl_workbook, self.wb.xl_workbook)
        wb2.close()

    def test_get_selection(self):
        Range('A1').value = 1000
        assert_equal(self.wb.get_selection().value, 1000)

    def test_reference_two_unsaved_wb(self):
        """Covers GH Issue #63"""
        wb1 = Workbook(app_visible=False, app_target=APP_TARGET)
        wb2 = Workbook(app_visible=False, app_target=APP_TARGET)

        Range('A1').value = 2.  # wb2
        Range('A1', wkb=wb1).value = 1.  # wb1

        assert_equal(Range('A1').value, 2.)
        assert_equal(Range('A1', wkb=wb1).value, 1.)

        wb1.close()
        wb2.close()

    def test_save_naked(self):

        cwd = os.getcwd()
        wb1 = Workbook(app_visible=False, app_target=APP_TARGET)
        target_file_path = os.path.join(cwd, wb1.name + '.xlsx')
        if os.path.isfile(target_file_path):
            os.remove(target_file_path)

        wb1.save()

        assert_equal(os.path.isfile(target_file_path), True)

        wb2 = Workbook(target_file_path, app_visible=False, app_target=APP_TARGET)
        wb2.close()

        if os.path.isfile(target_file_path):
            os.remove(target_file_path)

    def test_save_path(self):

        cwd = os.getcwd()
        wb1 = Workbook(app_visible=False, app_target=APP_TARGET)
        target_file_path = os.path.join(cwd, 'TestFile.xlsx')
        if os.path.isfile(target_file_path):
            os.remove(target_file_path)

        wb1.save(target_file_path)

        assert_equal(os.path.isfile(target_file_path), True)

        wb2 = Workbook(target_file_path, app_visible=False, app_target=APP_TARGET)
        wb2.close()

        if os.path.isfile(target_file_path):
            os.remove(target_file_path)

    def test_mock_caller(self):
        # Can't really run this one with app_visible=False
        _skip_if_not_default_xl()

        Workbook.set_mock_caller(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_workbook_1.xlsx'))
        wb = Workbook.caller()
        Range('A1', wkb=wb).value = 333
        assert_equal(Range('A1', wkb=wb).value, 333)

    def test_unicode_path(self):
        # pip3 seems to struggle with unicode filenames
        src = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'unicode_path.xlsx')
        dst = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ünicödé_päth.xlsx')
        shutil.move(src, dst)
        wb = Workbook(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ünicödé_päth.xlsx'), app_visible=False, app_target=APP_TARGET)
        Range('A1').value = 1
        wb.close()
        shutil.move(dst, src)

    def test_unsaved_workbook_reference(self):
        wb = Workbook(app_visible=False, app_target=APP_TARGET)
        Range('B2').value = 123
        wb2 = Workbook(wb.name, app_visible=False, app_target=APP_TARGET)
        assert_equal(Range('B2', wkb=wb2).value, 123)
        wb2.close()

    def test_delete_named_item(self):
        Range('B10:C11').name = 'to_be_deleted'
        assert_equal(Range('to_be_deleted').name, 'to_be_deleted')
        del self.wb.names['to_be_deleted']
        assert_not_equal(Range('B10:C11').name, 'to_be_deleted')

    def test_names_collection(self):
        Range('A1').name = 'name1'
        Range('A2').name = 'name2'
        assert_true('name1' in self.wb.names and 'name2' in self.wb.names)

        Range('A3').name = 'name3'
        assert_true('name1' in self.wb.names and 'name2' in self.wb.names and
                    'name3' in self.wb.names)

    def test_active_workbook(self):
        # TODO: add test over multiple Excel instances on Windows
        Range('A1').value = 'active_workbook'
        wb_active = Workbook.active(app_target=APP_TARGET)
        assert_equal(Range('A1', wkb=wb_active).value, 'active_workbook')

    def test_workbook_name(self):
        Range('A10').value = 'name-test'
        wb2 = Workbook('test_workbook_1.xlsx', app_visible=False, app_target=APP_TARGET)
        assert_equal(Range('A10', wkb=wb2).value, 'name-test')

class TestSheet:
    def setUp(self):
        # Connect to test file and make Sheet1 the active sheet
        xl_file1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_workbook_1.xlsx')
        self.wb = Workbook(xl_file1, app_visible=False, app_target=APP_TARGET)
        Sheet('Sheet1').activate()

    def tearDown(self):
        class_teardown(self.wb)

    def test_activate(self):
        Sheet('Sheet2').activate()
        assert_equal(Sheet.active().name, 'Sheet2')
        Sheet(3).activate()
        assert_equal(Sheet.active().index, 3)

    def test_name(self):
        Sheet(1).name = 'NewName'
        assert_equal(Sheet(1).name, 'NewName')

    def test_index(self):
        assert_equal(Sheet('Sheet1').index, 1)

    def test_clear_content_active_sheet(self):
        Range('G10').value = 22
        Sheet.active().clear_contents()
        cell = Range('G10').value
        assert_equal(cell, None)

    def test_clear_active_sheet(self):
        Range('G10').value = 22
        Sheet.active().clear()
        cell = Range('G10').value
        assert_equal(cell, None)

    def test_clear_content(self):
        Range('Sheet2', 'G10').value = 22
        Sheet('Sheet2').clear_contents()
        cell = Range('Sheet2', 'G10').value
        assert_equal(cell, None)

    def test_clear(self):
        Range('Sheet2', 'G10').value = 22
        Sheet('Sheet2').clear()
        cell = Range('Sheet2', 'G10').value
        assert_equal(cell, None)

    def test_autofit(self):
        Range('Sheet1', 'A1:D4').value = 'test_string'
        Sheet('Sheet1').autofit()
        Sheet('Sheet1').autofit('r')
        Sheet('Sheet1').autofit('c')
        Sheet('Sheet1').autofit('rows')
        Sheet('Sheet1').autofit('columns')

    def test_add_before(self):
        new_sheet = Sheet.add(before='Sheet1')
        assert_equal(Sheet(1).name, new_sheet.name)

    def test_add_after(self):
        Sheet.add(after=Sheet.count())
        assert_equal(Sheet(Sheet.count()).name, Sheet.active().name)

        Sheet.add(after=1)
        assert_equal(Sheet(2).name, Sheet.active().name)

    def test_add_default(self):
        # TODO: test call without args properly
        Sheet.add()

    def test_add_named(self):
        Sheet.add('test', before=1)
        assert_equal(Sheet(1).name, 'test')

    @raises(Exception)
    def test_add_name_already_taken(self):
        Sheet.add('Sheet1')

    def test_count(self):
        count = Sheet.count()
        assert_equal(count, 3)

    def test_all(self):
        all_names = [i.name for i in Sheet.all()]
        assert_equal(all_names, ['Sheet1', 'Sheet2', 'Sheet3'])

class TestRange:
    def setUp(self):
        # Connect to test file and make Sheet1 the active sheet
        xl_file1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_range_1.xlsx')
        self.wb = Workbook(xl_file1, app_visible=False, app_target=APP_TARGET)
        Sheet('Sheet1').activate()

    def tearDown(self):
        class_teardown(self.wb)

    def test_cell(self):
        params = [('A1', 22),
                  ((1,1), 22),
                  ('A1', 22.2222),
                  ((1,1), 22.2222),
                  ('A1', 'Test String'),
                  ((1,1), 'Test String'),
                  ('A1', 'éöà'),
                  ((1,1), 'éöà'),
                  ('A2', test_date_1),
                  ((2,1), test_date_1),
                  ('A3', test_date_2),
                  ((3,1), test_date_2)]
        for param in params:
            yield self.check_cell, param[0], param[1]

    def check_cell(self, address, value):
        # Active Sheet
        Range(address).value = value
        cell = Range(address).value
        assert_equal(cell, value)

        # SheetName
        Range('Sheet2', address).value = value
        cell = Range('Sheet2', address).value
        assert_equal(cell, value)

        # SheetIndex
        Range(3, address).value = value
        cell = Range(3, address).value
        assert_equal(cell, value)

    def test_range_address(self):
        """ Style: Range('A1:C3') """
        address = 'C1:E3'

        # Active Sheet
        Range(address[:2]).value = data  # assign to starting cell only
        cells = Range(address).value
        assert_equal(cells, data)

        # Sheetname
        Range('Sheet2', address).value = data
        cells = Range('Sheet2', address).value
        assert_equal(cells, data)

        # Sheetindex
        Range(3, address).value = data
        cells = Range(3, address).value
        assert_equal(cells, data)

    def test_range_index(self):
        """ Style: Range((1,1), (3,3)) """
        index1 = (1,3)
        index2 = (3,5)

        # Active Sheet
        Range(index1, index2).value = data
        cells = Range(index1, index2).value
        assert_equal(cells, data)

        # Sheetname
        Range('Sheet2', index1, index2).value = data
        cells = Range('Sheet2', index1, index2).value
        assert_equal(cells, data)

        # Sheetindex
        Range(3, index1, index2).value = data
        cells = Range(3, index1, index2).value
        assert_equal(cells, data)

    def test_named_range_value(self):
        value = 22.222
        # Active Sheet
        Range('cell_sheet1').value = value
        cells = Range('cell_sheet1').value
        assert_equal(cells, value)

        Range('range_sheet1').value = data
        cells = Range('range_sheet1').value
        assert_equal(cells, data)

        # Sheetname
        Range('Sheet2', 'cell_sheet2').value = value
        cells = Range('Sheet2', 'cell_sheet2').value
        assert_equal(cells, value)

        Range('Sheet2', 'range_sheet2').value = data
        cells = Range('Sheet2', 'range_sheet2').value
        assert_equal(cells, data)

        # Sheetindex
        Range(3, 'cell_sheet3').value = value
        cells = Range(3, 'cell_sheet3').value
        assert_equal(cells, value)

        Range(3, 'range_sheet3').value = data
        cells = Range(3, 'range_sheet3').value
        assert_equal(cells, data)

    def test_array(self):
        _skip_if_no_numpy()

        # 1d array
        Range('Sheet6', 'A1').value = array_1d
        cells = Range('Sheet6', 'A1:D1', asarray=True).value
        assert_array_equal(cells, array_1d)

        # 2d array
        Range('Sheet6', 'A4').value = array_2d
        cells = Range('Sheet6', 'A4', asarray=True).table.value
        assert_array_equal(cells, array_2d)

        # 1d array (atleast_2d)
        Range('Sheet6', 'A10').value = array_1d
        cells = Range('Sheet6', 'A10:D10', asarray=True, atleast_2d=True).value
        assert_array_equal(cells, np.atleast_2d(array_1d))

        # 2d array (atleast_2d)
        Range('Sheet6', 'A12').value = array_2d
        cells = Range('Sheet6', 'A12', asarray=True, atleast_2d=True).table.value
        assert_array_equal(cells, array_2d)

    def sheet_ref(self):
        Range(Sheet(1), 'A20').value = 123
        assert_equal(Range(1, 'A20').value, 123)

        Range(Sheet(1), (2,2), (4,4)).value = 321
        assert_equal(Range(1, (2,2)).value, 321)

    def test_vertical(self):
        Range('Sheet4', 'A10').value = data
        if sys.platform.startswith('win') and self.wb.xl_app.Version == '14.0':
            Range('Sheet4', 'A12:B12').xl_range.NumberFormat = 'dd/mm/yyyy'  # Hack for Excel 2010 bug, see GH #43
        cells = Range('Sheet4', 'A10').vertical.value
        assert_equal(cells, [row[0] for row in data])

    def test_horizontal(self):
        Range('Sheet4', 'A20').value = data
        cells = Range('Sheet4', 'A20').horizontal.value
        assert_equal(cells, data[0])

    def test_table(self):
        Range('Sheet4', 'A1').value = data
        if sys.platform.startswith('win') and self.wb.xl_app.Version == '14.0':
            Range('Sheet4', 'A3:B3').xl_range.NumberFormat = 'dd/mm/yyyy'  # Hack for Excel 2010 bug, see GH #43
        cells = Range('Sheet4', 'A1').table.value
        assert_equal(cells, data)

    def test_list(self):

        # 1d List Row
        Range('Sheet4', 'A27').value = list_row_1d
        cells = Range('Sheet4', 'A27:C27').value
        assert_equal(list_row_1d, cells)

        # 2d List Row
        Range('Sheet4', 'A29').value = list_row_2d
        cells = Range('Sheet4', 'A29:C29', atleast_2d=True).value
        assert_equal(list_row_2d, cells)

        # 1d List Col
        Range('Sheet4', 'A31').value = list_col
        cells = Range('Sheet4', 'A31:A33').value
        assert_equal([i[0] for i in list_col], cells)
        # 2d List Col
        cells = Range('Sheet4', 'A31:A33', atleast_2d=True).value
        assert_equal(list_col, cells)

    def test_is_cell(self):
        assert_equal(Range('A1').is_cell(), True)
        assert_equal(Range('A1:B1').is_cell(), False)
        assert_equal(Range('A1:A2').is_cell(), False)
        assert_equal(Range('A1:B2').is_cell(), False)

    def test_is_row(self):
        assert_equal(Range('A1').is_row(), False)
        assert_equal(Range('A1:B1').is_row(), True)
        assert_equal(Range('A1:A2').is_row(), False)
        assert_equal(Range('A1:B2').is_row(), False)

    def test_is_column(self):
        assert_equal(Range('A1').is_column(), False)
        assert_equal(Range('A1:B1').is_column(), False)
        assert_equal(Range('A1:A2').is_column(), True)
        assert_equal(Range('A1:B2').is_column(), False)

    def test_is_table(self):
        assert_equal(Range('A1').is_table(), False)
        assert_equal(Range('A1:B1').is_table(), False)
        assert_equal(Range('A1:A2').is_table(), False)
        assert_equal(Range('A1:B2').is_table(), True)

    def test_formula(self):
        Range('A1').formula = '=SUM(A2:A10)'
        assert_equal(Range('A1').formula, '=SUM(A2:A10)')

    def test_current_region(self):
        values = [[1.,2.],[3.,4.]]
        Range('A20').value = values
        assert_equal(Range('B21').current_region.value, values)

    def test_clear_content(self):
        Range('Sheet4', 'G1').value = 22
        Range('Sheet4', 'G1').clear_contents()
        cell = Range('Sheet4', 'G1').value
        assert_equal(cell, None)

    def test_clear(self):
        Range('Sheet4', 'G1').value = 22
        Range('Sheet4', 'G1').clear()
        cell = Range('Sheet4', 'G1').value
        assert_equal(cell, None)

    def test_dataframe_1(self):
        _skip_if_no_pandas()

        df_expected = df_1
        Range('Sheet5', 'A1').value = df_expected
        cells = Range('Sheet5', 'B1:C5').value
        df_result = DataFrame(cells[1:], columns=cells[0])
        assert_frame_equal(df_expected, df_result)

    def test_dataframe_2(self):
        """ Covers GH Issue #31"""
        _skip_if_no_pandas()

        df_expected = df_2
        Range('Sheet5', 'A9').value = df_expected
        cells = Range('Sheet5', 'B9:B15').value
        df_result = DataFrame(cells[1:], columns=[cells[0]])
        assert_frame_equal(df_expected, df_result)

    def test_dataframe_multiindex(self):
        _skip_if_no_pandas()

        df_expected = df_multiindex
        Range('Sheet5', 'A20').value = df_expected
        cells = Range('Sheet5', 'D20').table.value
        multiindex = Range('Sheet5', 'A20:C28').value
        ix = pd.MultiIndex.from_tuples(multiindex[1:], names=multiindex[0])
        df_result = DataFrame(cells[1:], columns=cells[0], index=ix)
        assert_frame_equal(df_expected, df_result)

    def test_dataframe_multiheader(self):
        _skip_if_no_pandas()

        df_expected = df_multiheader
        Range('Sheet5', 'A52').value = df_expected
        cells = Range('Sheet5', 'B52').table.value
        df_result = DataFrame(cells[2:], columns=pd.MultiIndex.from_arrays(cells[:2]))
        assert_frame_equal(df_expected, df_result)

    def test_dataframe_dateindex(self):
        _skip_if_no_pandas()

        df_expected = df_dateindex
        Range('Sheet5', 'A100').value = df_expected
        if sys.platform.startswith('win') and self.wb.xl_app.Version == '14.0':
            Range('Sheet5', 'A100').vertical.xl_range.NumberFormat = 'dd/mm/yyyy'  # Hack for Excel 2010 bug, see GH #43
        cells = Range('Sheet5', 'B100').table.value
        index = Range('Sheet5', 'A101').vertical.value
        df_result = DataFrame(cells[1:], index=index, columns=cells[0])
        assert_frame_equal(df_expected, df_result)

    def test_series_1(self):
        _skip_if_no_pandas()

        series_expected = series_1
        Range('Sheet5', 'A32').value = series_expected
        cells = Range('Sheet5', 'B32:B37').value
        series_result = Series(cells)
        assert_series_equal(series_expected, series_result)

    def test_timeseries_1(self):
        _skip_if_no_pandas()

        series_expected = timeseries_1
        Range('Sheet5', 'A40').value = series_expected
        if sys.platform.startswith('win') and self.wb.xl_app.Version == '14.0':
            Range('Sheet5', 'A40').vertical.xl_range.NumberFormat = 'dd/mm/yyyy'  # Hack for Excel 2010 bug, see GH #43
        cells = Range('Sheet5', 'B40:B49').value
        date_index = Range('Sheet5', 'A40:A49').value
        series_result = Series(cells, index=date_index)
        assert_series_equal(series_expected, series_result)

    def test_none(self):
        """ Covers GH Issue #16"""
        # None
        Range('Sheet1', 'A7').value = None
        assert_equal(None, Range('Sheet1', 'A7').value)
        # List
        Range('Sheet1', 'A7').value = [None, None]
        assert_equal(None, Range('Sheet1', 'A7').horizontal.value)

    def test_scalar_nan(self):
        """Covers GH Issue #15"""
        _skip_if_no_numpy()

        Range('Sheet1', 'A20').value = np.nan
        assert_equal(None, Range('Sheet1', 'A20').value)

    def test_atleast_2d_scalar(self):
        """Covers GH Issue #53a"""
        Range('Sheet1', 'A50').value = 23
        result = Range('Sheet1', 'A50', atleast_2d=True).value
        assert_equal([[23]], result)

    def test_atleast_2d_scalar_as_array(self):
        """Covers GH Issue #53b"""
        _skip_if_no_numpy()

        Range('Sheet1', 'A50').value = 23
        result = Range('Sheet1', 'A50', atleast_2d=True, asarray=True).value
        assert_equal(np.array([[23]]), result)

    def test_column_width(self):
        Range('Sheet1', 'A1:B2').column_width = 10.0
        result = Range('Sheet1', 'A1').column_width
        assert_equal(10.0, result)

        Range('Sheet1', 'A1:B2').value = 'ensure cells are used'
        Range('Sheet1', 'B2').column_width = 20.0
        result = Range('Sheet1', 'A1:B2').column_width
        if sys.platform.startswith('win'):
            assert_equal(None, result)
        else:
            assert_equal(kw.missing_value, result)

    def test_row_height(self):
        Range('Sheet1', 'A1:B2').row_height = 15.0
        result = Range('Sheet1', 'A1').row_height
        assert_equal(15.0, result)

        Range('Sheet1', 'A1:B2').value = 'ensure cells are used'
        Range('Sheet1', 'B2').row_height = 20.0
        result = Range('Sheet1', 'A1:B2').row_height
        if sys.platform.startswith('win'):
            assert_equal(None, result)
        else:
            assert_equal(kw.missing_value, result)

    def test_width(self):
        """Width depends on default style text size, so do not test absolute widths"""
        Range('Sheet1', 'A1:D4').column_width = 10.0
        result_before = Range('Sheet1', 'A1').width
        Range('Sheet1', 'A1:D4').column_width = 12.0
        result_after = Range('Sheet1', 'A1').width
        assert_true(result_after > result_before)

    def test_height(self):
        Range('Sheet1', 'A1:D4').row_height = 60.0
        result = Range('Sheet1', 'A1:D4').height
        assert_equal(240.0, result)

    def test_autofit_range(self):
        # TODO: compare col/row widths before/after - not implemented yet
        Range('Sheet1', 'A1:D4').value = 'test_string'
        Range('Sheet1', 'A1:D4').autofit()
        Range('Sheet1', 'A1:D4').autofit('r')
        Range('Sheet1', 'A1:D4').autofit('c')
        Range('Sheet1', 'A1:D4').autofit('rows')
        Range('Sheet1', 'A1:D4').autofit('columns')

    def test_autofit_col(self):
        # TODO: compare col/row widths before/after - not implemented yet
        Range('Sheet1', 'A1:D4').value = 'test_string'
        Range('Sheet1', 'A:D').autofit()
        Range('Sheet1', 'A:D').autofit('r')
        Range('Sheet1', 'A:D').autofit('c')
        Range('Sheet1', 'A:D').autofit('rows')
        Range('Sheet1', 'A:D').autofit('columns')

    def test_autofit_row(self):
        # TODO: compare col/row widths before/after - not implemented yet
        Range('Sheet1', 'A1:D4').value = 'test_string'
        Range('Sheet1', '1:1000000').autofit()
        Range('Sheet1', '1:1000000').autofit('r')
        Range('Sheet1', '1:1000000').autofit('c')
        Range('Sheet1', '1:1000000').autofit('rows')
        Range('Sheet1', '1:1000000').autofit('columns')

    def test_number_format_cell(self):
        format_string = "mm/dd/yy;@"
        Range('Sheet1', 'A1').number_format = format_string
        result = Range('Sheet1', 'A1').number_format
        assert_equal(format_string, result)

    def test_number_format_range(self):
        format_string = "mm/dd/yy;@"
        Range('Sheet1', 'A1:D4').number_format = format_string
        result = Range('Sheet1', 'A1:D4').number_format
        assert_equal(format_string, result)

    def test_get_address(self):
        res = Range((1,1),(3,3)).get_address()
        assert_equal(res, '$A$1:$C$3')

        res = Range((1,1),(3,3)).get_address(False)
        assert_equal(res, '$A1:$C3')

        res = Range((1,1),(3,3)).get_address(True, False)
        assert_equal(res, 'A$1:C$3')

        res = Range((1,1),(3,3)).get_address(False, False)
        assert_equal(res, 'A1:C3')

        res = Range((1,1),(3,3)).get_address(include_sheetname=True)
        assert_equal(res, 'Sheet1!$A$1:$C$3')

        res = Range('Sheet2', (1,1),(3,3)).get_address(include_sheetname=True)
        assert_equal(res, 'Sheet2!$A$1:$C$3')

        res = Range((1,1),(3,3)).get_address(external=True)
        assert_equal(res, '[test_range_1.xlsx]Sheet1!$A$1:$C$3')

    def test_hyperlink(self):
        address = 'www.xlwings.org'
        # Naked address
        Range('A1').add_hyperlink(address)
        assert_equal(Range('A1').value, address)
        hyperlink = Range('A1').hyperlink
        if not hyperlink.endswith('/'):
            hyperlink += '/'
        assert_equal(hyperlink, 'http://' + address + '/')

        # Address + FriendlyName
        Range('A2').add_hyperlink(address, 'test_link')
        assert_equal(Range('A2').value, 'test_link')
        hyperlink = Range('A2').hyperlink
        if not hyperlink.endswith('/'):
            hyperlink += '/'
        assert_equal(hyperlink, 'http://' + address + '/')

    def test_hyperlink_formula(self):
        Range('B10').formula = '=HYPERLINK("http://xlwings.org", "xlwings")'
        assert_equal(Range('B10').hyperlink, 'http://xlwings.org')

    def test_color(self):
        rgb = (30, 100, 200)

        Range('A1').color = rgb
        assert_equal(rgb, Range('A1').color)

        Range('A2').color = RgbColor.rgbAqua
        assert_equal((0, 255, 255), Range('A2').color)

        Range('A2').color = None
        assert_equal(Range('A2').color, None)

        Range('A1:D4').color = rgb
        assert_equal(rgb, Range('A1:D4').color)

    def test_size(self):
        assert_equal(Range('A1:C4').size, 12)

    def test_shape(self):
        assert_equal(Range('A1:C4').shape, (4, 3))

    def test_len(self):
        assert_equal(len(Range('A1:C4')), 4)

    def test_iterator(self):
        Range('A20').value = [[1., 2.], [3., 4.]]
        l = []

        for i in Range('A20:B21'):
            l.append(i.value)

        assert_equal(l, [1., 2., 3., 4.])

        Range('Sheet2', 'A20').value = [[1., 2.], [3., 4.]]
        l = []

        for i in Range('Sheet2', 'A20:B21'):
            l.append(i.value)

        assert_equal(l, [1., 2., 3., 4.])

    def test_resize(self):
        r = Range('A1').resize(4, 5)
        assert_equal(r.shape, (4, 5))

        r = Range('A1').resize(row_size=4)
        assert_equal(r.shape, (4, 1))

        r = Range('A1:B4').resize(column_size=5)
        assert_equal(r.shape, (1, 5))

    def test_offset(self):
        o = Range('A1:B3').offset(3, 4)
        assert_equal(o.get_address(), '$E$4:$F$6')

        o = Range('A1:B3').offset(row_offset=3)
        assert_equal(o.get_address(), '$A$4:$B$6')

        o = Range('A1:B3').offset(column_offset=4)
        assert_equal(o.get_address(), '$E$1:$F$3')

    def test_date(self):
        date_1 = date(2000, 12, 3)
        Range('X1').value = date_1
        date_2 = Range('X1').value
        assert_equal(date_1, date(date_2.year, date_2.month, date_2.day))

    def test_row(self):
        assert_equal(Range('B3:F5').row, 3)

    def test_column(self):
        assert_equal(Range('B3:F5').column, 2)

    def test_last_cell(self):
        assert_equal(Range('B3:F5').last_cell.row, 5)
        assert_equal(Range('B3:F5').last_cell.column, 6)

    def test_get_set_named_range(self):
        Range('A100').name = 'test1'
        assert_equal(Range('A100').name, 'test1')

        Range('A200:B204').name = 'test2'
        assert_equal(Range('A200:B204').name, 'test2')

    def test_integers(self):
        """Covers GH 227"""
        Range('A99').value = 2147483647  # max SInt32
        assert_equal(Range('A99').value, 2147483647)

        Range('A100').value = 2147483648  # SInt32 < x < SInt64
        assert_equal(Range('A100').value, 2147483648)

        Range('A101').value = 10000000000000000000  # long
        assert_equal(Range('A101').value, 10000000000000000000)

    def test_numpy_datetime(self):
        _skip_if_no_numpy()

        Range('A55').value = np.datetime64('2005-02-25T03:30Z')
        assert_equal(Range('A55').value, datetime(2005, 2, 25, 3, 30))

    def test_dataframe_timezone(self):
        _skip_if_no_pandas()

        dt = np.datetime64(1434149887000, 'ms')
        ix = pd.DatetimeIndex(data=[dt], tz='GMT')
        df = pd.DataFrame(data=[1], index=ix, columns=['A'])
        Range('A1').value = df
        assert_equal(Range('A2').value, datetime(2015, 6, 12, 22, 58, 7))

    def test_datetime_timezone(self):
        eastern = pytz.timezone('US/Eastern')
        dt_naive = datetime(2002, 10, 27, 6, 0, 0)
        dt_tz = eastern.localize(dt_naive)
        Range('F34').value = dt_tz
        assert_equal(Range('F34').value, dt_naive)

class TestChart:
    def setUp(self):
        # Connect to test file and make Sheet1 the active sheet
        xl_file1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_chart_1.xlsx')
        self.wb = Workbook(xl_file1, app_visible=False, app_target=APP_TARGET)
        Sheet('Sheet1').activate()

    def tearDown(self):
        class_teardown(self.wb)

    def test_add_keywords(self):
        name = 'My Chart'
        chart_type = ChartType.xlLine
        Range('A1').value = chart_data
        chart = Chart.add(chart_type=chart_type, name=name, source_data=Range('A1').table)

        chart_actual = Chart(name)
        name_actual = chart_actual.name
        chart_type_actual = chart_actual.chart_type
        assert_equal(name, name_actual)
        if sys.platform.startswith('win'):
            assert_equal(chart_type, chart_type_actual)
        else:
            assert_equal(kw.line_chart, chart_type_actual)

    def test_add_properties(self):
        name = 'My Chart'
        chart_type = ChartType.xlLine
        Range('Sheet2', 'A1').value = chart_data
        chart = Chart.add('Sheet2')
        chart.chart_type = chart_type
        chart.name = name
        chart.set_source_data(Range('Sheet2', 'A1').table)

        chart_actual = Chart('Sheet2', name)
        name_actual = chart_actual.name
        chart_type_actual = chart_actual.chart_type
        assert_equal(name, name_actual)
        if sys.platform.startswith('win'):
            assert_equal(chart_type, chart_type_actual)
        else:
            assert_equal(kw.line_chart, chart_type_actual)

if __name__ == '__main__':
    nose.main()


"""
The :mod:`sklearn.ensemble` module includes ensemble-based methods for
classification and regression.
"""

from .base import BaseEnsemble
from .forest import RandomForestClassifier
from .forest import RandomForestRegressor
from .forest import RandomTreesEmbedding
from .forest import ExtraTreesClassifier
from .forest import ExtraTreesRegressor
from .bagging import BaggingClassifier
from .bagging import BaggingRegressor
from .weight_boosting import AdaBoostClassifier
from .weight_boosting import AdaBoostRegressor
from .gradient_boosting import GradientBoostingClassifier
from .gradient_boosting import GradientBoostingRegressor
from .voting_classifier import VotingClassifier

from . import bagging
from . import forest
from . import weight_boosting
from . import gradient_boosting
from . import partial_dependence

__all__ = ["BaseEnsemble",
           "RandomForestClassifier", "RandomForestRegressor",
           "RandomTreesEmbedding", "ExtraTreesClassifier",
           "ExtraTreesRegressor", "BaggingClassifier",
           "BaggingRegressor", "GradientBoostingClassifier",
           "GradientBoostingRegressor", "AdaBoostClassifier",
           "AdaBoostRegressor", "VotingClassifier",
           "bagging", "forest", "gradient_boosting",
           "partial_dependence", "weight_boosting"]