diff --git a/imcal.py b/imcal.py
index 7c27d3845b7de3cde65c8c561d33569881582e5c..7482ae9f3a17e9f459a7f2d73941af636ab96e10 100755
--- a/imcal.py
+++ b/imcal.py
@@ -34,6 +34,12 @@ makesourcedb_bin = distutils.spawn.find_executable('makesourcedb') or '/home/off
 bbs2model_bin = distutils.spawn.find_executable('bbs2model') or '/home/offringa/Software/lofartools/build/bbs2model'
 render_bin = distutils.spawn.find_executable('render') or '/home/offringa/Software/lofartools/build/render'
 
+# Tom's masking code
+makeMaskFits = '/home/kutkin/rapthor/makeMaskFits'
+makeNoiseMapFits = '/home/kutkin/rapthor/makeNoiseMapFits'
+cfitsio_dir = '/home/kutkin/lib/cfitsio-3.49'
+
+
 _POOL_TIME = 300 # SECONDS
 _MAX_TIME = 1 * 3600 # SECONDS
 _MAX_POOL = _MAX_TIME // _POOL_TIME
@@ -48,38 +54,63 @@ def modify_filename(fname, string, ext=None):
 
 
 def wsclean(msin, outname=None, pixelsize=3, mgain=0.8, imagesize=3072, multifreq=8, autothresh=0.3,
-            automask=3, multiscale=False, kwstring=''):
+            automask=3, niter=1000000, multiscale=False, save_source_list=True,
+            usefitsmask=False, fitsmaskname='mask.fits',
+            kwstring=''):
     """
     wsclean
     """
-    # wsclean_bin = subprocess.check_output('which wsclean; exit 0', shell=True).strip() or '/home/soft/wsclean/wsclean/build/wsclean'
-    # logging.debug('wsclean binary: {}'.format(wsclean_bin))
     msbase = os.path.splitext(msin)[0]
     if outname is None:
         outname = msbase
-
     if multiscale:
         kwstring += ' -multiscale'
     if autothresh is not None:
         kwstring += f' -auto-threshold {autothresh}'
+    if automask is not None:
+        kwstring += f' -auto-mask {automask}'
+    if mgain is not None:
+        kwstring += f' -mgain {mgain}'
+    if save_source_list:
+        kwstring += ' -save-source-list'
     if multifreq:
         kwstring += f' -join-channels -channels-out {multifreq} -fit-spectral-pol 2'
-    cmd = f'{wsclean_bin} -name {outname} -size {imagesize} {imagesize} -scale {pixelsize}asec -niter 1000000 \
-              -auto-mask {automask} -save-source-list -mgain {mgain} {kwstring} {msin}'
-              # .\
-              # format(wsclean=wsclean_bin, outname=outname, pix=pixelsize, autothresh=autothresh,
-                     # automask=automask, imsize=imagesize, kwstring=kwstring, msin=msin)
+    if usefitsmask:
+        kwstring += f' -fits-mask {fitsmaskname}'
+
+    cmd = f'{wsclean_bin} -name {outname} -size {imagesize} {imagesize} -scale {pixelsize}asec -niter {niter} \
+            {kwstring} {msin}'
     cmd = " ".join(cmd.split())
     logging.debug("Running command: %s", cmd)
     subprocess.call(cmd, shell=True)
 
-    if multifreq:
-        for fname in glob.glob(msbase+'-*.fits'):
-            newname = fname.replace('MFS-', '')
-            os.rename(fname, newname)
+    for fname in glob.glob(outname+'*.fits'):
+        newname = fname.replace('MFS-', '')
+        os.rename(fname, newname)
     return 0
 
 
+def create_mask(imgfits, residfits, clipval, outname='mask.fits'):
+    """
+    Create mask using Tom's code (e-mail on 1 Jul 2021)
+    """
+    if not cfitsio_dir in os.environ['LD_LIBRARY_PATH']:
+        os.environ['LD_LIBRARY_PATH'] += f':{cfitsio_dir}'
+
+    subprocess.call(f'{makeNoiseMapFits} {imgfits} {residfits} noise.fits noiseMap.fits', shell=True)
+    subprocess.call(f'{makeMaskFits} noiseMap.fits {outname} {clipval}', shell=True)
+    return outname
+
+
+def get_image_max(msin):
+    """
+    Determine maximum image value for msin
+    """
+    cmd = f'{wsclean_bin} -niter 0 -size 3072 3072 -scale 3arcsec -use-wgridder {msin}'
+    subprocess.call(cmd, shell=True)
+    return np.nanmax(fits.getdata('wsclean-image.fits'))
+
+
 def makesourcedb(modelfile, out=None):
     """ Make sourcedb file from a clustered model """
     # makesourcedb_bin = subprocess.check_output('which makesourcedb; exit 0', shell=True).strip() or makesourcedb_bin
