def plot_height_profiles():
	"""
	Plot the bilayer height profile with protein positions.
	"""
	#---one plot per simulation
	for sn in work.sns():
		mesh = data[sn]['data']['mesh']
		surf = mesh.mean(axis=0).mean(axis=0)
		surf -= surf.mean()
		hmax = np.abs(surf).max()
		fig = plt.figure()
		ax = fig.add_subplot(111)
		vecs = data[sn]['data']['vecs'].mean(axis=0)
		im = ax.imshow(surf.T,origin='lower',
			interpolation='nearest',cmap=mpl.cm.__dict__['RdBu_r'],
			extent=[0,vecs[0],0,vecs[1]],vmax=hmax,vmin=-1*hmax)
		#---! add a check for whether we have proteins or not
		if sn in data_prot:
			from render.wavevids import plothull
			points_all = data_prot[sn]['data']['points_all'] 
			points_all_mean_time = points_all.mean(axis=0)
			plothull(ax,points_all_mean_time[...,:2],griddims=surf.shape,vecs=vecs,c='k',lw=0)	
		from mpl_toolkits.axes_grid1.inset_locator import inset_axes
		axins = inset_axes(ax,width="5%",height="100%",loc=3,
			bbox_to_anchor=(1.05,0.,1.,1.),bbox_transform=ax.transAxes,borderpad=0)
		cbar = plt.colorbar(im,cax=axins,orientation="vertical")
		cbar.set_label(r"$\mathrm{\langle z \rangle (nm)}$",labelpad=-40,y=1.05,rotation=0)
		axins.tick_params(axis='y',which='both',left='off',right='off',labelright='on')
		ax.set_title('average bilayer height')
		ax.set_xlabel('x (nm)')
		ax.set_ylabel('y (nm)')
		ax.tick_params(axis='y',which='both',left='off',right='off',labelleft='on')
		ax.tick_params(axis='x',which='both',top='off',bottom='off',labelbottom='on')
		picturesave('fig.height_average.%s'%sn,work.plotdir,backup=False,version=True,meta={})
def plot_hull_and_trial_centers(data,
                                sn,
                                ax,
                                n_instances=None,
                                debug_frame=0,
                                color=None):
    """Plot the protein hull along with the positions of the trial functions."""
    global postdat
    #---! currently only set for a single protein
    trials = data[sn]['drop_gaussians_points'].transpose(1, 0, 2)
    nframes = len(trials)
    if n_instances != None:
        samples = np.arange(0, nframes, nframes / n_instances)
    else:
        samples = np.array([debug_frame])
    pts = np.concatenate(trials[samples])
    for ptsnum, pts in enumerate(trials[samples]):
        color_this = mpl.cm.__dict__['jet'](
            float(ptsnum) / len(samples)) if not color else color
        ax.scatter(*pts.T, s=1, c=color_this)
    griddims = data[sn]['cf'].shape
    vecs, points_protein = [postdat[sn][i] for i in ['vecs', 'points_protein']]
    for ptsnum, pts in enumerate(points_protein[samples][..., :2]):
        color_this = mpl.cm.__dict__['jet'](
            float(ptsnum) / len(samples)) if not color else color
        plothull(ax, pts, griddims=griddims, vecs=vecs, lw=0, c=color_this)
    ax.set_xlim((0, vecs[0]))
    ax.set_ylim((0, vecs[1]))
    ax.set_aspect(1.0)
def plothull_protein_center_average(ax, sn, vecs, tag):
    """Plot the protein hull in the center of the box."""
    dat_protein = data[protein_abstractor_name][sn]['data']
    protein_noh = np.array([
        ii for ii, i in enumerate(dat_protein['names'])
        if not re.match('^H', i)
    ])
    protein_pts = dat_protein['points_all']
    if protein_pts.shape[1] != 1:
        raise Exception('cannot center multiple proteins!')
    mean_prot_pts = protein_pts[:, 0].mean(axis=0)[:, :2]
    prot_center = mean_prot_pts - mean_prot_pts.mean(axis=0) + vecs[:2] / 2.
    plothull(ax, [prot_center],
             griddims=datas[tag][sn]['cf'].shape,
             vecs=vecs,
             c='k',
             lw=0)
