from __future__ import absolute_import
from glob import glob
import os
import re
import sys
import shutil

# the solution here to findCalModels should be reworked
# CASA5 uses the casa dict to set the default roots parameter values
# and that dict is not available in CASA6, where ctsys.resolve is
# available
# Here: defaultRoots is defined differently for CASA6 and CASA5 and
# that values is used as the default value for the roots parameter in
# findCalModels.
# Inside findCalModels there is a new section at the top to use
# ctsys.resolve to make the initial attempt to find the models.
# If that fails or is unavailable it falls back to the CASA5 code.

# get is_python3 and is_CASA6
from casatasks.private.casa_transition import *
if is_CASA6:
    from .setjy_helper import * 
    from .parallel.parallel_data_helper import ParallelDataHelper
    from .parallel.parallel_task_helper import ParallelTaskHelper
    from .mstools import write_history
    from casatools import ctsys, ms, imager, calibrater
    from casatasks import casalog

    # used in one type comparison
    strType = str

    # default roots argument for findCalModels
    defaultRoots = ['.']
else:
    from setjy_helper import * 
    from taskinit import *
    from taskinit import mstool as ms
    from taskinit import imtool as imager
    from taskinit import cbtool as calibrater
    from mstools import write_history
    from parallel.parallel_data_helper import ParallelDataHelper
    from parallel.parallel_task_helper import ParallelTaskHelper

    # used in one type comparison
    strType = string

    # default roots argument for findCalModels
    defaultRoots = ['.', casa['dirs']['data']]

# Helper class for Multi-MS processing (by SC)
class SetjyHelper():
    def __init__(self, msfile=None):
        self.__msfile = msfile
        
    def resetModelCol(self):
        rstatus = True
        # Hide the log info
        casalog.post("Resetting the log filter to WARN", "DEBUG")
        casalog.post("Initialize the MODEL columns of sub-MSs to default 1", "DEBUG")
        casalog.filter('WARN')

        myms = ms()
        try:
            try:
                myms.open(self.__msfile)
                submslist = myms.getreferencedtables()
                parentms = myms.name()
                myms.close()
            except:
                if (os.path.exists(os.path.join(self.__msfile,'SUBMSS'))):
                    casalog.post("MS may be corrupted. Try to initialize sub-MSs anyway...","DEBUG")
                    submslist = [os.path.abspath(os.path.join(self.__msfile,'SUBMSS',fn))
                                 for fn in os.listdir(os.path.join(self.__msfile,'SUBMSS')) if fn.endswith('.ms') ]
                else:
                    rstatus = False

            mycb = calibrater()
            if parentms!= submslist[0]:
                for subms in submslist:
                    mycb.open(subms, addcorr=False, addmodel=True)
                    mycb.close()            
        except:
            rstatus = False
                
        casalog.filter('INFO')

        return rstatus


def setjy(vis=None, field=None, spw=None,
          selectdata=None, timerange=None, scan=None, intent=None, observation=None,
          scalebychan=None, standard=None, model=None, 
          listmodels=None, fluxdensity=None, spix=None, reffreq=None, polindex=None,
          polangle=None, rotmeas=None, fluxdict=None, 
          useephemdir=None, interpolation=None, usescratch=None, ismms=None):
    """Fills the model column for flux density calibrators."""

    casalog.origin('setjy')
    casalog.post("standard="+standard,'DEBUG1')
    mylocals = locals()

    if not listmodels: # listmmodels=T does not require vis 
        sh = SetjyHelper(vis)
        rstat = sh.resetModelCol()


    # Take care of the trivial parallelization
    if ( not listmodels and ParallelDataHelper.isMMSAndNotServer(vis) and usescratch):
        # jagonzal: We actually operate in parallel when usescratch=True because only
        # in this case there is a good trade-off between the parallelization overhead
        # and speed up due to the load involved with MODEL_DATA column creation
        # Create the default MODEL columns in all sub-MSs to avoid corruption of the MMS
        # when there are NULL MS selections
        #
        # TT: Use ismms is used to change behavior of some of the execption handling
        # for MMS case. It is a hidden task parameter only modified when input vis
        # is identified as MMS via SetjyHelper.resetModel().
      
        #sh = SetjyHelper(vis)
        #rstat = sh.resetModelCol()

        if not rstat:
            raise RuntimeError("Could not initialize MODEL columns in sub-MSs", 'SEVERE')

        ismms=rstat
        mylocals['ismms']=ismms
        helper = ParallelTaskHelper('setjy', mylocals)
        helper._consolidateOutput = False
        retval = helper.go()

        # Remove the subMS names from the returned dictionary. Pick the first dictionary from
        # the list of subMS dictionaries
        if (any(isinstance(v, dict) for v in retval.values())):
            for subMS in retval:
                dict_i = retval[subMS]
                # Take the first *non-empty dict* (CAS-13645)
                if isinstance(dict_i,dict) and dict_i:
                    retval = dict_i
                    break
        else:
            raise RuntimeError("Error in parallel processing of MMS, retval: {}".
                               format(retval),'SEVERE')

    else:
        retval = setjy_core(vis, field, spw, selectdata, timerange, 
                        scan, intent, observation, scalebychan, standard, model, 
                        listmodels, fluxdensity, spix, reffreq,
                        polindex, polangle, rotmeas, fluxdict, 
                        useephemdir, interpolation, usescratch, ismms)

    return retval