@@ -152,7 +183,7 @@ def split_ms(msin_path, startchan, nchan=0, msout_path=''):
 
 
 def dical(msin, srcdb, msout=None, h5out=None, solint=1, startchan=0, split_nchan=0,
-          mode='phaseonly', cal_nchan=31, uvlambdamin=500):
+          mode='phaseonly', cal_nchan=0, uvlambdamin=500):
     """ direction independent calibration with DPPP """
     h5out = h5out or modify_filename(msin, f'_dical_dt{solint}_{mode}', ext='.h5')
     msout = msout or modify_filename(msin, f'_dical_dt{solint}_{mode}')
@@ -215,7 +246,7 @@ def phase_shift(msin, new_center, msout=None):
     subprocess.call(cmd, shell=True)
 
 
-def view_sols(h5param):
+def view_sols(h5param, outname=None):
     """ read and plot the gains """
     path = os.path.split(os.path.abspath(h5param))[0]
     def plot_sols(h5param, key):
@@ -244,17 +275,18 @@ def view_sols(h5param):
                     ax.set_xlabel('Time (hrs)')
         return fig, ax
 
-    try:
-        fig, ax = plot_sols(h5param, 'amplitude000')
-        fig.savefig(path + '/amp_sols.png')
-    except:
-        logging.error('No amplitude solutions found')
+    if outname is not None:
+        try:
+            fig1, ax1 = plot_sols(h5param, 'amplitude000')
+            fig1.savefig(f'{outname}_amp.png')
+        except:
+            logging.error('No amplitude solutions found')
 
-    try:
-        fig, ax = plot_sols(h5param, 'phase000')
-        fig.savefig(path + '/phase_sols.png')
-    except:
-        logging.error('No phase solutions found')
+        try:
+            fig2, ax2 = plot_sols(h5param, 'phase000')
+            fig2.savefig(f'{outname}_phase.png')
+        except:
+            logging.error('No phase solutions found')
 
     # plt.show()
 
@@ -299,11 +331,16 @@ def main(msin, outbase=None, cfgfile='imcal.yml'):
 
     ms_split = msbase + '_splt.MS'
 
+    img0 = outbase + '_0'
     img1 = outbase + '_1'
     img2 = outbase + '_2'
     img3 = outbase + '_3'
     img_final = outbase
 
+    mask0 = 'mask0.fits'
+    mask1 = 'mask1.fits'
+    mask2 = 'mask2.fits'
+
     model1 = outbase + '_model1.sourcedb'
     model2 = outbase + '_model2.sourcedb'
     model3 = outbase + '_model3.sourcedb'
@@ -326,7 +363,15 @@ def main(msin, outbase=None, cfgfile='imcal.yml'):
 
 # Clean + DIcal
 
-    # img_peak = fits.getdata('
+
+    if not os.path.exists(img0 +'-image.fits') and (not os.path.exists(img0 +'-MFS-image.fits')):
+        img_max = get_image_max(ms_split)
+        threshold = img_max/cfg['clean0']['max_over_thresh']
+        wsclean(ms_split, outname=img0, automask=None, save_source_list=False, multifreq=False, mgain=None,
+            kwstring=f'-threshold {threshold}')
+        create_mask(img0 +'-image.fits', img0 +'-residual.fits', clipval=20, outname='mask0.fits')
+
+# clean1
     if not os.path.exists(img1 +'-image.fits') and (not os.path.exists(img1 +'-MFS-image.fits')):
         wsclean(ms_split, outname=img1, **cfg['clean1']) # fast shallow clean
 
@@ -335,28 +380,31 @@ def main(msin, outbase=None, cfgfile='imcal.yml'):
 
     if not os.path.exists(dical1):
         dical1 = dical(ms_split, model1, msout=dical1, h5out=h5_1, **cfg['dical1'])
