from __future__ import absolute_import import os import sys # get is_CASA6 and is_python3 from casatasks.private.casa_transition import * if is_CASA6: from casatools import image, quanta from casatasks import casalog from .ialib import write_image_history _qa = quanta() else: from taskinit import * from ialib import write_image_history image = iatool # not a local tool _qa = qa def importfits(fitsimage,imagename,whichrep,whichhdu,zeroblanks,overwrite,defaultaxes,defaultaxesvalues,beam): """Convert an image FITS file into a CASA image: Keyword arguments: fitsimage -- Name of input image FITS file default: none; example='3C273XC1.fits' imagename -- Name of output CASA image default: none; example: imagename='3C273XC1.image' whichrep -- If fits image has multiple coordinate reps, choose one. default: 0 means first; example: whichrep=1 whichhdu -- If its file contains multiple images, choose one (0 = first HDU, -1 = first valid image) default=-1 ; example: whichhdu=1 zeroblanks -- Set blanked pixels to zero (not NaN) default=True; example: zeroblanks=True overwrite -- Overwrite pre-existing imagename default=False; example: overwrite=True defaultaxes -- Add the default 4D coordinate axes where they are missing default=False, example: defaultaxes=True defaultaxesvalues -- List of values to assign to added degenerate axes when defaultaxes==True (ra,dec,freq,stokes) default = [], example: defaultaxesvalues=['13.5h', '-2.5deg', '88.5GHz', 'Q'] beam -- List of values to be used to define the synthesized beam [BMAJ,BMIN,BPA] (as in the FITS keywords) default = [] (i.e. take from FITS file), example: beam=['0.35arcsec', '0.24arcsec', '25deg'] """ #Python script casalog.origin('importfits') _myia = image() tmpname = imagename reorder = False addaxes = False adddir = False addstokes = False addfreq=False defaultorder = ['Right Ascension', 'Declination', 'Stokes', 'Frequency'] addbeam = False try: _myia.dohistory(False) if os.path.exists(imagename): if not overwrite: raise RuntimeError('Output image exists already and you did not set overwrite to True.') else: os.system('rm -rf '+imagename) if defaultaxes: if len(defaultaxesvalues)!=4: raise TypeError('When defaultaxes==True, parameter defaultaxesvalues must be provided as a list of 4 values: RA, Dec, Freq, Stokes,\n e.g. [\'13.5h\', \'-2.5deg\', \'88.5GHz\', \'I\']\nFor existing axes, empty strings can be given as values.') _myia.open(fitsimage) _mycs=_myia.coordsys() acts = _mycs.axiscoordinatetypes() cnames = _mycs.names() _myia.close() if ('Direction' in acts and not ('Right Ascension' in cnames and 'Declination' in cnames)): raise RuntimeError('Non-standard direction axes. Cannot add default axes.') if ('Spectral' in acts and not 'Frequency' in cnames): raise RuntimeError('Non-standard spectral axis. Cannot add default axes.') if ('Stokes' in acts and not 'Stokes' in cnames): raise RuntimeError('Non-standard Stokes axis. Cannot add default axes.') if not ('Right Ascension' in cnames and 'Declination' in cnames): addaxes = True adddir = True if not ('Frequency' in cnames): addaxes = True addfreq = True if not ('Stokes' in cnames): addaxes = True addstokes = True if not addaxes and cnames!=defaultorder: reorder = True if addaxes or reorder: tmpname = imagename+'.tmp' os.system('rm -rf '+tmpname) if beam!=[]: # user has set beam if type(beam)!=list or len(beam)!=3 or not (type(beam[0])==str and type(beam[1])==str and type(beam[2])): raise TypeError("Parameter beam is invalid (should be list of 3 strings or empty): %s" % beam) qabeam = [] for i in range(0,3): try: qabeam.append(_qa.quantity(beam[i])) tmp = _qa.toangle(qabeam[i]) except: raise TypeError("Parameter beam[%s] is invalid (should be an angle): %s" % (i,beam[i])) if (_qa.convert(qabeam[0], 'arcsec')['value'] >= _qa.convert(qabeam[1], 'arcsec')['value']): addbeam = True else: raise TypeError("Parameter beam[%s] is invalid (major axis must be >= minor axis): %s" % (i,beam)) _myia.fromfits(tmpname,fitsimage,whichrep,whichhdu,zeroblanks) _myia.close() if addaxes: casalog.post('Adding missing coodinate axes ...', 'INFO') tmpname2 = imagename+'.tmp2' os.system('rm -rf '+tmpname2) _myia.open(tmpname) ia2 = _myia.adddegaxes(outfile=tmpname2, direction=True, spectral=True, stokes=defaultaxesvalues[3], silent=True) _myia.close() os.system('rm -rf '+tmpname) ia2.close() ia2.open(tmpname2) # set the right reference values in the added axes _mynewcs=ia2.coordsys() raval = 0. decval = 0. freqval = 0. if adddir: ra = defaultaxesvalues[0] if type(ra)==int or type(ra)==float: raval = ra else: qara = _qa.quantity(_qa.angle(ra)[0]) if qara['unit'].find('deg') < 0: raise TypeError("RA default value is not a valid angle quantity: %s" % ra) raval = qara['value'] dec = defaultaxesvalues[1] if type(dec)==int or type(dec)==float: decval = dec else: qadec = _qa.quantity(_qa.angle(dec)[0]) if qadec['unit'].find('deg') < 0: raise TypeError("DEC default value is not a valid angle quantity: %s" % dec) decval = qadec['value'] _mynewcs.setunits(value='deg deg', type='direction') _mynewcs.setreferencevalue(type='direction', value=[raval,decval]) if addfreq: freq = defaultaxesvalues[2] if type(freq)==int or type(freq)==float: freqval = freq else: qafreq = _qa.quantity(freq) if qafreq['unit'].find('Hz') < 0: raise TypeError("Freq default value is not a valid frequency quantity: %s" % freq) freqval = _qa.convertfreq(qafreq,'Hz')['value'] _mynewcs.setunits(value='Hz', type='spectral') _mynewcs.setreferencevalue(type='spectral', value=freqval) _mynewcs.setrestfrequency(freqval) # Note: stokes default value was already set in adddegaxes if adddir or addfreq: ia2.setcoordsys(_mynewcs.torecord()) ia2.close() cnames = _mynewcs.names() if len(cnames)==4 and not (cnames == defaultorder): # need to reorder reorder = True tmpname = tmpname2 else: os.system('mv '+tmpname2+' '+imagename) if reorder: casalog.post('Transposing coodinate axes ...', 'INFO') _myia.open(tmpname) ia2 = _myia.transpose(outfile=imagename, order=defaultorder) _myia.close() ia2.close() os.system('rm -rf '+tmpname) _myia.open(imagename) if addbeam: _myia.setrestoringbeam(beam[0], beam[1], beam[2]) else: mybeam = _myia.restoringbeam() if mybeam =={}: # the fits image had no beam casalog.post("This image has no beam or angular resolution provided, so you will not receive warnings from\n" "tasks such as imregrid if your image pixels do not sample the the angular resolution well.\n" "(This only affects warnings, not any functionality).\n" "Providing a beam and brightness units in an image can also be useful for flux calculations.\n" "If you wish to add a beam or brightness units to your image, please use\n" "the \"beam\" parameter or ia.setrestoringbeam() and ia.setbrightnessunit()", 'WARN') try: param_names = importfits.__code__.co_varnames[:importfits.__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_image_history(_myia, sys._getframe().f_code.co_name, param_names, param_vals, casalog) except Exception as instance: casalog.post("*** Error \'%s\' updating HISTORY" % instance, 'WARN') finally: _myia.done()