def mosaic_image_data(self, extname='SCI', tile=False, block=None, return_ROI=True): """ Creates the output mosaic ndarray of the requested IMAGE extension. :param extname: (default 'SCI'). Extname from AD to mosaic. :param tile: (boolean). If True, the mosaics returned are not corrected for shifting and rotation. :param block: default is (None). Allows a specific block to be returned as the output mosaic. The tuple notation is (col,row) (zero-based) where (0,0) is the lower left block. This is position of the reference block w/r to mosaic_grid. :param return_ROI: (True). Returns the minimum frame size calculated from the location of the amplifiers in a given block. If False uses the blocksize value. """ # Check if we have already a mosaic_data_array in memory. The user # has set this reference. Use this instead of re(creating) # it. # if len(self.mosaic_data_array) != 0: # It could be an arbitrary array shape; is up to the user # to correct for any implied problem. # Return the user supplied array only if it matches the current # extname. if extname in self.mosaic_data_array: return self.mosaic_data_array[extname] # Here as oppose to the as_astrodata method we can handle only one # extension name. # if extname == '' or (extname == None): extname = self.ref_extname if (extname != None) and (extname not in self.extnames): raise ValueError("mosaic: EXTNAME '"+extname+ \ "' not found in AD object.") # If data_list in memory is different from requested then # read data in from the requested extname. self.update_data(extname) # Setup attribute for transforming a DQ extension if any. # We need to set dq_data here, since the base class method # does not know about extension names. # dq_data = False if extname == 'DQ' and self.dq_planes: dq_data = True # Use the base method. out = Mosaic.mosaic_image_data(self,tile=tile,block=block,\ return_ROI=return_ROI, dq_data=dq_data, jfactor=self.jfactor) return out
def at3(): """ Verify that a mosaic is created from a list of ndarrays """ from gempy.library.mosaic import Mosaic, MosaicData import numpy print '\n at3 REQUIREMENT.......' print ('*****When positioning information is not available, Mosaic shall by ' 'default tile horizontally the list of input ndarrays of the same shape') # Make one ndarray with pixel values between 0 and 1000 data =numpy.linspace(0.,1000.,1024*2048).reshape(2048,1024) # Replicate the ndarray 4 times data_list = [data*(-1)**k for k in numpy.arange(4)] # Create a valid object with only a data list md = MosaicData(data_list) # Create a Mosaic object using this MosaicData object mo = Mosaic(md) # Now produce a mosaic by simply tiling the input # ndarrays since we do not have geometry information. mosaic_data = mo.mosaic_image_data() # If using the above input data list, the output # shloud be (2048,2048). print mosaic_data.shape list_average=[numpy.average(data_list[k]) for k in range(4)] print 'Input data average is:',numpy.average(list_average) print ' The expected result is: 0.0' print 'Output mosaic average:',numpy.average(mosaic_data) print ' The expected result is: 0.0'
def at8(): """ Create a 2 ndarrays list and mark a strip of the 2nd ndarray with a higher value. Set the Geometry dictionary with 'rotate' this ndarray by 5 degrees. Now we create the mosaic with default interpolation function and again with the 'spline' function of order 5. We plot a column from each mosaic. """ import numpy as np from gempy.library.mosaic import Mosaic,MosaicGeometry, MosaicData from matplotlib import pyplot as pl print '\n at8 REQUIREMENT.......' print ('*****It must be possible to select a different interpolator function') geometry = { 'transformation': { # shift and magnification will # have default values 'rotation': (0.0, 5.), }, 'blocksize': (100,100), 'mosaic_grid': (2,1) } mosaic_geometry = MosaicGeometry(geometry) # Make an ndarray data = np.zeros((100,100),dtype=np.float32) # put a stripe of 5 rows with value 5 data[45:50,:] = 5 # Make a 2x1 array with this rectangle. data_list = [data,data] mosaic_data = MosaicData(data_list) # With these two objects we instantiate a Mosaic object mo = Mosaic(mosaic_data, mosaic_geometry) # Finally make the mosaic mosaic_linear = mo.mosaic_image_data() # Now reset the interpolator function mo.set_interpolator('spline',5) # Create the mosaic. mosaic_spline = mo.mosaic_image_data() # Now plot one column across the stripes pl.plot(mosaic_linear[:,140]) # The transformation of block two to the reference # block (one) was done now using a spline interpolator # of order 5 which will create edge effects as seen in # this plot. pl.plot(mosaic_spline[:,140]) # # The tester should see the following values: # mosaic_linear[43] is 0.0 # mosaic_spline[43] is -0.3 # # mosaic_linear[48] is 5.0 # mosaic_spline[48] is 5.3 jj = raw_input("Press Enter to exit the test") pl.close()
def at7(): """ AT-mosaic-7 Verify that Mosaic can return a given block. The test creates a MosaicGeometry object from just 2 input values a blocksize and mosaic_grid tuples. Then it creates a MosaicData object with 4 data ndarrays and a dictionary names 'coords' with coordinates information about the input data. For Success Criteria 1), we create coords['amp_mosaic_coord'] such that we have 1 amplifier per block. For Success Criteria 2), we create coords['amp_mosaic_coord'] such that we have 2 amplifiers per block """ import numpy from gempy.library.mosaic import Mosaic,MosaicGeometry, MosaicData print '\n at7 REQUIREMENT.......' print ('*****The system shall return an ndarray from a given block number') geometry = {'blocksize':(1024,2048),'mosaic_grid':(4,1)} geometry = MosaicGeometry(geometry) # Now make four data ndarrays: (2048,1024) with pixel values # between 0 and 1000. data = numpy.linspace(0.,1000.,1024*2048).reshape(2048,1024) data_list = [data*(-1)**k for k in numpy.arange(4)] # Here is the coordinates description for each of the data # ndarray. The order is (x1,x2,y1,y2). # # Success Criteria 1. # Set 'amp_mosaic_coord' for Success Criteria 1) coords = {'amp_mosaic_coord': [(0, 1024, 0, 2048), (1024, 2048, 0, 2048), (2048, 3072, 0, 2048), (3072, 4096, 0, 2048)], 'amp_block_coord': [(0, 1024, 0, 2048), (0, 1024, 0, 2048), (0, 1024, 0, 2048), (0, 1024, 0, 2048)]} # Now create the data object mosaic_data = MosaicData(data_list,coords) # Instantiates Mosaic object with these 2 input objects mo = Mosaic(mosaic_data, geometry) # Finally get the given block. block_data = mo.mosaic_image_data(block=(1,0)) print 'Success Criteria 1..................' print 'Median value of input block(1,0):',numpy.median(data_list[1]) print 'Median value of output block:', numpy.median(block_data) # Print the shape: (height, width) in pixels. This should be # (2048,1024) print 'Output block shape should be(2048,1024):' print block_data.shape # print '\nStarting Criteria 2 ...................' # Success Criteria 2. # Setting up 'amp_mosaic_coord' # Make 2 amplifiers per block. We need 8 input ndarrays data = numpy.linspace(0.,1000.,512*2048).reshape(2048,512) data_list = [data*(-1)**k for k in numpy.arange(8)] amp_mosaic_coord = [] amp_block_coord = [] coords={} for k in range(8): x1 = 512*k bx1 = 512*(k%2) amp_mosaic_coord.append((x1,x1+512,0,2048)) amp_block_coord.append((bx1,bx1+512,0,2048)) coords['amp_mosaic_coord'] = amp_mosaic_coord coords['amp_block_coord'] = amp_block_coord # Now create the data object mosaic_data = MosaicData(data_list,coords) # Instantiates Mosaic object with these 2 input objects mo = Mosaic(mosaic_data, geometry) # Finally get the given block. block_data = mo.mosaic_image_data(block=(1,0)) print 'Success Criteria 2..................' print 'Median value of input block(1,0):',numpy.median(data_list[1]) print 'Median value of output block:',numpy.median(block_data) # Print the shape: (height, width) in pixels. This should be # (2048,1024) print 'Output block shape should be(2048,1024):' print block_data.shape
def at5(): """ The test instantiates a MosaicGeometry object from an input dictionary, a MosaicData object from a set of 4 data ndarrays and with these 2 object as input, instantiates a Mosaic object. """ import numpy as np from gempy.library.mosaic import Mosaic,MosaicGeometry, MosaicData try: from stsci.numdisplay import display except ImportError: from numdisplay import display print '\n at5 REQUIREMENT.......' print ('*****MosaicData shall correctly use the geometry dictionary to mosaic the input ndarrays.') geometry = { 'transformation': { 'shift': [(0.,0.), (-10,20), (-10,20), (0,0)], 'rotation': (0.0, 0.0, 45.0, 45.), 'magnification': (1., 1., 1., .5), }, 'interpolator': 'linear', 'gap_dict': { 'tile_gaps': {(0,0):(20,30),(1,0):(20,30), (0,1):(20,30),(1,1):(20,30)}, 'transform_gaps': {(0,0):(20,30),(1,0):(20,30), (0,1):(20,30),(1,1):(20,30)}, }, 'blocksize': (200,300), 'ref_block': (0,0), # 0-based 'mosaic_grid': (2,2) } mosaic_geometry = MosaicGeometry(geometry) # Make a rectangle (200,300) (wide,high). data = np.ones((300,200),dtype=np.float32) data = data*20 # make the background 20 # Make a 2x2 array with this rectangle data_list = [data,data,data,data] # Inside each block, make a small box 50x50 # starting at (50,50) with value 100 for k in range(4): data_list[k][50:101,50:101] = 100. # Mark the block borders with value 400 data_list[k][:,0] =400 data_list[k][:,199]=400 data_list[k][0,:] =400 data_list[k][299,:]=400 # Now create the MosaicData object mosaic_data = MosaicData(data_list) # With these two objects we instantiate a Mosaic object mo = Mosaic(mosaic_data, mosaic_geometry) # Finally make the mosaic mosaic_data = mo.mosaic_image_data() # Success Criteria 1. ref_block = mo.geometry.ref_block blksz_x,blksz_y = mo.geometry.blocksize print (int(mosaic_data.shape[0]/blksz_y), int(mosaic_data.shape[1]/blksz_x)) # Success Criteria 2. x_gap,y_gap= mo.geometry.gap_dict['tile_gaps'][ref_block] nblkx,nblky = mo.geometry.mosaic_grid print 'nx:', nblkx*blksz_x + (x_gap)*( nblkx-1) print 'ny:', nblky*blksz_y + (y_gap)*( nblky-1) # Success Criteria 3. # Now display the mosaic and the mask display(mosaic_data,frame=1,z1=0,z2=400.5)
def __init__(self, ad, mosaic_ad_function, ref_extname='SCI', column_names='default',dq_planes=False): """ Parameters ---------- :param ad: Input Astrodata object :param mosaic_ad_function: Is a user supplied function that will act as an interface to the particular ad, e.g., knows which keywords represent the coordinate systems to use and whether they are binned or not, or which values in the geometry look up table require to be binned. For help of this function please see its description in the mosaic.py module. :type mosaic_ad_function: A required user function returning a MosaicData and a MosaicGeometry objects. :param ref_extname: Is the IMAGE EXTNAME that should be used as the primary reference when reading the ad data arrays. :type ref_extname: string. Default is 'SCI'. :param column_names: Dictionary with bintable extension names that are associates with input images. The extension name is the key with value a tuple: (X_pixel_columnName, Y_pixel_columnName, RA_degrees_columnName, DEC_degrees_columnName) Example: column_names = {'OBJCAT': ('Xpix', 'Ypix', 'RA', 'DEC'), 'REFCAT': (None, None, 'RaRef', 'DecRef')} :param dq_planes: (False). Boolean flag to transform bit_plane by bit_plane for rotation, shifting and scaling. At this the algorithmm has a bad performance. Default value is False. """ # Instantiate the log logutils.config(mode='debug', console_lvl='stdinfo',file_name='mosaic.log') self.log = logutils.get_logger(__name__) self.log.debug("******* Debug.STARTING MosaicAD **********") self.log.info( "******* INFO.STARTING MosaicAD ***********") # Make sure we have the default extension name in the input AD. if ad[ref_extname] == None: raise ValueError("Extension name: '"+ref_extname+"' not found.") self.ad = ad # The input file ougth to have more than one extension to mosaic. if ad.count_exts(ref_extname) <= 1: raise ValueError("Nothing to mosaic. Input file has 1 extension.") # Execute the input user function. mosaic_data, geometry = mosaic_ad_function(ad,ref_extname) self.ref_extname = ref_extname self.extnames = None # All extensions names in AD self.im_extnames = None # All IMAGE extensions names in AD self.tab_extnames = None # All BINTABLE extensions names in AD self.get_extnames() # Form extnames, im_extnames, # tab_extnames. self.dq_planes = dq_planes # (False) Input parameter # Transform bit_plane byt bit_plane self.mosaic_data_array = {} # attribute to reference # numpy array by extension. # Set by method set_mosaic_data() # Instantiate the Base class Mosaic.__init__(self,mosaic_data,geometry) # Internal attribute to be used when loading data from another # extension name. # self.__current_extname = ref_extname # These are the default column names for merging catalogs. if column_names == 'default': self.column_names = \ {'OBJCAT': ('X_IMAGE', 'Y_IMAGE', 'X_WORLD', 'Y_WORLD'), 'REFCAT': (None, None, 'RAJ2000', 'DEJ2000') } else: self.column_names = column_names self.jfactor = [] # Jacobian factors applied to the # interpolated pixels to conserve flux. self.calculate_jfactor() # Fill out the jfactor list with the # jacobian of the transformation matrix. # See transformation() self.associated_tab_extns = [] # List of binary extension names that # have the same number and values of # extvers as the reference extension name. self.associated_im_extns = [] # List of image extension names that # have the same number and values of # extvers as the reference extension name. self.non_associated_extns = [] # List of remaining extension names that # are not in the above 2 lists. self.make_associations() # Look for associations between image extension