Esempio n. 1
0
    def __init__(self,
                 env,
                 x_init,
                 min_dist=.3,
                 nfourier=20,
                 t_horizon=2,
                 t_history=0,
                 mode='mi',
                 gui=True):
        self.x = x_init
        self.bounds = env.bounds
        self.u_max = env.get_u_max()
        self.min_dist = min_dist
        self.nfourier = nfourier
        self.t_horizon = t_horizon
        self.nagents = x_init.shape[0]
        self.tp_rate = env.tp_rate
        self.fp_rate = env.fp_rate
        self.u = [np.zeros((2, t_horizon)) for i in range(self.nagents)]

        K1, K2 = np.meshgrid(np.arange(nfourier),
                             np.arange(nfourier),
                             indexing='ij')
        self.k1 = K1.flatten() * np.pi
        self.k2 = K2.flatten() * np.pi

        self.hk = np.ones(self.k1.shape[0])
        self.hk[self.k1 != 0] *= np.sqrt(.5)
        self.hk[self.k2 != 0] *= np.sqrt(.5)

        s = (2 + 1) / 2
        self.Lambdak = (1 + np.square(self.k1) + np.square(self.k2))**(-s)

        self.t_history = t_history
        self.ck_history_cum = []

        r = env.target_r + env.view_r
        npix = int(np.ceil(r / env.grid_dx) * 2 + 1)
        reg = CirclePixelRegion(center=PixCoord(npix, npix),
                                radius=r / env.grid_dx)
        self.footprint_mask = reg.to_mask(mode='exact').data

        self.image1 = None
        self.image2 = None
        self.lines = None

        # self.change_paramt0 = 5
        # self.change_param = .01

        self.change_paramt0 = .1
        self.change_param = .01

        self.mode = mode
        self.gui = gui
Esempio n. 2
0
def makeMask(xs, ys, radius, cenx, ceny):
    shape = (xs, ys)
    fin_mask = np.zeros(shape)
    print(radius)
    for i in np.arange(len(cenx)):
        if radius[i] > 5:
            radius[i] = 6
        center = PixCoord(cenx[i], ceny[i])
        circle = CirclePixelRegion(center, radius[i] - 1)
        mask = circle.to_mask()
        newmask = mask.to_image(shape)
        fin_mask += newmask
    fin_mask[fin_mask > 1] = 1
    return fin_mask
