import os,zipfile
from casatools import msmetadata,table,measures,quanta,agentflagger,image,calibrater,ms
from casatasks import *
import sys,logging,numpy as np,copy,glob,psutil,time,multiprocessing as mp,subprocess,getpass
from paircarstools.basic_func import *
from paircarstools.access_ms import *
from paircarstools.decor import *
from paircarstools.flagger import *
from paircarstools.fullpol_selfcal_LTS import *
from paircarstools.libpaircars import send_paircars_notification
from optparse import OptionParser
from astropy.io import fits
from paircarstools.libpaircars import send_paircars_notification,send_to_database
from multiprocessing import Process
from astropy import wcs
os.system('rm -rf casa*log')
'''
Code is written by Devojyoti Kansabanik , 2 May, 2021
'''

# cpulimit check
###########
def CPULIMIT_check():
	a=os.system('cpulimit -h > cpulimit_tmp')
	if a==256:
		os.system('rm -rf cpulimit_tmp')
		return 0
	else:
		os.system('rm -rf cpulimit_tmp')
		return 1

global final_imagelog
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s',datefmt='%Y-%m-%d %H:%M:%S')
final_imagelog = logging.getLogger('final_caltable_log')
final_imagelog.setLevel(logging.DEBUG)

def init_logger_console(logdir='',logger_name='',verbose=False):
	'''
	Initial logger
	Parameters
	----------
	working_dir : str
		Name of the working directory
	verbose : bool
		Verbose output or not
	'''
	if verbose==True:
		console=logging.StreamHandler(sys.stdout)
		console.setFormatter(formatter)
		final_imagelog.addHandler(console)
	if logdir!='' and logger_name!='':
		if os.path.exists(logdir+'/'+logger_name+'.log'):
			os.system('rm -rf '+logdir+'/'+logger_name+'.log')
		if os.path.isdir(logdir)==False:
			os.makedirs(logdir)
		filehandle=logging.FileHandler(logdir+'/'+logger_name+'.log')
		filehandle.setFormatter(formatter)
		final_imagelog.addHandler(filehandle)
	final_imagelog.propagate = False
	return


