Ejemplo n.º 1
0
def run_rmclean(mDictS,
                aDict,
                cutoff,
                maxIter=1000,
                gain=0.1,
                nBits=32,
                showPlots=False,
                verbose=False,
                log=print):
    """Run RM-CLEAN on a complex FDF spectrum given a RMSF.

    Args:
        mDictS (dict): Summary of RM synthesis results.
        aDict (dict): Data output by RM synthesis.
        cutoff (float): CLEAN cutoff in flux units

    Kwargs:
        maxIter (int): Maximum number of CLEAN iterations per pixel.
        gain (float): CLEAN loop gain.
        nBits (int): Precision of floating point numbers.
        showPlots (bool): Show plots?
        verbose (bool): Verbosity.
        log (function): Which logging function to use.

    Returns:
        mDict (dict): Summary of RMCLEAN results.
        arrdict (dict): Data output by RMCLEAN.

    """
    phiArr_radm2 = aDict["phiArr_radm2"]
    freqArr_Hz = aDict["freqArr_Hz"]
    weightArr = aDict["weightArr"]
    dirtyFDF = aDict["dirtyFDF"]
    phi2Arr_radm2 = aDict["phi2Arr_radm2"]
    RMSFArr = aDict["RMSFArr"]

    lambdaSqArr_m2 = np.power(C / freqArr_Hz, 2.0)

    # If the cutoff is negative, assume it is a sigma level
    if verbose:
        log("Expected RMS noise = %.4g flux units" % (mDictS["dFDFth"]))
    if cutoff < 0:
        if verbose: log("Using a sigma cutoff of %.1f." % (-1 * cutoff))
        cutoff = -1 * mDictS["dFDFth"] * cutoff
        if verbose: log("Absolute value = %.3g" % cutoff)
    else:
        if verbose:
            log("Using an absolute cutoff of %.3g (%.1f x expected RMS)." %
                (cutoff, cutoff / mDictS["dFDFth"]))

    startTime = time.time()
    # Perform RM-clean on the spectrum
    cleanFDF, ccArr, iterCountArr, residFDF = \
              do_rmclean_hogbom(dirtyFDF        = dirtyFDF,
                                phiArr_radm2    = phiArr_radm2,
                                RMSFArr         = RMSFArr,
                                phi2Arr_radm2   = phi2Arr_radm2,
                                fwhmRMSFArr     = np.array(mDictS["fwhmRMSF"]),
                                cutoff          = cutoff,
                                maxIter         = maxIter,
                                gain            = gain,
                                verbose         = verbose,
                                doPlots         = showPlots)

    # ALTERNATIVE RM_CLEAN CODE ----------------------------------------------#
    '''
    cleanFDF, ccArr, fwhmRMSF, iterCount = \
              do_rmclean(dirtyFDF     = dirtyFDF,
                         phiArr       = phiArr_radm2,
                         lamSqArr     = lamSqArr_m2,
                         cutoff       = cutoff,
                         maxIter      = maxIter,
                         gain         = gain,
                         weight       = weightArr,
                         RMSFArr      = RMSFArr,
                         RMSFphiArr   = phi2Arr_radm2,
                         fwhmRMSF     = mDictS["fwhmRMSF"],
                         doPlots      = True)
    '''
    #-------------------------------------------------------------------------#

    endTime = time.time()
    cputime = (endTime - startTime)
    if verbose: log("> RM-CLEAN completed in %.4f seconds." % cputime)

    # Measure the parameters of the deconvolved FDF
    mDict = measure_FDF_parms(
        FDF=cleanFDF,
        phiArr=phiArr_radm2,
        fwhmRMSF=mDictS["fwhmRMSF"],
        #dFDF        = mDictS["dFDFth"],
        lamSqArr_m2=lambdaSqArr_m2,
        lam0Sq=mDictS["lam0Sq_m2"])
    mDict["cleanCutoff"] = cutoff
    mDict["nIter"] = int(iterCountArr)

    # Measure the complexity of the clean component spectrum
    mDict["mom2CCFDF"] = measure_fdf_complexity(phiArr=phiArr_radm2, FDF=ccArr)

    #Calculating observed errors (based on dFDFcorMAD)
    mDict["dPhiObserved_rm2"] = mDict["dPhiPeakPIfit_rm2"] * mDict[
        "dFDFcorMAD"] / mDictS["dFDFth"]
    mDict["dAmpObserved"] = mDict["dFDFcorMAD"]
    mDict["dPolAngleFitObserved_deg"] = mDict["dPolAngleFit_deg"] * mDict[
        "dFDFcorMAD"] / mDictS["dFDFth"]

    nChansGood = np.sum(np.where(lambdaSqArr_m2 == lambdaSqArr_m2, 1.0, 0.0))
    varLamSqArr_m2 = (np.sum(lambdaSqArr_m2**2.0) -
                      np.sum(lambdaSqArr_m2)**2.0 / nChansGood) / (nChansGood -
                                                                   1)
    mDict["dPolAngle0ChanObserved_deg"] = \
    np.degrees(np.sqrt( mDict["dFDFcorMAD"]**2.0 / (4.0*(nChansGood-2.0)*mDict["ampPeakPIfit"]**2.0) *
                 ((nChansGood-1)/nChansGood + mDictS["lam0Sq_m2"]**2.0/varLamSqArr_m2) ))

    if verbose:
        # Print the results to the screen
        log()
        log('-' * 80)
        log('RESULTS:\n')
        log('FWHM RMSF = %.4g rad/m^2' % (mDictS["fwhmRMSF"]))
        log('Pol Angle = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
            (mDict["polAngleFit_deg"], mDict["dPolAngleFitObserved_deg"],
             mDict["dPolAngleFit_deg"]))
        log('Pol Angle 0 = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
            (mDict["polAngle0Fit_deg"], mDict["dPolAngle0ChanObserved_deg"],
             mDict["dPolAngle0Fit_deg"]))
        log('Peak FD = %.4g (+/-%.4g observed, +- %.4g theoretical) rad/m^2' %
            (mDict["phiPeakPIfit_rm2"], mDict["dPhiObserved_rm2"],
             mDict["dPhiPeakPIfit_rm2"]))
        log('freq0_GHz = %.4g ' % (mDictS["freq0_Hz"] / 1e9))
        log('I freq0 = %.4g %s' % (mDictS["Ifreq0"], mDictS["units"]))
        log('Peak PI = %.4g (+/-%.4g observed, +- %.4g theoretical) %s' %
            (mDict["ampPeakPIfit"], mDict["dAmpObserved"],
             mDict["dAmpPeakPIfit"], mDictS["units"]))
        log('QU Noise = %.4g %s' % (mDictS["dQU"], mDictS["units"]))
        log('FDF Noise (theory)   = %.4g %s' %
            (mDictS["dFDFth"], mDictS["units"]))
        log('FDF Noise (Corrected MAD) = %.4g %s' %
            (mDict["dFDFcorMAD"], mDictS["units"]))
        log('FDF Noise (rms)   = %.4g %s' %
            (mDict["dFDFrms"], mDictS["units"]))

        log('FDF SNR = %.4g ' % (mDict["snrPIfit"]))
        log()
        log('-' * 80)

    # Pause to display the figure
    if showPlots:
        plot_clean_spec(phiArr_radm2, dirtyFDF, cleanFDF, ccArr, residFDF,
                        cutoff, mDictS["units"])
        print("Press <RETURN> to exit ...", end=' ')
        input()

    #add array dictionary
    arrdict = dict()
    arrdict["phiArr_radm2"] = phiArr_radm2
    arrdict["freqArr_Hz"] = freqArr_Hz
    arrdict["cleanFDF"] = cleanFDF
    arrdict["ccArr"] = ccArr
    arrdict["iterCountArr"] = iterCountArr
    arrdict["residFDF"] = residFDF

    return mDict, arrdict