def setjy_core(vis=None, field=None, spw=None,
               selectdata=None, timerange=None, scan=None, intent=None, observation=None,
               scalebychan=None, standard=None, model=None, listmodels=None,
               fluxdensity=None, spix=None, reffreq=None,
               polindex=None, polangle=None, rotmeas=None, fluxdict=None,
               useephemdir=None, interpolation=None, usescratch=None, ismms=None):
    """Fills the model column for flux density calibrators."""

    retval = {}
    clnamelist=[]
    # remove componentlist generated
    deletecomp = True
    #deletecomp = False 
    try:
        # Here we only list the models available, but don't perform any operation
        if listmodels:
            casalog.post("Listing model candidates (listmodels == True).")
            if vis:
              casalog.post("%s is NOT being modified." % vis)

            if standard=='Butler-JPL-Horizons 2012':
                tpm_supported_objects = ['Ceres','Lutetia','Pallas','Vesta']
                ssmoddirs = findCalModels(target='SolarSystemModels',
                                          exts=['.im','.ms','tab'])
                sstpmdirs = findCalModels(target='SolarSystemModels',
                                          exts=['.im','.ms','tab'])
                if ssmoddirs==set([]):
                     casalog.post("No models were found. Missing SolarSystemModels in the CASA data directory","WARN")           
                for d in ssmoddirs:
                    lsmodims(d,modpat='*Tb*.dat', header='Tb models of solar system objects available for %s' % standard) 
                for d in sstpmdirs:
                    lsmodims(d,modpat='*fd_time.dat', header='Time variable models of asteroids available for %s [only applicable for the observation date 2014.01.01 0UT and beyond]' % standard) 
            elif standard=='Butler-JPL-Horizons 2010':
                availmodellist=['Venus', 'Mars', 'Jupiter', 'Uranus', 'Neptune', 'Pluto',
                                'Io', 'Europa', 'Ganymede', 'Callisto', 'Titan','Triton',
                                'Ceres', 'Pallas', 'Vesta', 'Juno', 'Victoria', 'Davida']
                casalog.post("Solar system objects recognized by %s:" % standard)
                casalog.posta(vailmodellist)
            else:
                lsmodims('.', modpat='*.im* *.mod*')
                calmoddirs = findCalModels()
                ssmoddirs=None
                for d in calmoddirs:
                    lsmodims(d)
        
        # Actual operation, when either the MODEL_DATA column or visibility model header are set
        else:
            if not os.path.isdir(vis):
              #casalog.post(vis + " must be a valid MS unless listmodels is True.",
              #             "SEVERE")
                raise Exception("%s is not a valid MS" % vis) 

            myms = ms()
            myim = imager()
            if ismms==None: ismms=False
            if type(vis) == str and os.path.isdir(vis):
                n_selected_rows = nselrows(vis, field, spw, observation, timerange, scan, intent, usescratch, ismms)
                # jagonzal: When  usescratch=True, creating the MODEL column only on a sub-set of
                # Sub-MSs causes problems because ms::open requires all the tables in ConCatTable 
                # to have the same description (MODEL data column must exist in all Sub-MSs)
                #
                # This is a bit of an over-doing but it is necessary for the sake of transparency
                #
                # Besides, this is also the same behavior as when running setjy vs a normal MS
                #
                # Finally, This does not affect the normal MS case because nselrows throws an
                # exception when the user enters an invalid data selection, but it works for the 
                # MMS case because every sub-Ms contains a copy of the entire MMS sub-tables
                ##if ((not n_selected_rows) and ((not usescratch) or (standard=="Butler-JPL-Horizons 2012"))) :
                #mylocals = locals()
                #if ((not n_selected_rows) and ((usescratch) or (standard=="Butler-JPL-Horizons 2012"))) :
                if ((not n_selected_rows) and ((ismms) or (standard=="Butler-JPL-Horizons 2012"))) :
                    # jagonzal: Turn this SEVERE into WARNING, as explained above
                    casalog.post("No rows were selected.", "WARNING")
                    return {}
                else:
                    if (not n_selected_rows):
                        raise Exception("No rows were selected. Please check your data selection")
                    myim.open(vis, usescratch=usescratch)

            else:
                raise Exception('Visibility data set not found - please verify the name')

            # remove modimage handling to use 'model' parameter only (use modimage internally??)

            #if modimage==None:  # defined as 'hidden' with default '' in the xml
      	    #                    # but the default value does not seem to set so deal
            #			        # with it here...
            #    modimage=''
            #if model:
            #    modimage=model
            #elif not model and modimage:
            #    casalog.post("The modimage parameter is deprecated please use model instead", "WARNING")
            # If modimage is not an absolute path, see if we can find exactly 1 match in the likely places.
            #if modimage and modimage[0] != '/':
            if model and model[0] != '/':
                cwd = os.path.abspath('.')
                calmoddirs = [cwd]
                # casa dict unavailable in CASA6
                if is_CASA6:
                    calmoddirs += findCalModels()
                else:
                    calmoddirs += findCalModels(roots=[cwd,
                                                       casa['dirs']['data']])
                candidates = []
                for calmoddir in calmoddirs:
                    cand = os.path.join(calmoddir,model)
                    if os.path.isdir(cand):
                        candidates.append(cand)
                if not candidates:
                    raise RuntimeError("%s was not found for model in %s." %(model,
                                 ', '.join(calmoddirs)))

                elif len(candidates) > 1:
                    casalog.post("More than 1 candidate for model was found:",
                         'SEVERE')
                    for c in candidates:
                        casalog.post("\t" + c, 'SEVERE')
                    raise RuntimeError("Please pick 1 and use the absolute path (starting with /).")

                else:
                    model = candidates[0]
                    casalog.post("Using %s for model." % model, 'INFO')

            # Write the parameters to HISTORY before the tool writes anything.
            try:
                param_names = setjy.__code__.co_varnames[:setjy.__code__.co_argcount]
                if is_python3:
                    vars = locals()
                    param_vals = [vars[p] for p in param_names]
                else:
                    param_vals = [eval(p) for p in param_names]

                write_history(myms, vis, 'setjy', param_names,
                              param_vals, casalog)
            except Exception as instance:
                casalog.post("*** Error \'%s\' updating HISTORY" % (instance),
                         'WARN')

            # Split the process for solar system objects
            # To maintain the behavior of SetJy such that if a flux density is specified
            # we use it rather than the model, we need to check the state of the 
            # input fluxdensity  JSK 10/25/2012
            # TT comment 07/01/2013: some what redundant as fluxdensity is moved to 
            # a subparameter but leave fluxdensity=-1 for backward compatibility
            userFluxDensity = fluxdensity is not None
            if userFluxDensity and isinstance(fluxdensity, list):
                userFluxDensity = fluxdensity[0] > 0.0
            elif userFluxDensity:
                userFluxDensity = fluxdensity > 0.0

            #in mpirun somehow subparameter defaulting does not work properly, 
            #it seems to pick up default defined in "constraint" clause in the task xml instead
            #of the one defined in "param", so userFluxDensity is not reliable to use in here
            # (and somewhat redundant in this case).
            #if standard=="Butler-JPL-Horizons 2012" and not userFluxDensity:
            if standard=="Butler-JPL-Horizons 2012":
                casalog.post("Using Butler-JPL-Horizons 2012")
                ssmoddirs = findCalModels(target='SolarSystemModels',
                                          exts=['.im','.ms','tab'])
                if ssmoddirs==set([]):
                     raise Exception("Missing Tb or fd  models in the data directory")

                setjyutil=ss_setjy_helper(myim,vis,casalog)
                retval=setjyutil.setSolarObjectJy(field=field,spw=spw,scalebychan=scalebychan,
                             timerange=timerange,observation=str(observation), scan=scan, 
                             intent=intent, useephemdir=useephemdir,usescratch=usescratch)
                clnamelist=setjyutil.getclnamelist()
            
            else:
                # Need to branch out the process for fluxscale since the input dictionary may 
                # contains multiple fields. Since fluxdensity parameter is just a vector contains 
                # IQUV flux densities and so need to run im.setjy per field 

                if standard=="fluxscale": 
                    instandard="Perley-Butler 2010"
                    # function to return selected field, spw, etc
                    fieldidused=parse_fluxdict(fluxdict, vis, field, spw, observation, timerange,
                                           scan, intent, usescratch)

                    if len(fieldidused):
                    
                        retval={}
                        for selfld in fieldidused:
                            #selspix=fluxdict[selfld]["spidx"][1]  # setjy only support alpha for now
                            selspix=fluxdict[selfld]["spidx"][1:]  # omit c0 (=log(So))
                            # set all (even if fluxdensity = -1
                            if spw=='':
                                selspw = [] 
                                invalidspw = []
                                for ispw in fluxdict["spwID"].tolist():
                                    # skip spw if fluxd=-1
                                    if fluxdict[selfld][str(ispw)]["fluxd"][0]>-1:
                                        selspw.append(ispw)
                                    else:
                                        invalidspw.append(ispw)
                                if len(invalidspw):
                                    casalog.post("Fluxdict does not contains valid fluxdensity for spw="+
                                                 str(invalidspw)+ 
                                                 ". Model will not set for those spws.", "WARN") 
                            else: # use spw selection
                                selspw = ms.msseltoindex(vis,spw=spw)["spw"].tolist()
                    
                            if fluxdict[selfld]["fitFluxd"]:
                                selfluxd = fluxdict[selfld]["fitFluxd"]
                                selreffreq = fluxdict[selfld]["fitRefFreq"] 
                            else:
                                # use first selected spw's flux density 
                                selfluxd = fluxdict[selfld][str(selspw[0])]['fluxd']
                                # assuming the fluxscale reporting the center freq of a given spw
                                selreffreq=fluxdict["freq"][selspw[0]] 
                            casalog.post("Use fluxdensity=%s, reffreq=%s, spix=%s" %
                                     (selfluxd,selreffreq,selspix)) 
                            curretval=myim.setjy(field=selfld,spw=selspw,modimage=model,
                                                 # enable spix in list
                                                 fluxdensity=selfluxd, spix=selspix, reffreq=selreffreq, 
                                                 #fluxdensity=selfluxd, spix=[selspix], reffreq=selreffreq, 
                                                 standard=instandard, scalebychan=scalebychan,
                                                 polindex=polindex, polangle=polangle, rotmeas=rotmeas,
                                                 time=timerange, observation=str(observation), scan=scan, 
                                                 intent=intent, interpolation=interpolation)
                            retval.update(curretval)
                    else:
                        raise Exception("No field is selected. Check fluxdict and field selection.")
                else: 
                    influxdensity=fluxdensity
                    if standard=="manual":
                        instandard="Perley-Butler 2010" # default standard when fluxdensity=-1 or 1
                    else:
                        instandard=standard
                        # From the task, fluxdensity=-1 always for standard!="manual" (but possible to 
                        # for im.setjy to run with both the stanadard and fluxdensity specified.
                        # Until CAS-6463 is fixed, need to catch and override inconsistent parameters. 
                        if userFluxDensity and instandard!='manual':
                            influxdensity=-1
                            #raise Exception("Use standard=\"manual\" to set the specified fluxdensity.")
                            casalog.post("*** fluxdensity > 0 but standard != 'manual' (possibly interaction with globals), override to set fluxdensity=-1.", 'WARN')
                             

                    if spix==[]: # handle the default 
                        spix=0.0
                    # need to modify imager to accept double array for spix
                    retval=myim.setjy(field=field, spw=spw, modimage=model, fluxdensity=influxdensity, 
                                      spix=spix, reffreq=reffreq, standard=instandard, scalebychan=scalebychan, 
                                      polindex=polindex, polangle=polangle, rotmeas=rotmeas,
                                      time=timerange, observation=str(observation), scan=scan, intent=intent, 
                                      interpolation=interpolation)

            myim.close()

    finally:
        if standard=='Butler-JPL-Horizons 2012':
            for cln in clnamelist:
                if deletecomp and os.path.exists(cln) and os.path.isdir(cln):
                    shutil.rmtree(cln,True) 
            if os.path.exists(os.path.basename(vis)+"_tmp_setjyCLfile"):
                shutil.rmtree(os.path.basename(vis)+"_tmp_setjyCLfile")

    return retval


