# summary_plots.py
# Make data plots with multiple observations,images etc.
#
#    Copyright (C) 2018 Andrew Chael
#
#    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 3 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, see <http://www.gnu.org/licenses/>.

# TODO add systematic noise to individual closure quantities?

from __future__ import division
from __future__ import print_function

from builtins import str
from builtins import range
from builtins import object

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.backends.backend_pdf import PdfPages
import datetime

from ehtim.plotting.comp_plots import plotall_obs_compare
from ehtim.plotting.comp_plots import plot_bl_obs_compare
from ehtim.plotting.comp_plots import plot_cphase_obs_compare
from ehtim.plotting.comp_plots import plot_camp_obs_compare
from ehtim.calibrating.self_cal import self_cal as selfcal
from ehtim.calibrating.pol_cal import leakage_cal, plot_leakage
import ehtim.const_def as ehc

FONTSIZE = 22
WSPACE = 0.8
HSPACE = 0.3
MARGINS = 0.5
PROCESSES = 4
MARKERSIZE = 5


def imgsum(im_or_mov, obs, obs_uncal, outname, outdir='.', title='imgsum', commentstr="",
           fontsize=FONTSIZE, cfun='afmhot', snrcut=0., maxset=False, ttype='nfft',
           gainplots=True, ampplots=True, cphaseplots=True, campplots=True, ebar=True,
           debias=True, cp_uv_min=False, force_extrapolate=True, processes=PROCESSES,
           sysnoise=0, syscnoise=0):
    """Produce an image summary plot for an image and uvfits file.

       Args:
           im_or_mov (Image or Movie): an Image object or Movie
           obs (Obsdata): the self-calibrated Obsdata object
           obs_uncal (Obsdata): the original Obsdata object
           outname (str): output pdf file name

           outdir (str): directory for output file
           title (str): the pdf file title
           commentstr (str): a comment for the top line of the pdf
           fontsize (float): the font size for text in the sheet
           cfun (float): matplotlib color function

           maxset (bool): True to use a maximal set of closure quantities

           gainplots (bool): include gain plots or not
           ampplots (bool): include amplitude consistency plots or not
           cphaseplots (bool): include closure phase consistency plots or not
           campplots (bool): include closure amplitude consistency plots or not
           ebar (bool): include error bars or not
           debias (bool): debias visibility amplitudes before computing chisq or not
           cp_uv_min (bool): minimum uv-distance cutoff for including a baseline in closure phase

           sysnoise (float): percent systematic noise added in quadrature
           syscnoise (float): closure phase systematic noise in degrees added in quadrature

           snrcut (dict): a dictionary of snrcut values for each quantity

           ttype (str): "fast" or "nfft" or "direct"
           force_extrapolate (bool): if True, always extrapolate movie start/stop frames
           processes (int): number of cores to use in multiprocessing
       Returns:

    """

    plt.close('all')  # close conflicting plots
    plt.rc('font', family='serif')
    plt.rc('text', usetex=True)
    plt.rc('font', size=FONTSIZE)
    plt.rc('axes', titlesize=FONTSIZE)
    plt.rc('axes', labelsize=FONTSIZE)
    plt.rc('xtick', labelsize=FONTSIZE)
    plt.rc('ytick', labelsize=FONTSIZE)
    plt.rc('legend', fontsize=FONTSIZE)
    plt.rc('figure', titlesize=FONTSIZE)

    if fontsize == 0:
        fontsize = FONTSIZE

    if maxset:
        count = 'max'
    else:
        count = 'min'

    snrcut_dict = {key: 0. for key in ['vis', 'amp', 'cphase', 'logcamp', 'camp']}

    if type(snrcut) is dict:
        for key in snrcut.keys():
            snrcut_dict[key] = snrcut[key]
    else:
        for key in snrcut_dict.keys():
            snrcut_dict[key] = snrcut

    with PdfPages(outname) as pdf:
        titlestr = 'Summary Sheet for %s on MJD %s' % (im_or_mov.source, im_or_mov.mjd)

        # pdf metadata
        d = pdf.infodict()
        d['Title'] = title
        d['Author'] = u'EHT Team 1'
        d['Subject'] = titlestr
        d['CreationDate'] = datetime.datetime.today()
        d['ModDate'] = datetime.datetime.today()

        # define the figure
        fig = plt.figure(1, figsize=(18, 28), dpi=200)
        gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)

        # user comments
        if len(commentstr) > 1:
            titlestr = titlestr+'\n'+str(commentstr)

        plt.suptitle(titlestr, y=.9, va='center', fontsize=int(1.2*fontsize))

        ################################################################################
        print("===========================================")
        print("displaying the image")
        ax = plt.subplot(gs[0:2, 0:2])
        ax.set_title('Submitted Image')

        movie = hasattr(im_or_mov, 'get_image')
        if movie:
            im_display = im_or_mov.avg_frame()

            # TODO --- ok to always extrapolate?
            if force_extrapolate:
                im_or_mov.reset_interp(bounds_error=False)
        elif hasattr(im_or_mov, 'make_image'):      
            im_display = im_or_mov.make_image(obs.res() * 10., 512)
        else:
            im_display = im_or_mov.copy()

        ax = _display_img(im_display, axis=ax, show=False,
                          has_title=False, cfun=cfun, fontsize=fontsize)

        print("===========================================")
        print("displaying the blurred image")
        ax = plt.subplot(gs[0:2, 2:5])
        ax.set_title('Image blurred to nominal resolution')
        fwhm = obs.res()
        print("blur_FWHM: ", fwhm/ehc.RADPERUAS)
        beamparams = [fwhm, fwhm, 0]

        imblur = im_display.blur_gauss(beamparams, frac=1.0)
        ax = _display_img(imblur, beamparams=beamparams, axis=ax, show=False,
                          has_title=False, cfun=cfun, fontsize=fontsize)

        ################################################################################
        print("===========================================")
        print("calculating statistics")
        # display the overall chi2
        ax = plt.subplot(gs[2, 0:2])
        ax.set_title('Image statistics')
        # ax.axis('off')
        ax.set_yticks([])
        ax.set_xticks([])

        flux = im_display.total_flux()

        # SNR ordering
        # obs.reorder_tarr_snr()
        # obs_uncal.reorder_tarr_snr()

        maxset = False
        # compute chi^2
        chi2vis = obs.chisq(im_or_mov, dtype='vis', ttype=ttype,
                            systematic_noise=sysnoise, maxset=maxset, snrcut=snrcut_dict['vis'])
        chi2amp = obs.chisq(im_or_mov, dtype='amp', ttype=ttype,
                            systematic_noise=sysnoise, maxset=maxset, snrcut=snrcut_dict['amp'])
        chi2cphase = obs.chisq(im_or_mov, dtype='cphase', ttype=ttype, systematic_noise=sysnoise,
                               systematic_cphase_noise=syscnoise,
                               maxset=maxset, cp_uv_min=cp_uv_min, snrcut=snrcut_dict['cphase'])
        chi2logcamp = obs.chisq(im_or_mov, dtype='logcamp', ttype=ttype, systematic_noise=sysnoise,
                                maxset=maxset, snrcut=snrcut_dict['logcamp'])
        chi2camp = obs.chisq(im_or_mov, dtype='camp', ttype=ttype,
                             systematic_noise=sysnoise, maxset=maxset, snrcut=snrcut_dict['camp'])

        chi2vis_uncal = obs_uncal.chisq(im_or_mov, dtype='vis', ttype=ttype, systematic_noise=0,
                                        maxset=maxset, snrcut=snrcut_dict['vis'])
        chi2amp_uncal = obs_uncal.chisq(im_or_mov, dtype='amp', ttype=ttype, systematic_noise=0,
                                        maxset=maxset, snrcut=snrcut_dict['amp'])
        chi2cphase_uncal = obs_uncal.chisq(im_or_mov, dtype='cphase', ttype=ttype,
                                           systematic_noise=0,
                                           systematic_cphase_noise=0, maxset=maxset,
                                           cp_uv_min=cp_uv_min, snrcut=snrcut_dict['cphase'])
        chi2logcamp_uncal = obs_uncal.chisq(im_or_mov, dtype='logcamp', ttype=ttype,
                                            systematic_noise=0, maxset=maxset,
                                            snrcut=snrcut_dict['logcamp'])
        chi2camp_uncal = obs_uncal.chisq(im_or_mov, dtype='camp', ttype=ttype, systematic_noise=0,
                                         maxset=maxset, snrcut=snrcut_dict['camp'])

        print("chi^2 vis: %0.2f %0.2f" % (chi2vis, chi2vis_uncal))
        print("chi^2 amp: %0.2f %0.2f" % (chi2amp, chi2amp_uncal))
        print("chi^2 cphase: %0.2f %0.2f" % (chi2cphase, chi2cphase_uncal))
        print("chi^2 logcamp: %0.2f %0.2f" % (chi2logcamp, chi2logcamp_uncal))
        print("chi^2 camp: %0.2f %0.2f" % (chi2logcamp, chi2logcamp_uncal))

        fs = int(1*fontsize)
        fs2 = int(.8*fontsize)
        ax.text(.05, .9, "Source:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .7, "MJD:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .5, "FREQ:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .3, "FOV:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .1, "FLUX:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.23, .9, "%s" % im_or_mov.source, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .7, "%i" % im_or_mov.mjd, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .5, "%0.0f GHz" % (im_or_mov.rf/1.e9), fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .3, "%0.1f $\mu$as" % (im_display.fovx()/ehc.RADPERUAS), fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .1, "%0.2f Jy" % flux, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.5, .9, "$\chi^2_{vis}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .7, "$\chi^2_{amp}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .5, "$\chi^2_{cphase}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .3, "$\chi^2_{log camp}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .1, "$\chi^2_{camp}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.72, .9, "%0.2f" % chi2vis, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .7, "%0.2f" % chi2amp, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .5, "%0.2f" % chi2cphase, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .3, "%0.2f" % chi2logcamp, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .1, "%0.2f" % chi2camp, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.85, .9, "(%0.2f)" % chi2vis_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .7, "(%0.2f)" % chi2amp_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .5, "(%0.2f)" % chi2cphase_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .3, "(%0.2f)" % chi2logcamp, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .1, "(%0.2f)" % chi2camp_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)

        ################################################################################
        print("===========================================")
        print("calculating cphase statistics")
        # display the closure  phase chi2
        ax = plt.subplot(gs[3:6, 0:2])
        ax.set_title('Closure phase statistics')
        ax.set_yticks([])
        ax.set_xticks([])

        # get closure triangle combinations
        # ANDREW -- hacky, fix this!
        cp = obs.c_phases(mode="all", count=count, uv_min=cp_uv_min, snrcut=snrcut_dict['cphase'])
        n_cphase = len(cp)
        alltris = [(str(cpp['t1']), str(cpp['t2']), str(cpp['t3'])) for cpp in cp]
        uniqueclosure_tri = []
        for tri in alltris:
            if tri not in uniqueclosure_tri:
                uniqueclosure_tri.append(tri)

        # generate data
        obs_model = im_or_mov.observe_same(obs, add_th_noise=False, ttype=ttype)

        # TODO: check SNR cut
        cphases_obs = obs.c_phases(mode='all', count='max', vtype='vis',
                                   uv_min=cp_uv_min, snrcut=snrcut_dict['cphase'])
        if snrcut_dict['cphase'] > 0:
            cphases_obs_all = obs.c_phases(mode='all', count='max',
                                           vtype='vis', uv_min=cp_uv_min, snrcut=0.)
            cphases_model_all = obs_model.c_phases(
                mode='all', count='max', vtype='vis', uv_min=cp_uv_min, snrcut=0.)
            mask = [cphase in cphases_obs for cphase in cphases_obs_all]
            cphases_model = cphases_model_all[mask]
            print('cphase snr cut', snrcut_dict['cphase'], ' : kept', len(
                cphases_obs), '/', len(cphases_obs_all))
        else:
            cphases_model = obs_model.c_phases(
                mode='all', count='max', vtype='vis', uv_min=cp_uv_min, snrcut=0.)

        # generate chi^2 -- NO SYSTEMATIC NOISES
        cphase_chisq_data = []
        for c in range(0, len(uniqueclosure_tri)):
            cphases_obs_tri = obs.cphase_tri(uniqueclosure_tri[c][0],
                                             uniqueclosure_tri[c][1],
                                             uniqueclosure_tri[c][2],
                                             vtype='vis', ang_unit='deg', cphases=cphases_obs)

            if len(cphases_obs_tri) > 0:
                cphases_model_tri = obs_model.cphase_tri(uniqueclosure_tri[c][0],
                                                         uniqueclosure_tri[c][1],
                                                         uniqueclosure_tri[c][2],
                                                         vtype='vis', ang_unit='deg',
                                                         cphases=cphases_model)

                resids = (cphases_obs_tri['cphase'] - cphases_model_tri['cphase'])*ehc.DEGREE
                chisq_tri = 2*np.sum((1.0 - np.cos(resids)) /
                                     ((cphases_obs_tri['sigmacp']*ehc.DEGREE)**2))

                npts = len(cphases_obs_tri)
                data = [uniqueclosure_tri[c][0], uniqueclosure_tri[c]
                        [1], uniqueclosure_tri[c][2], npts, chisq_tri]
                cphase_chisq_data.append(data)

        # sort by decreasing chi^2
        idx = np.argsort([data[-1] for data in cphase_chisq_data])
        idx = list(reversed(idx))

        chisqtab = (r"\begin{tabular}{ l|l|l|l } \hline Triangle " +
                    r"& $N_{tri}$ & $\chi^2_{tri}/N_{tri}$ & $\chi^2_{tri}/N_{tot}$" +
                    r"\\ \hline \hline")
        first = True
        for i in range(len(cphase_chisq_data)):
            if i > 30:
                break
            data = cphase_chisq_data[idx[i]]
            tristr = r"%s-%s-%s" % (data[0], data[1], data[2])
            nstr = r"%i" % data[3]
            rchisqstr = r"%0.1f" % (float(data[4])/float(data[3]))
            rrchisqstr = r"%0.3f" % (float(data[4])/float(n_cphase))
            if first:
                chisqtab += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
                first = False
            else:
                chisqtab += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
        chisqtab += r" \end{tabular}"

        ax.text(0.5, .975, chisqtab, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        ################################################################################
        print("===========================================")
        print("calculating camp statistics")
        # display the log closure amplitude chi2
        ax = plt.subplot(gs[2:6, 2::])
        ax.set_title('Log Closure amplitude statistics')
        # ax.axis('off')
        ax.set_yticks([])
        ax.set_xticks([])

        # get closure amplitude combinations
        # TODO -- hacky, fix this!
        cp = obs.c_amplitudes(mode="all", count=count, ctype='logcamp', debias=debias)
        n_camps = len(cp)
        allquads = [(str(cpp['t1']), str(cpp['t2']), str(cpp['t3']), str(cpp['t4'])) for cpp in cp]
        uniqueclosure_quad = []
        for quad in allquads:
            if quad not in uniqueclosure_quad:
                uniqueclosure_quad.append(quad)

        # generate data
        # TODO: check SNR cut
        camps_obs = obs.c_amplitudes(mode='all', count='max', ctype='logcamp',
                                     debias=debias, snrcut=snrcut_dict['logcamp'])
        if snrcut_dict['logcamp'] > 0:
            camps_obs_all = obs.c_amplitudes(
                mode='all', count='max', ctype='logcamp', debias=debias, snrcut=0.)
            camps_model_all = obs_model.c_amplitudes(
                mode='all', count='max', ctype='logcamp', debias=False, snrcut=0.)
            mask = [camp['camp'] in camps_obs['camp'] for camp in camps_obs_all]
            camps_model = camps_model_all[mask]
            print('closure amp snrcut', snrcut_dict['logcamp'],
                  ': kept', len(camps_obs), '/', len(camps_obs_all))
        else:
            camps_model = obs_model.c_amplitudes(
                mode='all', count='max', ctype='logcamp', debias=False, snrcut=0.)

        # generate chi2 -- NO SYSTEMATIC NOISES
        camp_chisq_data = []
        for c in range(0, len(uniqueclosure_quad)):
            camps_obs_quad = obs.camp_quad(uniqueclosure_quad[c][0], uniqueclosure_quad[c][1],
                                           uniqueclosure_quad[c][2],  uniqueclosure_quad[c][3],
                                           vtype='vis', camps=camps_obs, ctype='logcamp')

            if len(camps_obs_quad) > 0:
                camps_model_quad = obs.camp_quad(uniqueclosure_quad[c][0], uniqueclosure_quad[c][1],
                                                 uniqueclosure_quad[c][2], uniqueclosure_quad[c][3],
                                                 vtype='vis', camps=camps_model, ctype='logcamp')

                resids = camps_obs_quad['camp'] - camps_model_quad['camp']
                chisq_quad = np.sum(np.abs(resids/camps_obs_quad['sigmaca'])**2)
                npts = len(camps_obs_quad)

                data = (uniqueclosure_quad[c][0], uniqueclosure_quad[c][1],
                        uniqueclosure_quad[c][2], uniqueclosure_quad[c][3],
                        npts,
                        chisq_quad)
                camp_chisq_data.append(data)

        # sort by decreasing chi^2
        idx = np.argsort([data[-1] for data in camp_chisq_data])
        idx = list(reversed(idx))

        chisqtab = (r"\begin{tabular}{ l|l|l|l } \hline Quadrangle " +
                    r"& $N_{quad}$ & $\chi^2_{quad}/N_{quad}$ & $\chi^2_{quad}/N_{tot}$ " +
                    r"\\ \hline \hline")
        for i in range(len(camp_chisq_data)):
            if i > 45:
                break
            data = camp_chisq_data[idx[i]]
            tristr = r"%s-%s-%s-%s" % (data[0], data[1], data[2], data[3])
            nstr = r"%i" % data[4]
            rchisqstr = r"%0.1f" % (data[5]/float(data[4]))
            rrchisqstr = r"%0.3f" % (data[5]/float(n_camps))
            if i == 0:
                chisqtab += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr

        chisqtab += r" \end{tabular}"

        ax.text(0.5, .975, chisqtab, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        # save the first page of the plot
        print('saving pdf page 1')
        pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
        plt.close()

        ################################################################################
        # plot the vis amps
        fig = plt.figure(2, figsize=(18, 28), dpi=200)
        gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)

        print("===========================================")
        print("plotting vis amps")
        ax = plt.subplot(gs[0:2, 0:2])
        obs_tmp = obs_model.copy()
        obs_tmp.data['sigma'] *= 0.
        ax = plotall_obs_compare([obs, obs_tmp],
                                 'uvdist', 'amp', axis=ax, legend=False,
                                 clist=['k', ehc.SCOLORS[1]],
                                 ttype=ttype, show=False, debias=debias,
                                 snrcut=snrcut_dict['amp'],
                                 ebar=ebar, markersize=MARKERSIZE)
        # modify the labels
        ax.set_title('Calibrated Visiblity Amplitudes')
        ax.set_xlabel('u-v distance (G$\lambda$)')
        ax.set_xlim([0, 1.e10])
        ax.set_xticks([0, 2.e9, 4.e9, 6.e9, 8.e9, 10.e9])
        ax.set_xticklabels(["0", "2", "4", "6", "8", "10"])
        ax.set_xticks([1.e9, 3.e9, 5.e9, 7.e9, 9.e9], minor=True)
        ax.set_xticklabels([], minor=True)

        ax.set_ylabel('Amplitude (Jy)')
        ax.set_ylim([0, 1.2*flux])
        yticks_maj = np.array([0, .2, .4, .6, .8, 1])*flux
        ax.set_yticks(yticks_maj)
        ax.set_yticklabels(["%0.2f" % fl for fl in yticks_maj])
        yticks_min = np.array([.1, .3, .5, .7, .9])*flux
        ax.set_yticks(yticks_min, minor=True)
        ax.set_yticklabels([], minor=True)

        # plot the caltable gains
        if gainplots:
            print("===========================================")
            print("plotting gains")
            ax2 = plt.subplot(gs[0:2, 2:6])
            obs_tmp = obs_uncal.copy()
            for i in range(1):
                ct = selfcal(obs_tmp, im_or_mov,
                             method='amp', ttype=ttype,
                             caltable=True, gain_tol=.2,
                             processes=processes)
                ct = ct.pad_scans()
                obs_tmp = ct.applycal(obs_tmp, interp='nearest', extrapolate=True)
                if np.any(np.isnan(obs_tmp.data['vis'])):
                    print("Warning: NaN in applycal vis table!")
                    break
                if i > 0:
                    ct_out = ct_out.merge([ct])
                else:
                    ct_out = ct

            ax2 = ct_out.plot_gains('all', rangey=[.1, 10],
                                    yscale='log', axis=ax2, legend=True, show=False)

            # median gains
            ax = plt.subplot(gs[3:6, 2:5])
            ax.set_title('Station gain statistics')
            ax.set_yticks([])
            ax.set_xticks([])

            gain_data = []
            for station in ct_out.tarr['site']:
                try:
                    gain = np.median(np.abs(ct_out.data[station]['lscale']))
                except:
                    continue
                pdiff = np.abs(gain-1)*100
                data = (station, gain, pdiff)
                gain_data.append(data)

            # sort by decreasing chi^2
            idx = np.argsort([data[-1] for data in gain_data])
            idx = list(reversed(idx))

            chisqtab = (r"\begin{tabular}{ l|l|l } \hline Site & " +
                        r"Median Gain & Percent diff. \\ \hline \hline")
            for i in range(len(gain_data)):
                if i > 45:
                    break
                data = gain_data[idx[i]]
                sitestr = r"%s" % (data[0])
                gstr = r"%0.2f" % data[1]
                pstr = r"%0.0f" % data[2]
                if i == 0:
                    chisqtab += r" " + sitestr + " & " + gstr + " & " + pstr
                else:
                    chisqtab += r" \\" + sitestr + " & " + gstr + " & " + pstr

            chisqtab += r" \end{tabular}"
            ax.text(0.5, .975, chisqtab, ha="center", va="top",
                    transform=ax.transAxes, size=fontsize)

        # baseline amplitude chi2
        print("===========================================")
        print("baseline vis amps chisq")
        ax = plt.subplot(gs[3:6, 0:2])
        ax.set_title('Visibility amplitude statistics')
        ax.set_yticks([])
        ax.set_xticks([])

        bl_unpk = obs.unpack(['t1', 't2'], debias=debias)
        n_bl = len(bl_unpk)
        allbl = [(str(bl['t1']), str(bl['t2'])) for bl in bl_unpk]
        uniquebl = []
        for bl in allbl:
            if bl not in uniquebl:
                uniquebl.append(bl)

        # generate chi2 -- NO SYSTEMATIC NOISES
        bl_chisq_data = []
        for ii in range(0, len(uniquebl)):
            bl = uniquebl[ii]

            amps_bl = obs.unpack_bl(bl[0], bl[1], ['amp', 'sigma'], debias=debias)
            if len(amps_bl) > 0:

                amps_bl_model = obs_model.unpack_bl(bl[0], bl[1], ['amp', 'sigma'], debias=False)

                if snrcut_dict['amp'] > 0:
                    amask = amps_bl['amp']/amps_bl['sigma'] > snrcut_dict['amp']
                    amps_bl = amps_bl[amask]
                    amps_bl_model = amps_bl_model[amask]

                chisq_bl = np.sum(
                    np.abs((amps_bl['amp'] - amps_bl_model['amp'])/amps_bl['sigma'])**2)
                npts = len(amps_bl_model)

                data = (bl[0], bl[1],
                        npts,
                        chisq_bl)
                bl_chisq_data.append(data)

        # sort by decreasing chi^2
        idx = np.argsort([data[-1] for data in bl_chisq_data])
        idx = list(reversed(idx))

        chisqtab = (r"\begin{tabular}{ l|l|l|l } \hline Baseline & " +
                    r"$N_{amp}$ & $\chi^2_{amp}/N_{amp}$ & $\chi^2_{amp}/N_{total}$ " +
                    r"\\ \hline \hline")
        for i in range(len(bl_chisq_data)):
            if i > 45:
                break
            data = bl_chisq_data[idx[i]]
            tristr = r"%s-%s" % (data[0], data[1])
            nstr = r"%i" % data[2]
            rchisqstr = r"%0.1f" % (data[3]/float(data[2]))
            rrchisqstr = r"%0.3f" % (data[3]/float(n_bl))
            if i == 0:
                chisqtab += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr

        chisqtab += r" \end{tabular}"

        ax.text(0.5, .975, chisqtab, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        # save the first page of the plot
        print('saving pdf page 2')
        # plt.tight_layout()
        # plt.subplots_adjust(wspace=1,hspace=1)
        # plt.savefig(outname, pad_inches=MARGINS,bbox_inches='tight')
        pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
        plt.close()

        ################################################################################
        # plot the visibility amplitudes
        page = 3
        if ampplots:
            print("===========================================")
            print("plotting amplitudes")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Amplitude Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0
            switch = False

            obs_model.data['sigma'] *= 0
            amax = 1.1*np.max(np.abs(np.abs(obs_model.data['vis'])))
            obs_all = [obs, obs_model]
            for bl in uniquebl:
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'amp', rangey=[0, amax],
                                         markersize=MARKERSIZE, debias=debias,
                                         snrcut=snrcut_dict['amp'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype=ttype, show=False, ebar=ebar)
                if ax is None:
                    continue
                if switch:
                    i += 1
                    j = 0
                    switch = False
                else:
                    j = 1
                    switch = True

                ax.set_xlabel('')

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0
                    switch = False

            print('saving pdf page %i' % page)
            page += 1
            pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
            plt.close()

        ################################################################################
        # plot the closure phases
        if cphaseplots:
            print("===========================================")
            print("plotting closure phases")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Closure Phase Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0
            switch = False
            obs_all = [obs, obs_model]
            cphases_model['sigmacp'] *= 0
            cphases_all = [cphases_obs, cphases_model]
            for tri in uniqueclosure_tri:

                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_cphase_obs_compare(obs_all, tri[0], tri[1], tri[2], rangey=[-185, 185],
                                             cphases=cphases_all, markersize=MARKERSIZE,
                                             axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                             ttype=ttype, show=False, ebar=ebar)
                if ax is None:
                    continue
                if switch:
                    i += 1
                    j = 0
                    switch = False
                else:
                    j = 1
                    switch = True

                ax.set_xlabel('')

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0
                    switch = False
            print('saving pdf page %i' % page)
            page += 1
            pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
            plt.close()

        ################################################################################
        # plot the log closure amps
        if campplots:
            print("===========================================")
            print("plotting closure amplitudes")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Closure Amplitude Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0
            switch = False
            obs_all = [obs, obs_model]
            camps_model['sigmaca'] *= 0
            camps_all = [camps_obs, camps_model]
            cmax = 1.1*np.max(np.abs(camps_obs['camp']))
            for quad in uniqueclosure_quad:
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_camp_obs_compare(obs_all, quad[0], quad[1], quad[2], quad[3],
                                           markersize=MARKERSIZE,
                                           ctype='logcamp', rangey=[-cmax, cmax], camps=camps_all,
                                           axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                           ttype=ttype, show=False, ebar=ebar)
                if ax is None:
                    continue
                if switch:
                    i += 1
                    j = 0
                    switch = False
                else:
                    j = 1
                    switch = True

                ax.set_xlabel('')

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0
                    switch = False
            print('saving pdf page %i' % page)
            page += 1
            pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
            plt.close()


def imgsum_pol(im, obs, obs_uncal, outname,
               leakage_arr=False, nvec=False,
               outdir='.', title='imgsum_pol', commentstr="",
               fontsize=FONTSIZE, cfun='afmhot', snrcut=0.,
               dtermplots=True, pplots=True, mplots=True, qplots=True, uplots=True, ebar=True,
               sysnoise=0):
    """Produce a polarimetric image summary plot for an image and uvfits file.

       Args:
           im (Image): an Image object
           obs (Obsdata): the calibrated Obsdata object
           obs_uncal (Obsdata): the original Obsdata object
           outname (str): output pdf file name

           leakage_arr (bool): array with calibrated d-terms
           nvec (int): number of polarimetric vectors to plot in  each direction

           outdir (str): directory for output file
           title (str): the pdf file title
           commentstr (str): a comment for the top line of the pdf
           fontsize (float): the font size for text in the sheet
           cfun (float): matplotlib color function
           snrcut (dict): a dictionary of snrcut values for each quantity

           dtermplots (bool): plot the d-terms or not
           mplots (bool): plot the fractional polarizations or not
           pplots (bool): plot the P=RL polarization or not
           mplots (bool): plot the Q data or not
           pplots (bool): plot the U data or not

           ebar (bool): include error bars or not
           sysnoise (float): percent systematic noise added in quadrature

       Returns:

    """

    # switch polreps and mask nan data
    im = im.switch_polrep(polrep_out='stokes')
    obs = obs.switch_polrep(polrep_out='stokes')
    obs_uncal = obs_uncal.switch_polrep(polrep_out='stokes')

    mask_nan = (np.isnan(obs_uncal.data['vis']) +
                np.isnan(obs_uncal.data['qvis']) +
                np.isnan(obs_uncal.data['uvis']) +
                np.isnan(obs_uncal.data['vvis']))
    obs_uncal.data = obs_uncal.data[~mask_nan]

    mask_nan = (np.isnan(obs.data['vis']) +
                np.isnan(obs.data['qvis']) +
                np.isnan(obs.data['uvis']) +
                np.isnan(obs.data['vvis']))
    obs.data = obs.data[~mask_nan]

    if len(im.qvec) == 0 or len(im.uvec) == 0:
        raise Exception("the image isn't polarized!")

    plt.close('all')  # close conflicting plots
    plt.rc('font', family='serif')
    plt.rc('text', usetex=True)
    plt.rc('font', size=FONTSIZE)
    plt.rc('axes', titlesize=FONTSIZE)
    plt.rc('axes', labelsize=FONTSIZE)
    plt.rc('xtick', labelsize=FONTSIZE)
    plt.rc('ytick', labelsize=FONTSIZE)
    plt.rc('legend', fontsize=FONTSIZE)
    plt.rc('figure', titlesize=FONTSIZE)

    if fontsize == 0:
        fontsize = FONTSIZE

    snrcut_dict = {key: 0. for key in ['m', 'pvis', 'qvis', 'uvis']}

    if type(snrcut) is dict:
        for key in snrcut.keys():
            snrcut_dict[key] = snrcut[key]
    else:
        for key in snrcut_dict.keys():
            snrcut_dict[key] = snrcut

    # TODO -- ok? prevent errors in divisition
    if(np.any(im.ivec == 0)):
        im.ivec += 1.e-50*np.max(im.ivec)

    with PdfPages(outname) as pdf:
        titlestr = 'Summary Sheet for %s on MJD %s' % (im.source, im.mjd)

        # pdf metadata
        d = pdf.infodict()
        d['Title'] = title
        d['Author'] = u'EHT Team 1'
        d['Subject'] = titlestr
        d['CreationDate'] = datetime.datetime.today()
        d['ModDate'] = datetime.datetime.today()

        # define the figure
        fig = plt.figure(1, figsize=(18, 28), dpi=200)
        gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)

        # user comments
        if len(commentstr) > 1:
            titlestr = titlestr+'\n'+str(commentstr)

        plt.suptitle(titlestr, y=.9, va='center', fontsize=int(1.2*fontsize))

        ################################################################################
        print("===========================================")
        print("displaying the images")

        # unblurred image IQU
        ax = plt.subplot(gs[0:2, 0:2])
        ax.set_title('I')

        ax = _display_img_pol(im, axis=ax, show=False, has_title=False, cfun=cfun,
                              pol='I', polticks=True,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ax = plt.subplot(gs[2:4, 0:2])
        ax.set_title('Q')
        ax = _display_img_pol(im, axis=ax, show=False, has_title=False, cfun=plt.get_cmap('bwr'),
                              pol='Q', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=True,
                              fontsize=fontsize)

        ax = plt.subplot(gs[4:6, 0:2])
        ax.set_title('U')
        ax = _display_img_pol(im, axis=ax, show=False, has_title=False, cfun=plt.get_cmap('bwr'),
                              pol='U', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=True,
                              fontsize=fontsize)

        # blurred image IQU
        ax = plt.subplot(gs[0:2, 2:5])
        beamparams = obs_uncal.fit_beam()
        fwhm = np.min((np.abs(beamparams[0]), np.abs(beamparams[1])))
        print("blur_FWHM: ", fwhm/ehc.RADPERUAS)

        imblur = im.blur_gauss(beamparams, frac=1.0, frac_pol=1.)

        ax = _display_img_pol(imblur, axis=ax, show=False, has_title=False, cfun=cfun,
                              pol='I', polticks=True, beamparams=beamparams,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ax = plt.subplot(gs[2:4, 2:5])
        ax = _display_img_pol(imblur, axis=ax, show=False, has_title=False,
                              cfun=plt.get_cmap('bwr'),
                              pol='Q', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=True,
                              fontsize=fontsize)

        ax = plt.subplot(gs[4:6, 2:5])
        ax = _display_img_pol(imblur, axis=ax, show=False, has_title=False,
                              cfun=plt.get_cmap('bwr'),
                              pol='U', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=True,
                              fontsize=fontsize)

        print('saving pdf page 1')
        pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
        plt.close()

        # unblurred image m chi
        fig = plt.figure(2, figsize=(18, 28), dpi=200)
        gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)

        ax = plt.subplot(gs[0:2, 0:2])
        ax.set_title('m')
        ax = _display_img_pol(im, axis=ax, show=True, has_title=False,
                              cfun=plt.get_cmap('jet'),
                              pol='m', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ax = plt.subplot(gs[2:4, 0:2])
        ax.set_title('chi')
        ax = _display_img_pol(im, axis=ax, show=False, has_title=False,
                              cfun=plt.get_cmap('jet'),
                              pol='chi', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ax = plt.subplot(gs[0:2, 2:5])
        ax = _display_img_pol(imblur, axis=ax, show=False, has_title=False,
                              cfun=plt.get_cmap('jet'),
                              pol='m', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ax = plt.subplot(gs[2:4, 2:5])
        ax = _display_img_pol(imblur, axis=ax, show=False, has_title=False,
                              cfun=plt.get_cmap('jet'),
                              pol='chi', polticks=False,
                              nvec=nvec, pcut=0.1,  mcut=0.01, contour=False,
                              fontsize=fontsize)

        ################################################################################
        print("===========================================")
        print("calculating statistics")
        # display the overall chi2
        ax = plt.subplot(gs[4, 0:2])
        ax.set_title('Image statistics')
        # ax.axis('off')
        ax.set_yticks([])
        ax.set_xticks([])

        flux = im.total_flux()

        # SNR ordering
        # obs.reorder_tarr_snr()
        # obs_uncal.reorder_tarr_snr()

        # compute chi^2
        chi2pvis = obs.polchisq(im, dtype='m', ttype='nfft',
                                systematic_noise=sysnoise, pol_trans=False)
        chi2m = obs.polchisq(im, dtype='m', ttype='nfft',
                             systematic_noise=sysnoise, pol_trans=False)
        chi2qvis = obs.chisq(im, dtype='vis', ttype='nfft',
                             systematic_noise=sysnoise, pol='Q')
        chi2uvis = obs.chisq(im, dtype='vis', ttype='nfft',
                             systematic_noise=sysnoise, pol='U')

        chi2pvis_uncal = obs_uncal.polchisq(im, dtype='m', ttype='nfft',
                                            systematic_noise=sysnoise, pol_trans=False)
        chi2m_uncal = obs_uncal.polchisq(im, dtype='m', ttype='nfft',
                                         systematic_noise=sysnoise, pol_trans=False)
        chi2qvis_uncal = obs_uncal.chisq(im, dtype='vis', ttype='nfft',
                                         systematic_noise=sysnoise, pol='Q')
        chi2uvis_uncal = obs_uncal.chisq(im, dtype='vis', ttype='nfft',
                                         systematic_noise=sysnoise, pol='U')

        print("chi^2 m: %0.2f %0.2f" % (chi2m, chi2m_uncal))
        print("chi^2 pvis: %0.2f %0.2f" % (chi2pvis, chi2pvis_uncal))
        print("chi^2 qvis: %0.2f %0.2f" % (chi2qvis, chi2qvis_uncal))
        print("chi^2 uvis: %0.2f %0.2f" % (chi2uvis, chi2uvis_uncal))

        fs = int(1*fontsize)
        fs2 = int(.8*fontsize)
        ax.text(.05, .9, "Source:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .7, "MJD:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .5, "FREQ:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .3, "FOV:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.05, .1, "FLUX:", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.23, .9, "%s" % im.source, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .7, "%i" % im.mjd, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .5, "%0.0f GHz" % (im.rf/1.e9), fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .3, "%0.1f $\mu$as" % (im.fovx()/ehc.RADPERUAS), fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.23, .1, "%0.2f Jy" % flux, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.5, .9, "$\chi^2_{m}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .7, "$\chi^2_{P}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .5, "$\chi^2_{Q}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.5, .3, "$\chi^2_{U}$", fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.72, .9, "%0.2f" % chi2m, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .7, "%0.2f" % chi2pvis, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .5, "%0.2f" % chi2qvis, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.72, .3, "%0.2f" % chi2uvis, fontsize=fs,
                ha='left', va='center', transform=ax.transAxes)

        ax.text(.85, .9, "(%0.2f)" % chi2m_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .7, "(%0.2f)" % chi2pvis_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .5, "(%0.2f)" % chi2qvis_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)
        ax.text(.85, .3, "(%0.2f)" % chi2uvis_uncal, fontsize=fs2,
                ha='left', va='center', transform=ax.transAxes)

        ################################################################################
        # plot the D terms

        if dtermplots:
            print("===========================================")
            print("plotting d terms")
            ax = plt.subplot(gs[4:6, 2:5])

            if leakage_arr:
                obs_polcal = obs_uncal.copy()
                obs_polcal.tarr = leakage_arr.tarr
            else:
                obs_polcal = leakage_cal(obs_uncal, im, leakage_tol=1e6, ttype='nfft')

            ax = plot_leakage(obs_polcal, axis=ax, show=False,
                              rangex=[-20, 20], rangey=[-20, 20], markersize=5)

            print('saving pdf page 2')
            pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
            plt.close()

        # 3
        # baseline amplitude chi2
        fig = plt.figure(2, figsize=(18, 28), dpi=200)
        gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)

        print("===========================================")
        print("baseline m&p  chisq")

        bl_unpk = obs.unpack(['t1', 't2'])
        n_bl = len(bl_unpk)
        allbl = [(str(bl['t1']), str(bl['t2'])) for bl in bl_unpk]
        uniquebl = []
        for bl in allbl:
            if bl not in uniquebl:
                uniquebl.append(bl)

        # generate data
        obs_model = im.observe_same(obs, add_th_noise=False, ttype='nfft')

        # generate chi2 -- NO SYSTEMATIC NOISES
        bl_chisq_data_m = []
        bl_chisq_data_pvis = []
        bl_chisq_data_qvis = []
        bl_chisq_data_uvis = []

        for ii in range(0, len(uniquebl)):
            bl = uniquebl[ii]

            m_bl = obs.unpack_bl(bl[0], bl[1], ['m', 'msigma'], debias=False)
            pvis_bl = obs.unpack_bl(bl[0], bl[1], ['pvis', 'psigma'], debias=False)
            qvis_bl = obs.unpack_bl(bl[0], bl[1], ['qvis', 'qsigma'], debias=False)
            uvis_bl = obs.unpack_bl(bl[0], bl[1], ['uvis', 'usigma'], debias=False)

            if len(m_bl) > 0:

                m_bl_model = obs_model.unpack_bl(bl[0], bl[1], ['m', 'msigma'], debias=False)
                pvis_bl_model = obs_model.unpack_bl(bl[0], bl[1], ['pvis', 'psigma'], debias=False)
                qvis_bl_model = obs_model.unpack_bl(bl[0], bl[1], ['qvis', 'qsigma'], debias=False)
                uvis_bl_model = obs_model.unpack_bl(bl[0], bl[1], ['uvis', 'usigma'], debias=False)

                if snrcut_dict['m'] > 0:
                    amask = np.abs(m_bl['m'])/m_bl['msigma'] > snrcut_dict['m']
                    m_bl = m_bl[amask]
                    m_bl_model = m_bl_model[amask]
                if snrcut_dict['pvis'] > 0:
                    amask = np.abs(pvis_bl['pvis'])/pvis_bl['psigma'] > snrcut_dict['pvis']
                    pvis_bl = pvis_bl[amask]
                    pvis_bl_model = pvis_bl_model[amask]
                if snrcut_dict['qvis'] > 0:
                    amask = np.abs(qvis_bl['qvis'])/qvis_bl['qsigma'] > snrcut_dict['qvis']
                    qvis_bl = qvis_bl[amask]
                    qvis_bl_model = qvis_bl_model[amask]
                if snrcut_dict['uvis'] > 0:
                    amask = np.abs(uvis_bl['uvis'])/uvis_bl['usigma'] > snrcut_dict['uvis']
                    uvis_bl = uvis_bl[amask]
                    uvis_bl_model = uvis_bl_model[amask]

                chisq_m_bl = np.sum(np.abs((m_bl['m'] - m_bl_model['m'])/m_bl['msigma'])**2)
                npts_m = len(m_bl_model)
                data_m = (bl[0], bl[1], npts_m, chisq_m_bl)
                bl_chisq_data_m.append(data_m)

                chisq_pvis_bl = np.sum(
                    np.abs((pvis_bl['pvis'] - pvis_bl_model['pvis'])/pvis_bl['psigma'])**2)
                npts_pvis = len(pvis_bl_model)
                data_pvis = (bl[0], bl[1], npts_pvis, chisq_pvis_bl)
                bl_chisq_data_pvis.append(data_pvis)

                chisq_qvis_bl = np.sum(
                    np.abs((qvis_bl['qvis'] - qvis_bl_model['qvis'])/qvis_bl['qsigma'])**2)
                npts_qvis = len(qvis_bl_model)
                data_qvis = (bl[0], bl[1], npts_qvis, chisq_qvis_bl)
                bl_chisq_data_qvis.append(data_qvis)

                chisq_uvis_bl = np.sum(
                    np.abs((uvis_bl['uvis'] - uvis_bl_model['uvis'])/uvis_bl['usigma'])**2)
                npts_uvis = len(uvis_bl_model)
                data_uvis = (bl[0], bl[1], npts_uvis, chisq_uvis_bl)
                bl_chisq_data_uvis.append(data_uvis)

        # sort by decreasing chi^2
        idx_m = np.argsort([data[-1] for data in bl_chisq_data_m])
        idx_m = list(reversed(idx_m))
        idx_p = np.argsort([data[-1] for data in bl_chisq_data_pvis])
        idx_p = list(reversed(idx_p))
        idx_q = np.argsort([data[-1] for data in bl_chisq_data_qvis])
        idx_q = list(reversed(idx_q))
        idx_u = np.argsort([data[-1] for data in bl_chisq_data_uvis])
        idx_u = list(reversed(idx_u))

        chisqtab_m = (r"\begin{tabular}{ l|l|l|l } \hline Baseline & $N_{m}$ & " +
                      r"$\chi^2_{m}/N_{m}$ & $\chi^2_{m}/N_{total}$ \\ " +
                      r"\hline \hline")
        chisqtab_p = (r"\begin{tabular}{ l|l|l|l } \hline Baseline & $N_{p}$ & " +
                      r"$\chi^2_{p}/N_{p}$ & $\chi^2_{p}/N_{total}$ \\ " +
                      r"\hline \hline")
        chisqtab_q = (r"\begin{tabular}{ l|l|l|l } \hline Baseline & $N_{Q}$ & " +
                      r"$\chi^2_{Q}/N_{Q}$ & $\chi^2_{Q}/N_{total}$ \\ " +
                      r"\hline \hline")
        chisqtab_u = (r"\begin{tabular}{ l|l|l|l } \hline Baseline & $N_{U}$ & " +
                      r"$\chi^2_{U}/N_{U}$ & $\chi^2_{U}/N_{total}$ \\ " +
                      r"\hline \hline")

        for i in range(len(bl_chisq_data_m)):
            if i > 45:
                break
            data = bl_chisq_data_m[idx_m[i]]
            tristr = r"%s-%s" % (data[0], data[1])
            nstr = r"%i" % data[2]
            chisqstr = r"%0.1f" % data[3]
            rchisqstr = r"%0.1f" % (data[3]/float(data[2]))
            rrchisqstr = r"%0.3f" % (data[3]/float(n_bl))
            if i == 0:
                chisqtab_m += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab_m += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
        for i in range(len(bl_chisq_data_pvis)):
            if i > 45:
                break
            data = bl_chisq_data_pvis[idx_p[i]]
            tristr = r"%s-%s" % (data[0], data[1])
            nstr = r"%i" % data[2]
            rchisqstr = r"%0.1f" % (data[3]/float(data[2]))
            rrchisqstr = r"%0.3f" % (data[3]/float(n_bl))
            if i == 0:
                chisqtab_p += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab_p += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
        for i in range(len(bl_chisq_data_qvis)):
            if i > 45:
                break
            data = bl_chisq_data_qvis[idx_q[i]]
            tristr = r"%s-%s" % (data[0], data[1])
            nstr = r"%i" % data[2]
            rchisqstr = r"%0.1f" % (data[3]/float(data[2]))
            rrchisqstr = r"%0.3f" % (data[3]/float(n_bl))
            if i == 0:
                chisqtab_q += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab_q += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
        for i in range(len(bl_chisq_data_uvis)):
            if i > 45:
                break
            data = bl_chisq_data_qvis[idx_u[i]]
            tristr = r"%s-%s" % (data[0], data[1])
            nstr = r"%i" % data[2]
            rchisqstr = r"%0.1f" % (data[3]/float(data[2]))
            rrchisqstr = r"%0.3f" % (data[3]/float(n_bl))
            if i == 0:
                chisqtab_u += r" " + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr
            else:
                chisqtab_u += r" \\" + tristr + " & " + nstr + " & " + rchisqstr + " & " + rrchisqstr

        chisqtab_m += r" \end{tabular}"
        chisqtab_p += r" \end{tabular}"
        chisqtab_q += r" \end{tabular}"
        chisqtab_u += r" \end{tabular}"

        ax = plt.subplot(gs[0:3, 0:2])
        ax.set_title('baseline m statistics')
        ax.set_yticks([])
        ax.set_xticks([])
        ax.text(0.5, .975, chisqtab_m, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        ax = plt.subplot(gs[0:3, 2:5])
        ax.set_title('baseline P statistics')
        ax.set_yticks([])
        ax.set_xticks([])
        ax.text(0.5, .975, chisqtab_p, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        ax = plt.subplot(gs[3:6, 0:2])
        ax.set_title('baseline Q statistics')
        ax.set_yticks([])
        ax.set_xticks([])
        ax.text(0.5, .975, chisqtab_q, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        ax = plt.subplot(gs[3:6, 2:5])
        ax.set_title('baseline U statistics')
        ax.set_yticks([])
        ax.set_xticks([])
        ax.text(0.5, .975, chisqtab_u, ha="center", va="top", transform=ax.transAxes, size=fontsize)

        # save the first page of the plot
        print('saving pdf page 3')
        pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
        plt.close()

        ################################################################################
        # plot the baseline pol amps and  phases
        page = 4
        if mplots:
            print("===========================================")
            print("plotting fractional polarizatons")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Fractional  Polarization Plots", y=.9,
                         va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0

            obs_model.data['sigma'] *= 0
            obs_model.data['qsigma'] *= 0
            obs_model.data['usigma'] *= 0
            obs_model.data['vsigma'] *= 0

            amax = 1.1*np.max(np.abs(np.abs(obs_model.unpack(['mamp'])['mamp'])))
            obs_all = [obs, obs_model]
            for nbl, bl in enumerate(uniquebl):
                j = 0
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'mamp', rangey=[0, amax],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['m'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                ax.set_xlabel('')
                j = 1
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'mphase', rangey=[-180, 180],

                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['m'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                i += 1
                ax.set_xlabel('')

                if ax is None:
                    continue

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0

                if nbl == len(uniquebl):
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()

        if pplots:
            print("===========================================")
            print("plotting total polarizaton")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Total  Polarization Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0

            obs_model.data['sigma'] *= 0
            obs_model.data['qsigma'] *= 0
            obs_model.data['usigma'] *= 0
            obs_model.data['vsigma'] *= 0

            amax = 1.1*np.max(np.abs(np.abs(obs_model.unpack(['pamp'])['pamp'])))
            obs_all = [obs, obs_model]
            for nbl, bl in enumerate(uniquebl):
                j = 0
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'pamp', rangey=[0, amax],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['pvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                ax.set_xlabel('')
                j = 1
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'pphase', rangey=[-180, 180],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['pvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                i += 1
                ax.set_xlabel('')

                if ax is None:
                    continue

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0

                if nbl == len(uniquebl):
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()

        if qplots:
            print("===========================================")
            print("plotting Q fit")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("Q Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0

            obs_model.data['sigma'] *= 0
            obs_model.data['qsigma'] *= 0
            obs_model.data['usigma'] *= 0
            obs_model.data['vsigma'] *= 0

            amax = 1.1*np.max(np.abs(np.abs(obs_model.unpack(['qamp'])['qamp'])))
            obs_all = [obs, obs_model]
            for nbl, bl in enumerate(uniquebl):
                j = 0
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'qamp', rangey=[0, amax],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['qvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                ax.set_xlabel('')
                j = 1
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'qphase', rangey=[-180, 180],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['qvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                i += 1
                ax.set_xlabel('')

                if ax is None:
                    continue

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0

                if nbl == len(uniquebl):
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()

        if uplots:
            print("===========================================")
            print("plotting U fit")
            fig = plt.figure(3, figsize=(18, 28), dpi=200)
            plt.suptitle("U Plots", y=.9, va='center', fontsize=int(1.2*fontsize))
            gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
            i = 0
            j = 0

            obs_model.data['sigma'] *= 0
            obs_model.data['qsigma'] *= 0
            obs_model.data['usigma'] *= 0
            obs_model.data['vsigma'] *= 0

            amax = 1.1*np.max(np.abs(np.abs(obs_model.unpack(['uamp'])['uamp'])))
            obs_all = [obs, obs_model]
            for nbl, bl in enumerate(uniquebl):
                j = 0
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'uamp', rangey=[0, amax],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['uvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                ax.set_xlabel('')
                j = 1
                ax = plt.subplot(gs[2*i:2*(i+1), 2*j:2*(j+1)])
                ax = plot_bl_obs_compare(obs_all, bl[0], bl[1], 'uphase', rangey=[-180, 180],
                                         markersize=MARKERSIZE, debias=False,
                                         snrcut=snrcut_dict['uvis'],
                                         axis=ax, legend=False, clist=['k', ehc.SCOLORS[1]],
                                         ttype='nfft', show=False, ebar=ebar)
                i += 1
                ax.set_xlabel('')

                if ax is None:
                    continue

                if i == 3:
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()
                    fig = plt.figure(3, figsize=(18, 28), dpi=200)
                    gs = gridspec.GridSpec(6, 4, wspace=WSPACE, hspace=HSPACE)
                    i = 0
                    j = 0

                if nbl == len(uniquebl):
                    print('saving pdf page %i' % page)
                    page += 1
                    pdf.savefig(pad_inches=MARGINS, bbox_inches='tight')
                    plt.close()


def _display_img(im, beamparams=None, scale='linear', gamma=0.5, cbar_lims=False,
                 has_cbar=True, has_title=True, cfun='afmhot', dynamic_range=100,
                 axis=False, show=False, fontsize=FONTSIZE):
    """display the figure on a given axis
       cannot use im.display because  it makes a new figure
    """

    interp = 'gaussian'

    if axis:
        ax = axis
    else:
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)

    imvec = np.array(im.imvec).reshape(-1)
    # flux unit is mJy/uas^2
    imvec = imvec * 1.e3
    fovfactor = im.xdim*im.psize*(1/ehc.RADPERUAS)
    factor = (1./fovfactor)**2 / (1./im.xdim)**2
    imvec = imvec * factor

    imarr = (imvec).reshape(im.ydim, im.xdim)
    unit = 'mJy/$\mu$ as$^2$'
    if scale == 'log':
        if (imarr < 0.0).any():
            print('clipping values less than 0')
            imarr[imarr < 0.0] = 0.0
        imarr = np.log(imarr + np.max(imarr)/dynamic_range)
        unit = 'log(' + unit + ')'

    if scale == 'gamma':
        if (imarr < 0.0).any():
            print('clipping values less than 0')
            imarr[imarr < 0.0] = 0.0
        imarr = (imarr + np.max(imarr)/dynamic_range)**(gamma)
        unit = '(' + unit + ')^gamma'

    if cbar_lims:
        imarr[imarr > cbar_lims[1]] = cbar_lims[1]
        imarr[imarr < cbar_lims[0]] = cbar_lims[0]

    if cbar_lims:
        ax = ax.imshow(imarr, cmap=plt.get_cmap(cfun), interpolation=interp,
                       vmin=cbar_lims[0], vmax=cbar_lims[1])
    else:
        ax = ax.imshow(imarr, cmap=plt.get_cmap(cfun), interpolation=interp)

    if has_cbar:
        cbar = plt.colorbar(ax, fraction=0.046, pad=0.04, format='%1.2g')
        cbar.set_label(unit, fontsize=fontsize)
        cbar.ax.xaxis.set_label_position('top')
        cbar.ax.tick_params(labelsize=16)
        if cbar_lims:
            plt.clim(cbar_lims[0], cbar_lims[1])

    if not(beamparams is None):
        beamparams = [beamparams[0], beamparams[1], beamparams[2],
                      -.35*im.fovx(), -.35*im.fovy()]
        beamimage = im.copy()
        beamimage.imvec *= 0
        beamimage = beamimage.add_gauss(1, beamparams)
        halflevel = 0.5*np.max(beamimage.imvec)
        beamimarr = (beamimage.imvec).reshape(beamimage.ydim, beamimage.xdim)
        plt.contour(beamimarr, levels=[halflevel], colors='w', linewidths=3)
        ax = plt.gca()

    plt.axis('off')
    fov_uas = im.xdim * im.psize / ehc.RADPERUAS  # get the fov in uas
    roughfactor = 1./3.  # make the bar about 1/3 the fov
    fov_scale = 40
    start = im.xdim * roughfactor / 3.0  # select the start location
    end = start + fov_scale/fov_uas * im.xdim  # determine the end location
    plt.plot([start, end], [im.ydim-start, im.ydim-start], color="white", lw=1)  # plot line
    plt.text(x=(start+end)/2.0, y=im.ydim-start-im.ydim/20, s=str(fov_scale) + " $\mu$as",
             color="white", ha="center", va="center",
             fontsize=int(1.2*fontsize), fontweight='bold')

    ax.axes.get_xaxis().set_visible(False)
    ax.axes.get_yaxis().set_visible(False)

    if show:
        #plt.show(block=False)
        ehc.show_noblock()

    return ax


def _display_img_pol(im, beamparams=None, scale='linear', gamma=0.5, cbar_lims=False,
                     has_cbar=True, has_title=True, cfun='afmhot', pol=None, polticks=False,
                     nvec=False, pcut=0.1,  mcut=0.01, contour=False, dynamic_range=100,
                     axis=False, show=False, fontsize=FONTSIZE):
    """display the polarimetric figure on a given axis
       cannot use im.display because  it makes a new figure
    """

    interp = 'gaussian'

    if axis:
        ax = axis
    else:
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)

    if pol == 'm':
        imvec = im.mvec
        unit = r'$|\breve{m}|$'
        factor = 1
        cbar_lims = [0, 1]
    elif pol == 'chi':
        imvec = im.chivec / ehc.DEGREE
        unit = r'$\chi (^\circ)$'
        factor = 1
        cbar_lims = [0, 180]
    else:
        # flux unit is Tb
        factor = 3.254e13/(im.rf**2 * im.psize**2)
        unit = 'Tb (K)'
        try:
            imvec = np.array(im._imdict[pol]).reshape(-1)
        except KeyError:
            try:
                if im.polrep == 'stokes':
                    im2 = im.switch_polrep('circ')
                elif im.polrep == 'circ':
                    im2 = im.switch_polrep('stokes')
                imvec = np.array(im2._imdict[pol]).reshape(-1)
            except KeyError:
                raise Exception("Cannot make pol %s image in display()!" % pol)

    # flux unit is Tb
    imvec = imvec * factor
    imarr = (imvec).reshape(im.ydim, im.xdim)

    if scale == 'log':
        if (imarr < 0.0).any():
            print('clipping values less than 0')
            imarr[imarr < 0.0] = 0.0
        imarr = np.log(imarr + np.max(imarr)/dynamic_range)
        unit = 'log(' + unit + ')'

    if scale == 'gamma':
        if (imarr < 0.0).any():
            print('clipping values less than 0')
            imarr[imarr < 0.0] = 0.0
        imarr = (imarr + np.max(imarr)/dynamic_range)**(gamma)
        unit = '(' + unit + ')^gamma'

    if cbar_lims:
        imarr[imarr > cbar_lims[1]] = cbar_lims[1]
        imarr[imarr < cbar_lims[0]] = cbar_lims[0]

    if cbar_lims:
        ax = ax.imshow(imarr, cmap=plt.get_cmap(cfun), interpolation=interp,
                       vmin=cbar_lims[0], vmax=cbar_lims[1])
    else:
        ax = ax.imshow(imarr, cmap=plt.get_cmap(cfun), interpolation=interp)

    if contour:
        plt.contour(imarr, colors='k', linewidths=.25)

    if polticks:
        im_stokes = im.switch_polrep(polrep_out='stokes')
        ivec = np.array(im_stokes.imvec).reshape(-1)
        qvec = np.array(im_stokes.qvec).reshape(-1)
        uvec = np.array(im_stokes.uvec).reshape(-1)
        vvec = np.array(im_stokes.vvec).reshape(-1)

        if len(ivec) == 0:
            ivec = np.zeros(im_stokes.ydim*im_stokes.xdim)
        if len(qvec) == 0:
            qvec = np.zeros(im_stokes.ydim*im_stokes.xdim)
        if len(uvec) == 0:
            uvec = np.zeros(im_stokes.ydim*im_stokes.xdim)
        if len(vvec) == 0:
            vvec = np.zeros(im_stokes.ydim*im_stokes.xdim)

        if not nvec:
            nvec = im.xdim // 2

        thin = im.xdim//nvec
        maska = (ivec).reshape(im.ydim, im.xdim) > pcut * np.max(ivec)
        maskb = (np.abs(qvec + 1j*uvec)/ivec).reshape(im.ydim, im.xdim) > mcut
        mask = maska * maskb
        mask2 = mask[::thin, ::thin]
        x = (np.array([[i for i in range(im.xdim)] for j in range(im.ydim)])[::thin, ::thin])
        x = x[mask2]
        y = (np.array([[j for i in range(im.xdim)] for j in range(im.ydim)])[::thin, ::thin])
        y = y[mask2]
        a = (-np.sin(np.angle(qvec+1j*uvec)/2).reshape(im.ydim, im.xdim)[::thin, ::thin])
        a = a[mask2]
        b = (np.cos(np.angle(qvec+1j*uvec)/2).reshape(im.ydim, im.xdim)[::thin, ::thin])
        b = b[mask2]

        plt.quiver(x, y, a, b,
                   headaxislength=20, headwidth=1, headlength=.01, minlength=0, minshaft=1,
                   width=.01*im.xdim, units='x', pivot='mid', color='k', angles='uv',
                   scale=1.0/thin)
        plt.quiver(x, y, a, b,
                   headaxislength=20, headwidth=1, headlength=.01, minlength=0, minshaft=1,
                   width=.005*im.xdim, units='x', pivot='mid', color='w', angles='uv',
                   scale=1.1/thin)

    if has_cbar:
        cbar = plt.colorbar(ax, fraction=0.046, pad=0.04, format='%1.2g')
        cbar.set_label(unit, fontsize=fontsize)
        cbar.ax.xaxis.set_label_position('top')
        cbar.ax.tick_params(labelsize=16)
        if cbar_lims:
            ax.set_clim(cbar_lims[0], cbar_lims[1])

    if not(beamparams is None):
        beamparams = [beamparams[0], beamparams[1], beamparams[2],
                      -.35*im.fovx(), -.35*im.fovy()]
        beamimage = im.copy()
        beamimage.imvec *= 0
        beamimage = beamimage.add_gauss(1, beamparams)
        halflevel = 0.5*np.max(beamimage.imvec)
        beamimarr = (beamimage.imvec).reshape(beamimage.ydim, beamimage.xdim)
        plt.contour(beamimarr, levels=[halflevel], colors='w', linewidths=3)
        ax = plt.gca()

    plt.axis('off')
    if has_cbar:
        fov_uas = im.xdim * im.psize / ehc.RADPERUAS  # get the fov in uas
        roughfactor = 1./3.  # make the bar about 1/3 the fov
        fov_scale = 40
        # round around 1/3 the fov to nearest 10
        start = im.xdim * roughfactor / 3.0  # select the start location
        end = start + fov_scale/fov_uas * im.xdim
        # determine the end location based on the size of the bar
        plt.plot([start, end], [im.ydim-start, im.ydim-start], color="white", lw=1)  # plot line
        plt.text(x=(start+end)/2.0, y=im.ydim-start-im.ydim/20, s=str(fov_scale) + " $\mu$as",
                 color="white", ha="center", va="center",
                 fontsize=int(1.2*fontsize), fontweight='bold')

    ax.axes.get_xaxis().set_visible(False)
    ax.axes.get_yaxis().set_visible(False)

    if show:
        #plt.show(block=False)
        ehc.show_noblock()

    return ax