Ejemplo n.º 2
0
def run_rmclean(fitsFDF,
                fitsRMSF,
                cutoff_mJy,
                maxIter=1000,
                gain=0.1,
                prefixOut="",
                outDir="",
                nBits=32,
                write_separate_FDF=False,
                verbose=True,
                log=print):
    """Run RM-CLEAN on a FDF cube given a RMSF cube."""

    # Default data types
    dtFloat = "float" + str(nBits)
    dtComplex = "complex" + str(2 * nBits)

    # Read the FDF
    dirtyFDF, head, FD_axis = read_FDF_cube(fitsFDF)

    phiArr_radm2 = fits_make_lin_axis(head, axis=FD_axis - 1, dtype=dtFloat)

    # Read the RMSF

    RMSFArr, headRMSF, FD_axis = read_FDF_cube(fitsRMSF)
    HDULst = pf.open(fitsRMSF, "readonly", memmap=True)
    fwhmRMSFArr = HDULst[3].data
    HDULst.close()
    phi2Arr_radm2 = fits_make_lin_axis(headRMSF,
                                       axis=FD_axis - 1,
                                       dtype=dtFloat)

    startTime = time.time()

    # Do the clean
    cleanFDF, ccArr, iterCountArr = \
        do_rmclean_hogbom(dirtyFDF         = dirtyFDF * 1e3,
                          phiArr_radm2     = phiArr_radm2,
                          RMSFArr          = RMSFArr,
                          phi2Arr_radm2    = phi2Arr_radm2,
                          fwhmRMSFArr      = fwhmRMSFArr,
                          cutoff           = cutoff_mJy,
                          maxIter          = maxIter,
                          gain             = gain,
                          verbose          = verbose,
                          doPlots          = False)
    cleanFDF /= 1e3
    ccArr /= 1e3

    endTime = time.time()
    cputime = (endTime - startTime)
    if (verbose): log("> RM-clean completed in %.2f seconds." % cputime)
    if (verbose): log("Saving the clean FDF and ancillary FITS files")

    if outDir == '':  #To prevent code breaking if file is in current directory
        outDir = '.'

    #Move FD axis back to original position:
    Ndim = head['NAXIS']
    cleanFDF = np.moveaxis(cleanFDF, 0, Ndim - FD_axis)
    ccArr = np.moveaxis(ccArr, 0, Ndim - FD_axis)

    # Save the clean FDF
    if not write_separate_FDF:
        fitsFileOut = outDir + "/" + prefixOut + "FDF_clean.fits"
        if (verbose): log("> %s" % fitsFileOut)
        hdu0 = pf.PrimaryHDU(cleanFDF.real.astype(dtFloat), head)
        hdu1 = pf.ImageHDU(cleanFDF.imag.astype(dtFloat), head)
        hdu2 = pf.ImageHDU(np.abs(cleanFDF).astype(dtFloat), head)
        hduLst = pf.HDUList([hdu0, hdu1, hdu2])
        hduLst.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        hduLst.close()
    else:
        hdu0 = pf.PrimaryHDU(cleanFDF.real.astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_clean_real.fits"
        hdu0.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)
        hdu1 = pf.PrimaryHDU(cleanFDF.imag.astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_clean_im.fits"
        hdu1.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)
        hdu2 = pf.PrimaryHDU(np.abs(cleanFDF).astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_clean_tot.fits"
        hdu2.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)

    if not write_separate_FDF:
        #Save the complex clean components as another file.
        fitsFileOut = outDir + "/" + prefixOut + "FDF_CC.fits"
        if (verbose): log("> %s" % fitsFileOut)
        hdu0 = pf.PrimaryHDU(ccArr.real.astype(dtFloat), head)
        hdu1 = pf.ImageHDU(ccArr.imag.astype(dtFloat), head)
        hdu2 = pf.ImageHDU(np.abs(ccArr).astype(dtFloat), head)
        hduLst = pf.HDUList([hdu0, hdu1, hdu2])
        hduLst.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        hduLst.close()
    else:
        hdu0 = pf.PrimaryHDU(ccArr.real.astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_CC_real.fits"
        hdu0.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)
        hdu1 = pf.PrimaryHDU(ccArr.imag.astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_CC_im.fits"
        hdu1.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)
        hdu2 = pf.PrimaryHDU(np.abs(ccArr).astype(dtFloat), head)
        fitsFileOut = outDir + "/" + prefixOut + "FDF_CC_tot.fits"
        hdu2.writeto(fitsFileOut, output_verify="fix", overwrite=True)
        if (verbose): log("> %s" % fitsFileOut)

    # Save the iteration count mask
    fitsFileOut = outDir + "/" + prefixOut + "CLEAN_nIter.fits"
    if (verbose): log("> %s" % fitsFileOut)
    head["BUNIT"] = "Iterations"
    hdu0 = pf.PrimaryHDU(iterCountArr.astype(dtFloat), head)
    hduLst = pf.HDUList([hdu0])
    hduLst.writeto(fitsFileOut, output_verify="fix", overwrite=True)
    hduLst.close()