def better_glob(pats):
    """
    Unlike ls, glob.glob('pat1 pat2') does not return  
    the union of matches to pat1 and pat2.  This does.
    """
    retset = set([])
    patlist = pats.split()
    for p in patlist:
        retset.update(glob(p))
    return retset
  

def lsmodims(path, modpat='*', header='Candidate models'):
    """
    Does an ls -d of files or directories in path matching modpat.
  
    Header describes what is being listed.
    """
    if os.path.isdir(path):
        if better_glob(os.path.join(path,modpat)):
            casalog.post("\n%s (%s) in %s:" % (header, modpat, path))
            sys.stdout.flush()
            os.system('cd ' + path + ';ls -d ' + modpat)
        else:
            casalog.post("\nNo %s matching '%s' found in %s" % (header.lower(),
                                                                modpat, path))


def findCalModels(target='CalModels',
                  roots=defaultRoots,
                  #permexcludes = ['.svn', 'regression', 'ephemerides',
                  permexcludes = ['regression', 'ephemerides',
                                  'geodetic', 'gui'],
                  exts=['.ms', '.im', '.tab']):
    """
    Returns a set of directories ending in target that are in the trees of roots.

    Because casa['dirs']['data'] can contain a lot, and CASA tables are
    directories, branches matching permexcludes or exts are excluded for speed.
    """

    retset = set([])
    ##
    ## first attempt to resolve using data path - only available in CASA6
    ##
    if is_CASA6:
        standard_locations = { 'CalModels': [ 'nrao/VLA/CalModels' ],
                               'SolarSystemModels': [ 'alma/SolarSystemModels' ] }
        if target in standard_locations:
            for p in standard_locations[target]:
                candidate = ctsys.resolve(p)
                if os.path.isdir(candidate):
                    retset.add(candidate)

    if len(retset) > 0:
        return retset

    # exclulde all hidden(.xxx) directories
    regex = re.compile('^\.\S+')
    # extra skip for OSX 
    if sys.platform == "darwin": 
        permexcludes.append('Frameworks')
        permexcludes.append('Library')
        permexcludes.append('lib')
    for root in roots:
      # Do a walk to find target directories in root.
      # 7/5/2011: glob('/export/data_1/casa/gnuactive/data/*/CalModels/*') doesn't work.
      for path, dirs, fnames in os.walk(root, followlinks=True):
          realpath = os.path.realpath(path)
          if not realpath in retset:
              excludes = permexcludes[:]
              for ext in exts:
                  excludes += [d for d in dirs if ext in d]
                  excludes += [m.group(0) for d in dirs for m in [regex.search(d)] if m]
              for d in excludes:
                  if d in dirs:
                      dirs.remove(d)
              if path.split('/')[-1] == target:
              # make path realpath to resolve the issue with duplicated path resulted from symlinks
                  retset.add(realpath)
    return retset             