def render_hydrogen_bonding_pattern(fr, frameno):
    """..."""
    #status('drawing for %s'%sn,i=fr,looplen=nframes,tag='render')
    #---copy points so that we can smooth the points in the box
    points = np.array(lipid_mesh['%d.%d.points' % (top_mono, fr)])
    if smooth_window: points[:nmol] = points_inside_smooth[fr]
    ax = plt.subplot(111)
    vec = dat_lipids['vecs'][fr]
    #---get the hydrogen bonds for this plot
    resname_inds = np.array([
        bond_spec_keys.split().index(j)
        for j in ['resid_%d' % i for i in [1, 2]]
    ])
    #---use frameno here because obs is over valid_frames only
    bonds_this_all = bonds[np.where(obs[frameno])[0]][:,
                                                      resname_inds].astype(int)
    #---filter out intramolecular hyrogen bonds
    bonds_this = bonds_this_all[np.where(
        bonds_this_all[:, 0] != bonds_this_all[:, 1])[0]]
    #---! note no check for resname type
    #---get bonds that are in the mesh
    bonds_this_valid = np.where(
        [np.all([np.in1d(i, r2m.keys()) for i in b]) for b in bonds_this])[0]
    ghosts = lipid_mesh['%d.%d.ghost_ids' % (top_mono, fr)]
    #---draw a line for each bond
    for lnum, link_resids in enumerate(bonds_this[bonds_this_valid]):
        verts = np.array([r2m[j] for j in link_resids])
        points_this = points[verts, :2]
        if not np.any(points_this.ptp(axis=0) >= vec[:2] / 2.):
            ax.plot(*points_this.T, c='k', lw=1, zorder=2)
        else:
            targs = np.where(np.in1d(ghosts, verts))[0]
            for target in targs:
                for urp in link_resids:
                    possible_long_bond = np.array([target, r2m[urp]])
                    try:
                        if not np.any((points[possible_long_bond].ptp(axis=0)
                                       >= vec / 2.)[:2]):
                            ax.plot(*points[possible_long_bond][:, :2].T,
                                    c='k',
                                    lw=1,
                                    zorder=2)
                    except:
                        pass
    #---formulate the color list
    colors = np.array(
        [colorize(work.meta[sn], resname=r) for r in resnames_all[ghosts]])
    #---stray dots are transparent
    ax.scatter(*points[:, :2].T,
               s=dot_size_small,
               color=colors,
               alpha=0.35,
               zorder=3,
               lw=0)
    #---active dots have color
    highlit = np.array(
        [r2m[j] for j in np.unique(bonds_this[bonds_this_valid])])
    #---note that only the non-ghost points can be highlit so the color list below is complete
    if highlit.max() >= m2r.shape[0]:
        raise Exception('some highlit points are not in the mesh keys!')
    ax.scatter(
        *points[highlit, :2].T,
        lw=0.25,
        s=dot_size_small,
        zorder=4,
        edgecolor='k',
        c=[colorize(work.meta[sn], resname=r) for r in resnames_all[highlit]])
    #---highlight the PIP2
    highlit_pip2 = np.where(
        np.in1d(resnames_all[highlit],
                work.vars['selectors']['resnames_PIP2'] + ['PtdIns']))[0]
    ax.scatter(*points[highlit[highlit_pip2], :2].T,
               lw=0.25,
               s=dot_size_large,
               zorder=5,
               edgecolor='k',
               c=[
                   colorize(work.meta[sn], resname=r)
                   for r in resnames_all[highlit[highlit_pip2]]
               ])
    #---show protein hull if necessary
    if show_proteins:
        plothull(ax, [data_prot[sn]['data']['points'][fr][:, :2]],
                 vecs=data_prot[sn]['data']['vecs'][fr],
                 griddims=None,
                 fill=True,
                 lw=0,
                 alpha=0.35,
                 c='k')
    #---plot a box
    lims_prop = 0.1
    ax.set_xlim((vec[0] * -lims_prop, vec[0] * (1. + lims_prop)))
    ax.set_ylim((vec[1] * -lims_prop, vec[1] * (1. + lims_prop)))
    box_prop = (lims_prop * 2 + 1.0) / lims_prop
    ax.axhline(0,
               xmin=1. / box_prop,
               xmax=(box_prop - 1.0) / box_prop,
               c='k',
               lw=1)
    ax.axhline(vec[1],
               xmin=1. / box_prop,
               xmax=(box_prop - 1.0) / (box_prop),
               c='k',
               lw=1)
    ax.axvline(0,
               ymin=1. / box_prop,
               ymax=(box_prop - 1.0) / (box_prop),
               c='k',
               lw=1)
    ax.axvline(vec[0],
               ymin=1. / box_prop,
               ymax=(box_prop - 1.0) / (box_prop),
               c='k',
               lw=1)
    ax.set_aspect('equal')
    ax.set_xticks([])
    ax.set_yticks([])
    ax.tick_params(axis=u'both', which=u'both', length=0)
    ax.axis('off')
    picturesave('snap.%05d' % frameno,
                out_dn,
                backup=False,
                version=True,
                meta={},
                extras=[],
                loud=False)