-        view_sols(h5_1)
-
+        view_sols(h5_1, outname='dical1')
+# clean2
     if (not os.path.exists(img2 +'-image.fits')) and (not os.path.exists(img2 +'-MFS-image.fits')):
         wsclean(dical1, outname=img2, **cfg['clean2'])
+        create_mask(img2 +'-image.fits', img2 +'-residual.fits', clipval=7, outname='mask1.fits')
 
     if not os.path.exists(model2):
         makesourcedb(img2+'-sources.txt', out=model2)
 
     if not os.path.exists(dical2):
         dical2 = dical(dical1, model2, msout=dical2, h5out=h5_2, **cfg['dical2'])
-        view_sols(h5_2)
-
+        view_sols(h5_2, outname='dical2')
+# clean3
     if (not os.path.exists(img3 +'-image.fits')) and (not os.path.exists(img3 +'-MFS-image.fits')):
         wsclean(dical2, outname=img3, **cfg['clean3'])
+        create_mask(img3 +'-image.fits', img3 +'-residual.fits', clipval=5, outname='mask2.fits')
 
     if not os.path.exists(model3):
         makesourcedb(img3+'-sources.txt', out=model3)
 
     if not os.path.exists(dical3):
         dical3 = dical(dical2, model3, msout=dical3, h5out=h5_3, **cfg['dical3'])
-        view_sols(h5_3)
+        view_sols(h5_3, outname='dical3')
 
+# clean4
     if (not os.path.exists(img_final +'-image.fits')) and (not os.path.exists(img_final +'-MFS-image.fits')):
         wsclean(dical3, outname=img_final, **cfg['clean4'])
 
diff --git a/imcal.yml b/imcal.yml
index 334750a73e2368fcdd8537019f893edb4b4f7164..1138945c20ed5817471e6f294100c2f9a2114a35 100644
--- a/imcal.yml
+++ b/imcal.yml
@@ -14,14 +14,20 @@ split1:
     startchan: 40 # start channel to split from
     nchan: 0 # 0 means till the end
 
+clean0: # initial clean
+    max_over_thresh: 250 # the threshold for initial CLEAN is set to image_max/max_over_thresh
+
+    
 clean1: # wsclean setup
     imagesize: 3072
     pixelsize: 3 
-    multifreq: 8  
+    multifreq: 0
     automask: 20
     autothresh: 5
+    usefitsmask: True
+    fitsmaskname: 'mask0.fits'
     multiscale: False
-    kwstring: '-use-wgridder -parallel-deconvolution 1400 -parallel-gridding 8 -deconvolution-channels 3' # use this for additional wsclean options, e.g. '-weight uniform -use-idg' 
+    kwstring: '-use-wgridder -parallel-deconvolution 1400' # use this for additional wsclean options, e.g. '-weight uniform -use-idg' 
 
 dical1: # DPPP setup for direction independent calibration
     solint: 20
@@ -33,8 +39,10 @@ clean2:
     imagesize: 3072
     pixelsize: 3 
     multifreq: 8  
-    automask: 6
-    autothresh: 1
+    automask: 10
+    autothresh: 5
+    usefitsmask: True
+    fitsmaskname: 'mask0.fits'
     multiscale: True
     kwstring: '-use-wgridder -parallel-deconvolution 1400 -parallel-gridding 8 -deconvolution-channels 3'
     
@@ -48,13 +56,15 @@ clean3:
     imagesize: 3072
     pixelsize: 3 
     multifreq: 8  
-    automask: 6
-    autothresh: 1
+    automask: 7
+    autothresh: 3.5
+    usefitsmask: True
+    fitsmaskname: 'mask1.fits'
     multiscale: True
     kwstring: '-use-wgridder -parallel-deconvolution 1400 -parallel-gridding 8 -deconvolution-channels 3'
     
 dical3:
-    solint: 1000
+    solint: 800
     mode: 'diagonal'
     uvlambdamin: 500 # Ignore baselines / channels with UV < uvlambdamin wavelengths.
     cal_nchan: 31 # number of chans with the same solutions
@@ -66,6 +76,8 @@ clean4:
     automask: 4.5
     autothresh: 0.5
     multiscale: True
+    usefitsmask: True
+    fitsmaskname: 'mask2.fits'
     kwstring: '-use-wgridder -parallel-deconvolution 1400 -parallel-gridding 8 -deconvolution-channels 3 -weight briggs -1.0'
 
 ### END