def nselrows(vis, field='', spw='', obs='', timerange='', scan='', intent='', usescratch=None, ismms=False):

    # modified to use ms.msselect. If no row is selected ms.msselect will
    # raise an exception  - TT 2013.12.13
    retval = 0
    myms = ms()
    #msselargs = {'vis': vis}
    msselargs = {}
    if field:
        msselargs['field'] = field
    if spw:
        msselargs['spw'] = spw
    if intent:
       msselargs['scanintent'] = intent

  # only applicable for usescratch=T
    if usescratch:
        if obs:
            if not type(obs) == strType:
               sobs = str(obs)
            msselargs['observation'] = sobs
        if timerange:
            msselargs['time'] = timerange
        if scan:
            msselargs['scan'] = scan
    else:
        warnstr='Data selection by '
        datasels=[]
        if timerange: datasels.append('timerange')
        if scan: datasels.append('scan') 
        if obs: datasels.append('observation') 
        if len(datasels):
            warnstr+=str(datasels)+' will be ignored for usescartch=False'
            casalog.post(warnstr,'WARN')
 
    # === skip this use ms.msselect instead ====
    # ms.msseltoindex only goes by the subtables - it does NOT check
    # whether the main table has any rows matching the selection.
#    try:
#        selindices = myms.msseltoindex(**msselargs)
#        casalog.post("msselargs=",msselargs," selindices=",selindices)
#    except Exception, instance:
#        casalog.post('nselrowscore exception: %s' % instance,'SEVERE')
#        raise instance
#    query = []
#    if field:
#        query.append("FIELD_ID in " + str(selindices['field'].tolist()))
#    if spw:
#        query.append("DATA_DESC_ID in " + str(selindices['spw'].tolist()))
#    if obs and usescratch:
#        query.append("OBSERVATION_ID in " + str(selindices['obsids'].tolist()))

    # I don't know why ms.msseltoindex takes a time argument 
    # - It doesn't seem to appear in the output.
    