def plot_curvature(sn, **kwargs):
    """
	Plot a map of the curvature.
	"""
    global curvs_map_all
    dat = data[sn]['data']
    nframes = int(dat['nframes'])

    def get(mn, fr, name):
        return dat['%d.%d.%s' % (mn, fr, name)]

    spacing = kwargs.pop('spacing', 1.0)
    if kwargs: raise Exception('unprocessed kwargs %s' % kwargs)
    mvecs = np.mean([get(0, fr, 'vec') for fr in range(nframes)], axis=0)
    ngrid = np.round(mvecs / spacing).astype(int)
    #---curvature of each leaflet
    curvs_map_all = [np.zeros((ngrid[0], ngrid[1])) for mn in range(2)]
    for mn in range(2):
        curvs = np.zeros((ngrid[0], ngrid[1]))
        curvs_counts = np.zeros((ngrid[0], ngrid[1]))
        nmol = int(dat['%d.1.nmol' % mn])
        for fr in range(nframes):
            simps = get(mn, fr, 'simplices')
            pts = get(mn, fr, 'points')
            vec = get(mn, fr, 'vec')
            curv = get(mn, fr, 'mean')
            #---repack the points in the box
            pts_repack = (pts - np.floor(pts / vec) * vec)
            pts_rounded = (pts_repack / (vec / ngrid)).astype(int)[:, :2]
            curvs[pts_rounded[:nmol, 0], pts_rounded[:nmol, 1]] += curv[:nmol]
            curvs_counts[pts_rounded[:nmol, 0], pts_rounded[:nmol, 1]] += 1
        obs = np.where(curvs_counts > 0)
        means = curvs[obs] / curvs_counts[obs]
        curvs_map_all[mn][obs] = means

    from mpl_toolkits.axes_grid1.inset_locator import inset_axes
    import scipy
    import scipy.ndimage

    #---average the leaflets
    curvs_map = np.mean(curvs_map_all, axis=0)
    #---! removed the following line which sets nan (white on imshow). not sure what it is for
    #---ironically back to nan for the imshow
    if False: curvs_map[np.where(curvs_counts == 0)] = np.nan
    #---! it might be nice to smooth the plots but beware!
    if False:
        curvs_map = scipy.ndimage.gaussian_filter(curvs_map,
                                                  sigma=(4, 4),
                                                  order=0)
    vmax = max([abs(j) for j in [curvs_map.max(), curvs_map.min()]])
    ax = plt.gca()
    im = ax.imshow(curvs_map,
                   cmap=mpl.cm.RdBu_r,
                   vmax=vmax,
                   vmin=-1 * vmax,
                   origin='lower',
                   extent=[0, mvecs[0], 0, mvecs[1]])
    axins = inset_axes(ax,
                       width="5%",
                       height="100%",
                       loc=3,
                       bbox_to_anchor=(1.05, 0., 1., 1.),
                       bbox_transform=ax.transAxes,
                       borderpad=0)
    cbar = plt.colorbar(im, cax=axins, orientation="vertical")
    cbar.set_label(r'$C_0\,({nm}^{-1})$', labelpad=-40, y=1.05, rotation=0)
    ax.set_xlabel('x (nm)')
    ax.set_ylabel('y (nm)')
    ax.tick_params(axis='y',
                   which='both',
                   left='off',
                   right='off',
                   labelleft='on')
    ax.tick_params(axis='x',
                   which='both',
                   top='off',
                   bottom='off',
                   labelbottom='on')
    axins.tick_params(axis='y',
                      which='both',
                      left='off',
                      right='off',
                      labelright='on')
    ax.set_title('curvature map')
    if sn in data_prot:
        from render.wavevids import plothull
        points_all = data_prot[sn]['data']['points_all']
        points_all_mean_time = points_all.mean(axis=0)
        plothull(ax,
                 points_all_mean_time[..., :2],
                 griddims=curvs_map.shape,
                 vecs=mvecs,
                 c='k',
                 lw=0)
    picturesave('fig.%s.%s' % ('curvature', sn),
                work.plotdir,
                backup=False,
                version=True,
                meta={})
    plt.close()