def final_imaging(msname,metafits,basedir,mode,caltables=[],residual_frac=0.1,quality_factor=1,savedir='',cutoutbox='',want_automask=False,savemodel=False,\
	saveres=False,use_ankflag=False,do_pol=False,mask='',freq_interval=160,time_interval=10.0,verbose=False,freq_width=40,time_width=0.5,time_avg=0.5,freq_avg=40,sigma=5,\
	thresh=[0.1],use_wsclean=True,obsid=0,input_file='',logdir='',logger_name='',cpu_list=[]):
	'''
	Function to make final images for database
	Parameters
	----------
	msname : str 
		Name of the measurement set
	workdir : str 
		Name of the working directory
	caltables : list
		Caltables to apply
	residual_frac : float
		Residual flux fraction
	quality_factor : int
		Quality factor
	savedir : str
		Save directory
	cutoutbox : str
		Cutout box 
	want_automask : bool
		Want auto masking (Using only CASA)
	savemodel : bool
		Save final models
	saveres : bool
		Save final residuals 
	use_ankflag : bool
		Use aNKflag
	do_pol : bool
		Perform polarization imaging
	mask : str
		CASA mask (Only for CASA imaging)
	freq_interval : float
		Frequency intervals of imaging
	time_interval : bool
		Time intervals of imaging
	verbose : bool
		Verbose output
	freq_width : float
		Frequency bandwidth of imaging
	time_width : float
		Temporal width of imaging
	time_avg : float
		Visibility averaging along time for imaging
	freq_avg : float
		Visibility averaging along frequency for imaging
	sigma : float
		Final sigma
	thresh : list
		RMS threshold list
	use_wsclean : bool
		Use WSClean for imaging (except CASA) 	
	obsid : int
		Observation ID
	input_file : str
		P-AIRCARS input file
	logdir : str
		Name of the log directory
	logger_name : str
		Name of the log basename
	Returns
	-------
	int
		(0 on success, 1 on failure), Total number of splited ms for imaging
	'''
	c=0
	try:
		sys.path.append(os.getcwd())
		import selfcal_inputs as inputs
	except:
		if input_file==None or os.path.exists(input_file)==False:
			print ('Please provide correct input file.\n')
			return 1,0
		os.system('cp -r '+inputfile+' '+os.getcwd()+'/selfcal_inputs.py')
		sys.path.append(os.getcwd())
		import selfcal_inputs as inputs

	OBSID=int(fits.getheader(str(metafits))['GPSTIME'])
	#final_imagelog.info('Calculating final PSF size.....\n')  # TODO : list for different frequencies
	#maj,minor,pa=get_final_psf(msname,weight=inputs.weight,robust=inputs.robust)
	total_instance=int(get_available_threads()/2)
	image_counter=0
	if len(caltables)!=0:
		caltables=','.join(caltables)
	else:
		caltables=''
	if basedir[-1]=='/':
		basedir=basedir[:-1]
	if savedir=='':
		savedir=basedir+'/final_images'
	if mode=='Database_Imaging':
		imaging_mode='database'
	elif mode=='Final_Imaging':
		imaging_mode='final'
	AM=AccessMS(msname)
	freqres=AM.calc_freqres()
	timeres=AM.calc_timeres()
	
	if time_avg<=timeres:
		time_avg=timeres

	if freq_avg<=freqres:
		freq_avg=freqres
	
	freqs=AM.get_freqs()/10**6

	AM=AccessMS(msname)
	total_bandwidth=AM.calc_bandwidth()/1000.0
	total_time=AM.calc_total_time()
	total_chunks=int(int(total_bandwidth/freq_interval)*int(total_time/time_interval))
	if len(cpu_list)!=0:
		total_allowed_cpus=len(cpu_list)
	else:
		total_allowed_cpus=int(psutil.cpu_count()*inputs.cpu_frac) 
		cpu_list=get_free_cpu_list(inputs.cpu_frac)
	if total_allowed_cpus>10:
		total_allowed_cpus=10
	if total_allowed_cpus>psutil.cpu_count():
		total_allowed_cpus=psutil.cpu_count()-1
	
	allowed_cpu_frac=total_allowed_cpus/psutil.cpu_count()
	ms_cmd_args=['--msname='+msname,'--savedir='+savedir,'--freq_interval='+str(freq_interval),'--time_interval='+str(time_interval),'--freq_width='+str(freq_width),\
		'--time_width='+str(time_width),'--cpu_frac='+str(allowed_cpu_frac),'--verbose='+str(verbose)]
	if imaging_mode!='database':
		if inputs.timerange!='':
			ms_cmd_args.append('--timerange='+str(inputs.timerange))
		if inputs.chanrange!='':
			freqrange=[]	
			chanrange=inputs.chanrange.split(',')
			for chan in chanrange:
				s_chan=int(chan.split('~')[0])
				e_chan=int(chan.split('~')[-1])
				freqrange.append(str(freqs[s_chan])+'~'+str(freqs[e_chan]))
			freqrange=','.join(freqrange)
			ms_cmd_args.append('--freq_list='+str(freqrange))
	if caltables=='':
		ms_cmd_args.append('--datacolumn=corrected')
	else:
		ms_cmd_args.append('--datacolumn=DATA')
	common_ms_cmd_args=copy.deepcopy(ms_cmd_args)
	
	total_blocks=int(total_chunks/total_allowed_cpus)
	cpu_list_copy=copy.deepcopy(cpu_list)
	cur_block=0
	pre_casa_instance=0
	casa_instance=0
	if len(thresh)==2:
		thresh=[np.mean(np.array(thresh))]
	thresh=[str(i) for i in thresh]
	if do_pol==True:
		stokes='IQUV'
		if len(thresh)!=4:
			thresh=thresh*4
	else:
		if len(thresh)>1:
			thresh=thresh[0]
		stokes='pseudoI'
	threshold=','.join(thresh)
	finished_touch_files_for_ms=glob.glob(basedir+'/.Finished_final_imaging_'+str(imaging_mode)+'*')
	num_pixel_in_psf=5
	latest_image_list=[]
	final_imagelog.info('Total cpus available P-AIRCARS : '+str(len(cpu_list))+'\n')
	final_total_image_touch_list=glob.glob(basedir+'/.Imaging_*')
	final_total_image_list=[os.path.basename(a).split('.Imaging_')[-1].split('_freq')[0]+'_freq_'+os.path.basename(a).split('.Imaging_')[-1].split('_freq')[-1].split('_')[1] for a in final_total_image_touch_list]
	final_total_images=len(final_total_image_list)
	final_imagelog.info('Total blocks : '+str(total_blocks)+'\n')	
	while True:
		ms_cmd_args=copy.deepcopy(common_ms_cmd_args)
		if cur_block<=total_blocks:
			block_dir=savedir+'/'+os.path.basename(msname).split('.ms')[0]+'_block_'+str(cur_block)
			if os.path.isdir(block_dir) and len(glob.glob(block_dir+'/*.ms'))>0:
				temp_block_ms=glob.glob(block_dir+'/*.ms')
				block_ms=[]
				if len(temp_block_ms)!=0:
					for i in temp_block_ms:
						if '_cor' not in i:
							os.system('rm -rf '+i+'.flagversions')
							block_ms.append(i)
						else:
							os.system('rm -rf '+i+' '+i+'.flagversions')
			else:
				if os.path.isdir(block_dir)==False:
					os.makedirs(block_dir)
				ms_cmd_args.append('--total_block='+str(total_blocks))
				ms_cmd_args.append('--cur_block='+str(cur_block))
				ms_cmd_args.append('--force False')
				if cur_block==0:
					final_imagelog.info('parallel_ms_split '+' '.join(ms_cmd_args)+' --splitms False\n')
					a=os.system('parallel_ms_split '+' '.join(ms_cmd_args)+' --splitms False')
				final_imagelog.info('parallel_ms_split '+' '.join(ms_cmd_args)+'\n')
				a=os.system('parallel_ms_split '+' '.join(ms_cmd_args))
				ms_cmd_args=ms_cmd_args[:-2]	
				if os.WEXITSTATUS(a)!=0:
					final_imagelog.info('Error in spliting block '+str(cur_block)+'.\n')
					pass
				else:
					final_imagelog.info('Spliting of ms is done for block '+str(cur_block)+'.\n')
				splited_ms=glob.glob(savedir+'/splited_ms/'+os.path.basename(msname).split('.ms')[0]+'/*.ms')		
				for ms in splited_ms:
					if 'temp_aocal' in ms or 'chan' in ms or 'avg' in ms or 'aNKflag' in ms or '_cor.ms' in ms or '_cor_cor.ms' in ms:
						pass
					else:
						os.system('mv '+ms+' '+block_dir+'/'+os.path.basename(ms))		
				block_ms=sorted(glob.glob(block_dir+'/*.ms'))
				total_block_ms=len(block_ms)
				os.system('touch '+block_dir+'/.total_ms_'+str(total_block_ms))
			if len(block_ms)==0:
				block_ms_touch_file=sorted(glob.glob(block_dir+'/.Imaging_*'))
				num_block_ms=glob.glob(block_dir+'/.total_ms_*')
				if len(num_block_ms)==0:
					total_block_ms=0
				else:
					total_block_ms=int(num_block_ms[0].split('_')[-1])
				if total_block_ms>0 and len(block_ms_touch_file)>=total_block_ms:
					final_imagelog.info('Imaging is already done for block number : '+str(cur_block)+'\n')
					image_counter+=total_block_ms
					os.system('rm -rf '+block_dir)
					cur_block+=1
					time.sleep(1)
					continue
				elif total_block_ms==0:
					final_imagelog.info('No unflagged measurement set to be imaged for block number : '+str(cur_block)+'\n')
					os.system('rm -rf '+block_dir)
					image_counter+=total_block_ms
					cur_block+=1
					time.sleep(1)
					continue
				else:
					if os.path.isdir(block_dir)==False:
						os.makedirs(block_dir)
					ms_cmd_args.append('--total_block='+str(total_blocks))
					ms_cmd_args.append('--cur_block='+str(cur_block))
					if cur_block==0:
						ms_cmd_args.append('--force True')
					else:
						ms_cmd_args.append('--force False')
					final_imagelog.info('parallel_ms_split '+' '.join(ms_cmd_args)+'\n')
					a=os.system('parallel_ms_split '+' '.join(ms_cmd_args))
					ms_cmd_args=ms_cmd_args[:-2]	
					if os.WEXITSTATUS(a)!=0:
						final_imagelog.info('Error in spliting block '+str(cur_block)+'.\n')
						pass
					else:
						final_imagelog.info('Spliting of ms is done for block '+str(cur_block)+'.\n')
					splited_ms=glob.glob(savedir+'/splited_ms/'+os.path.basename(msname).split('.ms')[0]+'/*.ms')		
					for ms in splited_ms:
						if 'temp_aocal' in ms or 'chan' in ms or 'avg' in ms or 'aNKflag' in ms or '_cor.ms' in ms or '_cor_cor.ms' in ms:
							pass
						else:
							os.system('mv '+ms+' '+block_dir+'/'+os.path.basename(ms))		
					block_ms=sorted(glob.glob(block_dir+'/*.ms'))
					total_block_ms=len(block_ms)
					image_counter+=total_block_ms
					os.system('touch '+block_dir+'/.total_ms_'+str(total_block_ms))
			else:
				total_block_ms=len(block_ms)
				count_spawned_ms=0
				for ms in block_ms:
					if ms[-1]=='/':
						ms=ms[:-1]
					check_thread_availability(4)
					workdir=os.path.dirname(os.path.abspath(ms))+'/workdir_'+os.path.basename(ms).split('.ms')[0]
					cmd_args=['--msname '+ms,' --metafits '+metafits,' --basedir '+basedir,' --workdir '+workdir,' --savedir '+savedir,' --savemodel '+str(savemodel),\
							' --saveres '+str(saveres),' --stokes '+stokes,' --sigma '+str(sigma),' --threshold '+str(threshold),' --wsclean '+str(use_wsclean),' --verbose '+str(verbose),\
							' --want_automask '+str(want_automask),' --quality_factor '+str(quality_factor),' --use_ankflag '+str(use_ankflag),' --imaging_mode '+str(imaging_mode),\
							' --residual_frac '+str(residual_frac),'--caltables '+str(caltables)]#,'--major_axis '+str(maj),'--minor_axis '+str(minor),'--pa '+str(pa)]
					if mask!='':
						cmd_args.append(' --maskfile '+str(mask))
					if cutoutbox!='':
						cmd_args.append(' --cutoutbox '+cutoutbox)
					if mode=='Final_Imaging':
						cmd_args.append(' --num_pixel_in_psf '+str(num_pixel_in_psf))
					cmd_args.append(' --time_avg '+str(time_avg))
					cmd_args.append(' --freq_avg '+str(freq_avg))
					cmd='paircars_final_imaging '+' '.join(cmd_args)
					screen_name=str(obsid)+'_'+imaging_mode+'_'+os.path.basename(ms).split('.ms')[0]+'_'+str(inputs.job_id)
					finished_touch_file=basedir+'/.Finished_final_imaging_'+str(imaging_mode)+'_'+os.path.basename(ms).split('.ms')[0]
					finished_touch_file_exists=glob.glob(finished_touch_file+'*')
					if len(finished_touch_file_exists)>0:
						if os.path.exists(savedir+'/All_final_images/'+str(OBSID)+'/'+os.path.basename(ms).split('.ms')[0]+'.fits'):
							final_imagelog.info('Imaging for ms : '+os.path.basename(ms)+' is already done.\n')
							if len(finished_touch_file_exists)>0:
								basedir_touch_file_msg=finished_touch_file_exists[0].split('_')[-1]
							else:
								basedir_touch_file_msg='nofound'
							if basedir_touch_file_msg=='success':
								os.system('touch '+org_msname_touch_file+'.success')
							else:
								os.system('touch '+org_msname_touch_file+'.error')
							ms_basedir=os.path.dirname(ms)
							os.system('rm -rf '+ms)
							if len(glob.glob(ms_basedir+'/*.ms'))==0:
								final_imagelog.info('Removing block directory : '+ms_basedir+'\n')
								os.system('rm -rf '+ms_basedir)
							image_counter+=1
							continue
						else:
							org_msname_touch_file=basedir+'/.Imaging_'+os.path.basename(ms).split('.ms')[0]
							if len(finished_touch_file_exists)>0:
								basedir_touch_file_msg=finished_touch_file_exists[0].split('_')[-1]
							else:
								basedir_touch_file_msg='nofound'
							if basedir_touch_file_msg=='success':
								os.system('touch '+org_msname_touch_file+'.success')
							else:
								os.system('touch '+org_msname_touch_file+'.error')
							final_imagelog.info('Imaging for ms : '+os.path.basename(ms)+' is already done.\n')
							ms_basedir=os.path.dirname(ms)
							os.system('rm -rf '+ms)
							if len(glob.glob(ms_basedir+'/*.ms'))==0:
								final_imagelog.info('Removing block directory : '+ms_basedir+'\n')
								os.system('rm -rf '+ms_basedir)
							image_counter+=1
							continue
					else:
						batch_file=paircars_instance_runner(cmd,basedir,inputs.paircars_dir,screen_name,finished_touch_file,inputs.job_id)
						cur_cpu_list=[]
						while len(cur_cpu_list)<=0:
							cpu_fracs=np.array(psutil.cpu_percent(percpu=True,interval=1))
							for cpu in cpu_list:
								cpu=int(cpu)
								cpu_frac=cpu_fracs[cpu]
								if cpu_frac<=75:
									cur_cpu_list.append(cpu)
								else:
									cpu_list.remove(cpu)
								if len(cpu_list)==0:
									cpu_list=copy.deepcopy(cpu_list_copy)
								if len(cur_cpu_list)==3:
									break
						run_batch_scripts_cpulist(batch_file,cpu_list=cur_cpu_list)
						cur_cpu_str=''
						for i in cur_cpu_list:
							cur_cpu_str+=str(i)+','
						cur_cpu_str=cur_cpu_str[:-1]
						os.system('rm -rf '+basedir+'/.cpulist_'+os.path.basename(ms).split('.ms')[0]+'_*')
						os.system('touch '+basedir+'/.cpulist_'+os.path.basename(ms).split('.ms')[0]+'_'+cur_cpu_str)	
						count_spawned_ms+=1
					if len(cpu_list)==0:
						final_imagelog.info('Waiting for finishing imaging spawned already...\n')
						while True:
							total_image_touch_list=glob.glob(basedir+'/.Imaging_*')
							total_image_list=[os.path.basename(a).split('.Imaging_')[-1].split('_freq')[0]+'_freq_'+os.path.basename(a).split('.Imaging_')[-1].split('_freq')[-1].split('_')[1] for a in total_image_touch_list]
							total_images=len(total_image_list)
							latest_image_list=[]
							for i in total_image_list:
								#if i not in final_total_image_list:
								latest_image_list.append(i)
							while True:
								if len(latest_image_list)>0 or count_spawned_ms==0:
									cpu_list=copy.deepcopy(cpu_list_copy)
								else:
									cpu_list=[]
								if len(cpu_list)>0:
									final_imagelog.info('New '+str(len(cpu_list))+' cpus available for P-AIRCARS instances .\n')
									final_total_images=total_images
									final_total_image_list=total_image_list
									count_spawned_ms=0		
									latest_image_list=[]
									break
								else:
									time.sleep(1)
							break
				if total_block_ms==0:
					final_imagelog.info('No ms is available for block number : '+str(cur_block-1)+'\n')
				elif total_block_ms<len(cpu_list):
					if len(cpu_list)<=0:
						cpu_list=get_free_cpu_list(inputs.cpu_frac,per_cpu_free_frac=0.25,cpu_list=cpu_list_copy)	
					final_imagelog.info('New '+str(len(cpu_list))+' cpus available for P-AIRCARS instances.\n')
					total_image_touch_list=glob.glob(basedir+'/.Imaging_*')
					total_image_list=[os.path.basename(a).split('.Imaging_')[-1].split('_freq')[0]+'_freq_'+os.path.basename(a).split('.Imaging_')[-1].split('_freq')[-1].split('_')[1] for a in total_image_touch_list]
					total_images=len(total_image_list)
					final_total_images=total_images
					final_total_image_list=total_image_list
				else:
					final_imagelog.info('Waiting for finishing imaging spawned already ...\n')
					while True:
						total_image_touch_list=glob.glob(basedir+'/.Imaging_*')
						total_image_list=[os.path.basename(a).split('.Imaging_')[-1].split('_freq')[0]+'_freq_'+os.path.basename(a).split('.Imaging_')[-1].split('_freq')[-1].split('_')[1] for a in total_image_touch_list]
						total_images=len(total_image_list)
						latest_image_list=[]
						for i in total_image_list:
							#if i not in final_total_image_list:
							latest_image_list.append(i)
						while True:
							if len(latest_image_list)>0 or count_spawned_ms==0 :
								cpu_list=copy.deepcopy(cpu_list_copy)
							else:
								cpu_list=[]
							if len(cpu_list)>0:
								final_imagelog.info('New '+str(len(cpu_list))+' cpus available for P-AIRCARS instances.\n')
								final_total_images=total_images
								final_total_image_list=total_image_list
								count_spawned_ms=0		
								latest_image_list=[]
								break
							else:
								time.sleep(1)
						break	
				cur_block+=1
				time.sleep(1)
		else:
			final_imagelog.info('Spliting of ms is done.\n')
			if os.path.exists(savedir+'/'+str(os.path.basename(msname)).split('.ms')[0]+'_split_params.npy'):
				os.system('rm -rf '+savedir+'/'+str(os.path.basename(msname)).split('.ms')[0]+'_split_params.npy')
			break	
	finished_touch_ms=glob.glob(basedir+'/.Finished_final_imaging_'+str(imaging_mode)+'*')
	splited_ms=glob.glob(savedir+'/splited_ms/'+os.path.basename(msname).split('.ms')[0]+'/*.ms')
	final_imagelog.info('Imaging of total '+str(image_counter)+' has started.\n')
	return 0,image_counter