#    if scan and usescratch:
#        query.append("SCAN_NUMBER in " + str(selindices['scan'].tolist()))

    #if timerange and usescratch:
    #    query.append("TIME in [select TIME where 

    # for intent (OBS_MODE in STATE subtable), need a subquery part...
#    if intent:
#        query.append("STATE_ID in [select from ::STATE where OBS_MODE==pattern(\""+\
#                  intent+"\") giving [ROWID()]]")
#    casalog.post("query=",query)
#    mytb = tbtool()
#    mytb.open(vis)
    myms = ms()
    casalog.post(str(msselargs))
    myms.open(vis)

    if (len(msselargs)==0):
        retval = myms.nrow()
        myms.close()
    else:
        try:
#            st = mytb.query(' and '.join(query),style='python')  # Does style matter here?
#            retval = st.nrows()
#            st.close() # needed to clear tablecache? 
#            mytb.close()
            myms.msselect(msselargs)
            retval = myms.nrow(True)

        finally:
            #if ismms:
            #     casalog.post('nselrows: %s' % instance,'WARN')
            #else:
                 # this is probably redundant as the exception will be handle in setjy()
                 #casalog.post('nselrowscore exception: %s' % instance,'SEVERE')
            #     pass
            
            myms.close()
            #if not ismms: 
            #    raise Exception, instance
            #else:
            #    casalog.post('Proceed as it appears to be dealing with a MMS...','DEBUG')

    return retval