def plot_curvature_basic(sn, **kwargs):
    """
	Plot a map of the curvature.
	Note: you must use a bin spacing of 2.0 or 5.0 and not 0.5 otherwise the curvature ends up biased 
	very strongly in one direction (this is a methodology error of some kind, related to binnning.)
	A Gaussian blur is necessary to get usable information from the map, however this washes out the 
	curvature magnitudes leaving only a relative pattern.
	"""
    dat = data[sn]['data']
    nframes = int(dat['nframes'])

    def get(mn, fr, name):
        return dat['%d.%d.%s' % (mn, fr, name)]

    spacing = kwargs.pop('spacing', 2.0)
    sigma = kwargs.pop('blur', 0.0)
    if kwargs: raise Exception('unprocessed kwargs %s' % kwargs)
    mvecs = np.mean([get(0, fr, 'vec') for fr in range(nframes)], axis=0)
    ngrid = np.round(mvecs / spacing).astype(int)
    #---curvature of each leaflet
    curvs_mean_all = []
    curvs_map_all = [np.zeros((ngrid[0], ngrid[1])) for mn in range(2)]
    for mn in range(2)[::-1]:
        curvs = np.zeros((ngrid[0], ngrid[1]))
        curvs_counts = np.zeros((ngrid[0], ngrid[1]))
        nmol = int(dat['%d.1.nmol' % mn])
        curvs_mean = []
        for fr in range(nframes):
            simps = get(mn, fr, 'simplices')
            pts = get(mn, fr, 'points')
            vec = get(mn, fr, 'vec')
            curv = get(mn, fr, 'mean')
            #---previously implemented a filter
            if False:
                filt = np.where(np.abs(curv) < 0.5)
                pts, curv = pts[filt], curv[filt]
            #---repack the points in the box
            pts_repack = (pts - np.floor(pts / vec) * vec)
            pts_rounded = (pts_repack / (vec / ngrid)).astype(int)[:, :2]
            curvs[pts_rounded[:nmol, 0], pts_rounded[:nmol, 1]] += curv[:nmol]
            curvs_mean.append(curv[:nmol].mean())
            curvs_counts[pts_rounded[:nmol, 0], pts_rounded[:nmol, 1]] += 1
        curvs_mean_all.append(curvs_mean)
        obs = np.where(curvs_counts > 0)
        means = curvs[obs] / curvs_counts[obs]
        curvs_map_all[mn][obs] = means
    #---average the leaflets
    curvs_map = np.mean(curvs_map_all, axis=0)
    #---! removed the following line which sets nan (white on imshow). not sure what it is for
    #---ironically back to nan for the imshow
    if False: curvs_map[np.where(curvs_counts == 0)] = np.nan
    #---! it might be nice to smooth the plots but beware!
    if True:
        curvs_map = scipy.ndimage.gaussian_filter(curvs_map,
                                                  sigma=(sigma, sigma),
                                                  order=0)
    vmax = max([abs(j) for j in [curvs_map.max(), curvs_map.min()]])
    ax = plt.gca()
    im = ax.imshow(curvs_map,
                   cmap=mpl.cm.RdBu_r,
                   vmax=vmax,
                   vmin=-1 * vmax,
                   origin='lower',
                   extent=[0, mvecs[0], 0, mvecs[1]])
    axins = inset_axes(ax,
                       width="5%",
                       height="100%",
                       loc=3,
                       bbox_to_anchor=(1.05, 0., 1., 1.),
                       bbox_transform=ax.transAxes,
                       borderpad=0)
    cbar = plt.colorbar(im, cax=axins, orientation="vertical")
    cbar.set_label(r'$C_0\,({nm}^{-1})$', labelpad=-40, y=1.05, rotation=0)
    ax.set_xlabel('x (nm)')
    ax.set_ylabel('y (nm)')
    ax.tick_params(axis='y',
                   which='both',
                   left='off',
                   right='off',
                   labelleft='on')
    ax.tick_params(axis='x',
                   which='both',
                   top='off',
                   bottom='off',
                   labelbottom='on')
    axins.tick_params(axis='y',
                      which='both',
                      left='off',
                      right='off',
                      labelright='on')
    ax.set_title('curvature map')
    if sn in data_prot:
        from render.wavevids import plothull
        points_all = data_prot[sn]['data']['points_all']
        points_all_mean_time = points_all.mean(axis=0)
        plothull(ax,
                 points_all_mean_time[..., :2],
                 griddims=curvs_map.shape,
                 vecs=mvecs,
                 c='k',
                 lw=0)
    picturesave('fig.%s.%s' % ('curvature', sn),
                work.plotdir,
                backup=False,
                version=True,
                meta={})
    plt.close()