Ejemplo n.º 3
0
def run_rmclean(fitsFDF,
                fitsRMSF,
                cutoff_mJy,
                maxIter=1000,
                gain=0.1,
                prefixOut="",
                outDir="",
                nBits=32):
    """Run RM-CLEAN on a FDF cube given a RMSF cube."""

    # Default data types
    dtFloat = "float" + str(nBits)
    dtComplex = "complex" + str(2 * nBits)

    # Read the FDF
    HDULst = pf.open(fitsFDF, "readonly", memmap=True)
    head = HDULst[0].header.copy()
    FDFreal = HDULst[0].data
    FDFimag = HDULst[1].data
    dirtyFDF = FDFreal + 1j * FDFimag
    phiArr_radm2 = fits_make_lin_axis(HDULst[0].header, axis=2, dtype=dtFloat)

    # Read the RMSF
    HDULst = pf.open(fitsRMSF, "readonly", memmap=True)
    RMSFreal = HDULst[0].data
    RMSFimag = HDULst[1].data
    fwhmRMSFArr = HDULst[3].data
    RMSFArr = RMSFreal + 1j * RMSFimag
    phi2Arr_radm2 = fits_make_lin_axis(HDULst[0].header, axis=2, dtype=dtFloat)

    startTime = time.time()

    # Do the clean
    cleanFDF, ccArr, iterCountArr = \
        do_rmclean_hogbom(dirtyFDF         = dirtyFDF * 1e3,
                          phiArr_radm2     = phiArr_radm2,
                          RMSFArr          = RMSFArr,
                          phi2Arr_radm2    = phi2Arr_radm2,
                          fwhmRMSFArr      = fwhmRMSFArr,
                          cutoff           = cutoff_mJy,
                          maxIter          = maxIter,
                          gain             = gain,
                          verbose          = True,
                          doPlots          = False)
    cleanFDF /= 1e3
    ccArr /= 1e3

    endTime = time.time()
    cputime = (endTime - startTime)
    print "> RM-clean completed in %.2f seconds." % cputime
    print "Saving the clean FDF and ancillary FITS files"

    # Save the clean FDF
    fitsFileOut = outDir + "/" + prefixOut + "FDF_clean.fits"
    print "> %s" % fitsFileOut
    hdu0 = pf.PrimaryHDU(cleanFDF.real.astype(dtFloat), head)
    hdu1 = pf.ImageHDU(cleanFDF.imag.astype(dtFloat), head)
    hdu2 = pf.ImageHDU(np.abs(cleanFDF).astype(dtFloat), head)
    hdu3 = pf.ImageHDU(ccArr.astype(dtFloat), head)
    hduLst = pf.HDUList([hdu0, hdu1, hdu2, hdu3])
    hduLst.writeto(fitsFileOut, output_verify="fix", clobber=True)
    hduLst.close()

    # Save the iteration count mask
    fitsFileOut = outDir + "/" + prefixOut + "CLEAN_nIter.fits"
    print "> %s" % fitsFileOut
    head["BUNIT"] = "Iterations"
    hdu0 = pf.PrimaryHDU(iterCountArr.astype(dtFloat), head)
    hduLst = pf.HDUList([hdu0])
    hduLst.writeto(fitsFileOut, output_verify="fix", clobber=True)
    hduLst.close()
Ejemplo n.º 4
0
def run_rmclean(mDictS,
                aDict,
                cutoff,
                maxIter=1000,
                gain=0.1,
                prefixOut="",
                outDir="",
                nBits=32,
                showPlots=False,
                doAnimate=False,
                verbose=False,
                log=print):
    """
    Run RM-CLEAN on a complex FDF spectrum given a RMSF.
    """
    phiArr_radm2 = aDict["phiArr_radm2"]
    freqArr_Hz = aDict["freqArr_Hz"]
    weightArr = aDict["weightArr"]
    dirtyFDF = aDict["dirtyFDF"]
    phi2Arr_radm2 = aDict["phi2Arr_radm2"]
    RMSFArr = aDict["RMSFArr"]

    lambdaSqArr_m2 = np.power(C / freqArr_Hz, 2.0)

    # If the cutoff is negative, assume it is a sigma level
    if verbose:
        log("Expected RMS noise = %.4g mJy/beam/rmsf" %
            (mDictS["dFDFth_Jybm"] * 1e3))
    if cutoff < 0:
        log("Using a sigma cutoff of %.1f." % (-1 * cutoff))
        cutoff = -1 * mDictS["dFDFth_Jybm"] * cutoff
        log("Absolute value = %.3g" % cutoff)
    else:
        log("Using an absolute cutoff of %.3g (%.1f x expected RMS)." %
            (cutoff, cutoff / mDictS["dFDFth_Jybm"]))

    startTime = time.time()
    # Perform RM-clean on the spectrum
    cleanFDF, ccArr, iterCountArr = \
              do_rmclean_hogbom(dirtyFDF        = dirtyFDF,
                                phiArr_radm2    = phiArr_radm2,
                                RMSFArr         = RMSFArr,
                                phi2Arr_radm2   = phi2Arr_radm2,
                                fwhmRMSFArr     = np.array(mDictS["fwhmRMSF"]),
                                cutoff          = cutoff,
                                maxIter         = maxIter,
                                gain            = gain,
                                verbose         = verbose,
                                doPlots         = showPlots,
                                doAnimate       = doAnimate)

    # ALTERNATIVE RM_CLEAN CODE ----------------------------------------------#
    '''
    cleanFDF, ccArr, fwhmRMSF, iterCount = \
              do_rmclean(dirtyFDF     = dirtyFDF,
                         phiArr       = phiArr_radm2,
                         lamSqArr     = lamSqArr_m2,
                         cutoff       = cutoff,
                         maxIter      = maxIter,
                         gain         = gain,
                         weight       = weightArr,
                         RMSFArr      = RMSFArr,
                         RMSFphiArr   = phi2Arr_radm2,
                         fwhmRMSF     = mDictS["fwhmRMSF"],
                         doPlots      = True)
    '''
    #-------------------------------------------------------------------------#

    endTime = time.time()
    cputime = (endTime - startTime)
    log("> RM-CLEAN completed in %.4f seconds." % cputime)

    # Measure the parameters of the deconvolved FDF
    mDict = measure_FDF_parms(
        FDF=cleanFDF,
        phiArr=phiArr_radm2,
        fwhmRMSF=mDictS["fwhmRMSF"],
        #dFDF        = mDictS["dFDFth_Jybm"],
        lamSqArr_m2=lambdaSqArr_m2,
        lam0Sq=mDictS["lam0Sq_m2"])
    mDict["cleanCutoff"] = cutoff
    mDict["nIter"] = int(iterCountArr)

    # Measure the complexity of the clean component spectrum
    mDict["mom2CCFDF"] = measure_fdf_complexity(phiArr=phiArr_radm2, FDF=ccArr)

    #Calculating observed errors (based on dFDFcorMAD)
    mDict["dPhiObserved_rm2"] = mDict["dPhiPeakPIfit_rm2"] * mDict[
        "dFDFcorMAD_Jybm"] / mDictS["dFDFth_Jybm"]
    mDict["dAmpObserved_Jybm"] = mDict["dFDFcorMAD_Jybm"]
    mDict["dPolAngleFitObserved_deg"] = mDict["dPolAngleFit_deg"] * mDict[
        "dFDFcorMAD_Jybm"] / mDictS["dFDFth_Jybm"]

    nChansGood = np.sum(np.where(lambdaSqArr_m2 == lambdaSqArr_m2, 1.0, 0.0))
    varLamSqArr_m2 = (np.sum(lambdaSqArr_m2**2.0) -
                      np.sum(lambdaSqArr_m2)**2.0 / nChansGood) / (nChansGood -
                                                                   1)
    mDict["dPolAngle0ChanObserved_deg"] = \
    np.degrees(np.sqrt( mDict["dFDFcorMAD_Jybm"]**2.0 / (4.0*(nChansGood-2.0)*mDict["ampPeakPIfit_Jybm"]**2.0) *
                 ((nChansGood-1)/nChansGood + mDictS["lam0Sq_m2"]**2.0/varLamSqArr_m2) ))

    # Save the deconvolved FDF and CC model to ASCII files
    log("Saving the clean FDF and component model to ASCII files.")
    outFile = prefixOut + "_FDFclean.dat"
    log("> %s" % outFile)
    np.savetxt(outFile, list(zip(phiArr_radm2, cleanFDF.real, cleanFDF.imag)))
    outFile = prefixOut + "_FDFmodel.dat"
    log("> %s" % outFile)
    np.savetxt(outFile, list(zip(phiArr_radm2, ccArr.real, ccArr.imag)))

    # Save the RM-clean measurements to a "key=value" text file
    log("Saving the measurements on the FDF in 'key=val' and JSON formats.")
    outFile = prefixOut + "_RMclean.dat"
    log("> %s" % outFile)
    FH = open(outFile, "w")
    for k, v in mDict.items():
        FH.write("%s=%s\n" % (k, v))
    FH.close()
    outFile = prefixOut + "_RMclean.json"
    log("> %s" % outFile)
    json.dump(mDict, open(outFile, "w"))

    # Print the results to the screen
    log()
    log('-' * 80)
    log('RESULTS:\n')
    log('FWHM RMSF = %.4g rad/m^2' % (mDictS["fwhmRMSF"]))
    log('Pol Angle = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
        (mDict["polAngleFit_deg"], mDict["dPolAngleFitObserved_deg"],
         mDict["dPolAngleFit_deg"]))
    log('Pol Angle 0 = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
        (mDict["polAngle0Fit_deg"], mDict["dPolAngle0ChanObserved_deg"],
         mDict["dPolAngle0Fit_deg"]))
    log('Peak FD = %.4g (+/-%.4g observed, +- %.4g theoretical) rad/m^2' %
        (mDict["phiPeakPIfit_rm2"], mDict["dPhiObserved_rm2"],
         mDict["dPhiPeakPIfit_rm2"]))
    log('freq0_GHz = %.4g ' % (mDictS["freq0_Hz"] / 1e9))
    log('I freq0 = %.4g mJy/beam' % (mDictS["Ifreq0_mJybm"]))
    log('Peak PI = %.4g (+/-%.4g observed, +- %.4g theoretical) mJy/beam' %
        (mDict["ampPeakPIfit_Jybm"] * 1e3, mDict["dAmpObserved_Jybm"] * 1e3,
         mDict["dAmpPeakPIfit_Jybm"] * 1e3))
    log('QU Noise = %.4g mJy/beam' % (mDictS["dQU_Jybm"] * 1e3))
    log('FDF Noise (theory)   = %.4g mJy/beam' % (mDictS["dFDFth_Jybm"] * 1e3))
    log('FDF Noise (Corrected MAD) = %.4g mJy/beam' %
        (mDict["dFDFcorMAD_Jybm"] * 1e3))
    log('FDF Noise (rms)   = %.4g mJy/beam' % (mDict["dFDFrms_Jybm"] * 1e3))

    log('FDF SNR = %.4g ' % (mDict["snrPIfit"]))
    log()
    log('-' * 80)

    # Pause to display the figure
    if showPlots or doAnimate:
        print("Press <RETURN> to exit ...", end=' ')
        input()

    return mDict
