def test_infinite(self):
# Check that database insertion doesn't choke on infinite errors.
dataset = DataSet(data={'description': 'example dataset'},
database=self.database)
image = Image(dataset=dataset, data=db_subs.example_dbimage_data_dict())
# Inserting a standard example extractedsource should be fine
extracted_source = db_subs.example_extractedsource_tuple()
image.insert_extracted_sources([extracted_source])
inserted = columns_from_table('extractedsource',
where= {'image' : image.id})
self.assertEqual(len(inserted), 1)
# But if the source has infinite errors we drop it and log a warning
extracted_source = db_subs.example_extractedsource_tuple(error_radius=float('inf'),
peak_err=float('inf'),
flux_err=float('inf'))
# We will add a handler to the root logger which catches all log
# output in a buffer.
iostream = BytesIO()
hdlr = logging.StreamHandler(iostream)
logging.getLogger().addHandler(hdlr)
image.insert_extracted_sources([extracted_source])
logging.getLogger().removeHandler(hdlr)
# We want to be sure that the error has been appropriately logged.
self.assertIn("Dropped source fit with infinite flux errors",
iostream.getvalue())
inserted = columns_from_table('extractedsource',
where= {'image' : image.id})
self.assertEqual(len(inserted), 1)
def test_infinite(self):
# Check that database insertion doesn't choke on infinite errors
dataset = DataSet(data={'description': 'example dataset'},
database=self.database)
image = Image(dataset=dataset, data=db_subs.example_dbimage_datasets(1)[0])
# Inserting an example extractedsource should be fine
extracted_source = db_subs.example_extractedsource_tuple()
image.insert_extracted_sources([extracted_source])
# But it should also be fine if the source has infinite errors
extracted_source = db_subs.example_extractedsource_tuple(error_radius=float('inf'))
image.insert_extracted_sources([extracted_source])
开发者ID:hughbg,项目名称:tkp,代码行数:13,代码来源:test_orm.py
示例4: test_two_field_overlap_nulling_src
def test_two_field_overlap_nulling_src(self):
"""Similar to above, but one source disappears:
Two overlapping fields, 4 sources:
one steady source only in lower field,
one steady source in both fields,
one steady source only in upper field,
one transient source in both fields but only at *1st* timestep.
"""
n_images = 2
xtr_radius = 1.5
im_params = db_subs.generate_timespaced_dbimages_data(n_images,
xtr_radius=xtr_radius)
im_params[1]['centre_decl'] += xtr_radius * 1
imgs = []
lower_steady_src = db_subs.example_extractedsource_tuple(
ra=im_params[0]['centre_ra'],
dec=im_params[0]['centre_decl'] - 0.5 * xtr_radius)
upper_steady_src = db_subs.example_extractedsource_tuple(
ra=im_params[1]['centre_ra'],
dec=im_params[1]['centre_decl'] + 0.5 * xtr_radius)
overlap_steady_src = db_subs.example_extractedsource_tuple(
ra=im_params[0]['centre_ra'],
dec=im_params[0]['centre_decl'] + 0.2 * xtr_radius)
overlap_transient = db_subs.example_extractedsource_tuple(
ra=im_params[0]['centre_ra'],
dec=im_params[0]['centre_decl'] + 0.8 * xtr_radius)
imgs.append(tkp.db.Image(dataset=self.dataset, data=im_params[0]))
imgs.append(tkp.db.Image(dataset=self.dataset, data=im_params[1]))
imgs[0].insert_extracted_sources([lower_steady_src, overlap_steady_src,
overlap_transient])
imgs[0].associate_extracted_sources(deRuiter_r=0.1,
new_source_sigma_margin=new_source_sigma_margin)
nd_posns = dbnd.get_nulldetections(imgs[0].id)
self.assertEqual(len(nd_posns), 0)
imgs[1].insert_extracted_sources([upper_steady_src, overlap_steady_src])
imgs[1].associate_extracted_sources(deRuiter_r=0.1,
new_source_sigma_margin=new_source_sigma_margin)
#This time we don't expect to get an immediate transient detection,
#but we *do* expect to get a null-source forced extraction request:
nd_posns = dbnd.get_nulldetections(imgs[1].id)
self.assertEqual(len(nd_posns), 1)
runcats = columns_from_table('runningcatalog',
where={'dataset':self.dataset.id})
self.assertEqual(len(runcats), 4) #sanity check.
def test_probably_not_a_transient(self):
"""
No source at 250MHz, but we detect a source at 50MHz.
Not necessarily a transient.
Should trivially ignore 250MHz data when looking at a new 50MHz source.
"""
img_params = self.img_params
img0 = img_params[0]
# This time around, we just manually exclude the steady src from
# the first image detections.
steady_low_freq_src = MockSource(
example_extractedsource_tuple(ra=img_params[0]['centre_ra'],
dec=img_params[0]['centre_decl']
),
lightcurve=defaultdict(lambda :self.always_detectable_flux)
)
# Insert first image, no sources.
tkp.db.Image(data=img_params[0],dataset=self.dataset)
# Now set up second image.
img1 = tkp.db.Image(data=img_params[1],dataset=self.dataset)
xtr = steady_low_freq_src.simulate_extraction(img1,
extraction_type='blind')
insert_extracted_sources(img1._id, [xtr], 'blind')
associate_extracted_sources(img1._id, deRuiter_r, self.new_source_sigma_margin)
transients = get_newsources_for_dataset(self.dataset.id)
# Should have no marked transients
self.assertEqual(len(transients), 0)
def test_null_detection_business_as_usual(self):
"""
If we do not blindly extract a steady source due to increased RMS,
then we expect a null-detection forced-fit to be triggered.
However, if the source properties are steady, this should not
result in the source being identified as transient.
"""
img0 = self.img_params[0]
steady_src_flux = self.barely_detectable_flux
steady_src = MockSource(
example_extractedsource_tuple(ra=img0['centre_ra'],
dec=img0['centre_decl']
),
lightcurve=defaultdict(lambda :steady_src_flux)
)
image, blind_xtr,forced_fits = insert_image_and_simulated_sources(
self.dataset,self.img_params[0],[steady_src],
self.new_source_sigma_margin)
self.assertEqual(len(blind_xtr),1)
self.assertEqual(len(forced_fits),0)
image, blind_xtr,forced_fits = insert_image_and_simulated_sources(
self.dataset,self.img_params[1],[steady_src],
self.new_source_sigma_margin)
self.assertEqual(len(blind_xtr),0)
self.assertEqual(len(forced_fits),1)
get_sources_filtered_by_final_variability(dataset_id=self.dataset.id,
**self.search_params)
transients=get_newsources_for_dataset(self.dataset.id)
self.assertEqual(len(transients),0)
def test_single_epoch_weak_transient(self):
"""
A weak (barely detected in blind extraction) transient appears at
field centre in one image, then disappears entirely.
Because it is a weak extraction, it will not be immediately marked
as transient, but it will get flagged up after forced-fitting due to
the variability search.
"""
im_params = self.im_params
transient_src = db_subs.MockSource(
template_extractedsource=db_subs.example_extractedsource_tuple(
ra=im_params[0]['centre_ra'],
dec=im_params[0]['centre_decl'],
),
lightcurve={im_params[2]['taustart_ts'] :
self.barely_detectable_flux}
)
inserted_sources = []
for img_pars in im_params[:3]:
image, _,forced_fits = insert_image_and_simulated_sources(
self.dataset,img_pars,[transient_src],
self.new_source_sigma_margin)
self.assertEqual(forced_fits, [])
newsources = get_newsources_for_dataset(self.dataset.id)
self.assertEqual(len(newsources), 0)
transients = get_sources_filtered_by_final_variability(
dataset_id=self.dataset.id, **self.search_params)
#No variability yet
self.assertEqual(len(transients), 0)
#Now, the final, empty image:
image, blind_extractions, forced_fits = insert_image_and_simulated_sources(
self.dataset,im_params[3],[transient_src],
self.new_source_sigma_margin)
self.assertEqual(len(blind_extractions),0)
self.assertEqual(len(forced_fits), 1)
#No changes to newsource table
newsources = get_newsources_for_dataset(self.dataset.id)
self.assertEqual(len(newsources), 0)
#But it now has high variability
transients = get_sources_filtered_by_final_variability(
dataset_id=self.dataset.id, **self.search_params)
self.assertEqual(len(transients), 1)
transient_properties = transients[0]
# Check that the bands for the images are the same as the transient's band
freq_bands = self.dataset.frequency_bands()
self.assertEqual(len(freq_bands), 1)
self.assertEqual(freq_bands[0], transient_properties['band'])
#Sanity check that the runcat is correctly matched
runcats = self.dataset.runcat_entries()
self.assertEqual(len(runcats), 1)
self.assertEqual(runcats[0]['runcat'], transient_properties['runcat_id'])
def test_marginal_transient(self):
"""
( flux1 > (rms_min0*(det0 + margin) )
but ( flux1 < (rms_max0*(det0 + margin) )
--> Possible transient
If it was in a region of rms_min, we would (almost certainly) have seen
it in the first image. So new source --> Possible transient.
But if it was in a region of rms_max, then perhaps we would have missed
it. In which case, new source --> Just seeing deeper.
Note that if we are tiling overlapping images, then the first time
a field is processed with image-centre at the edge of the old field,
we may get a bunch of unhelpful 'possible transients'.
Furthermore, this will pick up fluctuating sources near the
image-margins even with a fixed field of view.
But without a more complex store of image-rms-per-position, we cannot
do better.
Hopefully we can use a 'distance from centre' feature to separate out
the good and bad candidates in this case.
"""
img_params = self.img_params
#Must pick flux value carefully to fire correct logic branch:
marginal_transient_flux = self.reliably_detected_at_image_centre_flux
marginal_transient = MockSource(
example_extractedsource_tuple(ra=img_params[0]['centre_ra'],
dec=img_params[0]['centre_decl']),
lightcurve={img_params[1]['taustart_ts'] : marginal_transient_flux}
)
#First, check that we've set up the test correctly:
rms_min0 = img_params[0]['rms_min']
rms_max0 = img_params[0]['rms_max']
det0 = img_params[0]['detection_thresh']
self.assertTrue(marginal_transient_flux <
rms_max0*(det0 + self.new_source_sigma_margin ) )
self.assertTrue(marginal_transient_flux >
rms_min0*(det0 + self.new_source_sigma_margin ) )
for pars in self.img_params:
img = tkp.db.Image(data=pars,dataset=self.dataset)
xtr = marginal_transient.simulate_extraction(img,
extraction_type='blind')
if xtr is not None:
img.insert_extracted_sources([xtr],'blind')
img.associate_extracted_sources(deRuiter_r, self.new_source_sigma_margin)
newsources = get_newsources_for_dataset(self.dataset.id)
#Should have one 'possible' transient
self.assertEqual(len(newsources),1)
self.assertTrue(
newsources[0]['low_thresh_sigma'] > self.new_source_sigma_margin)
self.assertTrue(
newsources[0]['high_thresh_sigma'] < self.new_source_sigma_margin)
def test_only_first_epoch_source(self):
"""test_only_first_epoch_source
- Pretend to extract a source only from the first image.
- Run source association for each image, as we would in TraP.
- Check the image source listing works
- Check runcat and assocxtrsource are correct.
"""
first_epoch = True
extracted_source_ids=[]
for im in self.im_params:
self.db_imgs.append( Image( data=im, dataset=self.dataset) )
last_img =self.db_imgs[-1]
if first_epoch:
last_img.insert_extracted_sources(
[db_subs.example_extractedsource_tuple()],'blind')
last_img.associate_extracted_sources(deRuiter_r,
new_source_sigma_margin)
#First, check the runcat has been updated correctly:
running_cat = columns_from_table(table="runningcatalog",
keywords=['datapoints'],
where={"dataset":self.dataset.id})
self.assertEqual(len(running_cat), 1)
self.assertEqual(running_cat[0]['datapoints'], 1)
last_img.update()
last_img.update_sources()
img_xtrsrc_ids = [src.id for src in last_img.sources]
# print "ImageID:", last_img.id
# print "Imgs sources:", img_xtrsrc_ids
if first_epoch:
self.assertEqual(len(img_xtrsrc_ids),1)
extracted_source_ids.extend(img_xtrsrc_ids)
assocxtrsrcs_rows = columns_from_table(table="assocxtrsource",
keywords=['runcat', 'xtrsrc' ],
where={"xtrsrc":img_xtrsrc_ids[0]})
self.assertEqual(len(assocxtrsrcs_rows),1)
self.assertEqual(assocxtrsrcs_rows[0]['xtrsrc'], img_xtrsrc_ids[0])
else:
self.assertEqual(len(img_xtrsrc_ids),0)
first_epoch=False
#Assocxtrsources still ok after multiple images?
self.assertEqual(len(extracted_source_ids),1)
assocxtrsrcs_rows = columns_from_table(table="assocxtrsource",
keywords=['runcat', 'xtrsrc' ],
where={"xtrsrc":extracted_source_ids[0]})
self.assertEqual(len(assocxtrsrcs_rows),1)
self.assertEqual(assocxtrsrcs_rows[0]['xtrsrc'], extracted_source_ids[0],
"Runcat xtrsrc entry must match the only extracted source")
def test_single_fixed_source(self):
"""test_single_fixed_source
- Pretend to extract the same source in each of a series of images.
- Perform source association
- Check the image source listing works
- Check runcat, assocxtrsource.
"""
fixed_src_runcat_id = None
for img_idx, im in enumerate(self.im_params):
self.db_imgs.append( Image(data=im, dataset=self.dataset))
last_img = self.db_imgs[-1]
insert_extracted_sources(last_img._id,
[db_subs.example_extractedsource_tuple()],'blind')
associate_extracted_sources(last_img._id, deRuiter_r,
new_source_sigma_margin)
running_cat = columns_from_table(table="runningcatalog",
keywords=['id', 'datapoints'],
where={"dataset":self.dataset.id})
self.assertEqual(len(running_cat), 1)
self.assertEqual(running_cat[0]['datapoints'], img_idx+1)
# Check runcat ID does not change for a steady single source
if img_idx == 0:
fixed_src_runcat_id = running_cat[0]['id']
self.assertIsNotNone(fixed_src_runcat_id, "No runcat id assigned to source")
self.assertEqual(running_cat[0]['id'], fixed_src_runcat_id,
"Multiple runcat ids for same fixed source")
runcat_flux = columns_from_table(table="runningcatalog_flux",
keywords=['f_datapoints'],
where={"runcat":fixed_src_runcat_id})
self.assertEqual(len(runcat_flux),1)
self.assertEqual(img_idx+1, runcat_flux[0]['f_datapoints'])
last_img.update()
last_img.update_sources()
img_xtrsrc_ids = [src.id for src in last_img.sources]
self.assertEqual(len(img_xtrsrc_ids), 1)
#Get the association row for most recent extraction:
assocxtrsrcs_rows = columns_from_table(table="assocxtrsource",
keywords=['runcat', 'xtrsrc' ],
where={"xtrsrc":img_xtrsrc_ids[0]})
# print "ImageID:", last_img.id
# print "Imgs sources:", img_xtrsrc_ids
# print "Assoc entries:", assocxtrsrcs_rows
# print "First extracted source id:", ds_source_ids[0]
# if len(assocxtrsrcs_rows):
# print "Associated source:", assocxtrsrcs_rows[0]['xtrsrc']
self.assertEqual(len(assocxtrsrcs_rows),1,
msg="No entries in assocxtrsrcs for image number "+str(img_idx))
self.assertEqual(assocxtrsrcs_rows[0]['runcat'], fixed_src_runcat_id,
"Mismatched runcat id in assocxtrsrc table")
def TestDeRuiterCalculation(self):
"""Check all the unit conversions are correct"""
dataset = DataSet(data={'description':"Assoc 1-to-1:" + self._testMethodName})
n_images = 2
im_params = db_subs.example_dbimage_datasets(n_images, centre_ra=10,
centre_decl=0)
#Note ra / ra_fit_err are in degrees.
# ra_sys_err is in arcseconds, but we set it = 0 so doesn't matter.
#ra_fit_err cannot be zero or we get div by zero errors.
#Also, there is a hard limit on association radii:
#currently this defaults to 0.03 degrees== 108 arcseconds
src0 = db_subs.example_extractedsource_tuple(ra=10.00, dec=0.0,
ra_fit_err=0.1, dec_fit_err=1.00,
ra_sys_err=0.0, dec_sys_err=0.0)
src1 = db_subs.example_extractedsource_tuple(ra=10.02, dec=0.0,
ra_fit_err=0.1, dec_fit_err=1.00,
ra_sys_err=0.0, dec_sys_err=0.0)
src_list = [src0, src1]
#NB dec_fit_err nonzero, but since delta_dec==0 this simplifies to:
expected_DR_radius = math.sqrt((src1.ra - src0.ra) ** 2 /
(src0.ra_fit_err ** 2 + src1.ra_fit_err ** 2))
# print "Expected DR", expected_DR_radius
for idx in [0, 1]:
image = tkp.db.Image(dataset=dataset,
data=im_params[idx])
image.insert_extracted_sources([src_list[idx]])
#Peform very loose association since we just want to store DR value.
associate_extracted_sources(image.id, deRuiter_r=100)
runcat = columns_from_table('runningcatalog', ['id'],
where={'dataset':dataset.id})
# print "***\nRESULTS:", runcat, "\n*****"
self.assertEqual(len(runcat), 1)
assoc = columns_from_table('assocxtrsource', ['r'],
where={'runcat':runcat[0]['id']})
# print "Got assocs:", assoc
self.assertEqual(len(assoc), 2)
self.assertAlmostEqual(assoc[1]['r'], expected_DR_radius)
def test_rejected_initial_image(self):
"""
An image which is rejected should not be taken into account when
deciding whether a patch of sky has been previously observed, and
hence whether any detections in that area are (potential) transients.
Here, we create a database with two images. The first
(choronologically) is rejected; the second contains a source. That
source should not be marked as a transient.
"""
dataset = tkp.db.DataSet(data={"description": "Trans:" + self._testMethodName}, database=tkp.db.Database())
# We use a dataset with two images
# NB the routine in db_subs automatically increments time between
# images.
n_images = 2
db_imgs = [
tkp.db.Image(data=im_params, dataset=dataset)
for im_params in db_subs.generate_timespaced_dbimages_data(n_images)
]
# The first image is rejected for an arbitrary reason
# (for the sake of argument, we use an unacceptable RMS).
db_quality.reject(
imageid=db_imgs[0].id,
reason=db_quality.reject_reasons["rms"],
comment=self._testMethodName,
session=self.session,
)
# Have to commit here: old DB code makes queries in a separate transaction.
self.session.commit()
# Since we rejected the first image, we only find a source in the
# second.
source = db_subs.example_extractedsource_tuple()
insert_extracted_sources(db_imgs[1]._id, [source])
# Standard source association procedure etc.
associate_extracted_sources(db_imgs[1].id, deRuiter_r=3.7, new_source_sigma_margin=3)
# Our source should _not_ be a transient. That is, there should be no
# entries in the newsource table for this dataset.
cursor = tkp.db.execute(
"""\
SELECT t.id FROM newsource t, runningcatalog rc
WHERE t.runcat = rc.id
AND rc.dataset = %(ds_id)s
""",
{"ds_id": dataset.id},
)
self.assertEqual(cursor.rowcount, 0)
def test_new_skyregion_insertion(self):
"""Here we test the association logic executed upon insertion of a
new skyregion.
We expect that any pre-existing entries in the runningcatalog
which lie within the field of view will be marked as
'within this region', through the presence of an entry in table
``assocskyrgn``.
Conversely sources outside the FoV should not be marked as related.
We begin with img0, with a source at centre.
Then we add 2 more (empty) images/fields at varying positions.
"""
n_images = 6
im_params = db_subs.generate_timespaced_dbimages_data(n_images)
src_in_img0 = db_subs.example_extractedsource_tuple(
ra=im_params[0]['centre_ra'],
dec=im_params[0]['centre_decl'],)
##First image:
image0 = tkp.db.Image(dataset=self.dataset, data=im_params[0])
image0.insert_extracted_sources([src_in_img0])
image0.associate_extracted_sources(deRuiter_r, new_source_sigma_margin)
image0.update()
runcats = columns_from_table('runningcatalog',
where={'dataset':self.dataset.id})
self.assertEqual(len(runcats), 1) #Just a sanity check.
##Second, different *But overlapping* image:
idx = 1
im_params[idx]['centre_decl'] += im_params[idx]['xtr_radius'] * 0.9
image1 = tkp.db.Image(dataset=self.dataset, data=im_params[idx])
image1.update()
assocs = columns_from_table('assocskyrgn',
where={'skyrgn':image1._data['skyrgn']})
self.assertEqual(len(assocs), 1)
self.assertEqual(assocs[0]['runcat'], runcats[0]['id'])
##Third, different *and NOT overlapping* image:
idx = 2
im_params[idx]['centre_decl'] += im_params[idx]['xtr_radius'] * 1.1
image2 = tkp.db.Image(dataset=self.dataset, data=im_params[idx])
image2.update()
assocs = columns_from_table('assocskyrgn',
where={'skyrgn':image2._data['skyrgn']})
self.assertEqual(len(assocs), 0)
请发表评论