1) fit line through electrodes
    2) rotate electrodes so that line lies in the horizontal plane
    3) translate z-coordinates so that all z-coordinates are negative

def homogenize_grid(grid_old, dx, dy):
    """
    1) fit line through electrodes
    2) rotate electrodes so that line lies in the horizontal plane
    3) translate z-coordinates so that all z-coordinates are negative
    """

    # 1 line fit
    x = grid_old.electrodes[:, 0]
    y = grid_old.electrodes[:, 1]
    sort_indices = np.argsort(x)
    x_sort = x[sort_indices]
    y_sort = y[sort_indices]
    p = np.polyfit(x_sort, y_sort, 1)

    # 2. rotate around first electrode
    offsetx = x_sort[0]
    offsety = y_sort[0]

    alpha = -np.arctan2(p[0], 1.0)  # * 180 / np.pi

    xn = []
    yn = []
    for xc, yc in zip(x, y):
        rotx, roty = rotate_point(offsetx, offsety, xc, yc, alpha)
        xn.append(rotx + offsetx)
        yn.append(roty + offsety)

    new_coordinates = np.vstack((xn, yn)).T

    # move vertically

    # this line is a horizontal line
    p_rot = np.polyfit(
        new_coordinates[:, 0],
        new_coordinates[:, 1],
        1
    )
    y_rot = np.polyval(
        p_rot,
        new_coordinates[:, 0],
    )
    ymax = y_rot[0]

    new_coordinates_trans = np.copy(new_coordinates)
    new_coordinates_trans[:, 1] -= ymax

    #
    fig, ax = plt.subplots(1, 1)
    ax.scatter(x, y, color='r', label='original')

    ax.plot(
        x,
        np.polyval(p, x),
        '-',
        label='fit',
        color='r',
    )

    ax.scatter(
        xn, yn,
        color='c',
        label='rotated',
    )

    ax.plot(
        xn,
        y_rot,
        '-',
        label='fit',
        color='c',
    )

    ax.scatter(
        new_coordinates_trans[:, 0],
        new_coordinates_trans[:, 1],
        label='homog',
    )

    # plot the line through the new coordintes
    pnew = np.polyfit(
        new_coordinates_trans[:, 0],
        new_coordinates_trans[:, 1],
        1
    )
    ax.plot(
        new_coordinates_trans[:, 0],
        np.polyval(pnew, new_coordinates_trans[:, 0]),
        '-',
        label='fit homogenized',
    )

    ax.legend(loc='best')

    ax.set_xlabel('x [m]')
    ax.set_ylabel('y [m]')

    fig.tight_layout()
    fig.savefig('output_electrodes.png', dpi=300)

    # electrodes = np.hstack((
    # boundaries
    bx = new_coordinates_trans[sort_indices, 0]
    by = new_coordinates_trans[sort_indices, 1]
    btype = [12 for i in bx]

    # add boundary
    # get deepest boundary coordinate
    y1 = by[-1] - dy
    y2 = by[0] - dy

    ymin = min(y1, y2)

    bx = np.hstack(
        (bx[0] - dx,
         bx,
         [bx[-1] + dx, bx[-1] + dx, bx[0] - dx])
    )

    by = np.hstack(
        (by[0],
         by,
         [by[-1], ymin, ymin]
         )
    )

    btype = np.hstack((12,
                       btype,
                       [11, 11, 11]))

    boundaries = np.vstack((bx, by, btype)).T

    # fig, ax = plt.subplots(1, 1)
    # ax.scatter(bx, by)
    # ax.set_aspect('equal')
    # fig.tight_layout()
    # fig.savefig('boundaries.png', dpi=300)

    grid_new = grid_container(None, None, grid_old.char_length_file)
    grid_new.boundaries = np.copy(boundaries)
    grid_new.electrodes = np.copy(new_coordinates_trans)

    fig, ax = plt.subplots(1, 1)
    ax.scatter(bx, by, color='g', label='boundaries')
    ax.scatter(new_coordinates[:, 0], new_coordinates[:, 1], color='g',
               label='electrodes')
    ax.set_aspect('equal')
    ax.legend()
    fig.tight_layout()
    fig.savefig('output_boundaries.png', dpi=300)

    def transform_back(data):
        new_data = np.copy(data)
        new_data[:, 1] += ymax
        new_data[:, 0] -= offsetx
        new_data[:, 1] -= offsety

        tmpx = (new_data[:, 0]) * np.cos(-alpha) - (new_data[:, 1]) * np.sin(
            -alpha)
        tmpy = (new_data[:, 0]) * np.sin(-alpha) + (new_data[:, 1]) * np.cos(
            -alpha)
        tmpx += offsetx
        tmpy += offsety
        return tmpx, tmpy

    shell_script = ''
    shell_script += '#!/bin/bash\n'
    shell_script += 'cr_trig_create grid\n'

    cmd1 = ''.join((
        'grid_translate -e grid/elem.dat ',
        '--dx {0} --dz {1} -o elem_trans1.dat'.format(
            offsetx, ymax - offsety)
    ))
    cmd2 = ''.join((
        'grid_rotate -e elem_trans1.dat ',
        '-a {0} -o elem_trans1_rot1.dat'.format(-alpha * 180 / np.pi)
    ))
    cmd3 = ''.join((
        'grid_translate -e elem_trans1_rot1.dat ',
        '--dx {0} --dz {1} -o elem_trans1_rot1_trans2.dat'.format(
            offsetx, offsety)
    ))
    shell_script += cmd1 + '\n'
    shell_script += cmd2 + '\n'
    shell_script += cmd3 + '\n'

    shell_script += ''.join((
        'grid_plot_wireframe --fancy -t grid/elec.dat ',
        '-e elem_trans1_rot1_trans2.dat -o trans1_rot1_trans2.png'
    ))

    grid_new.script = shell_script

    tmpx, tmpy = transform_back(grid_new.electrodes)
    bx, by = transform_back(grid_new.boundaries[:, 0:2])

    grid_map = grid_container(char_length_file=grid_old.char_length_file)
    grid_map.electrodes = np.vstack((tmpx, tmpy)).T
    grid_map.boundaries = np.vstack((bx, by, grid_new.boundaries[:, 2])).T

    fig, ax = plt.subplots(1, 1)
    ax.scatter(tmpx, tmpy, color='r', label='new')
    ax.scatter(x, y, color='b', label='old')
    ax.scatter(bx, by, color='g', label='boundaries')
    ax.set_aspect('equal')
    ax.legend()
    fig.tight_layout()
    fig.savefig('output_map.png', dpi=300)

    return grid_new, grid_map