Ejemplo n.º 5
0
def run_rmclean(fitsFDF,
                fitsRMSF,
                cutoff,
                maxIter=1000,
                gain=0.1,
                nBits=32,
                pool=None,
                chunksize=None,
                verbose=True,
                log=print):
    """Run RM-CLEAN on a 2/3D FDF cube given an RMSF cube stored as FITS.

    If you want to run RM-CLEAN on arrays, just use util_RM.do_rmclean_hogbom.

    Args:
        fitsFDF (str): Name of FDF FITS file.
        fitsRMSF (str): Name of RMSF FITS file
        cutoff (float): CLEAN cutoff in flux units

    Kwargs:
        maxIter (int): Maximum number of CLEAN iterations per pixel.
        gain (float): CLEAN loop gain.
        nBits (int): Precision of floating point numbers.
        pool (multiprocessing Pool): Pool function from multiprocessing
            or schwimmbad
        chunksize (int): Number of chunks which it submits to the process pool
            as separate tasks. The (approximate) size of these chunks can be
            specified by setting chunksize to a positive integer.
        verbose (bool): Verbosity.
        log (function): Which logging function to use.

    Returns:
        cleanFDF (ndarray): Cube of RMCLEANed FDFs.
        ccArr (ndarray): Cube of RMCLEAN components (i.e. the model).
        iterCountArr (ndarray): Cube of number of RMCLEAN iterations.
        residFDF (ndarray): Cube of residual RMCLEANed FDFs.
        head (fits.header): Header of FDF FITS file for template.

    """

    # Default data types
    dtFloat = "float" + str(nBits)
    dtComplex = "complex" + str(2 * nBits)

    # Read the FDF
    dirtyFDF, head, FD_axis = read_FDF_cubes(fitsFDF)

    phiArr_radm2 = fits_make_lin_axis(head, axis=FD_axis - 1, dtype=dtFloat)

    # Read the RMSF

    RMSFArr, headRMSF, FD_axis = read_FDF_cubes(fitsRMSF)
    HDULst = pf.open(fitsRMSF.replace('_real', '_FWHM').replace(
        '_im', '_FWHM').replace('_tot', '_FWHM'),
                     "readonly",
                     memmap=True)
    fwhmRMSFArr = np.squeeze(HDULst[0].data)
    HDULst.close()
    phi2Arr_radm2 = fits_make_lin_axis(headRMSF,
                                       axis=FD_axis - 1,
                                       dtype=dtFloat)

    startTime = time.time()

    # Do the clean
    cleanFDF, ccArr, iterCountArr, residFDF  = \
        do_rmclean_hogbom(dirtyFDF         = dirtyFDF,
                          phiArr_radm2     = phiArr_radm2,
                          RMSFArr          = RMSFArr,
                          phi2Arr_radm2    = phi2Arr_radm2,
                          fwhmRMSFArr      = fwhmRMSFArr,
                          cutoff           = cutoff,
                          maxIter          = maxIter,
                          gain             = gain,
                          verbose          = verbose,
                          doPlots          = False,
                          pool             = pool,
                          chunksize        = chunksize)

    endTime = time.time()
    cputime = (endTime - startTime)
    if (verbose): log("> RM-clean completed in %.2f seconds." % cputime)
    if (verbose): log("Saving the clean FDF and ancillary FITS files")

    #Move FD axis back to original position:
    Ndim = cleanFDF.ndim
    cleanFDF = np.moveaxis(cleanFDF, 0, Ndim - FD_axis)
    ccArr = np.moveaxis(ccArr, 0, Ndim - FD_axis)

    return cleanFDF, ccArr, iterCountArr, residFDF, head