Esempio n. 3
0
def fftMask(sciImg, wavel_lambda, plateScale):
    # sciImg: this is actually the FFT image, not the science detector image
    # wavel_lambda: wavelenth of the observation
    # plateScale: plate scale of the detector (asec/pixel)

    # make division lines separating different parts of the PSF
    line_M1diam_pixOnFFT = findFFTloc(8.25,
                                      np.shape(sciImg)[0], wavel_lambda,
                                      plateScale)
    line_center2center_pixOnFFT = findFFTloc(14.4,
                                             np.shape(sciImg)[0], wavel_lambda,
                                             plateScale)
    line_edge2edge_pixOnFFT = findFFTloc(22.65,
                                         np.shape(sciImg)[0], wavel_lambda,
                                         plateScale)

    # define circles
    circRad = 60  # pixels in FFT space
    circle_highFreqPerfect_L = CirclePixelRegion(center=PixCoord(
        x=line_center2center_pixOnFFT[0], y=0.5 * np.shape(sciImg)[0]),
                                                 radius=circRad)
    circle_highFreqPerfect_R = CirclePixelRegion(center=PixCoord(
        x=line_center2center_pixOnFFT[1], y=0.5 * np.shape(sciImg)[0]),
                                                 radius=circRad)
    circle_lowFreqPerfect = CirclePixelRegion(center=PixCoord(
        x=0.5 * np.shape(sciImg)[1], y=0.5 * np.shape(sciImg)[0]),
                                              radius=circRad)

    # define central rectangular region that includes all three nodes
    rect_pix = PolygonPixelRegion(
        vertices=PixCoord(x=[
            line_edge2edge_pixOnFFT[0], line_edge2edge_pixOnFFT[1],
            line_edge2edge_pixOnFFT[1], line_edge2edge_pixOnFFT[0]
        ],
                          y=[
                              line_M1diam_pixOnFFT[1], line_M1diam_pixOnFFT[1],
                              line_M1diam_pixOnFFT[0], line_M1diam_pixOnFFT[0]
                          ]))

    # make the masks
    mask_circHighFreq_L = circle_highFreqPerfect_L.to_mask()
    mask_circHighFreq_R = circle_highFreqPerfect_R.to_mask()
    mask_circLowFreq = circle_lowFreqPerfect.to_mask()
    mask_rect = rect_pix.to_mask()

    # apply the masks
    sciImg1 = np.copy(
        sciImg)  # initialize arrays of same size as science image
    sciImg2 = np.copy(sciImg)
    sciImg3 = np.copy(sciImg)
    sciImg4 = np.copy(sciImg)

    # region 1
    sciImg1.fill(np.nan)  # initialize arrays of nans
    mask_circHighFreq_L.data[
        mask_circHighFreq_L.data ==
        0] = np.nan  # make zeros within mask cutout (but not in the mask itself) nans
    sciImg1[
        mask_circHighFreq_L.bbox.
        slices] = mask_circHighFreq_L.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg1 = np.multiply(
        sciImg1,
        sciImg)  # 'transmit' the original science image through the mask

    # region 2
    sciImg2.fill(np.nan)  # initialize arrays of nans
    mask_circHighFreq_R.data[
        mask_circHighFreq_R.data ==
        0] = np.nan  # make zeros within mask cutout (but not in the mask itself) nans
    sciImg2[
        mask_circHighFreq_R.bbox.
        slices] = mask_circHighFreq_R.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg2 = np.multiply(
        sciImg2,
        sciImg)  # 'transmit' the original science image through the mask

    # region 3
    sciImg3.fill(np.nan)  # initialize arrays of nans
    mask_circLowFreq.data[
        mask_circLowFreq.data ==
        0] = np.nan  # make zeros within mask cutout (but not in the mask itself) nans
    sciImg3[
        mask_circLowFreq.bbox.
        slices] = mask_circLowFreq.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg3 = np.multiply(
        sciImg3,
        sciImg)  # 'transmit' the original science image through the mask

    # region 4
    sciImg4.fill(np.nan)  # initialize arrays of nans
    mask_rect.data[
        mask_rect.data ==
        0] = np.nan  # make zeros within mask cutout (but not in the mask itself) nans
    sciImg4[
        mask_rect.bbox.
        slices] = mask_rect.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg4 = np.multiply(
        sciImg4,
        sciImg)  # 'transmit' the original science image through the mask

    # return medians of regions under masks
    med_highFreqPerfect_L = np.nanmedian(sciImg1)
    med_highFreqPerfect_R = np.nanmedian(sciImg2)
    med_lowFreqPerfect = np.nanmedian(sciImg3)
    med_rect = np.nanmedian(sciImg4)

    # return normal vectors corresponding to [x,y,z] to surfaces (x- and y- components are of interest)
    normVec_highFreqPerfect_L = normalVector(sciImg1)
    normVec_highFreqPerfect_R = normalVector(sciImg2)
    normVec_lowFreqPerfect = normalVector(sciImg3)
    normVec_rect = normalVector(sciImg4)

    # generate images showing footprints of regions of interest
    # (comment this bit in/out as desired)
    '''
    plt.imshow(sciImg1, origin='lower')
    plt.show()
    
    plt.imshow(sciImg2, origin='lower')
    plt.show()
    
    plt.imshow(sciImg3, origin='lower')
    plt.show()
    
    plt.imshow(sciImg4, origin='lower')
    plt.show()
    
    plt.clf()
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    cax = ax.imshow(sciImg, origin="lower")
    ax.axhline(line_M1diam_pixOnFFT[0])
    ax.axhline(line_M1diam_pixOnFFT[1])
    ax.axvline(line_M1diam_pixOnFFT[0])
    ax.axvline(line_M1diam_pixOnFFT[1])
    ax.axvline(line_center2center_pixOnFFT[0])
    ax.axvline(line_center2center_pixOnFFT[1])
    ax.axvline(line_edge2edge_pixOnFFT[0]) 
    ax.axvline(line_edge2edge_pixOnFFT[1]) 
    ax.add_patch(circle_highFreqPerfect_L.as_patch(facecolor='none', edgecolor='blue')) 
    ax.add_patch(circle_highFreqPerfect_R.as_patch(facecolor='none', edgecolor='blue')) 
    ax.add_patch(circle_lowFreqPerfect.as_patch(facecolor='none', edgecolor='blue')) 
    ax.add_patch(rect_pix.as_patch(facecolor='none', edgecolor='red')) 
    cbar = fig.colorbar(cax)
    plt.savefig("junk.pdf")
    '''

    dictFFTstuff = {}
    dictFFTstuff["med_highFreqPerfect_L"] = med_highFreqPerfect_L
    dictFFTstuff["med_highFreqPerfect_R"] = med_highFreqPerfect_R
    dictFFTstuff["med_lowFreqPerfect"] = med_lowFreqPerfect
    dictFFTstuff["med_rect"] = med_rect
    # note vectors are [a,b,c] corresponding to the eqn Z = a*X + b*Y + c
    dictFFTstuff["normVec_highFreqPerfect_L"] = normVec_highFreqPerfect_L
    dictFFTstuff["normVec_highFreqPerfect_R"] = normVec_highFreqPerfect_R
    dictFFTstuff["normVec_lowFreqPerfect"] = normVec_lowFreqPerfect
    dictFFTstuff["normVec_rect"] = normVec_rect

    return dictFFTstuff
    def __call__(self, abs_sci_name):
        '''
        PCA-based background subtraction, for a single frame so as to parallelize job

        INPUTS:
        abs_sci_name: science array filename
        '''

        # start the timer
        start_time = time.time()

        # read in the science frame from raw data directory
        sciImg, header_sci = fits.getdata(abs_sci_name, 0, header=True)

        # apply mask over weird detector regions to science image
        sciImg = np.multiply(sciImg, make_first_pass_mask(self.quad_choice))

        ## mask the PSF

        # define region
        psf_loc = find_airy_psf(sciImg)  # center of science PSF
        print("PSF location in " + os.path.basename(abs_sci_name) + ": [" +
              str(psf_loc[0]) + ", " + str(psf_loc[1]) + "]")
        radius = 30.  # radius around PSF that will be masked
        center = PixCoord(x=psf_loc[1], y=psf_loc[0])
        region = CirclePixelRegion(center, radius)
        mask_psf_region = region.to_mask()

        # apply the mask to science array
        psf_mask = np.ones(np.shape(
            sciImg))  # initialize arrays of same size as science image
        mask_psf_region.data[
            mask_psf_region.data ==
            1] = np.nan  # make zeros within mask cutout (but not in the mask itself) nans
        mask_psf_region.data[mask_psf_region.data == 0] = 1
        ##mask_psf_region.data[mask_psf_region.data == -99999] = 0 # have to avoid nans in the linear algebra
        psf_mask[
            mask_psf_region.bbox.
            slices] = mask_psf_region.data  # place the mask cutout (consisting only of 1s) onto the array of nans

        # I don't know why, but the sciImg nans in weird detector regions become zeros by this point, and I want them to stay nans
        # so, re-apply the mask over the bad regions of the detector
        sciImg = np.multiply(sciImg, make_first_pass_mask(self.quad_choice))

        sciImg_masked = np.multiply(
            sciImg, psf_mask)  # this is now the masked science frame

        # subtract the median (just a constant) from the remaining science image
        sciImg_psf_masked = np.subtract(
            sciImg_masked, np.nanmedian(sciImg_masked))  # where PSF is masked
        sciImg_psf_not_masked = np.subtract(
            sciImg, np.nanmedian(sciImg_masked))  # where PSF is not masked

        # apply the PSF mask to PCA slices, with which we will do the fitting
        pca_cube_masked = np.multiply(self.pca_cube, psf_mask)

        ## PCA-decompose

        # flatten the science array and PCA cube
        pca_not_masked_1ds = np.reshape(
            self.pca_cube,
            (np.shape(self.pca_cube)[0],
             np.shape(self.pca_cube)[1] * np.shape(self.pca_cube)[2]))
        sci_masked_1d = np.reshape(
            sciImg_psf_masked,
            (np.shape(sciImg_masked)[0] * np.shape(sciImg_masked)[1]))
        pca_masked_1ds = np.reshape(
            pca_cube_masked,
            (np.shape(pca_cube_masked)[0],
             np.shape(pca_cube_masked)[1] * np.shape(pca_cube_masked)[2]))

        ## remove nans from the linear algebra

        # indices of finite elements over a single flattened frame
        idx = np.logical_and(np.isfinite(pca_masked_1ds[0, :]),
                             np.isfinite(sci_masked_1d))

        # reconstitute only the finite elements together in another PCA cube and a science image
        pca_masked_1ds_noNaN = np.nan * np.ones(
            (len(pca_masked_1ds[:, 0]), np.sum(idx))
        )  # initialize array with slices the length of number of finite elements
        for t in range(
                0, len(pca_masked_1ds[:, 0])
        ):  # for each PCA component, populate the arrays without nans with the finite elements
            pca_masked_1ds_noNaN[t, :] = pca_masked_1ds[t, idx]
        sci_masked_1d_noNaN = np.array(1, np.sum(idx))  # science frame
        sci_masked_1d_noNaN = sci_masked_1d[idx]

        # the vector of component amplitudes
        soln_vector = np.linalg.lstsq(pca_masked_1ds_noNaN[0:self.n_PCA, :].T,
                                      sci_masked_1d_noNaN)

        # reconstruct the background based on that vector
        # note that the PCA components WITHOUT masking of the PSF location is being
        # used to reconstruct the background
        recon_backgrnd_2d = np.dot(self.pca_cube[0:self.n_PCA, :, :].T,
                                   soln_vector[0]).T
        # now do the same, but for the channel bias variation contributions only (assumes 32 elements only)
        recon_backgrnd_2d_channels_only_no_psf_masking = np.dot(
            self.pca_cube[0:32, :, :].T,
            soln_vector[0][0:32]).T  # without PSF masking
        recon_backgrnd_2d_channels_only_psf_masked = np.dot(
            self.pca_cube[0:32, :, :].T,
            soln_vector[0][0:32]).T  # with PSF masking

        # do the actual subtraction:
        # all-background subtraction
        sciImg_subtracted = np.subtract(sciImg_psf_not_masked,
                                        recon_backgrnd_2d)
        # background subtraction of channels only:
        # without PSF masking
        #sciImg_subtracted_channels_only_no_psf_masking = np.subtract(sciImg_psf_not_masked,recon_backgrnd_2d_channels_only)
        # with PSF masking
        sciImg_subtracted_channels_only_psf_masked = np.subtract(
            sciImg_psf_masked,
            np.multiply(recon_backgrnd_2d_channels_only_psf_masked,
                        np.multiply(self.pca_cube, psf_mask)))

        # add last reduction step to header
        header_sci["RED_STEP"] = "pca_background_subtracted"

        # save reconstructed background for checking
        abs_recon_bkgd = str(self.config_data["data_dirs"]["DIR_OTHER_FITS"] +
                             'recon_bkgd_quad_' +
                             str("{:0>2d}".format(self.quad_choice)) +
                             '_PCAseqStart_' +
                             str("{:0>6d}".format(self.cube_start_framenum)) +
                             '_PCAseqStop_' +
                             str("{:0>6d}".format(self.cube_stop_framenum)) +
                             '_' + os.path.basename(abs_sci_name))
        fits.writeto(filename=abs_recon_bkgd,
                     data=recon_backgrnd_2d,
                     overwrite=True)

        # save masked science frame BEFORE background-subtraction
        abs_masked_sci_before_bkd_subt = str(
            self.config_data["data_dirs"]["DIR_OTHER_FITS"] +
            'masked_sci_before_bkd_subt_quad_' +
            str("{:0>2d}".format(self.quad_choice)) + '_PCAseqStart_' +
            str("{:0>6d}".format(self.cube_start_framenum)) + '_PCAseqStop_' +
            str("{:0>6d}".format(self.cube_stop_framenum)) +
            os.path.basename(abs_sci_name))
        fits.writeto(filename=abs_masked_sci_before_bkd_subt,
                     data=sciImg_psf_masked,
                     overwrite=True)

        # save masked, background-subtracted science frame
        background_subtracted_masked = np.multiply(
            sciImg_subtracted, make_first_pass_mask(self.quad_choice))
        background_subtracted_masked = np.multiply(
            background_subtracted_masked, psf_mask)
        abs_masked_sci_after_bkd_subt = str(
            self.config_data["data_dirs"]["DIR_OTHER_FITS"] +
            'masked_sci_after_bkd_subt_quad_' +
            str("{:0>2d}".format(self.quad_choice)) + '_PCAseqStart_' +
            str("{:0>6d}".format(self.cube_start_framenum)) + '_PCAseqStop_' +
            str("{:0>6d}".format(self.cube_stop_framenum)) +
            os.path.basename(abs_sci_name))
        fits.writeto(filename=abs_masked_sci_after_bkd_subt,
                     data=background_subtracted_masked,
                     overwrite=True)

        # save background-subtracted science frame
        sciImg_subtracted_name = str(
            self.config_data["data_dirs"]["DIR_PCAB_SUBTED"] +
            os.path.basename(abs_sci_name))
        fits.writeto(filename=sciImg_subtracted_name,
                     data=sciImg_subtracted,
                     header=header_sci,
                     overwrite=True)
        print('Background-subtracted frame ' + os.path.basename(abs_sci_name) +
              ' written out. PCA = ' + str(self.n_PCA))

        ## make FYI plots of the effectiveness of the background subtraction
        # (N.b. the PSF and weird detector regions are masked here)
        self.vital_stats(file_base_name=str(os.path.basename(abs_sci_name)),
                         sci_img_pre=sciImg_masked,
                         sci_img_post_channel_subt=
                         sciImg_subtracted_channels_only_psf_masked,
                         sci_img_post_all_subt=background_subtracted_masked,
                         pca_spec=soln_vector[0])

        print('Elapsed time:')
        elapsed_time = time.time() - start_time
        print('--------------------------------------------------------------')
        print(elapsed_time)
