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
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()
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()
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
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
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
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)
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()