Multi-epoch data combination for spectral cubes =============================================== (After the original guide by Dane Kleiner) There are several ways to combine multi-epoch data with ASKAPsoft: * Do all the calibration and imaging separately and then combine the images using linear mosaicking (program linmos-mpi) * Combine data for the same beams and footprints in the UV-plane during imaging, gaining the advantage of better signal to noise during the deconvolution, then combine the images as before using linmos * Combine all the data during imaging, doing a full non-linear mosaic using A-projection. This option would be preferred to best recover extended emission, but it requires knowledge of the primary beams to an accuracy we don't have yet. It also tends to requires more memory (and possibly time) than is available on galaxy and thus will not be described here at the moment. General info: To submit any of the example slurm files, copy the text into a .sbatch, modify the necessary parts and submit using *sbatch file.sbatch*. In any of the slurm files: 1. If you want to produce the slurm output, log and parset then you need to point each of them to a valid directory. E.g., I create a directory for each in the work directory that I run the task. 2. Submit to galaxy/magnus in the #SBATCH preamble clusters 3. Insert your email address into #SBATCH ­­mail 4. Set your work directory using #SBATCH workdir 5. Change the #SBATCH ­­output, parset and log directories 6. Change the #SBATCH ­­job­name according to the beam you are processing. 1) Combining in the Image plane ------------------------------- This is the most straightforward method. You just feed the linmos program all the individual restored images and corresponding weights images. Beware that this path limits your clean deconvolution to the sensitivity of a single night. Here is an example slurm file that will use linmos to mosaic images together:: #!/bin/bash -l #SBATCH --partition=workq #SBATCH --clusters=galaxy # Using the default account # No reservation requested #SBATCH --time=12:00:00 #SBATCH --ntasks=200 #SBATCH --ntasks-per-node=20 #SBATCH --job-name=linmosFullScontsub #SBATCH --mail-user=first.last@csiro.au #SBATCH --mail-type=FAIL #SBATCH --export=NONE #SBATCH --workdir=/group/askap///COMBINED_IMAGE_PLANE #SBATCH --output=slurmOutput/slurm-linmosS-%j.out # Using user-defined askapsoft module module use /group/askap/modulefiles module load askapdata # ### Decide if we need a specific version here module load askapsoft module load askappipeline IMAGETYPE_SPECTRAL="casa" imList="$(cat imList.txt)" wtList="$(cat wtList.txt)" imageName=image.restored.wr.1.i..cube.combined16_img.contsub.linmos weightsImage=weights.wr.1.i..cube.combined16_img.contsub.linmos echo "Mosaicking to form ${imageName}" parset=parsets/science_linmos_${SLURM_JOB_ID}.in log=logs/science_linmos_${SLURM_JOB_ID}.log cat > "${parset}" << EOFINNER linmos.names = [${imList}] linmos.weights = [${wtList}] linmos.imagetype = ${IMAGETYPE_SPECTRAL} linmos.outname = ${imageName%%.fits} linmos.outweight = ${weightsImage%%.fits} linmos.weightstate = Inherent linmos.weighttype = Combined linmos.cutoff = 0.2 EOFINNER NCORES=200 NPPN=20 srun --export=ALL --ntasks=${NCORES} --ntasks-per-node=${NPPN} linmos-mpi -c "$parset" > "$log" Things to change / be aware of: * imList is the list of images you give to linmos. In this example, I'm pointing it to a text file (imList.txt) that lists the images separated by a comma e.g. restored.contsub.image1, restored.contsub.image2 . Alternatively, you can give the list of images to the imList variable in the slurm file. * wtList is the list of weights images produced by imager specified in exactly the same fashion as imList. * imageName and weightsImage are the names of the output image and weight map from linmos. * Provided no primary beam correction has been applied weightstate=Inherent and weighttype=Combined 2) Hybrid combination: UV + image plane --------------------------------------- This is broken into 3 parts: 1. Imaging 2. Image based continuum subtraction 3. Mosaicking 2.1) Imaging ------------ Important info: 1. This method uses the imager program. You feed imager calibrated measurement sets (i.e., the sciencedata.ms not averaged.ms or averaged_cal.ms) with the same phase centre (pointing). Essentially, this can only be done on individual beams of the same footprint and orientation. 2. Each calibrated measurement set must have the same number of channels and the same starting frequency 3. This job can and should be parallelised. To do so, you need to set: #SBATCH ­­ntasks and Cimager.nchanpercore. To do this: Start with the number of channels in your measurement set (649 in this case), nchanpercore = a number (11 in this case) that evenly divides into your number of channels and ntasks-1 = (# of chans) / nchanpercore (60 in this case). NCORES (found at the bottom of the slurm file) is the same as ntasks and they should be set to the same value. To clarify ­ ntask­per­node is the number of processes that run on a single node. It has to be <=ntasks where the maximum is 20 for galaxy and 24 for magnus. The choice of this number is going to be influenced by the memory usage of your job ­ if you increase the size of images, for instance, you may not be able to fit 20 jobs on a node given the total node memory budget of 64GB) 4. The example below allows to combine old and new data with slightly different frequency labelling (up to 10 Hz in this case). The line Cimager.channeltolerance=10.0 takes care of that. 5. Below is an example slurm file that will use imager to image multiple measurement sets.:: #!/bin/bash -l #SBATCH --partition=workq #SBATCH --clusters=galaxy # Using the default account # No reservation requested #SBATCH --time=12:00:00 #SBATCH --ntasks=60 #SBATCH --ntasks-per-node=10 #SBATCH --job-name=spec_F00B09 #SBATCH --mail-user=first.last@csiro.au #SBATCH --mail-type=FAIL #SBATCH --export=NONE #SBATCH --workdir=/group/askap///COMBINED_ALL #SBATCH --output=slurmOutput/slurm-science_spectral_imager-B09-%j.out # Using user-defined askapsoft module module use /group/askap/modulefiles module load askapdata module unload askapsoft module load askapsoft/0.19.6 module unload askappipeline module load askappipeline/0.19.6 beam_no="09" parset=parsets/science_spectral_imager_F00_B${beam_no}_${SLURM_JOB_ID}.in # Footprint A # Beam 09 direction="[22h20m51.830, -45.42.58.82, J2000]" # Footprint A msin="11Aug_${beam_no}_A_1-649.ms, 12Aug_${beam_no}_A_1-649.ms, 11Oct_${beam_no}_A_1-649.ms" # Output name imOut="image.i..cube.combinedA.b${beam_no}" cat > "$parset" << EOF Cimager.dataset = [$msin] Cimager.imagetype = casa Cimager.channeltolerance=10.0 # Cimager.Images.Names = [$imOut] Cimager.Images.shape = [1024, 1024] Cimager.Images.cellsize = [6arcsec, 6arcsec] Cimager.Images.direction= ${direction} Cimager.Images.restFrequency = HI # Options for the alternate imager Cimager.nchanpercore = 11 Cimager.usetmpfs = false Cimager.tmpfs = /dev/shm # barycentre and multiple solver mode not supported in continuum imaging (yet) Cimager.barycentre = true Cimager.solverpercore = true Cimager.nwriters = 1 Cimager.singleoutputfile= false # # This defines the parameters for the gridding. Cimager.gridder.snapshotimaging = true Cimager.gridder.snapshotimaging.wtolerance = 2600 Cimager.gridder.snapshotimaging.longtrack = true Cimager.gridder.snapshotimaging.clipping = 0.01 Cimager.gridder = WProject Cimager.gridder.WProject.wmax = 2600 Cimager.gridder.WProject.nwplanes = 99 Cimager.gridder.WProject.oversample = 4 Cimager.gridder.WProject.maxsupport = 512 Cimager.gridder.WProject.variablesupport = true Cimager.gridder.WProject.offsetsupport = true # # These parameters define the clean algorithm Cimager.solver = Clean Cimager.solver.Clean.algorithm = BasisfunctionMFS Cimager.solver.Clean.niter = 5000 Cimager.solver.Clean.gain = 0.1 Cimager.solver.Clean.scales = [0,3,10] Cimager.solver.Clean.verbose = False Cimager.solver.Clean.tolerance = 0.01 Cimager.solver.Clean.weightcutoff = zero Cimager.solver.Clean.weightcutoff.clean = false Cimager.solver.Clean.psfwidth = 512 Cimager.solver.Clean.logevery = 50 Cimager.threshold.minorcycle = [40%, 9mJy] Cimager.threshold.majorcycle = 10mJy Cimager.ncycles = 5 Cimager.Images.writeAtMajorCycle = false # Cimager.preconditioner.Names = [Wiener] #Cimager.preconditioner.GaussianTaper = 30arcsec Cimager.preconditioner.preservecf = true Cimager.preconditioner.Wiener.robustness = 0.5 # # These parameter govern the restoring of the image and the recording of the beam Cimager.restore = true Cimager.restore.beam = fit Cimager.restore.beam.cutoff = 0.5 Cimager.restore.beamReference = mid EOF log=logs/science_spectral_imager_F00_B${beam_no}_${SLURM_JOB_ID}.log # Now run the imager NCORES=60 NPPN=10 srun --export=ALL --ntasks=${NCORES} --ntasks-per-node=${NPPN} imager -c "$parset" > "$log" Things to change / be aware of: * Change the beam_no, object name etc. * Change the workdir accordingly and make sure­ the calibrated measurement sets are all there. * The direction is essential. It can be found in the science_imager parset from when you ran the pipeline on the same beam and orientation. You will need to look this up and replace it with the relevant co­ordinates. * Change msin to point to all the measurement sets you would like to image. I.e., If you want to put 3 images together, there should be 3 measurement sets in msin. * imOut sets the image name of the output. * Change the imaging parameters according to your preferred weighting, cleaning algorithm etc. See documentation on imager. * The most important parameters to change are the cleaning thresholds: Cimager.threshold.minorcycle and Cimager.threshold.majorcycle. minorcyle should be ~4 sigma and majorcycle should be ~4.1 sigma based on the expected rms given the number of images you are feeding imager. * Remember to set Cimager.nchanpercore and ntasks accordingly. ­ NCORES (bottom of slurm file) is the same as ntasks, make sure you change it as well. 2.2) Image based continuum subtraction -------------------------------------- ­As you have just imaged N MeasurementSets together, it is likely that continuum residuals have become visible and a (second) continuum subtraction is needed. This can be accomplished by feeding imcontsub the combined image cube produced in the previous step. Here is an example slurm file that will use imcontsub to remove continuum residuals:: #!/bin/bash -l #SBATCH --partition=workq #SBATCH --clusters=galaxy # Using the default account # No reservation requested #SBATCH --time=12:00:00 #SBATCH --ntasks=1 #SBATCH --ntasks-per-node=1 #SBATCH --job-name=imcontsub1_F00B09 #SBATCH --mail-user=first.last@csiro.au #SBATCH --mail-type=FAIL #SBATCH --export=NONE #SBATCH --workdir=/group/askap///COMBINED_ALL #SBATCH --output=slurmOutput/slurm-imcontsubSL-%j.out # Swapping to the requested askapsoft module module use /group/askap/modulefiles module load askapdata module load askapsoft module load askappipeline module load casa beam_no="09" IMAGE_BASE_SPECTRAL=i..cube.combinedA.beam${beam_no} imageName=image.restored.wr.1.${IMAGE_BASE_SPECTRAL} if [ ! -e "${imageName}" ]; then echo "Image cube ${imageName} does not exist." echo "Not running image-based continuum subtraction" else # Make a working directory - the casapy & ipython log files will go in here. # This will prevent conflicts between simultaneous jobs workdir=imcontsub-working-beam${BEAM} mkdir -p $workdir cd $workdir pyscript=../parsets/spectral_imcontsub_F00_B${beam_no}_${SLURM_JOB_ID}.py cat > "$pyscript" << EOFINNER #!/usr/bin/env python # Need to import this from ACES import sys sys.path.append('/group/askap/acesops/ACES-r47210/tools') from robust_contsub import robust_contsub image="../${imageName}" threshold=2.0 fit_order=2 n_every=1 rc=robust_contsub() rc.poly(infile=image,threshold=threshold,verbose=True,fit_order=fit_order,n_every=n_every,log_every=10) EOFINNER log=logs/spectral_imcontsub_F00_B${beam_no}_${SLURM_JOB_ID}.log NCORES=1 NPPN=1 #srun --export=ALL --ntasks=${NCORES} --ntasks-per-node=${NPPN} casa --nogui --nologger --log2term -c $ACES/tools/robust_contsub.py srun --export=ALL --ntasks=${NCORES} --ntasks-per-node=${NPPN} casa --nogui --nologger --log2term -c "$pyscript" > "$log" err=$? cd .. if [ $err != 0 ]; then exit $err fi if [ "${imageName%%.fits}" != "${imageName}" ]; then # Want image.contsub.fits, not image.fits.contsub echo "Renaming ${imageName}.contsub to ${imageName%%.fits}.contsub.fits" mv ${imageName}.contsub ${imageName%%.fits}.contsub.fits fi fi Things to change / be aware of: * Change the beam_no accordingly. * IMAGE_BASE_SPECTRAL and imageName is where you tell imcontsub the input image. Alternatively, you could directly give it in imageName. 2.3 Mosaicking -------------- This step is almost the same as the mosaicking task when combining in the image plane:­­ feed linmos combined, continuum subtracted images you previously made instead of the images of each individual night. Here is an example slurm file that will use linmos to mosaic (combined) images together:: #!/bin/bash -l #SBATCH --partition=workq #SBATCH --clusters=galaxy # Using the default account # No reservation requested #SBATCH --time=12:00:00 #SBATCH --ntasks=650 #SBATCH --ntasks-per-node=20 #SBATCH --job-name=linmosFullScontsub #SBATCH --mail-user=first.last@csiro.au #SBATCH --mail-type=FAIL #SBATCH --export=NONE #SBATCH --workdir=/group/askap///COMBINED_ALL #SBATCH --output=slurmOutput/slurm-linmosS-%j.out # Using user-defined askapsoft module module use /group/askap/modulefiles module load askapdata module load askapsoft module load askappipeline IMAGETYPE_SPECTRAL="casa" imList="image.restored.wr.1.i.N7232.cube.B0.b10.contsub","image.restored.wr.1.i.N7232.cube.B0.b25.contsub","image.restored.wr.1.i.N7232.cube.2Arot.b08" wtList="weights.wr.1.i.N7232.cube.B0.b10","weights.wr.1.i.N7232.cube.B0.b25","weights.wr.1.i.N7232.cube.2Arot.b08" imageName=image.restored.wr.1.i.N7232.cube.combined16_R.5.linmos.contsub weightsImage=weights.wr.1.i.N7232.cube.combined16_R.5.linmos.contsub echo "Mosaicking to form ${imageName}" parset=parsets/science_linmos_${SLURM_JOB_ID}.in log=logs/science_linmos_${SLURM_JOB_ID}.log cat > "${parset}" << EOFINNER linmos.names = [${imList}] linmos.weights = [${wtList}] linmos.imagetype = ${IMAGETYPE_SPECTRAL} linmos.outname = ${imageName%%.fits} linmos.outweight = ${weightsImage%%.fits} linmos.weightstate = Inherent linmos.weighttype = Combined linmos.cutoff = 0.2 EOFINNER NCORES=650 NPPN=20 srun --export=ALL --ntasks=${NCORES} --ntasks-per-node=${NPPN} linmos-mpi -c "$parset" > "$log" Things to change / be aware of: * imList is the list of images you give to linmos. In this example, I have given the combined, continuum subtracted images directly to the imList variable. * wtList is the list of weights images produced by imager specified in exactly the same fashion as imList. * imageName and weightsImage are the names of the output image and weight map from linmos. * Provided no primary beam correction has been applied use weightstate=Inherent and weighttype=Combined