def main():
	usage= 'P-AIRCARS final image spawn'
	parser = OptionParser(usage=usage)
	parser.add_option('--msname',dest="msname",default=None,help="Name of the measurement set",metavar="Measurement set")
	parser.add_option('--metafits',dest="metafits",default=None,help="Name of the metafits file",metavar="Metafits file")
	parser.add_option('--basedir',dest="basedir",default=None,help="Name of base directory for a given day",metavar="Directory path")
	parser.add_option('--localdatabase',dest="localdatabase",default=None,help="Name of local database",metavar="Directory path")
	parser.add_option('--inputfile',dest='inputfile',default=None,help='Path of the P-AIRCARS input file',metavar="File path")
	parser.add_option('--verbose',dest='verbose',default=False,help='Verbose output',metavar="Boolean")
	parser.add_option('--wsclean',dest="use_wsclean",default=True,help="Use WSClean for imaging or not",metavar="Boolean")
	parser.add_option('--final_imaging',dest="final_imaging",default=True,help="Perform final imaging",metavar="Boolean")
	parser.add_option('--database_imaging',dest="do_database_imaging",default=False,help="Perform imaging for database",metavar="Boolean")
	parser.add_option('--onlycal',dest="only_cal",default=False,help="Perform only calibration",metavar="Boolean")
	parser.add_option('--cpu_list',dest="cpu_str",default=None,help="CPU thread list",metavar="Comma separated string")
	parser.add_option('--caltables',dest="caltables",default=None,help="Caltable list",metavar="Comma separated string")
	(options, args) = parser.parse_args()

	if os.path.isdir(str(options.msname))==False:
		print ('Measurement set is not present.\n')
		return 1
		
	if options.basedir==None:
		print ('No base directory path is given. Please give base directory path to continue.\n')
		return 1
	elif os.path.isdir(str(options.basedir))==False:
		os.makedirs(str(options.basedir))

	if options.inputfile==None or os.path.isfile(str(options.inputfile))==False:
		print ('P-AIRCARS input file is not present. Please give the input file and re run.\n')
		return 1

	os.chdir(str(options.basedir))
	inputfile=str(options.inputfile)
	if inputfile[-1]=='/':
		inputfile=inputfile[:-1]
	cwd=os.getcwd()
	if os.path.isfile(cwd+'/selfcal_inputs.py')==False and (options.inputfile==None or os.path.isfile(options.inputfile)==False): 
		print('Input file does not exist.1\n')
		return 1
	elif options.inputfile!=None and os.path.isfile(cwd+'/selfcal_inputs.py')==False:
		os.system('cp -r '+options.inputfile+' '+cwd+'/selfcal_inputs.py')
	inputfile=cwd+'/selfcal_inputs.py'
	sys.path.append(cwd)
	import selfcal_inputs as inputs

	finished_file_list=glob.glob(str(options.basedir)+'/.Imaging_done_'+str(os.path.basename(options.msname))+'_*')
	all_image_finished_list=glob.glob(str(options.basedir)+'/.Imaging_done_*')
	all_image_finished_coarse=[]
	for a in all_image_finished_list:
		a=os.path.basename(a)
		coarse_list=a.split('coarse_')[-1].split('_')[:-1]
		for k in coarse_list:
			all_image_finished_coarse.append(int(k))
	if len(finished_file_list)>0:
		if inputs.savedir=='':
			savedir=str(options.basedir)+'/final_images'
		else:
			savedir=inputs.savedir
		AM=AccessMS(options.msname)
		ms_coarse=[str(i) for i in AM.get_coarse_chan()]
		ms_coarse_str='_'.join(ms_coarse)
		final_touch_file=str(options.basedir)+'/.Imaging_done_'+str(os.path.basename(options.msname))+'_success_coarse_'+str(ms_coarse_str)
		for coarse in ms_coarse:
			if int(coarse) in all_image_finished_coarse:
				for i in all_image_finished_list:
					if coarse in i:
						final_touch_file=i
						a=os.path.basename(i)
						coarse_list=a.split('coarse_')[-1].split('_')[:-1]
				final_touch_file='_'.join(final_touch_file.split('_')[:-1])
		OBSID=int(fits.getheader(str(options.metafits))['GPSTIME'])
		imagedir=savedir+'/All_final_images/'+str(OBSID)
		imagelist=glob.glob(imagedir+'/*fits')+glob.glob(imagedir+'/*junk')
		image_coarse_chan_list=np.array([freq_to_MWA_coarse(float(a.split('freq_')[-1].split('_')[0])) for a in imagelist])
		image_counter=0	
		for coarse in coarse_list:
			pos=np.where(image_coarse_chan_list==int(coarse))[0]
			image_counter+=len(pos)		
		if image_counter>0:
			print ('Imaging is already done for ms : '+str(options.msname)+'\n')
			print('Total final ms : '+str(image_counter)+'\n')
			print('###########################\nFinal imaging spawned.\n###########################\n')
			os.system('rm -rf '+final_touch_file+'_*')
			os.system('touch '+final_touch_file+'_'+str(image_counter))
			return 0
		else:
			print ('Imaging is already tried for ms : '+str(options.msname)+'. No images were made, hence trying again.\n')
			for i in finished_file_list:
				os.system('rm -rf '+i)
	if options.cpu_str==None:
		print ('No CPU list is provided. Estimating CPU thread list.\n')
		cpu_list= get_free_cpu_list(inputs.cpu_frac)
	else:
		temp_list=str(options.cpu_str).split(',')
		cpu_list=[]
		for i in temp_list:
			cpu_list.append(int(i))
	cpu_list_copy=copy.deepcopy(cpu_list)

	AM=AccessMS(str(options.msname))
	freqs=AM.get_freqs()/10**6
	coarse_chan_0=freq_to_MWA_coarse(freqs[0])
	coarse_chan_1=freq_to_MWA_coarse(freqs[-1])
	OBSID=int(fits.getheader(str(options.metafits))['GPSTIME'])
	is_internet=check_internet()
	if inputs.keep_logger:
		logdir=str(options.basedir)+'/verbose_logs/'+str(OBSID)
		logger_name=str(OBSID)+'_final_imagelog'	
	else:
		logdir=logger_name=''
	init_logger_console(logdir=logdir,logger_name=logger_name,verbose=eval(str(options.verbose)))

	# Appying solution to main ms
	#############################
	caltables_to_apply=str(options.caltables).split(',')
	for i in caltables_to_apply:
		if '.pcal' in i:
			do_polcal=True
			break
		else:
			do_polcal=False

	final_imagelog.info('Caltables : '+str(caltables_to_apply)+'\n')
	if inputs.calc_selfcalib_params==True:
		final_imagelog.info('Determining imaging parameters....\n')
		calparams=CalcParams(str(options.msname),inputs.quality_factor,inputs.safety_factor)
		residual_frac=float(calparams.calc_calibration_params()[2])
	else:
		residual_frac=0.1	

	if inputs.maskfile!='':
		mask=inputs.maskfile
	elif inputs.maskstr!='':
		mask=inputs.maskstr
	else:
		mask=''

	try:
		rms_list=np.load(str(options.basedir)+'/Ref_time_chan_sigma.npy',allow_pickle=True)[1]
	except:
		rms_list=[0.5]

	final_imagelog.info('Flagging MWA coarse channel edges.\n')
	flag_MWA_coarse(str(options.msname),edgewidth=280,do_flag=True)
	final_imagelog.info('Flagging QUACK times.\n')
	quacktime=flag_MWA_quack(str(options.msname),str(options.metafits))
	final_imagelog.info('Flagged '+str(quacktime)+' s at beginning and end.\n')
	AM=AccessMS(str(options.msname))
	npol=AM.get_npol()
	if do_polcal==True:
		if npol!=4:
			do_polcal=False
	total_instance=int(get_available_threads()/2)
	is_internet=check_internet()
	OBSID=int(fits.getheader(str(options.metafits))['GPSTIME'])
	if is_internet:
		database_notification_sent=0
		final_imaging_notification_sent=0
	else:
		database_notification_sent=1
		final_imaging_notification_sent=1
	if eval(str(options.do_database_imaging)):	
		if is_internet:
			final_imagelog.info('Start making images for global MWA solar database.\n')
			c=0	
			database_imaging_msg,total_database_ms=final_imaging(str(options.msname),str(options.metafits),str(options.basedir),'Database_Imaging',caltables=caltables_to_apply,\
			residual_frac=0.1,quality_factor=0,input_file=inputfile,time_avg=5.0,freq_avg=160.0,savedir=localdatabase+'/'+str(OBSID)+'/images',\
			cutoutbox='5,5',want_automask=False,savemodel=False,saveres=False,use_ankflag=inputs.use_ankflagger,do_pol=do_polcal,mask=mask,freq_interval=1280,\
			time_interval=30,freq_width=160,time_width=5,sigma=5,thresh=rms_list,use_wsclean=eval(str(options.use_wsclean)),obsid=OBSID,verbose=eval(str(options.verbose)),cpu_list=cpu_list)
			ms_freq=AM.calc_meanfreq()/10**6	
			os.system('touch '+str(options.basedir)+'/.Database_imaging_done_'+str(os.path.basename(options.msname))+'_success_'+str(total_database_ms))

		try:
			cutoutbox=inputs.cutoutbox
		except:
			cutoutbox='5,5'

		c=0
		while True:
			cpu_list=get_free_cpu_list(inputs.cpu_frac,cpu_list=cpu_list_copy)	
			if len(cpu_list)>int(len(cpu_list_copy)/2):
				final_imagelog.info('Now available cpu cores : '+str(len(cpu_list))+'\n')
				break
			elif c==0:
				final_imagelog.info('Waiting for free cores......\n')
				c+=1
			else:
				c+=1

	if eval(str(options.final_imaging)):	
		if inputs.savedir=='':
			savedir=str(options.basedir)+'/final_images'
		else:
			savedir=inputs.savedir
		if float(inputs.image_time)>2:
			timeavg=2
		else:
			timeavg=float(inputs.image_time)
		if float(inputs.image_freq)>160:
			freqavg=160
		else:
			freqavg=float(inputs.image_freq)

		final_imagelog.info('Start making final images.\n')	
		final_imaging_msg,total_final_ms=final_imaging(str(options.msname),str(options.metafits),str(options.basedir),'Final_Imaging',caltables=caltables_to_apply,\
		residual_frac=residual_frac,quality_factor=inputs.quality_factor,input_file=inputfile,savedir=savedir,cutoutbox=inputs.cutoutbox,want_automask=\
		inputs.want_auto_masking,savemodel=inputs.savemodel,saveres=inputs.saveresidual,use_ankflag=inputs.use_ankflagger,do_pol=do_polcal,mask=mask,freq_interval=\
		inputs.image_delta_freq,time_interval=inputs.image_delta_time,freq_width=inputs.image_freq,time_width=inputs.image_time,sigma=6,\
		thresh=rms_list,use_wsclean=eval(str(options.use_wsclean)),time_avg=float(timeavg),freq_avg=float(freqavg),obsid=OBSID,verbose=eval(str(options.verbose)),cpu_list=cpu_list_copy)

		if eval(str(options.verbose))==False:
			print ('All final imaging has been started....\n')
		final_imagelog.info('All final imaging has been started....\n')
		final_imagelog.info('Total final ms : '+str(total_final_ms)+'\n')

	finished_file_list=glob.glob(str(options.basedir)+'/.Imaging_done_'+str(os.path.basename(options.msname))+'_*')
	all_image_finished_list=glob.glob(str(options.basedir)+'/.Imaging_done_*')
	all_image_finished_coarse=[]
	for a in all_image_finished_list:
		a=os.path.basename(a)
		coarse_list=a.split('coarse_')[-1].split('_')[:-1]
		for k in coarse_list:
			all_image_finished_coarse.append(int(k))
	AM=AccessMS(options.msname)
	ms_coarse=[str(i) for i in AM.get_coarse_chan()]
	ms_coarse_str='_'.join(ms_coarse)
	final_touch_file=str(options.basedir)+'/.Imaging_done_'+str(os.path.basename(options.msname))+'_success_coarse_'+str(ms_coarse_str)
	for coarse in ms_coarse:
		if int(coarse) in all_image_finished_coarse:
			for i in all_image_finished_list:
				if coarse in i:
					final_touch_file=i
					a=os.path.basename(i)
					coarse_list=a.split('coarse_')[-1].split('_')[:-1]
			final_touch_file='_'.join(final_touch_file.split('_')[:-1])
	OBSID=int(fits.getheader(str(options.metafits))['GPSTIME'])
	imagedir=savedir+'/All_final_images/'+str(OBSID)
	imagelist=glob.glob(imagedir+'/*fits')+glob.glob(imagedir+'/*junk')
	image_coarse_chan_list=np.array([freq_to_MWA_coarse(float(a.split('freq_')[-1].split('_')[0])) for a in imagelist])
	image_counter=0	
	for coarse in coarse_list:
		pos=np.where(image_coarse_chan_list==int(coarse))[0]
		image_counter+=len(pos)		
	total_final_ms+=image_counter
	final_imagelog.info('\n###########################\nFinal imaging spawned.\n###########################\n')
	os.system('rm -rf '+final_touch_file+'_*')
	os.system('touch '+final_touch_file+'_'+str(total_final_ms))
	return final_imaging_msg



if __name__=='__main__':
	result=main()
	os._exit(result)