Ejemplo n.º 6
0
def run_rmclean(mDict,
                aDict,
                cutoff,
                maxIter=1000,
                gain=0.1,
                nBits=32,
                showPlots=False,
                prefixOut="",
                verbose=False,
                log=print,
                saveFigures=False,
                window=None):
    """Run RM-CLEAN on a complex FDF spectrum given a RMSF.

    Args:
        mDict (dict): Summary of RM synthesis results.
        aDict (dict): Data output by RM synthesis.
        cutoff (float): CLEAN cutoff in flux units (positive)
                        or as multiple of theoretical noise (negative)
                        (i.e. -8 = clean to 8 sigma threshold)

    Kwargs:
        maxIter (int): Maximum number of CLEAN iterations per pixel.
        gain (float): CLEAN loop gain.
        nBits (int): Precision of floating point numbers.
        showPlots (bool): Show plots?
        verbose (bool): Verbosity.
        log (function): Which logging function to use.
        window (float): Threshold for deeper windowed cleaning

    Returns:
        mDict_cl (dict): Summary of RMCLEAN results.
        aDict_cl (dict): Data output by RMCLEAN.

    """
    phiArr_radm2 = aDict["phiArr_radm2"]
    freqArr_Hz = aDict["freqArr_Hz"]
    weightArr = aDict["weightArr"]
    dirtyFDF = aDict["dirtyFDF"]
    phi2Arr_radm2 = aDict["phi2Arr_radm2"]
    RMSFArr = aDict["RMSFArr"]

    lambdaSqArr_m2 = np.power(C / freqArr_Hz, 2.0)

    # If the cutoff is negative, assume it is a sigma level
    if verbose: log("Expected RMS noise = %.4g flux units" % (mDict["dFDFth"]))
    if cutoff < 0:
        if verbose: log("Using a sigma cutoff of %.1f." % (-1 * cutoff))
        cutoff = -1 * mDict["dFDFth"] * cutoff
        if verbose: log("Absolute value = %.3g" % cutoff)
    else:
        if verbose:
            log("Using an absolute cutoff of %.3g (%.1f x expected RMS)." %
                (cutoff, cutoff / mDict["dFDFth"]))

    if window is None:
        window = np.nan
    else:
        if window < 0:
            if verbose:
                log("Using a window sigma cutoff of %.1f." % (-1 * window))
            window = -1 * mDict["dFDFth"] * window
            if verbose: log("Absolute value = %.3g" % window)
        else:
            if verbose:
                log("Using an absolute window cutoff of %.3g (%.1f x expected RMS)."
                    % (window, window / mDict["dFDFth"]))

    startTime = time.time()
    # Perform RM-clean on the spectrum
    cleanFDF, ccArr, iterCountArr, residFDF = \
              do_rmclean_hogbom(dirtyFDF        = dirtyFDF,
                                phiArr_radm2    = phiArr_radm2,
                                RMSFArr         = RMSFArr,
                                phi2Arr_radm2   = phi2Arr_radm2,
                                fwhmRMSFArr     = np.array(mDict["fwhmRMSF"]),
                                cutoff          = cutoff,
                                maxIter         = maxIter,
                                gain            = gain,
                                verbose         = verbose,
                                doPlots         = showPlots,
                                window          = window
                                )

    # ALTERNATIVE RM_CLEAN CODE ----------------------------------------------#
    '''
    cleanFDF, ccArr, fwhmRMSF, iterCount = \
              do_rmclean(dirtyFDF     = dirtyFDF,
                         phiArr       = phiArr_radm2,
                         lamSqArr     = lamSqArr_m2,
                         cutoff       = cutoff,
                         maxIter      = maxIter,
                         gain         = gain,
                         weight       = weightArr,
                         RMSFArr      = RMSFArr,
                         RMSFphiArr   = phi2Arr_radm2,
                         fwhmRMSF     = mDict["fwhmRMSF"],
                         doPlots      = True)
    '''
    #-------------------------------------------------------------------------#

    endTime = time.time()
    cputime = (endTime - startTime)
    if verbose: log("> RM-CLEAN completed in %.4f seconds." % cputime)

    # Measure the parameters of the deconvolved FDF
    mDict_cl = measure_FDF_parms(FDF=cleanFDF,
                                 phiArr=phiArr_radm2,
                                 fwhmRMSF=mDict["fwhmRMSF"],
                                 dFDF=mDict["dFDFth"],
                                 lamSqArr_m2=lambdaSqArr_m2,
                                 lam0Sq=mDict["lam0Sq_m2"])
    mDict_cl["cleanCutoff"] = cutoff
    mDict_cl["nIter"] = int(iterCountArr)

    # Measure the complexity of the clean component spectrum
    mDict_cl["mom2CCFDF"] = measure_fdf_complexity(phiArr=phiArr_radm2,
                                                   FDF=ccArr)

    #Calculating observed errors (based on dFDFcorMAD)
    mDict_cl["dPhiObserved_rm2"] = mDict_cl["dPhiPeakPIfit_rm2"] * mDict_cl[
        "dFDFcorMAD"] / mDict["dFDFth"]
    mDict_cl["dAmpObserved"] = mDict_cl["dFDFcorMAD"]
    mDict_cl["dPolAngleFitObserved_deg"] = mDict_cl[
        "dPolAngleFit_deg"] * mDict_cl["dFDFcorMAD"] / mDict["dFDFth"]
    mDict_cl["dPolAngleFit0Observed_deg"] = mDict_cl[
        "dPolAngle0Fit_deg"] * mDict_cl["dFDFcorMAD"] / mDict["dFDFth"]

    if verbose:
        # Print the results to the screen
        log()
        log('-' * 80)
        log('RESULTS:\n')
        log('FWHM RMSF = %.4g rad/m^2' % (mDict["fwhmRMSF"]))
        log('Pol Angle = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
            (mDict_cl["polAngleFit_deg"], mDict_cl["dPolAngleFitObserved_deg"],
             mDict_cl["dPolAngleFit_deg"]))
        log('Pol Angle 0 = %.4g (+/-%.4g observed, +- %.4g theoretical) deg' %
            (mDict_cl["polAngle0Fit_deg"],
             mDict_cl["dPolAngleFit0Observed_deg"],
             mDict_cl["dPolAngle0Fit_deg"]))
        log('Peak FD = %.4g (+/-%.4g observed, +- %.4g theoretical) rad/m^2' %
            (mDict_cl["phiPeakPIfit_rm2"], mDict_cl["dPhiObserved_rm2"],
             mDict_cl["dPhiPeakPIfit_rm2"]))
        log('freq0_GHz = %.4g ' % (mDict["freq0_Hz"] / 1e9))
        log('I freq0 = %.4g %s' % (mDict["Ifreq0"], mDict["units"]))
        log('Peak PI = %.4g (+/-%.4g observed, +- %.4g theoretical) %s' %
            (mDict_cl["ampPeakPIfit"], mDict_cl["dAmpObserved"],
             mDict_cl["dAmpPeakPIfit"], mDict["units"]))
        log('QU Noise = %.4g %s' % (mDict["dQU"], mDict["units"]))
        log('FDF Noise (theory)   = %.4g %s' %
            (mDict["dFDFth"], mDict["units"]))
        log('FDF Noise (Corrected MAD) = %.4g %s' %
            (mDict_cl["dFDFcorMAD"], mDict["units"]))
        log('FDF Noise (rms)   = %.4g %s' %
            (mDict_cl["dFDFrms"], mDict["units"]))

        log('FDF SNR = %.4g ' % (mDict_cl["snrPIfit"]))
        log()
        log('-' * 80)

    # Pause to display the figure
    if showPlots or saveFigures:
        fdfFig = plot_clean_spec(phiArr_radm2, dirtyFDF, cleanFDF, ccArr,
                                 residFDF, cutoff, window, mDict["units"])
    # Pause if plotting enabled
    if showPlots:
        plt.show()
    if saveFigures:
        if verbose: print("Saving CLEAN FDF plot:")
        outFilePlot = prefixOut + "_cleanFDF-plots.pdf"
        if verbose: print("> " + outFilePlot)
        fdfFig.savefig(outFilePlot, bbox_inches='tight')
        # print("Press <RETURN> to exit ...", end=' ')
        # input()

    #add array dictionary
    aDict_cl = dict()
    aDict_cl["phiArr_radm2"] = phiArr_radm2
    aDict_cl["freqArr_Hz"] = freqArr_Hz
    aDict_cl["cleanFDF"] = cleanFDF
    aDict_cl["ccArr"] = ccArr
    aDict_cl["iterCountArr"] = iterCountArr
    aDict_cl["residFDF"] = residFDF

    return mDict_cl, aDict_cl