def fftMask(sciImg,wavel_lambda,plateScale,fyi_string=''):
    ''' 
    Take a FFT image, generate masks to select interesting areas of the FFT, and 
    return data about those areas (amplitudes, normal vectors, etc.)

    INPUTS:
    sciImg: this is actually the FFT image, not the science detector image
    wavel_lambda: wavelength of the observation
    plateScale: plate scale of the detector (asec/pixel)
    fyi_string: an FYI string that could be used for plots

    OUTPUTS:
    dictFFTstuff: dictionary with keys corresponding to different parts of the FFT
    '''

    # make division lines separating different parts of the PSF
    line_M1diam_pixOnFFT = findFFTloc(D,np.shape(sciImg)[0],wavel_lambda,plateScale)
    line_center2center_pixOnFFT = findFFTloc(B_c2c,np.shape(sciImg)[0],wavel_lambda,plateScale)
    line_edge2edge_pixOnFFT = findFFTloc(B_e2e,np.shape(sciImg)[0],wavel_lambda,plateScale)

    # define circles
    circRad = 60 # pixels in FFT space
    circle_highFreqPerfect_L = CirclePixelRegion(center=PixCoord(x=line_center2center_pixOnFFT[0], y=0.5*np.shape(sciImg)[0]), radius=circRad)
    circle_highFreqPerfect_R = CirclePixelRegion(center=PixCoord(x=line_center2center_pixOnFFT[1], y=0.5*np.shape(sciImg)[0]), radius=circRad)
    circle_lowFreqPerfect = CirclePixelRegion(center=PixCoord(x=0.5*np.shape(sciImg)[1], y=0.5*np.shape(sciImg)[0]), radius=circRad)

    # define central rectangular region that includes all three nodes
    rect_pix = PolygonPixelRegion(vertices=PixCoord(x=[line_edge2edge_pixOnFFT[0],line_edge2edge_pixOnFFT[1],line_edge2edge_pixOnFFT[1],line_edge2edge_pixOnFFT[0]], 
                                                       y=[line_M1diam_pixOnFFT[1],line_M1diam_pixOnFFT[1],line_M1diam_pixOnFFT[0],line_M1diam_pixOnFFT[0]]))

    # make the masks
    mask_circHighFreq_L = circle_highFreqPerfect_L.to_mask()
    mask_circHighFreq_R = circle_highFreqPerfect_R.to_mask()
    mask_circLowFreq = circle_lowFreqPerfect.to_mask()
    mask_rect = rect_pix.to_mask()

    ## apply the masks

    # initialize arrays of same size as science image
    sciImg1 = np.copy(sciImg)
    sciImg2 = np.copy(sciImg)
    sciImg3 = np.copy(sciImg)
    sciImg4 = np.copy(sciImg)

    # region 1: high-freq lobe, left
    sciImg1.fill(np.nan) # initialize arrays of nans
    mask_circHighFreq_L.data[mask_circHighFreq_L.data == 0] = np.nan    # make zeros within mask cutout (but not in the mask itself) nans
    sciImg1[mask_circHighFreq_L.bbox.slices] = mask_circHighFreq_L.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg1 = np.multiply(sciImg1,sciImg) # 'transmit' the original science image through the mask
    sciImg1 = sciImg1.filled(fill_value=np.nan) # turn all masked '--' elements to nans

    # region 2: high-freq lobe, right
    sciImg2.fill(np.nan) # initialize arrays of nans
    mask_circHighFreq_R.data[mask_circHighFreq_R.data == 0] = np.nan    # make zeros within mask cutout (but not in the mask itself) nans
    sciImg2[mask_circHighFreq_R.bbox.slices] = mask_circHighFreq_R.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg2 = np.multiply(sciImg2,sciImg) # 'transmit' the original science image through the mask
    sciImg2 = sciImg2.filled(fill_value=np.nan) # turn all masked '--' elements to nans

    # region 3: low-freq lobe
    sciImg3.fill(np.nan) # initialize arrays of nans
    mask_circLowFreq.data[mask_circLowFreq.data == 0] = np.nan    # make zeros within mask cutout (but not in the mask itself) nans
    sciImg3[mask_circLowFreq.bbox.slices] = mask_circLowFreq.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg3 = np.multiply(sciImg3,sciImg) # 'transmit' the original science image through the mask
    sciImg3 = sciImg3.filled(fill_value=np.nan) # turn all masked '--' elements to nans

    # region 4: rectangular region containing parts of all lobes
    sciImg4.fill(np.nan) # initialize arrays of nans
    mask_rect.data[mask_rect.data == 0] = np.nan    # make zeros within mask cutout (but not in the mask itself) nans
    sciImg4[mask_rect.bbox.slices] = mask_rect.data  # place the mask cutout (consisting only of 1s) onto the array of nans
    sciImg4 = np.multiply(sciImg4,sciImg) # 'transmit' the original science image through the mask
    sciImg4 = sciImg4.filled(fill_value=np.nan) # turn all masked '--' elements to nans

    # return medians of regions under masks
    med_highFreqPerfect_L = np.nanmedian(sciImg1)
    med_highFreqPerfect_R = np.nanmedian(sciImg2)
    med_lowFreqPerfect = np.nanmedian(sciImg3)
    med_rect = np.nanmedian(sciImg4)

    # return normal vectors corresponding to [x,y,z] to surfaces (x- and y- components are of interest)
    normVec_highFreqPerfect_L = normalVector(sciImg1)
    normVec_highFreqPerfect_R = normalVector(sciImg2)
    normVec_lowFreqPerfect = normalVector(sciImg3)
    normVec_rect = normalVector(sciImg4)

    # return stdev in each region
    std_highFreqPerfect_L = np.nanstd(sciImg1)
    std_highFreqPerfect_R = np.nanstd(sciImg2)
    std_lowFreqPerfect = np.nanstd(sciImg3)
    std_rect = np.nanstd(sciImg4)

    # generate images showing footprints of regions of interest
    # (comment this bit in/out as desired)

    # initialize dictionary to contain FFT data
    # N.b. all the info in this dictionary is EITHER for
    # the FFT amplitude OR the FFT phase, depending on what
    # the 'sciImg' is
    dictFFTstuff = {}

    # median of high-freq lobe on left side, within circular region centered around 
    # where a perfect high-freq lobe would be
    dictFFTstuff["med_highFreqPerfect_L"] = med_highFreqPerfect_L

    # median of right-side high-freq lobe
    dictFFTstuff["med_highFreqPerfect_R"] = med_highFreqPerfect_R

    # median of low-frequency lobe
    dictFFTstuff["med_lowFreqPerfect"] = med_lowFreqPerfect

    # median of rectangle that is drawn to contain both high- and low-freq lobes
    dictFFTstuff["med_rect"] = med_rect

    # stdev of the same regions
    dictFFTstuff["std_highFreqPerfect_L"] = std_highFreqPerfect_L

    # median of right-side high-freq lobe
    dictFFTstuff["std_highFreqPerfect_R"] = std_highFreqPerfect_R

    # median of low-frequency lobe
    dictFFTstuff["std_lowFreqPerfect"] = std_lowFreqPerfect

    # median of rectangle that is drawn to contain both high- and low-freq lobes
    dictFFTstuff["std_rect"] = std_rect

    # normal vectors to the high- and low- frequency 
    # note vectors are [a,b,c] corresponding to the eqn Z = a*X + b*Y + c
    dictFFTstuff["normVec_highFreqPerfect_L"] = normVec_highFreqPerfect_L
    dictFFTstuff["normVec_highFreqPerfect_R"] = normVec_highFreqPerfect_R
    dictFFTstuff["normVec_lowFreqPerfect"] = normVec_lowFreqPerfect
    dictFFTstuff["normVec_rect"] = normVec_rect

    return dictFFTstuff