def individual_reviews_plotter(viewnames,
                               out_fn,
                               seep=None,
                               figsize=(10, 10),
                               horizontal=False,
                               wspace=0.4,
                               **kwargs):
    """
	Loop over all upstream curvature-undulation coupling calculations and plot a panel of review plots.
	"""
    #---seeping namespace
    if seep != None:
        for key, val in seep.items():
            globals()[key] = val
    for tag in datas:
        for sn in work.sns():
            status('reviewing curvature for %s' % sn, tag='plot')
            cmap_name = 'RdBu_r'
            square_tiles_args = {}
            if wspace != None: square_tiles_args.update(wspace=wspace)
            axes, fig = square_tiles(len(viewnames),
                                     figsize,
                                     hspace=0.4,
                                     favor_rows=horizontal,
                                     **square_tiles_args)
            #---several plots use the same data
            vecs = postdat[sn]['vecs']
            if len(vecs.shape) == 2: vecs = vecs.mean(axis=0)
            griddims = datas[tag][sn]['cf'].shape
            #---shared variables for several plots
            cmax = np.abs(datas[tag][sn]['cf']).max()
            cmax_instant = np.abs(datas[tag][sn]['cf_first']).max()
            hicut = calcs[tag][sn]['calcs']['specs'].get('fitting', {}).get(
                'high_cutoff', 1.0)
            #---PLOT the mean curvature field
            if 'average_field' in viewnames:
                ax = axes[viewnames.index('average_field')]
                im = ax.imshow(datas[tag][sn]['cf'].T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2).mean(axis=0)
                ax.scatter(*mean_trial.T, s=1, c='k')
                ax.set_title('average field')
                add_colorbar(ax,
                             im,
                             title=r'$\mathrm{\langle C_0(x,y) \rangle}$')
            #---PLOT a single instance of the neighborhood (good for debugging)
            if 'neighborhood_static' in viewnames:
                ax = axes[viewnames.index('neighborhood_static')]
                debug_frame = 0
                plot_hull_and_trial_centers(datas[tag],
                                            sn,
                                            ax,
                                            debug_frame=debug_frame,
                                            color='k')
                ax.set_title('neighborhood, static, frame %d' % debug_frame)
            #---PLOT a composite of several frames of the neighborhood to see the dynamics
            if 'neighborhood_dynamic' in viewnames:
                ax = axes[viewnames.index('neighborhood_dynamic')]
                plot_hull_and_trial_centers(datas[tag], sn, ax, n_instances=10)
                ax.set_title('neighborhood, dynamic')
            #---PLOT the average height
            if 'average_height' in viewnames:
                mesh = data[undulations_name][sn]['data']['mesh']
                surf = mesh.mean(axis=0).mean(axis=0)
                surf -= surf.mean()
                hmax = np.abs(surf).max()
                ax = axes[viewnames.index('average_height')]
                try:
                    im = ax.imshow(surf.T,
                                   origin='lower',
                                   interpolation='nearest',
                                   cmap=mpl.cm.__dict__['RdBu_r'],
                                   extent=[0, vecs[0], 0, vecs[1]],
                                   vmax=hmax,
                                   vmin=-1 * hmax)
                except:
                    import ipdb
                    ipdb.set_trace()
                try:
                    mean_prot_pts = [postdat[sn]['points_protein_mean'][:, :2]]
                except:
                    try:
                        mean_prot_pts = data[protein_abstractor_name][sn][
                            'data']['points_all'].mean(axis=0)[..., :2]
                    except:
                        mean_prot_pts = [
                            data[protein_abstractor_name][sn]['data']
                            ['points'].mean(axis=0)[:, :2]
                        ]
                plothull(ax,
                         mean_prot_pts,
                         griddims=datas[tag][sn]['cf'].shape,
                         vecs=vecs,
                         c='k',
                         lw=0)
                ax.set_title('height profile')
                ax.set_xlabel('x (nm)')
                ax.set_ylabel('y (nm)')
                add_colorbar(ax,
                             im,
                             title=r'$\mathrm{\langle z \rangle \, (nm)}$')
            #---PLOT an example curvature field ('first' is hard-coded, instead of saving each frame)
            if 'example_field' in viewnames:
                ax = axes[viewnames.index('example_field')]
                example_frame = 0
                cf_first = datas[tag][sn]['cf_first']
                im = ax.imshow(cf_first.T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                add_colorbar(ax, im, title=r'$\mathrm{C_0\,({nm}^{-1})}$')
                ax.set_xlim((0, vecs[0]))
                ax.set_ylim((0, vecs[1]))
                ax.set_xlabel('x (nm)')
                ax.set_ylabel('y (nm)')
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2)[example_frame]
                ax.scatter(*mean_trial.T, s=1, c='k')
                ax.set_title('curvature field', fontsize=10)
            #---PLOT example curvature without the dots for the trial functions, including the protein hull
            if 'example_field_no_neighborhood' in viewnames:
                ax = axes[viewnames.index('example_field_no_neighborhood')]
                example_frame = 0
                cf_first = datas[tag][sn]['cf_first']
                im = ax.imshow(cf_first.T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                add_colorbar(ax, im, title=r'$\mathrm{C_0\,({nm}^{-1})}$')
                ax.set_xlim((0, vecs[0]))
                ax.set_ylim((0, vecs[1]))
                ax.set_xlabel('x (nm)')
                ax.set_ylabel('y (nm)')
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2)[example_frame]
                ax.set_title('curvature field', fontsize=10)
                ex_prot_pts = data[protein_abstractor_name][sn]['data'][
                    'points'][example_frame][:, :2]
                plothull(ax, [ex_prot_pts],
                         griddims=datas[tag][sn]['cf'].shape,
                         vecs=vecs,
                         c='k',
                         lw=0)
            #---PLOT periodic view of the example field
            if 'example_field_pbc' in viewnames:
                ax = axes[viewnames.index('example_field_pbc')]
                im = ax.imshow(
                    np.tile(cf_first.T, (3, 3)),
                    origin='lower',
                    interpolation='nearest',
                    vmax=cmax,
                    vmin=-1 * cmax,
                    cmap=mpl.cm.__dict__[cmap_name],
                    extent=[-vecs[0], 2 * vecs[0], -vecs[1], 2 * vecs[1]])
                ax.set_title('curvature field (max %.3f)' % cmax_instant)
                add_colorbar(ax, im, title=r'$\mathrm{C_0\,({nm}^{-1})}$')
            #---PLOT periodic view of the average height
            if 'average_height_pbc' in viewnames:
                ax = axes[viewnames.index('average_height_pbc')]
                im = ax.imshow(
                    np.tile(surf.T, (3, 3)),
                    origin='lower',
                    interpolation='nearest',
                    vmax=hmax,
                    vmin=-1 * hmax,
                    cmap=mpl.cm.__dict__[cmap_name],
                    extent=[-vecs[0], 2 * vecs[0], -vecs[1], 2 * vecs[1]])
                ax.set_title('average height')
                add_colorbar(ax, im, title=r'$\mathrm{\langle z \rangle}$')
                #---track the protein
                protein_pts = data[protein_abstractor_name][sn]['data'][
                    'points_all']
                #### if protein_pts.shape[1]!=1: raise Exception('only one protein')
                prot_traj = protein_pts[:, 0].mean(axis=1)[:, :2]
                #### more proteins
                prot_traj = np.concatenate(
                    data[protein_abstractor_name][sn]['data']
                    ['points_all'].mean(axis=0)[..., :2])
                for shift in np.concatenate(
                        np.transpose(np.meshgrid([-1, 0, 1],
                                                 [-1, 0, 1]))) * vecs[:2]:
                    ax.scatter(prot_traj[:, 0] + shift[0],
                               prot_traj[:, 1] + shift[1],
                               c='k',
                               s=1)
                ax.set_xlim((-vecs[0], 2 * vecs[0]))
                ax.set_ylim((-vecs[1], 2 * vecs[1]))
            #---PLOT spectrum
            if 'spectrum' in viewnames:
                ax = axes[viewnames.index('spectrum')]
                if len(datas[tag][sn]['qs_binned']) == len(
                        datas[tag][sn]['ratios']):
                    qs = datas[tag][sn]['qs_binned']
                else:
                    datas[tag][sn]['qs']
                ax.scatter(qs,
                           datas[tag][sn]['ratios'],
                           s=4,
                           c='k',
                           alpha=0.25)
                #---! high cutoff is hard-coded here but needs to be removed to the yaml
                #---! ...we need to get the default
                band = qs <= hicut
                ax.scatter(qs[band],
                           datas[tag][sn]['ratios'][band],
                           s=10,
                           c='k',
                           alpha=1.0)
                ax.axhline(1.0, c='k')
                ax.set_xscale('log')
                ax.set_yscale('log')
                error = datas[tag][sn]['bundle'][sn]['fun']
                ax.set_title('full spectrum')
                ax.grid(True)
                ax.axvline(hicut, ymin=0.0, ymax=1.0, c='k', lw=2)
            #---PLOT spectrum, relevant section
            if 'spectrum_zoom' in viewnames:
                ax = axes[viewnames.index('spectrum_zoom')]
                qs = datas[tag][sn]['qs']
                band = qs <= hicut
                ys = datas[tag][sn]['ratios'][band]
                ax.scatter(qs[band], ys, s=20, c='k', alpha=1.0, clip_on=False)
                ax.axhline(1.0, c='k')
                ax.set_xscale('log')
                ax.set_yscale('log', subsy=[])
                ax.set_yticks([min(ys), 1.0, max(ys)])
                #---intransigent ticks!
                ax.set_yticklabels([
                    ('%.2f' % i if type(i) != bool else '')
                    for i in [min(ys), False, max(ys)]
                ])
                ax.set_xlim(min(qs), hicut)
                error = datas[tag][sn]['bundle'][sn]['fun']
                ax.set_title('spectrum (error %.5f)' % error)
            #---PLOT average height profile RELATIVE TO THE PROTEIN POSITION
            if 'average_height_center' in viewnames:
                mesh = data[undulations_name][sn]['data']['mesh']
                surfs = mesh.mean(axis=0)  #.mean(axis=0)
                surfs_shifted = center_by_protein(sn, surfs)
                surf = np.mean(surfs_shifted, axis=0)
                surf -= surf.mean()
                hmax = np.abs(surf).max()
                ax = axes[viewnames.index('average_height_center')]
                im = ax.imshow(surf.T,
                               origin='lower',
                               interpolation='nearest',
                               cmap=mpl.cm.__dict__['RdBu_r'],
                               extent=[0, vecs[0], 0, vecs[1]],
                               vmax=hmax,
                               vmin=-1 * hmax)
                try:
                    mean_prot_pts = postdat[sn]['points_protein_mean'][:, :2]
                except:
                    mean_prot_pts = data[protein_abstractor_name][sn]['data'][
                        'points'].mean(axis=0)[:, :2]
                #---! still need to move the protein
                if False:
                    plothull(ax, [mean_prot_pts],
                             griddims=datas[tag][sn]['cf'].shape,
                             vecs=vecs,
                             c='k',
                             lw=0)
                plothull_protein_center_average(ax, sn, vecs, tag)
                ax.set_title('height profile (centered)')
                ax.set_xlabel('x (nm)')
                ax.set_ylabel('y (nm)')
                add_colorbar(ax,
                             im,
                             title=r'$\mathrm{\langle z \rangle \, (nm)}$')
            #---PLOT the average field shifted as if the protein were in the center
            #---we call this "naive" because it takes a single, average curvature field and moves it
            #---...to the average position of the protein. if the protein crosses the periodic bounds,
            #---...then moving *anything* to the average position of the protein makes no sense
            #---...so see the explicit version below called "curvature_field_center"
            if 'average_field_center' in viewnames:
                ax = axes[viewnames.index('average_field_center')]
                nframes = data[undulations_name][sn]['data']['mesh'].shape[1]
                cf_centered = center_by_protein(sn,
                                                np.array(
                                                    [datas[tag][sn]['cf']]),
                                                static=True)
                im = ax.imshow(cf_centered.T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2).mean(axis=0)
                if False: ax.scatter(*mean_trial.T, s=1, c='k')
                ax.set_title('curvature field (centered,naive)')
                add_colorbar(ax, im, title=r'$\mathrm{C_0\,({nm}^{-1})}$')
            #---PLOT the average curvature field, shifted to the instantaneous position of the protein
            #---...and then averaged. this makes slightly more sense than "average_field_center" but we are
            #---...still assuming an average and then just smearing it around. see "curvature_field_center"
            if 'average_field_center_smear' in viewnames:
                ax = axes[viewnames.index('average_field_center_smear')]
                nframes = data[undulations_name][sn]['data']['mesh'].shape[1]
                cf_centered = center_by_protein(
                    sn, np.tile(datas[tag][sn]['cf'],
                                (nframes, 1, 1))).mean(axis=0)
                im = ax.imshow(cf_centered.T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2).mean(axis=0)
                if False: ax.scatter(*mean_trial.T, s=1, c='k')
                ax.set_title('curvature field (centered,smear)')
                add_colorbar(ax, im, title=r'$\mathrm{C_0\,({nm}^{-1})}$')
            #---PLOT the average of the protein-centered instantaneous curvature fields
            #---note that you have to add "store_instantaneous_fields: True" to the design of the calculation
            if 'curvature_field_center' in viewnames:
                ax = axes[viewnames.index('curvature_field_center')]
                nframes = data[undulations_name][sn]['data']['mesh'].shape[1]
                cf_centered = center_by_protein(
                    sn, datas[tag][sn]['cfs']).mean(axis=0)
                im = ax.imshow(cf_centered.T,
                               origin='lower',
                               interpolation='nearest',
                               vmax=cmax,
                               vmin=-1 * cmax,
                               cmap=mpl.cm.__dict__[cmap_name],
                               extent=[0, vecs[0], 0, vecs[1]])
                mean_trial = datas[tag][sn]['drop_gaussians_points'].transpose(
                    1, 0, 2).mean(axis=0)
                if False: ax.scatter(*mean_trial.T, s=1, c='k')
                ax.set_title('curvature field (centered)')
                ax.set_xlabel('x (nm)')
                ax.set_ylabel('y (nm)')
                add_colorbar(
                    ax,
                    im,
                    title=r'$\mathrm{\langle C_0 \rangle \,({nm}^{-1})$')
                plothull_protein_center_average(ax, sn, vecs, tag)
            #---no tick marks on anything
            for ax in axes:
                ax.tick_params(axis='x',
                               which='both',
                               bottom='off',
                               top='off',
                               labelbottom='on')
                ax.tick_params(axis='y',
                               which='both',
                               left='off',
                               right='off',
                               labelbottom='off')
            #---the metadata for this plot comes from the design section
            try:
                meta = calcs[tag][sn]['calcs']['specs']['specs']
                #---! custom upstream calculations for e.g. dextran project put the specs one level down
            except:
                meta = calcs[tag][sn]['calcs']['specs']
            #---add high cutoff (from fitting parameters if defined) to the meta
            meta['high_cutoff'] = hicut
            picturesave('fig.%s.%s' % (out_fn, sn),
                        work.plotdir,
                        backup=False,
                        version=True,
                        meta=meta)