Ejemplo n.º 7
0
def RM_synth(stokes,
             weight=True, # weighting needs more testing. Fails on certain events
             upchan=False, 
             RM_lim=None, 
             nSamples=None,
             normed=False,
             noise_type='theory',
             diagnostic_plots=False,
             cutoff=None):
    
    """ Performs rotation measure synthesis to extract Faraday Dispersion Function and RM measurement
    
    Parameters
    __________
    
    stokes : list (freq,I,Q,U,V,dI,dQ,dU,dV)
        Stokes params.
    weight : Bool. 
        Freq. channel std., used as to create array of weights for FDF
    band_lo, band_hi : float
        bottom and top freq. band limits of burst. 
    upchan: Bool
        If true, sets nSamples=3 
    RM_lim: float (optional)
        limits in Phi space to calculate the FDF
    nSamples: int (optional)
        sampling density in Phi space
    diagnostic_plots: Bool.
        outputs diagnostic plots of FDF
            
    Returns
    _______
    FDF params, (phi, FDF_arr) : list, array_like
        (RM,RM_err,PA,PA_err), FDF_arr
    """

    freqArr=stokes[0].copy()
    IArr=stokes[1].copy()
    QArr=stokes[2].copy()
    UArr=stokes[3].copy()
    VArr=stokes[4].copy()
    dIArr=stokes[5].copy()
    dQArr=stokes[6].copy()
    dUArr=stokes[7].copy()
    dVArr=stokes[8].copy()


    freqArr_Hz=freqArr*1e6
    lamArr_m=phys_const.speed_of_light/freqArr_Hz # convert to wavelength in m
    lambdaSqArr_m2=lamArr_m**2
    
    if normed is True:
        dQArr=IArr*np.sqrt((dQArr/QArr)**2+(dIArr/IArr)**2)
        dUArr=IArr*np.sqrt((dUArr/UArr)**2+(dIArr/IArr)**2)
        QArr/=IArr
        UArr/=IArr


    dQUArr = (dQArr + dUArr)/2.0
    if weight is True:
        weightArr = 1.0 / np.power(dQUArr, 2.0)
    else:
        weightArr = np.ones(freqArr_Hz.shape, dtype=float)
    dFDFth = np.sqrt( np.sum(weightArr**2 * dQUArr**2) / (np.sum(weightArr))**2 ) # check this equation!!!
    
    if nSamples is None:
        if upchan:
            nSamples=3 # sampling resolution of the FDF. 
        else:
            nSamples=10

    lambdaSqRange_m2 = (np.nanmax(lambdaSqArr_m2) - np.nanmin(lambdaSqArr_m2) )  
    fwhmRMSF_radm2 = 2.0 * np.sqrt(3.0) / lambdaSqRange_m2

