def test_median_absolute_deviation_masked(): # Based on the changes introduces in #4658 # normal masked arrays without masked values are handled like normal # numpy arrays array = np.ma.array([1, 2, 3]) assert funcs.median_absolute_deviation(array) == 1 # masked numpy arrays return something different (rank 0 masked array) # but one can still compare it without np.all! array = np.ma.array([1, 4, 3], mask=[0, 1, 0]) assert funcs.median_absolute_deviation(array) == 1 # Just cross check if that's identical to the function on the unmasked # values only assert funcs.median_absolute_deviation(array) == ( funcs.median_absolute_deviation(array[~array.mask])) # Multidimensional masked array array = np.ma.array([[1, 4], [2, 2]], mask=[[1, 0], [0, 0]]) funcs.median_absolute_deviation(array) assert funcs.median_absolute_deviation(array) == 0 # Just to compare it with the data without mask: assert funcs.median_absolute_deviation(array.data) == 0.5 # And check if they are also broadcasted correctly np.testing.assert_array_equal( funcs.median_absolute_deviation(array, axis=0).data, [0, 1]) np.testing.assert_array_equal( funcs.median_absolute_deviation(array, axis=1).data, [0, 0])
def test_median_absolute_deviation_nans(): array = np.array([[1, 4, 3, np.nan], [2, 5, np.nan, 4]]) assert_equal(funcs.median_absolute_deviation(array, func=np.nanmedian, axis=1), [1, 1]) array = np.ma.masked_invalid(array) assert funcs.median_absolute_deviation(array) == 1
def test_median_absolute_deviation_nans(): array = np.array([[1, 4, 3, np.nan], [2, 5, np.nan, 4]]) assert_equal( funcs.median_absolute_deviation(array, func=np.nanmedian, axis=1), [1, 1]) array = np.ma.masked_invalid(array) assert funcs.median_absolute_deviation(array) == 1
def test_median_absolute_deviation_quantity(): # Based on the changes introduces in #4658 # Just a small test that this function accepts Quantities and returns a # quantity a = np.array([1, 16, 5]) * u.m mad = funcs.median_absolute_deviation(a) # Check for the correct unit and that the result is identical to the # result without units. assert mad.unit == a.unit assert mad.value == funcs.median_absolute_deviation(a.value)
def test_median_absolute_deviation_nans_masked(): """ Regression test to ensure ignore_nan=True gives same results for ndarray and masked arrays that contain +/-inf. """ data1 = np.array([1., np.nan, 2, np.inf]) data2 = np.ma.masked_array(data1, mask=False) mad1 = funcs.median_absolute_deviation(data1, ignore_nan=True) mad2 = funcs.median_absolute_deviation(data2, ignore_nan=True) assert_equal(mad1, mad2)
def aperture_mask(self, snr_threshold=5): """Returns an aperture photometry mask. snr_threshold : float Background detection threshold. """ # Find the pixels that are above the threshold in the median flux image median = self.median_flux() mad = median_absolute_deviation(median[np.isfinite(median)]) mad_cut = 1.4826 * mad * snr_threshold # 1.4826 turns MAD into STDEV for a Gaussian region = np.where(median > mad_cut, 1, 0) # Label all contiguous regions above the threshold labels = scipy.ndimage.label(region)[0] # Central pixel coordinate centralpix = [1 + median.shape[0] // 2, 1 + median.shape[1] // 2] # "//" is the integer division # find brightest pix within margin of central pix margin = 4 central_img = median[centralpix[0] - margin: centralpix[0] + margin, centralpix[1] - margin: centralpix[1] + margin] # unravel_index converts indices into a tuple of coordinate arrays brightestpix = np.unravel_index(central_img.argmax(), central_img.shape) bpixy, bpixx = brightestpix # Which label corresponds to the brightest pixel? regnum = labels[centralpix[0] - 4 + bpixy, centralpix[1] - 4 + bpixx] if regnum == 0: # No pixels above threshold? print('WARNING, no star was found in light curve, \ {} light curve will be junk!'.format(fn)) aperture_mask = labels == regnum return aperture_mask
def aperture_mask(self, snr_threshold=5): """Returns an aperture photometry mask. snr_threshold : float Background detection threshold. """ # Find the pixels that are above the threshold in the median flux image median = self.median_flux() mad = median_absolute_deviation(median[np.isfinite(median)]) mad_cut = 1.4826 * mad * snr_threshold # 1.4826 turns MAD into STDEV for a Gaussian region = np.where(median > mad_cut, 1, 0) # Label all contiguous regions above the threshold labels = scipy.ndimage.label(region)[0] # Central pixel coordinate centralpix = [1 + median.shape[0] // 2, 1 + median.shape[1] // 2] # "//" is the integer division # find brightest pix within margin of central pix margin = 4 central_img = median[centralpix[0] - margin:centralpix[0] + margin, centralpix[1] - margin:centralpix[1] + margin] # unravel_index converts indices into a tuple of coordinate arrays brightestpix = np.unravel_index(central_img.argmax(), central_img.shape) bpixy, bpixx = brightestpix # Which label corresponds to the brightest pixel? regnum = labels[centralpix[0] - 4 + bpixy, centralpix[1] - 4 + bpixx] if regnum == 0: # No pixels above threshold? print('WARNING, no star was found in light curve, \ {} light curve will be junk!'.format(fn)) aperture_mask = labels == regnum return aperture_mask
def test_median_absolute_deviation(): with NumpyRNGContext(12345): # test that it runs randvar = np.random.randn(10000) mad = funcs.median_absolute_deviation(randvar) # test whether an array is returned if an axis is used randvar = randvar.reshape((10, 1000)) mad = funcs.median_absolute_deviation(randvar, axis=1) assert len(mad) == 10 assert mad.size < randvar.size mad = funcs.median_absolute_deviation(randvar, axis=0) assert len(mad) == 1000 assert mad.size < randvar.size # Test some actual values in a 3 dimensional array x = np.arange(3 * 4 * 5) a = np.array([sum(x[:i + 1]) for i in range(len(x))]).reshape(3, 4, 5) mad = funcs.median_absolute_deviation(a) assert mad == 389.5 mad = funcs.median_absolute_deviation(a, axis=0) assert_allclose(mad, [[210., 230., 250., 270., 290.], [310., 330., 350., 370., 390.], [410., 430., 450., 470., 490.], [510., 530., 550., 570., 590.]]) mad = funcs.median_absolute_deviation(a, axis=1) assert_allclose(mad, [[27.5, 32.5, 37.5, 42.5, 47.5], [127.5, 132.5, 137.5, 142.5, 147.5], [227.5, 232.5, 237.5, 242.5, 247.5]]) mad = funcs.median_absolute_deviation(a, axis=2) assert_allclose(mad, [[3., 8., 13., 18.], [23., 28., 33., 38.], [43., 48., 53., 58.]])
def test_median_absolute_deviation(): with NumpyRNGContext(12345): # test that it runs randvar = np.random.randn(10000) mad = funcs.median_absolute_deviation(randvar) # test whether an array is returned if an axis is used randvar = randvar.reshape((10, 1000)) mad = funcs.median_absolute_deviation(randvar, axis=1) assert len(mad) == 10 assert mad.size < randvar.size mad = funcs.median_absolute_deviation(randvar, axis=0) assert len(mad) == 1000 assert mad.size < randvar.size # Test some actual values in a 3 dimensional array x = np.arange(3 * 4 * 5) a = np.array([sum(x[:i + 1]) for i in range(len(x))]).reshape(3, 4, 5) mad = funcs.median_absolute_deviation(a) assert mad == 389.5 mad = funcs.median_absolute_deviation(a, axis=0) assert_allclose( mad, [[210., 230., 250., 270., 290.], [310., 330., 350., 370., 390.], [410., 430., 450., 470., 490.], [510., 530., 550., 570., 590.]]) mad = funcs.median_absolute_deviation(a, axis=1) assert_allclose(mad, [[27.5, 32.5, 37.5, 42.5, 47.5], [127.5, 132.5, 137.5, 142.5, 147.5], [227.5, 232.5, 237.5, 242.5, 247.5]]) mad = funcs.median_absolute_deviation(a, axis=2) assert_allclose( mad, [[3., 8., 13., 18.], [23., 28., 33., 38.], [43., 48., 53., 58.]])
def aperture_mask(self, snr_threshold=5, margin=4): """Returns an aperture photometry mask. Parameters ---------- snr_threshold : float Background detection threshold. """ # Find the pixels that are above the threshold in the median flux image median = np.nanmedian(self.flux, axis=0) mad = median_absolute_deviation(median[np.isfinite(median)]) # 1.4826 turns MAD into STDEV for a Gaussian mad_cut = 1.4826 * mad * snr_threshold region = np.where(median > mad_cut, 1, 0) # Label all contiguous regions above the threshold labels = scipy.ndimage.label(region)[0] # Central pixel coordinate centralpix = [1 + median.shape[0] // 2, 1 + median.shape[1] // 2] # find brightest pix within margin of central pix central_img = median[centralpix[0] - margin:centralpix[0] + margin, centralpix[1] - margin:centralpix[1] + margin] # unravel_index converts indices into a tuple of coordinate arrays brightestpix = np.unravel_index(central_img.argmax(), central_img.shape) bpixy, bpixx = brightestpix # Which label corresponds to the brightest pixel? regnum = labels[centralpix[0] - margin + bpixy, centralpix[1] - margin + bpixx] if regnum == 0: warnings.warn( 'No star were found in light curve {}, ' 'light curve will be junk!'.format(self.path), UserWarning) aperture_mask = labels == regnum return aperture_mask
def extract_lightcurve(fn, qual_cut=False, toss_resat=True, bg_cut=5, skip=None): if skip is None: skip = 0 # Read the data into time, fluxarr, and quality with fits.open(fn) as f: time = f[1].data['TIME'][skip:] - f[1].data['TIME'][0] fluxarr = f[1].data['FLUX'][skip:] quality = f[1].data['QUALITY'][skip:] # Remove data that does not meet the quality criteria if qual_cut: time = time[quality == 0] fluxarr = fluxarr[quality == 0, :, :] elif toss_resat: # data the cadences where there is a wheel # resetuation event time = time[quality != 32800] fluxarr = fluxarr[quality != 32800, :, :] # fix dodgy data: the C0 data release included zeros # this will be changed later but we need this # fix for now fluxarr[fluxarr == 0] = np.nan # subtract background flux_b = median_subtract(fluxarr) # create a median image to calculate where # the pixels to use are flatim = np.nanmedian(flux_b, axis=0) # find pixels that are X MAD above the median vals = flatim[np.isfinite(flatim)].flatten() # 1.4826 turns a MAD into a STDEV for a Gaussian mad_cut = 1.4826 * median_absolute_deviation(vals) * bg_cut region = np.where(flatim > mad_cut, 1, 0) lab = scipy.ndimage.label(region)[0] # find the central pixel ("//" is the integer division) imshape = np.shape(flatim) centralpix = [1 + imshape[0] // 2, 1 + imshape[1] // 2] # find brightest pix within 9x9 of central pix centflatim = flatim[centralpix[0] - 4: centralpix[0] + 4, centralpix[1] - 4: centralpix[1] + 4] flatimfix = np.where(np.isfinite(centflatim), centflatim, 0) # unravel_index converts indices into a tuple of coordinate arrays brightestpix = np.unravel_index(flatimfix.argmax(), centflatim.shape) bpixy, bpixx = brightestpix regnum = lab[centralpix[0] - 4 + bpixy, centralpix[1] - 4 + bpixx] if regnum == 0: print('WARNING, no star was found in light curve, \ {} light curve will be junk!'.format(fn)) # Initialize return values lc = np.zeros_like(time) xbar = np.zeros_like(time) ybar = np.zeros_like(time) # there is a loop that performs the aperture photometry # lets also calcualte the moments of the image # make a rectangular aperture for the moments thing ymin = np.min(np.where(lab == regnum)[0]) ymax = np.max(np.where(lab == regnum)[0]) xmin = np.min(np.where(lab == regnum)[1]) xmax = np.max(np.where(lab == regnum)[1]) momlims = [ymin, ymax + 1, xmin, xmax + 1] for i, fl in enumerate(fluxarr): lc[i] = np.sum(fl[lab == regnum]) momim = fl[momlims[0]:momlims[1], momlims[2]:momlims[3]] momim[~np.isfinite(momim)] == 0.0 xbar[i], ybar[i], cov = intertial_axis(momim) return (time, lc, xbar - np.mean(xbar), ybar - np.mean(ybar), regnum)
def test_median_absolute_deviation_multidim_axis(): array = np.ones((5, 4, 3)) * np.arange(5)[:, np.newaxis, np.newaxis] assert_equal(funcs.median_absolute_deviation(array, axis=(1, 2)), np.zeros(5)) assert_equal(funcs.median_absolute_deviation(array, axis=np.array([1, 2])), np.zeros(5))
def test_median_absolute_deviation_multidim_axis(): array = np.ones((5, 4, 3)) * np.arange(5)[:, np.newaxis, np.newaxis] mad1 = funcs.median_absolute_deviation(array, axis=(1, 2)) mad2 = funcs.median_absolute_deviation(array, axis=(2, 1)) assert_equal(mad1, np.zeros(5)) assert_equal(mad1, mad2)
def test_median_absolute_deviation_multidim_axis(): array = np.ones((5, 4, 3)) * np.arange(5)[:, np.newaxis, np.newaxis] assert_equal(funcs.median_absolute_deviation(array, axis=(1, 2)), np.zeros(5)) assert_equal(funcs.median_absolute_deviation( array, axis=np.array([1, 2])), np.zeros(5))
def extract_lightcurve(fn, qual_cut=False, toss_resat=True, bg_cut=5, skip=None): if skip is None: skip = 0 # Read the data into time, fluxarr, and quality with fits.open(fn) as f: time = f[1].data['TIME'][skip:] - f[1].data['TIME'][0] fluxarr = f[1].data['FLUX'][skip:] quality = f[1].data['QUALITY'][skip:] # Remove data that does not meet the quality criteria if qual_cut: time = time[quality == 0] fluxarr = fluxarr[quality == 0, :, :] elif toss_resat: # data the cadences where there is a wheel # resetuation event time = time[quality != 32800] fluxarr = fluxarr[quality != 32800, :, :] # fix dodgy data: the C0 data release included zeros # this will be changed later but we need this # fix for now fluxarr[fluxarr == 0] = np.nan # subtract background flux_b = median_subtract(fluxarr) # create a median image to calculate where # the pixels to use are flatim = np.nanmedian(flux_b, axis=0) # find pixels that are X MAD above the median vals = flatim[np.isfinite(flatim)].flatten() # 1.4826 turns a MAD into a STDEV for a Gaussian mad_cut = 1.4826 * median_absolute_deviation(vals) * bg_cut region = np.where(flatim > mad_cut, 1, 0) lab = scipy.ndimage.label(region)[0] # find the central pixel ("//" is the integer division) imshape = np.shape(flatim) centralpix = [1 + imshape[0] // 2, 1 + imshape[1] // 2] # find brightest pix within 9x9 of central pix centflatim = flatim[centralpix[0] - 4:centralpix[0] + 4, centralpix[1] - 4:centralpix[1] + 4] flatimfix = np.where(np.isfinite(centflatim), centflatim, 0) # unravel_index converts indices into a tuple of coordinate arrays brightestpix = np.unravel_index(flatimfix.argmax(), centflatim.shape) bpixy, bpixx = brightestpix regnum = lab[centralpix[0] - 4 + bpixy, centralpix[1] - 4 + bpixx] if regnum == 0: print('WARNING, no star was found in light curve, \ {} light curve will be junk!'.format(fn)) # Initialize return values lc = np.zeros_like(time) xbar = np.zeros_like(time) ybar = np.zeros_like(time) # there is a loop that performs the aperture photometry # lets also calcualte the moments of the image # make a rectangular aperture for the moments thing ymin = np.min(np.where(lab == regnum)[0]) ymax = np.max(np.where(lab == regnum)[0]) xmin = np.min(np.where(lab == regnum)[1]) xmax = np.max(np.where(lab == regnum)[1]) momlims = [ymin, ymax + 1, xmin, xmax + 1] for i, fl in enumerate(fluxarr): lc[i] = np.sum(fl[lab == regnum]) momim = fl[momlims[0]:momlims[1], momlims[2]:momlims[3]] momim[~np.isfinite(momim)] == 0.0 xbar[i], ybar[i], cov = intertial_axis(momim) return (time, lc, xbar - np.mean(xbar), ybar - np.mean(ybar), regnum)