def parse_fluxdict(fluxdict, vis, field='', spw='', observation='', timerange='', scan='', intent='', usescratch=None):
    """
    Parser function for fluxdict (dictionary output from fluxscale) to set
    fluxdensity, spix, and reffreq parameters (as in 'manual' mode)
    """
    # set spix and reffreq if there  

    myms = ms()

    # dictionary for storing modified (taking AND between the data selection
    # and fluxdict content)
    modmsselargs={}
                    
    msselargs={}
    msselargs['field']=field 
    msselargs['spw']=spw 
    msselargs['scanintent']=intent
    # only applicable for usescratch=T
    if usescratch:
        if observation:
            msselargs['observation'] = observation
        if timerange:
           msselargs['time'] = timerange
        if scan:
           msselargs['scan'] = scan

    try:
        myms.open(vis)
        myms.msselect(msselargs)
        #selindices = myms.msselectedindices()
        msselfldids=myms.range(["FIELD_ID"])['field_id']
    except Exception as instance:
        casalog.post('parse_fluxdict exception: %s' % instance,'SEVERE')
        raise
    finally:
        myms.close()

    # check if fluxdict is valid
    if fluxdict=={}:
        raise Exception("fluxdict is empty")
    else:
        msg=""
        if not "freq" in fluxdict:
             msg+="freq "
        if not "spwID" in fluxdict:
             msg+="spwID "
        if len(msg):
             raise Exception("Input fluxdict is missing keywords:"+msg)

    # select fields only common to the dictionary and field selection
    fieldids=[]
    for ky in fluxdict.keys():
        try:
            int(ky) 
            fieldids.append(ky) # list in string field ids
        except:
            pass
    if not len(fieldids):
        casalog.post('No field ids was found in the dictionary given for fluxdict. Please check the input.', 'SEVERE')
       

    #if len(selindices['field']):
    if len(msselfldids):    
        # also check there is common field id, note field ids in selindices are in numpy.array
        #selfieldids = [fd for fd in fieldids if int(fd) in selindices['field'].tolist()]
        selfieldids = [fd for fd in fieldids if int(fd) in msselfldids]
        if not len(selfieldids):
            raise Exception("No field was found in fluxdict for the given data selection")
    else:
        selfieldids = fieldids   

    return selfieldids