#     dLambdaSqMin_m2 = np.nanmin(np.abs(np.diff(lambdaSqArr_m2)))
#     dLambdaSqMax_m2 = np.nanmax(np.abs(np.diff(lambdaSqArr_m2)))
    dLambdaSqMed_m2 = np.nanmedian(np.abs(np.diff(lambdaSqArr_m2)))

    dPhi_radm2 = fwhmRMSF_radm2 / nSamples

    #     phiMax_radm2 = np.sqrt(3.0) / dLambdaSqMax_m2
    phiMax_radm2 = np.sqrt(3.0) / dLambdaSqMed_m2 # sets the RM limit that can be probed based on intrachannel depolarization
    phiMax_radm2 = max(phiMax_radm2,600)    # Force the minimum phiMax

    if RM_lim  is None:
        # Faraday depth sampling. Zero always centred on middle channel
        nChanRM = int(round(abs((phiMax_radm2 - 0.0) / dPhi_radm2)) * 2.0 + 1.0)
        startPhi_radm2 = - (nChanRM-1.0) * dPhi_radm2 / 2.0
        stopPhi_radm2 = + (nChanRM-1.0) * dPhi_radm2 / 2.0
        phiArr_radm2 = np.linspace(startPhi_radm2, stopPhi_radm2, nChanRM)

    else:
        startPhi_radm2 = RM_lim[0]
        stopPhi_radm2 = RM_lim[1]
        nChanRM = int(round(abs((((stopPhi_radm2-startPhi_radm2)//2) - 0.0) / dPhi_radm2)) * 2.0 + 1.0)
        phiArr_radm2 = np.linspace(startPhi_radm2, stopPhi_radm2, nChanRM)
    
    phiArr_radm2 = phiArr_radm2.astype(np.float)
  
    ### constructing FDF ###

    dirtyFDF, lam0Sq_m2 = do_rmsynth_planes(
    QArr, 
    UArr, 
    lambdaSqArr_m2, 
    phiArr_radm2)

    RMSFArr, phi2Arr_radm2, fwhmRMSFArr, fitStatArr = get_rmsf_planes(
    lambdaSqArr_m2 = lambdaSqArr_m2,
    phiArr_radm2 = phiArr_radm2,
    weightArr=weightArr, 
    mskArr=None,
    lam0Sq_m2=lam0Sq_m2, 
    double = True) # routine needed for RM-cleaning 

    FDF, lam0Sq_m2 = do_rmsynth_planes(
    QArr, 
    UArr, 
    lambdaSqArr_m2, 
    phiArr_radm2,                   
    weightArr=weightArr, 
    lam0Sq_m2=None,
    nBits=32, 
    verbose=False)

    FDF_max=np.argmax(abs(FDF))
    FDF_med=np.median(abs(FDF))

    dFDFobs=np.median(abs(abs(FDF)-FDF_med)) / np.sqrt(np.pi/2) #MADFM definition of noise
#   dFDF_obs=np.nanstd(abs(FDF)) #std. definition of noise

    if noise_type is 'observed':
        FDF_snr=abs((abs(FDF)-FDF_med)/dFDFobs)/2
    if noise_type is 'theory':
        FDF_snr=abs((abs(FDF)-FDF_med)/dFDFth)/2

    mDict = measure_FDF_parms(FDF         = dirtyFDF,
                              phiArr      = phiArr_radm2,
                              fwhmRMSF    = fwhmRMSF_radm2,
                              dFDF        = dFDFth, #FDF_noise
                              lamSqArr_m2 = lambdaSqArr_m2,
                              lam0Sq      = lam0Sq_m2)

    RM_radm2_fit=mDict["phiPeakPIfit_rm2"]
    dRM_radm2_fit=mDict["dPhiPeakPIfit_rm2"]

    RM_radm2=phiArr_radm2[FDF_max]
    dRM_radm2=fwhmRMSF_radm2/(2*FDF_snr.max())

    polAngle0Fit_deg=mDict["polAngle0Fit_deg"]
    dPolAngle0Fit_deg=mDict["dPolAngle0Fit_deg"] * np.sqrt(freqArr.size) # np.sqrt(freqArr.size) term corrects for band-average noise 

    
    if cutoff is None:
    
        if diagnostic_plots:
            fig, ax = plt.subplots(2,1, figsize=(20,10))
            plt.subplots_adjust(left=0.1, bottom=0.1, right=0.99, top=0.95, wspace=0)
            ax[0].set_title('Faraday Dispersion Function')    
            ax[0].plot(phiArr_radm2,FDF_snr)
            ax[0].set_xlim([phiArr_radm2.min(), phiArr_radm2.max()])
            ax[1].plot(phiArr_radm2,FDF_snr)
            #     ax[1].axvline(RM_radm2, color='k', ls=':', label=r'RM=%.2f $\pm$ %0.2f rad/m$^2$' %(RM_radm2,dRM_radm2))
            ax[1].set_xlim(phiArr_radm2[FDF_max]-300,phiArr_radm2[FDF_max]+300)
            ax[1].set_xlabel('$\phi$ [rad/m$^2$]')
            fig.text(0.03, 0.5, 'Polarized Intensity [S/N]', va='center', rotation='vertical')
            #     plt.legend(fontsize=20)
            #     plt.tight_layout()

            if isinstance(diagnostic_plots, bool):
                plt.show()
            else:
                plot_name = "FDF.png"
                plt.savefig(os.path.join(diagnostic_plots, plot_name))
                plt.close("all")
            
        return (RM_radm2_fit,RM_radm2,dRM_radm2_fit,dRM_radm2,polAngle0Fit_deg,dPolAngle0Fit_deg),(phiArr_radm2,FDF_snr)

    else:

        if noise_type is 'observed':
            cutoff_abs = dFDFobs*cutoff
        if noise_type is 'theory':
            cutoff_abs = dFDFth*cutoff

        cleanFDF, ccArr, iterCountArr, residFDF = do_rmclean_hogbom(dirtyFDF = FDF,
                                phiArr_radm2    = phiArr_radm2,
                                RMSFArr         = RMSFArr,
                                phi2Arr_radm2   = phi2Arr_radm2,
                                fwhmRMSFArr     = fwhmRMSF_radm2,
                                cutoff          = cutoff_abs,
    #                                 maxIter         = maxIter,
    #                                 gain            = gain,
    #                                 verbose         = verbose,
                                doPlots         = True)


        FDF_max=np.argmax(abs(cleanFDF))
        FDF_med=np.median(abs(cleanFDF))

        dFDFobs=np.median(abs(abs(cleanFDF)-FDF_med)) / np.sqrt(np.pi/2) #MADFM definition of noise                                                      #   dFDF_obs=np.nanstd(abs(FDF)) #std. definition of noise                                                                                      
        if noise_type is 'observed':
            FDF_snr_clean=abs((abs(cleanFDF)-FDF_med)/dFDFobs)/2
            ccArr_snr=(abs(ccArr)/dFDFobs)/2
        if noise_type is 'theory':
            FDF_snr_clean=abs((abs(cleanFDF)-FDF_med)/dFDFth)/2
            ccArr_snr=(abs(ccArr)/dFDFth)/2

        mDict = measure_FDF_parms(FDF     = cleanFDF,
                              phiArr      = phiArr_radm2,
                              fwhmRMSF    = fwhmRMSF_radm2,
                              dFDF        = dFDFth, #FDF_noise
                              lamSqArr_m2 = lambdaSqArr_m2,
                              lam0Sq      = lam0Sq_m2)

        RM_radm2_fit=mDict["phiPeakPIfit_rm2"]
        dRM_radm2_fit=mDict["dPhiPeakPIfit_rm2"]

        RM_radm2=phiArr_radm2[FDF_max]
        dRM_radm2=fwhmRMSF_radm2/(2*FDF_snr_clean.max())

        polAngle0Fit_deg=mDict["polAngle0Fit_deg"]
        dPolAngle0Fit_deg=mDict["dPolAngle0Fit_deg"] * np.sqrt(freqArr.size) # np.sqrt(freqArr.size) term corrects for band-average noise 


        if diagnostic_plots:
            fig, ax = plt.subplots(2,1, figsize=(20,10))
            plt.subplots_adjust(left=0.1, bottom=0.1, right=0.99, top=0.95, wspace=0)
            ax[0].set_title('Faraday Dispersion Function')    
            ax[0].plot(phiArr_radm2,FDF_snr_clean, label='clean FDF')
            ax[0].plot(phiArr_radm2,FDF_snr, label='dirty FDF')
            ax[0].axhline(cutoff, ls='--', color='k', label='clean cutoff')
            ax[0].legend()
            ax[0].set_xlim([phiArr_radm2.min(), phiArr_radm2.max()])
            ax[1].plot(phiArr_radm2,FDF_snr_clean, label='clean FDF')
            ax[1].plot(phiArr_radm2,FDF_snr, label='dirty FDF')
            ax[1].axhline(cutoff, ls='--', color='k',label='clean cutoff')
            ax[1].legend()
            ax[1].set_xlim(phiArr_radm2[FDF_max]-300,phiArr_radm2[FDF_max]+300)
            ax[1].set_xlabel('$\phi$ [rad/m$^2$]')
            fig.text(0.03, 0.5, 'Polarized Intensity [S/N]', va='center', rotation='vertical')

            if isinstance(diagnostic_plots, bool):
                plt.show()
            else:
                plot_name = "FDF.png"
                plt.savefig(os.path.join(diagnostic_plots, plot_name))
                plt.close("all")
                            
            fig, ax = plt.subplots(2,1,figsize=(20,10))
            plt.subplots_adjust(left=0.1, bottom=0.1, right=0.99, top=0.95, wspace=0, hspace=0.0)
            ax[0].set_title('Faraday Dispersion Function')    
            ax[0].plot(phi2Arr_radm2,RMSFArr, label='RMTF')
            ax[0].set_xlim([-300,300])
            ax[0].xaxis.set_ticklabels([])
            ax[0].legend()
            ax[1].plot(phiArr_radm2,FDF_snr_clean, label='clean FDF')
            ax[1].bar(phiArr_radm2,ccArr_snr, color='g', label='clean components')
            ax[1].legend()
            ax[1].set_xlim(phiArr_radm2[FDF_max]-300,phiArr_radm2[FDF_max]+300)
            ax[1].set_xlabel('$\phi$ [rad/m$^2$]')
            fig.text(0.03, 0.5, 'Polarized Intensity [S/N]', va='center', rotation='vertical')
            #     plt.legend(fontsize=20)
            #     plt.tight_layout()

            if isinstance(diagnostic_plots, bool): 
                plt.show()
            else:
                plot_name = "FDF_clean.png"
                plt.savefig(os.path.join(diagnostic_plots, plot_name))
                plt.close("all")

        return (RM_radm2_fit,RM_radm2,dRM_radm2_fit,dRM_radm2,polAngle0Fit_deg,dPolAngle0Fit_deg),(phiArr_radm2,FDF_snr_clean)
Ejemplo n.º 8
0
def run_rmclean(fdfFile,
                rmsfFile,
                weightFile,
                rmSynthFile,
                cutoff,
                maxIter=1000,
                gain=0.1,
                prefixOut="",
                outDir="",
                nBits=32,
                showPlots=False,
                doAnimate=False):
    """
    Run RM-CLEAN on a complex FDF spectrum given a RMSF.
    """

    # Default data types
    dtFloat = "float" + str(nBits)
    dtComplex = "complex" + str(2 * nBits)

    # Read the frequency vector for the lambda^2 array
    freqArr_Hz, weightArr = np.loadtxt(weightFile, unpack=True, dtype=dtFloat)
    lambdaSqArr_m2 = np.power(C / freqArr_Hz, 2.0)

    # Read the FDF from the ASCII file
    phiArr_radm2, FDFreal, FDFimag = np.loadtxt(fdfFile,
                                                unpack=True,
                                                dtype=dtFloat)
    dirtyFDF = FDFreal + 1j * FDFimag

    # Read the RMSF from the ASCII file
    phi2Arr_radm2, RMSFreal, RMSFimag = np.loadtxt(rmsfFile,
                                                   unpack=True,
                                                   dtype=dtFloat)
    RMSFArr = RMSFreal + 1j * RMSFimag

    # Read the RM-synthesis parameters from the JSON file
    mDictS = json.load(open(rmSynthFile, "r"))

    # If the cutoff is negative, assume it is a sigma level
    print "Expected RMS noise = %.4g mJy/beam/rmsf"  % \
        (mDictS["dFDFth_Jybm"]*1e3)
    if cutoff < 0:
        print "Using a sigma cutoff of %.1f." % (-1 * cutoff),
        cutoff = -1 * mDictS["dFDFth_Jybm"] * cutoff
        print "Absolute value = %.3g" % cutoff
    else:
        print "Using an absolute cutoff of %.3g (%.1f x expected RMS)." % \
            (cutoff, cutoff/mDictS["dFDFth_Jybm"])

    startTime = time.time()

    # Perform RM-clean on the spectrum
    cleanFDF, ccArr, iterCountArr = \
              do_rmclean_hogbom(dirtyFDF        = dirtyFDF,
                                phiArr_radm2    = phiArr_radm2,
                                RMSFArr         = RMSFArr,
                                phi2Arr_radm2   = phi2Arr_radm2,
                                fwhmRMSFArr     = np.array(mDictS["fwhmRMSF"]),
                                cutoff          = cutoff,
                                maxIter         = maxIter,
                                gain            = gain,
                                verbose         = False,
                                doPlots         = showPlots,
                                doAnimate       = doAnimate)
    cleanFDF  #/= 1e3
    ccArr  #/= 1e3

    # ALTERNATIVE RM_CLEAN CODE ----------------------------------------------#
    '''
    cleanFDF, ccArr, fwhmRMSF, iterCount = \
              do_rmclean(dirtyFDF     = dirtyFDF,
                         phiArr       = phiArr_radm2,
                         lamSqArr     = lamSqArr_m2,
                         cutoff       = cutoff,
                         maxIter      = maxIter,
                         gain         = gain,
                         weight       = weightArr,
                         RMSFArr      = RMSFArr,
                         RMSFphiArr   = phi2Arr_radm2,
                         fwhmRMSF     = mDictS["fwhmRMSF"],
                         doPlots      = True)
    '''
    #-------------------------------------------------------------------------#

    endTime = time.time()
    cputime = (endTime - startTime)
    print "> RM-CLEAN completed in %.4f seconds." % cputime

    # Measure the parameters of the deconvolved FDF
    mDict = measure_FDF_parms(
        FDF=cleanFDF,
        phiArr=phiArr_radm2,
        fwhmRMSF=mDictS["fwhmRMSF"],
        #dFDF        = mDictS["dFDFth_Jybm"],
        lamSqArr_m2=lambdaSqArr_m2,
        lam0Sq=mDictS["lam0Sq_m2"])
    mDict["cleanCutoff"] = cutoff
    mDict["nIter"] = int(iterCountArr)

    # Measure the complexity of the clean component spectrum
    mDict["mom2CCFDF"] = measure_fdf_complexity(phiArr=phiArr_radm2, FDF=ccArr)

    # Save the deconvolved FDF and CC model to ASCII files
    print "Saving the clean FDF and component model to ASCII files."
    outFile = prefixOut + "_FDFclean.dat"
    print "> %s" % outFile
    np.savetxt(outFile, zip(phiArr_radm2, cleanFDF.real, cleanFDF.imag))
    outFile = prefixOut + "_FDFmodel.dat"
    print "> %s" % outFile
    np.savetxt(outFile, zip(phiArr_radm2, ccArr))

    # Save the RM-clean measurements to a "key=value" text file
    print "Saving the measurements on the FDF in 'key=val' and JSON formats."
    outFile = prefixOut + "_RMclean.dat"
    print "> %s" % outFile
    FH = open(outFile, "w")
    for k, v in mDict.iteritems():
        FH.write("%s=%s\n" % (k, v))
    FH.close()
    outFile = prefixOut + "_RMclean.json"
    print "> %s" % outFile
    json.dump(mDict, open(outFile, "w"))

    # Print the results to the screen
    print
    print '-' * 80
    print 'RESULTS:\n'
    print 'FWHM RMSF = %.4g rad/m^2' % (mDictS["fwhmRMSF"])

    print 'Pol Angle = %.4g (+/-%.4g) deg' % (mDict["polAngleFit_deg"],
                                              mDict["dPolAngleFit_deg"])
    print 'Pol Angle 0 = %.4g (+/-%.4g) deg' % (mDict["polAngle0Fit_deg"],
                                                mDict["dPolAngle0Fit_deg"])
    print 'Peak FD = %.4g (+/-%.4g) rad/m^2' % (mDict["phiPeakPIfit_rm2"],
                                                mDict["dPhiPeakPIfit_rm2"])
    print 'freq0_GHz = %.4g ' % (mDictS["freq0_Hz"] / 1e9)
    print 'I freq0 = %.4g mJy/beam' % (mDictS["Ifreq0_mJybm"])
    print 'Peak PI = %.4g (+/-%.4g) mJy/beam' % (
        mDict["ampPeakPIfit_Jybm"] * 1e3, mDict["dAmpPeakPIfit_Jybm"] * 1e3)
    print 'QU Noise = %.4g mJy/beam' % (mDictS["dQU_Jybm"] * 1e3)
    print 'FDF Noise (measure) = %.4g mJy/beam' % (mDict["dFDFms_Jybm"] * 1e3)
    print 'FDF SNR = %.4g ' % (mDict["snrPIfit"])
    print
    print '-' * 80

    # Pause to display the figure
    if showPlots or doAnimate:
        print "Press <RETURN> to exit ...",
        raw_input()