def __new__(cls, input_, sortby="date"): """Creates a new Map instance""" # Directory of files if isinstance(input_, basestring): filepaths = [] fits_arr = [] data = [] headers = [] # directory if os.path.isdir(input_): for filename in os.listdir(input_): filepaths.append(os.path.join(input_, filename)) # glob string else: from glob import glob filepaths = glob(input_) # read in files for filepath in filepaths: fits = pyfits.open(filepath) # append normalized header tags for use during sorting found_header_match = False for subcls in BaseMap.__subclasses__(): #pylint: disable=E1101 if subcls.is_datasource_for(fits[0].header): found_header_match = True fits.norm_header = subcls.get_properties(fits[0].header) if not found_header_match: raise UnrecognizedDataSouceError fits_arr.append(fits) # sort data if sortby and hasattr(cls, '_sort_by_%s' % sortby): fits_arr.sort(key=getattr(cls, '_sort_by_%s' % sortby)()) # create data cube for fits in fits_arr: data.append(fits[0].data) headers.append(fits[0].header) obj = np.asarray(data).view(cls) obj._headers = headers # List of data or filepaths elif isinstance(input_, list): obj = np.asarray(input_).view(cls) # ndarray elif isinstance(input_, np.ndarray): obj = input_ return obj
def __getitem__(self, key): """Overiding indexing operation""" if self.ndim is 3 and isinstance(key, int): data = np.ndarray.__getitem__(self, key) header = self._headers[key] for cls in BaseMap.__subclasses__(): if cls.is_datasource_for(header): return cls(data, header) raise UnrecognizedDataSouceError else: return np.ndarray.__getitem__(self, key)
def Map(input_): """Map class factory Attempts to determine the type of data associated with input and returns an instance of either the generic BaseMap class or a subclass of BaseMap such as AIAMap, EUVIMap, etc. Parameters ---------- input_ : filepath, data array The data source used to create the map object. This can be either a filepath to an image, a 2d list, or an ndarray. Returns ------- out : BaseMap Returns a BaseMap or BaseMap subclass instance Notes ----- PyFITS [1] Due to the way PyFITS works with images the header dictionary may differ depending on whether is accessed before or after the fits[0].data is requested. If the header is read before the data then the original header will be returned. If the header is read after the data has been accessed then the data will have been scaled and a modified header reflecting these changes will be returned: BITPIX may differ and BSCALE and B_ZERO may be dropped in the modified version. [2] The verify('fix') call attempts to handle violations of the FITS standard. For example, nan values will be converted to "nan" strings. Attempting to cast a pyfits header to a dictionary while it contains invalid header tags will result in an error so verifying it early on makes the header easier to work with later. References ---------- | http://stackoverflow.com/questions/456672/class-factory-in-python | http://stsdas.stsci.edu/download/wikidocs/The_PyFITS_Handbook.pdf """ if isinstance(input_, basestring): fits = pyfits.open(input_) fits.verify('silentfix') data = fits[0].data header = fits[0].header for cls in BaseMap.__subclasses__(): if cls.is_datasource_for(header): return cls(data, header) raise UnrecognizedDataSouceError else: return BaseMap(input_)