def pipeline_run_sim(path): startTime = time.time() if os.path.exists(path) == True: location = path + '/data' mask.MASK(path) ref_image(location) align_astroalign.align2(location) print("-> Combining images using swarp method...") psf.PSF(path) combine_swarp.swarp(location) psf.PSF(path) print("\n-> Subtracting images using AIS method...") subtract_ais.isis_sub(path) optimize.perform_optimization(path) print("-> Running SExtractor on residuals...") extract.EXTRACT(path, method='indiv') MR.MR_swarp(path) extract.EXTRACT(path, method='MR') endTime = time.time() print("-> Finished!\n-> Total runtime: %.2f seconds\n" % (endTime - startTime)) else: print( "\n-> Error: Unknown path entered\n-> Please enter the path to an existing exposure time directory\n-> Exiting...\n" ) sys.exit()
def generate_psf(x, y, cmap='hot', savebin=False, savetif=True, savevol=False, plot=True, **kwargs): """Calculate, save, and plot various point spread functions.""" args = { 'shape': (x, y), # number of samples in z and r direction 'dims': (10.0, 10.0), # size in z and r direction in micrometers 'ex_wavelen': 488.0, # excitation wavelength in nanometers 'em_wavelen': 520.0, # emission wavelength in nanometers 'num_aperture': 1.2, 'refr_index': 1.333, 'magnification': 1.0, 'pinhole_radius': 0.05, # in micrometers 'pinhole_shape': 'round', } args.update(kwargs) obsvol = psf.PSF(psf.ISOTROPIC | psf.CONFOCAL, **args) expsf = obsvol.expsf empsf = obsvol.empsf gauss = gauss2 = psf.PSF(psf.GAUSSIAN | psf.EXCITATION, **args) print(obsvol) return (obsvol.data)
def PIPELINE(path): '''The **OASIS Pipeline**. Runs all **OASIS** functions in succession. :param str path: Path of data file tree (contains the **configs**, **data**, **psf**, **residuals**, **sources**, **templates** directories). Use a comma-separated list for mapping to multiple datasets. :returns: All-in-one difference imaging pipeline. Raw science images are placed in the **data** directory, and residual images and source catalogs are outputted into the **residuals** and **sources** directories, respectively. ''' paths = (path.replace(' ', '')).split(',') del path for path in paths: startTime = time.time() if os.path.exists(path) == True: initialize.create(path) location = path + '/data' mask.MASK(path) sat = check_saturation.check_saturate(location) if sat == 0: ref_image(location) align_astroalign.align2(location) else: check = input( "-> Saturated images found\n-> Move saturated images to OASIS archive? (y/n): " ) if check == 'y': check_saturation.move_arch(sat) ref_image(location) align_astroalign.align2(location) elif check == 'n': ref_image(location) align_astroalign.align2(location) else: print("-> Error: Unknown input") sys.exit() print("-> Combining images using swarp method...") psf.PSF(path) combine_swarp.swarp(location) psf.PSF(path) print("\n-> Subtracting images using AIS method...") subtract_ais.isis_sub(path) optimize.perform_optimization(path) print("-> Running SExtractor on residuals...") extract.EXTRACT(path, method='indiv') MR.MR(path) extract.EXTRACT(path, method='MR') endTime = time.time() print("-> Finished!\n-> Total runtime: %.2f seconds\n" % (endTime - startTime)) else: print( "\n-> Error: Unknown path entered\n-> Please enter the path to an existing exposure time directory\n-> Exiting...\n" ) sys.exit()
def psf_sample(n_z_slices=64, depth_in_microns=0.4, r_in_microns=28.0): assert n_z_slices > 1 # psf.PSF fails if shape == 1 args = dict( shape=(n_z_slices, 128), # number of samples in z and r direction dims=( depth_in_microns, r_in_microns, ), # size in z and r direction in micrometers ex_wavelen=640.0, # excitation wavelength in nanometers em_wavelen=665.0, # emission wavelength in nanometers num_aperture=1.49, refr_index=1.51, magnification=1.0, pinhole_radius=1.50, # in micrometers pinhole_shape="round", ) obsvol = psf.PSF(psf.ISOTROPIC | psf.CONFOCAL, **args) width = 8 width2 = width // 2 psfs = [] for zi in range(n_z_slices): im = psf.mirror_symmetry(obsvol.empsf.slice(zi)) mea = im.shape[0] + 1 mea2 = mea // 2 im = im[mea2 - width2:mea2 + width2 - 1, mea2 - width2:mea2 + width2 - 1] im = im / np.sum(im) psfs += [im] return np.array(psfs)
def PSF(NA=1.2, n=1.46, sampling_z=None, shape_z=None): """ create an out of focus PSF """ args = { 'shape': (128, 128), # number of samples in z and r direction 'dims': (5.0, 5.0), # size in z and r direction in micrometers 'ex_wavelen': 488.0, # excitation wavelength in nanometers 'em_wavelen': 532.0, # emission wavelength in nanometers 'num_aperture': NA, 'refr_index': n, 'magnification': 1.0, # 'pinhole_radius': 0.05, # in micrometers # 'pinhole_shape': 'square', } if shape_z != None: args["shape"] = [shape_z, args["shape"][1]] abbe_r = args["em_wavelen"] / (2 * args["num_aperture"]) sampling_r = abbe_r / 2.2 dim_r = sampling_r * args['shape'][1] / 1000 #1.2 for a bit of oversampling if sampling_z == None: alpha = np.arcsin(args["num_aperture"] / args["refr_index"]) abbe_z = args["em_wavelen"] / (1 - np.cos(alpha)) sampling_z = abbe_z / 2.2 dim_z = sampling_z * args['shape'][0] / 1000 args["dims"] = [dim_z, dim_r] obsvol = psf.PSF(psf.ISOTROPIC | psf.WIDEFIELD, **args) empsf = obsvol.empsf # empsf.slice(100) # #def Main(): # params = { # 'figure.figsize': [8, 6], # 'legend.fontsize': 12, # 'text.usetex': False, # 'ytick.labelsize': 10, # 'ytick.direction': 'out', # 'xtick.labelsize': 20, # 'xtick.direction': 'out', # 'font.size': 10, # } ## mpl.rcParams.update(params) # # # title_font = {'fontname':'Arial', 'size':'16', 'color':'black', 'weight':'normal', # 'verticalalignment':'bottom'} # Bottom vertical alignment for more space # axis_font = {'fontname':'Arial', 'size':'18'} # plt.imshow(empsf.slice(100)) args["sampling"] = [sampling_z, sampling_r] return empsf, args
def pipeline_run_sim(path, sim_x=1, sim_y=1, sim_width=30, sim=True): import align_astroalign from ref_image import ref_image import combine_swarp import extract import subtract import mask import sys import psf import MR import os import time startTime = time.time() if os.path.exists(path) == True: location = path + '/data' ref_image(location) align_astroalign.align2(location) mask.MASK(path) print("-> Combining images using swarp method...") psf.PSF(path) combine_swarp.swarp(location) psf.PSF(path) print("\n-> Subtracting images...") subtract.SUBTRACT(path) # print("\n-> Subtracting images using AIS method...") # subtract_ais.isis_sub(path) # optimize.perform_optimization(path, s_x=sim_x, s_y=sim_y, s_width=sim_width, simulate=sim, qFloor=0.80, qValue=0.90, qInitial=0.95, use_config_file=False) print("-> Running SExtractor on residuals...") extract.EXTRACT(path, method='indiv') MR.MR(path) extract.EXTRACT(path, method='MR') endTime = time.time() print("-> Finished!\n-> Total runtime: %.2f seconds\n" % (endTime - startTime)) else: print( "\n-> Error: Unknown path entered\n-> Please enter the path to an existing exposure time directory\n-> Exiting...\n" ) sys.exit()
def psf_volume(voxel_dim, expansion, fluorophore, laser_wavelength, numerical_aperture,\ refractory_index, pinhole_radius, objective_factor, type, **kwargs): """ Creates a point spread volume, using the given parameters. Args: voxel_dim: (z, x, y) tuple the dimensions of a voxel in nm expansion: float the expansion factor fluorophore: string the fluorophore that is excited laser_wavelength: int the wavelength of the excitation laser in nm numerical_aperture: the numerical aperture of the system refractory_index: the refractory index, tipically 1.33 for ExM pinhole_radius: the pinhole raids in microns objective_factor: float objective factor of the microscope, tipically 0, 20 or 40 type: string one of 'confocal', 'widefield' or 'two photon' Returns: psf_vol: numpy 3d float64 array the point spread function """ fluorset = Fluorset() f = fluorset.get_fluor(fluorophore) #Map to psf type psf_type = { 'confocal': psf.CONFOCAL, 'widefield': psf.WIDEFIELD, 'two photon': psf.TWOPHOTON } #Upper bound for psf size precision = 16 z, x, y = np.array(voxel_dim) * expansion #Arguments back_projected_radius = pinhole_radius / float(objective_factor) #Fill args in dictionary args = dict(shape=(precision, precision), dims=(precision * z * 1e-3, precision * x * 1e-3),\ ex_wavelen=laser_wavelength, em_wavelen=f.find_emission_peak(),\ num_aperture=numerical_aperture, refr_index=refractory_index,\ pinhole_radius=back_projected_radius, magnification = 1) #Compute psf psf_vol = psf.PSF(psf.ISOTROPIC | psf_type[type], **args) return psf_vol.volume()
def SUBTRACT(path, method='ois', use_config_file=True): '''Performs difference imaging on the science images. The template image is convolved to match the science image's PSF, then the template is subtracted from the science image. This process is repeated for a number of different parameter configurations until an optimal residual is found. The actual convolution and subtraction is done with either the ``ISIS`` package (Alard) or ``hotpants`` (Becker). See documentation for details. :param str path: Path of data file tree (contains the **configs**, **data**, **psf**, **residuals**, **sources**, **templates** directories). Use a comma-separated list for mapping to multiple datasets. :param str method: Method of difference imaging. :param bool use_config_file: If ``True`` all input parameters are fetched from the local *OASIS.config* file. * *ois* (default): Optimal Image Subtraction. Christohpe Alard's ``ISIS`` package. * *hotpants*: Andrew Becker's ``hotpants`` program. Very similar to Alard's OIS, but differs in input parameters. May be useful to try if OIS is returning inadequate results. :returns: All science images are differenced and the corresponding residuals are placed in the **residuals** directory with the *_residual_* suffix. ''' paths = (path.replace(' ', '')).split(',') del path for path in paths: if use_config_file == True: method = get_config_value('sub_method') images = glob.glob(path + '/data/*.fits') psf_data = glob.glob(path + '/psf/*') if len(psf_data) != 2 * (len(images) + 1): psf.PSF(path) else: print("\n-> PSFs already exist...") if method == '' or method == 'ois': subtract_ais.isis_sub(path) optimize.perform_optimization(path) MR.MR_swarp(path) elif sub_method == 'hotpants': subtract_hotpants.hotpants(path) optimize.perform_optimization(path) MR.MR_swarp(path) else: print("\n-> Error: Unknown method") sys.exit()
def psf_generator(cmap='hot', savebin=False, savetif=False, savevol=False, plot=False, display=False, psfvol=False, psftype=0, expsf=False, empsf=False, realshape=(0,0), **kwargs): """Calculate and save point spread functions.""" args = { 'shape': (50, 50), # number of samples in z and r direction 'dims': (5.0, 5.0), # size in z and r direction in micrometers 'ex_wavelen': 488.0, # excitation wavelength in nanometers 'em_wavelen': 520.0, # emission wavelength in nanometers 'num_aperture': 1.2, 'refr_index': 1.333, 'magnification': 1.0, 'pinhole_radius': 0.05, # in micrometers 'pinhole_shape': 'round', } args.update(kwargs) if (psftype == 0): psf_matrix = psf.PSF(psf.ISOTROPIC | psf.EXCITATION, **args) print('psf.ISOTROPIC | psf.EXCITATION generated') if (psftype == 1): psf_matrix = psf.PSF(psf.ISOTROPIC | psf.EMISSION, **args) print('psf.ISOTROPIC | psf.EMISSION generated') if (psftype == 2): psf_matrix = psf.PSF(psf.ISOTROPIC | psf.WIDEFIELD, **args) print('psf.ISOTROPIC | psf.WIDEFIELD generated') if (psftype == 3): psf_matrix = psf.PSF(psf.ISOTROPIC | psf.CONFOCAL, **args) print('psf.ISOTROPIC | psf.CONFOCAL generated') if (psftype == 4): psf_matrix = psf.PSF(psf.ISOTROPIC | psf.TWOPHOTON, **args) print('psf.ISOTROPIC | psf.TWOPHOTON generated') if (psftype == 5): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.EXCITATION, **args) print('psf.GAUSSIAN | psf.EXCITATION generated') if (psftype == 6): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.EMISSION, **args) print('psf.GAUSSIAN | psf.EMISSION generated') if (psftype == 7): print('psf.GAUSSIAN | psf.WIDEFIELD generated') psf_matrix = psf.PSF(psf.GAUSSIAN | psf.WIDEFIELD, **args) if (psftype == 8): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.CONFOCAL, **args) print('psf.GAUSSIAN | psf.CONFOCAL generated') if (psftype == 9): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.TWOPHOTON, **args) print('psf.GAUSSIAN | psf.TWOPHOTON generated') if (psftype == 10): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.EXCITATION | psf.PARAXIAL, **args) print('psf.GAUSSIAN | psf.EXCITATION | psf.PARAXIAL generated') if (psftype == 11): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.EMISSION | psf.PARAXIAL, **args) print('psf.GAUSSIAN | psf.EMISSION | psf.PARAXIAL generated') if (psftype == 12): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.WIDEFIELD | psf.PARAXIAL, **args) print('psf.GAUSSIAN | psf.WIDEFIELD | psf.PARAXIAL generated') if (psftype == 13): print('psf.GAUSSIAN | psf.CONFOCAL | psf.PARAXIAL generated') psf_matrix = psf.PSF(psf.GAUSSIAN | psf.CONFOCAL | psf.PARAXIAL, **args) if (psftype == 14): psf_matrix = psf.PSF(psf.GAUSSIAN | psf.TWOPHOTON | psf.PARAXIAL, **args) print('psf.GAUSSIAN | psf.TWOPHOTON | psf.PARAXIAL generated') if empsf: psf_matrix = psf_matrix.expsf if expsf: psf_matrix = psf_matrix.empsf if psfvol: psf_matrix = normalize_matrix(psf_matrix.volume()) psf_matrix = psf_matrix[:realshape[0],:,:] psf_matrix = psf_matrix[:,:realshape[1],:realshape[1]] else: #psf_matrix = normalize_matrix(psf.mirror_symmetry(psf_matrix.data)) psf_matrix = psf.mirror_symmetry(psf_matrix.data) psf_matrix = psf_matrix[:realshape[1],:realshape[1]] if plot: import matplotlib.pyplot as plt plt.imshow(psf_matrix, cmap=cmap) plt.show() if display: import cv2 cv2.imshow('PSF',psf_matrix) cv2.waitKey(0) cv2.destroyAllWindows() if savetif: # save zr slices to TIFF files from tifffile import imsave imsave('psf_matrix.tif', psf_matrix, metadata = {'axes':'TZCYX'}, imagej=True) if savevol: # save xyz volumes to files. from tifffile import imsave imsave('psf_matrix_vol.tif', psf_matrix, metadata = {'axes':'TZCYX'}, imagej=True) print('PSF shape: ', psf_matrix.shape) return psf_matrix
def __init__(self, kernel_shape=7, multiple=5): self.kernel_shape = kernel_shape self.multiple = multiple self.psf_gen = psf.PSF(kernel_size=kernel_shape)
def TEST(): '''Tests the installation of **OasisPy** by downloading a set of images from an online public archive, adding fake sources to one of the images, and running the dataset through the **OASIS Pipeline**. If the fake sources are recovered, the test is a success. The images used are 118 second exposures of exoplanet HAT-P-37b taken with telescopes at the Las Cumbres Observatory. Results of the test are compared to control results located in **OasisPy**'s source code directory. :returns: Prints either 'TEST SUCCESSFUL!' or 'Test failure: Results do not match controls'. ''' frameNum = 30 q_initial = 1 q_value = 0.90 q_min = 0.80 startTime = time.time() #look for existing TEST folder and delete it og_test = loc + '/OASIS/targets/TEST' if os.path.exists(og_test) == True: shutil.rmtree(og_test) #get data from LCO public archive and put in target directory under 'TEST' folder print("\n-> Getting data from LCO...") object_name = 'HAT-P-37' response = requests.get('https://archive-api.lco.global/frames/?' + 'limit=%d&' % (frameNum) + 'RLEVEL=91&' + 'PROPID=' + 'LCOEPO2014B-007' + '&' + 'OBJECT=' + '%s&' % (object_name) + 'FILTER=' + 'w&' + 'start=' + '2019-05-29' + '&' 'end=' + '2019-05-31' + '&').json() frames = response['results'] # print(len(frames)) #take only the first 25 frames frames = frames[:frameNum] #download data temp_loc = loc + '/OASIS/temp/' os.mkdir(temp_loc + 'test_data') for frame in frames: with open(temp_loc + 'test_data/' + frame['filename'], 'wb') as f: f.write(requests.get(frame['url']).content) #funpack and move to 'TEST' folder obtain.process() obtain.movetar() old_data_location = obtain.rename() data_location = old_data_location.replace(object_name.replace(' ', '_'), 'TEST') os.rename("%s/OASIS/targets/%s" % (loc, object_name.replace(' ', '_')), "%s/OASIS/targets/TEST" % (loc)) #align and combine images test_loc = data_location[:-5] mask.MASK(test_loc) check_saturation.check_saturate(test_loc + '/data') ref_image.ref_image(test_loc + '/data') align_astroalign.align2(test_loc + '/data') psf.PSF(test_loc) combine_swarp.swarp(test_loc + '/data') #get PSFs of images so fake stars with same seeing can be added fake_im = '02:59:10.860_A_.fits' print('\n-> Image %s chosen as fake image\n' % (fake_im)) fake_residual = fake_im.replace('_A_', '_A_residual_') psf.PSF(test_loc) FWHM = psf.fwhm(test_loc + '/data/%s' % (fake_im)) #add three fake stars to reference image print("\n-> Adding fake stars to test image...") hdu = fits.open(test_loc + '/data/%s' % (fake_im)) hdu_data = hdu[0].data hdu_header = hdu[0].header hdu_mask = hdu[1].data h, w = np.shape(hdu_data) pos_x = [1500, 200, 1200] pos_y = [1600, 1400, 700] array = np.array([0.65343465, 0.50675629, 0.84946314]) fluxes = (200000.0 * array) + 300.0 print("\n-> Fake locations (in pixel coords):") print("\t X:", pos_x) print("\t Y:", pos_y) print("-> Fake fluxes (in ADUs):") print("\t ", fluxes) img = make_gaussian_im(h, w, fluxes=[fluxes[0], fluxes[1], fluxes[2]], x_pos=[pos_x[0], pos_x[1], pos_x[2]], y_pos=[pos_y[0], pos_y[1], pos_y[2]], std=[FWHM, FWHM, FWHM]) finalData = fits.PrimaryHDU(hdu_data + img, header=hdu_header) finalMask = fits.ImageHDU(hdu_mask) finalList = fits.HDUList([finalData, finalMask]) finalList.writeto(test_loc + '/data/%s' % (fake_im), overwrite=True) hdu.close() #subtract images using ISIS subtract_ais.isis_sub(test_loc) perform_optimization(test_loc, qInitial=q_initial, qValue=q_value, qFloor=q_min, use_config_file=False) MR.MR_swarp(test_loc) #perform SExtractor on residual images extract.EXTRACT(test_loc) #print TEST runtime endTime = time.time() print("\n-> Total test runtime: %.3fs\n" % (endTime - startTime)) residual = glob.glob(test_loc + '/residuals/%s' % (fake_residual)) fake1_check = False fake2_check = False fake3_check = False MR_sources, inds = filters.get_sources("%s/residuals/MR.fits" % (test_loc), filtered=True, MR=True) for src in MR_sources: if 1498 < src[1] < 1502 and 1598 < src[2] < 1602: fake1_check = True elif 198 < src[1] < 202 and 1398 < src[2] < 1402: fake2_check = True elif 1198 < src[1] < 1202 and 698 < src[2] < 702: fake3_check = True if fake1_check == True and fake2_check == True and fake3_check == True: print("\n-> Test SUCCESSFUL!") else: print("-> Test failure: Results do not match controls") #display final residual test image os.system('ds9 %s -scale zscale' % (residual[0]))
def psf_example(cmap='hot', savebin=False, savetif=False, savevol=False, plot=True, **kwargs): """Calculate, save, and plot various point spread functions.""" args = { 'shape': (512, 512), # number of samples in z and r direction 'dims': (5.0, 5.0), # size in z and r direction in micrometers 'ex_wavelen': 488.0, # excitation wavelength in nanometers 'em_wavelen': 520.0, # emission wavelength in nanometers 'num_aperture': 1.2, 'refr_index': 1.333, 'magnification': 1.0, 'pinhole_radius': 0.05, # in micrometers 'pinhole_shape': 'square', } args.update(kwargs) obsvol = psf.PSF(psf.ISOTROPIC | psf.CONFOCAL, **args) expsf = obsvol.expsf empsf = obsvol.empsf gauss = gauss2 = psf.PSF(psf.GAUSSIAN | psf.EXCITATION, **args) print(expsf) print(empsf) print(obsvol) print(gauss) print(gauss2) if savebin: # save zr slices to BIN files empsf.data.tofile('empsf.bin') expsf.data.tofile('expsf.bin') gauss.data.tofile('gauss.bin') obsvol.data.tofile('obsvol.bin') if savetif: # save zr slices to TIFF files from tifffile import imsave imsave('empsf.tif', empsf.data) imsave('expsf.tif', expsf.data) imsave('gauss.tif', gauss.data) imsave('obsvol.tif', obsvol.data) if savevol: # save xyz volumes to files. Requires 32 GB for 512x512x512 from tifffile import imsave imsave('empsf_vol.tif', empsf.volume()) imsave('expsf_vol.tif', expsf.volume()) imsave('gauss_vol.tif', gauss.volume()) imsave('obsvol_vol.tif', obsvol.volume()) if not plot: return # Log-plot xy, and rz slices pyplot.rc('font', family='sans-serif', weight='normal') pyplot.figure(dpi=96, figsize=(9.5, 5.0), frameon=True, facecolor='w', edgecolor='w') pyplot.subplots_adjust(bottom=0.02, top=0.92, left=0.02, right=0.98, hspace=0.01, wspace=0.01) ax = expsf.imshow(241, cmap=cmap)[0] empsf.imshow(242, sharex=ax, sharey=ax, cmap=cmap) obsvol.imshow(243, sharex=ax, sharey=ax, cmap=cmap) gauss.imshow(244, sharex=ax, sharey=ax, cmap=cmap) z = 0 psf.imshow(245, data=expsf.slice(z), sharex=ax, cmap=cmap) psf.imshow(246, data=empsf.slice(z), sharex=ax, cmap=cmap) psf.imshow(247, data=obsvol.slice(z), sharex=ax, cmap=cmap) psf.imshow(248, data=gauss.slice(z), sharex=ax, cmap=cmap) # plot cross sections z = numpy.arange(0, gauss.dims.ou[0], gauss.dims.ou[0] / gauss.dims.px[0]) r = numpy.arange(0, gauss.dims.ou[1], gauss.dims.ou[1] / gauss.dims.px[1]) zr_max = 20.0 pyplot.figure() pyplot.subplot(211) pyplot.title('PSF cross sections') pyplot.plot(r, expsf[0], 'r-', label=expsf.name + ' (r)') pyplot.plot(r, gauss2[0], 'r:', label='') # pyplot.plot(r, empsf.data[0], 'g--', label=empsf.name+' (r)') pyplot.plot(r, obsvol[0], 'b-', label=obsvol.name + ' (r)') pyplot.plot(r, gauss[0], 'b:', label="") pyplot.plot(z, expsf[:, 0], 'm-', label=expsf.name + ' (z)') pyplot.plot(z, gauss2[:, 0], 'm:', label='') # pyplot.plot(z, empsf.data[:,0], 'g--', label=empsf.name+' (z)') pyplot.plot(z, obsvol[:, 0], 'c-', label=obsvol.name + ' (z)') pyplot.plot(z, gauss[:, 0], 'c:', label='') pyplot.legend() pyplot.axis([0, zr_max, 0, 1]) pyplot.subplot(212) pyplot.title('Residuals of gaussian approximation') pyplot.plot(r, expsf[0] - gauss2[0], 'r-', label=expsf.name + ' (r)') pyplot.plot(r, obsvol[0] - gauss[0], 'b-', label=obsvol.name + ' (r)') pyplot.plot(z, expsf[:, 0] - gauss2[:, 0], 'm-', label=expsf.name + ' (z)') pyplot.plot(z, obsvol[:, 0] - gauss[:, 0], 'c-', label=obsvol.name + ' (z)') pyplot.axis([0, zr_max, -0.1, 0.1]) pyplot.tight_layout() pyplot.show()
def RUN(): ''' Master run function. Allows user to call any of the main **OASIS** methods. See documentation for details. ''' print('\n\t ------------------------------------------------------') print('\t OASIS v.1.0 ') print('\n\t Difference Imaging Software for Optical SETI Purposes ') print('\t Developed for the SDI Program @ UCSB ') print('\t http://www.deepspace.ucsb.edu ') print('\n\t Contact [email protected] for bug reports ') print('\t ------------------------------------------------------') print("\n-> Methods:") print("\n\tinitialize get mask align") print("\tpsf combine subtract mr") print("\textract pipeline simulate test") method = str(input('\n-> Enter method: ')) if method == 'get': import get get.GET() elif method == 'mask': path = input("-> Enter path to exposure time directory: ") import mask mask.MASK(path) elif method == 'align': path = input("-> Enter path to exposure time directory: ") import align align.ALIGN(path) elif method == 'psf': path = input("-> Enter path to exposure time directory: ") import psf psf.PSF(path) elif method == 'combine': path = input("-> Enter path to exposure time directory: ") import combine combine.COMBINE(path) elif method == 'subtract': path = input("-> Enter path to exposure time directory: ") import subtract subtract.SUBTRACT(path) elif method == 'mr': path = input("-> Enter path to exposure time directory: ") import MR MR.MR(path) elif method == 'extract': import extract path = input("-> Enter path to exposure time directory: ") extract_method = input("\n-> Extract method (both/indiv/MR): ") extract.EXTRACT(path, method=extract_method) elif method == 'pipeline': import pipeline path = input("-> Enter path to exposure time directory: ") pipeline.PIPELINE(path) elif method == 'initialize': import initialize initialize.INITIALIZE() elif method == 'test': import test test.TEST() elif method == 'simulate': import simulation simulation.SIM() else: print("-> Error: Method not recognized")
#! /usr/bin/env python # -*- coding: utf-8 -*- # Author: Patrick Wieschollek <*****@*****.**> from build import blur_library import cv2 import psf import numpy as np img = cv2.imread('input.jpg') img = img.astype(np.float32) / 255. psf = psf.PSF(kernel_size=17) k = next(psf.sample()).astype(np.float32) def single_image_blur(img, k, gpu_id=0): """Apply PSF to images on the GPU usin cuDNN Args: img (nd.array.float32): image in shape [H,W,C] k (nd.array.float32): kernel in shape [H,W] """ output = img.astype(np.float32).transpose((2, 0, 1)).copy() k = k.astype(np.float32) blur_library.blur(output, k, gpu_id) return output.transpose((1, 2, 0)) def batch_image_blur(img, k, gpu_id=0):
def get_PSF(stack, imagepath, conn, scriptParams): #Prepare the PSF for the deconvolution imageId = stack.getId() if scriptParams["Type_of_PSF"] == 'Measured PSF': #If a PSF is supplied, find the measured PSF and download it in the deconvolution folder. psfId = scriptParams["Measured_PSF_Image"] try: obs = conn.getObject("Image", psfId) except AttributeError: raise("The image supplied for the PSF (image %s) is not valid." %psfId) download(obs,str(imageId)+"PSF", 0, imagepath) else: #If no measured PSF is supplied, the theoretical PSF must be calculated. #Option1: Manually enter PSF parameters #Option2: Use OMERO metadata #First, prepare all the parameters that will be shared between the two options args = {} channelExcitation = [] channelEmission = [] sizeC = 0 sizeX = stack.getPrimaryPixels().getSizeX() pixelX = stack.getPrimaryPixels().getPhysicalSizeX().getValue() #The PSF parameters are passed to psf.py through the args dictionary args["shape"] = (int(round(sizeX / 2)+1), int(round(sizeX / 2))+1) #Need to divide by 2 and add 1 to get the right final number of pixels args["dims"] = (int(round(pixelX * sizeX / 2)), int(round(pixelX * sizeX / 2))) #Because of the previous operation the PSF will be inconsequentially too small (1/x) and off-centered. args["pinhole_radius"] = 0.55 #default value args["pinhole_shape"] = 'round' #the Olympus FV1200 confocal's pinhole is square #Option 1: Manual PSF if scriptParams["Type_of_PSF"] == 'Manual theoretical PSF': fluoType = scriptParams["Fluorescence_Microscopy_"] args["pinhole_radius"] = scriptParams["Confocal_Pinhole______"] args["num_aperture"] = scriptParams["Objective_NA_____________"] if scriptParams["Imaging_Medium_________"] == 'Oil': args["refr_index"] = 1.515 elif scriptParams["Imaging_Medium_________"] == 'Water': args["refr_index"] = 1.333 elif scriptParams["Imaging_Medium_________"] == 'Air': args["refr_index"] = 1.0 elif scriptParams["Imaging_Medium_________"] == 'CLARITY': args["refr_index"] = 1.45 if scriptParams["_____Channel_1_-_Excitation"] !=0: sizeC += 1 channelExcitation.append(scriptParams["_____Channel_1_-_Excitation"]) channelEmission.append(scriptParams["_____Channel_1_-_Emission__"]) if scriptParams["_____Channel_2_-_Excitation"] !=0: sizeC += 1 channelExcitation.append(scriptParams["_____Channel_2_-_Excitation"]) channelEmission.append(scriptParams["_____Channel_2_-_Emission__"]) if scriptParams["_____Channel_3_-_Excitation"] !=0: sizeC += 1 channelExcitation.append(scriptParams["_____Channel_3_-_Excitation"]) channelEmission.append(scriptParams["_____Channel_3_-_Emission__"]) if sizeC != stack.getSizeC(): raise ValueError("Wrong number of PSF channels parameters set. Make sure to set the right number of channels.") #Option 2: Automatic PSF. (Uses the metadata from the stack. Whether this will work depends on the metadata.) else: try: objective = stack.getObjectiveSettings().getObjective().getModel() except AttributeError: raise ("Couldn't identify the objective used for image %s. Please use the manual PSF settings." %imageId) try: args["num_aperture"] = stack.getObjectiveSettings().getObjective().getLensNA() except AttributeError: raise ("Couldn't find the numerical aperture for the objective used for image %s. Please use the manual PSF settings." %imageId) #Deduce immersion and microscopy type through the objective used: if objective in {"XLSLPLN25XGMP","XLPLN10XSVMP"}: #Two-photon CLARITY objectives fluoType = "TWOPHOTON" args["refr_index"] = 1.48 elif objective in {"XLPLN25XWMP2", "XLUMPLFLN-W"}: #Two-photon water objectives #need to double check the metadata name of the XLUM objective fluoType = "TWOPHOTON" args["refr_index"] = 1.333 elif objective == "PLAPON 60X O NA:1.42": #Confocal oil objectives fluoType = "CONFOCAL" args["refr_index"] = 1.515 args["pinhole_radius"] = 1 #TODO Figure out which metadata setting to select for pinhole_radius #TODO add air and widefield objectives else: raise AttributeError("Couldn't identify the objective used for image %s. Please use the manual PSF settings." %imageId) for c in stack.getChannels(): channel = c.getLogicalChannel() try: channelExcitation.append(channel.getExcitationWave().getValue()) channelEmission.append(channel.getEmissionWave().getValue()) except AttributeError: raise ("Couldn't find the excitation or emission wavelength of Channel %s from image %s. Please use the manual PSF settings." %(c,imageID)) sizeC = stack.getSizeC() #Calculate the PSF. for c in range(sizeC): #Loop through all channels since each one has a different theoretical PSF args["ex_wavelen"] = channelExcitation[c] args["em_wavelen"] = channelEmission[c] #This is the step where the image of the theoretical PSF is produced if fluoType == "TWOPHOTON": obsvol = psf.PSF(psf.GAUSSIAN | psf.TWOPHOTON, **args) #The settings are supplied through the args dictionary elif fluoType == "CONFOCAL": obsvol = psf.PSF(psf.GAUSSIAN | psf.CONFOCAL, **args) elif fluoType == "WIDEFIELD": obsvol = psf.PSF(psf.GAUSSIAN | psf.WIDEFIELD, **args) #The PSF needs to be completed with the mirror_symmetry function and corrected because it's produced with #one extra row and one extra column of pixels; we need to shave off those two extra lines. This doesn't seem ideal but this #is the recommandation from C. Gohlke and AIDA centers the PSF anyway. image_psf = psf.mirror_symmetry(obsvol.slice(0)) image_psf = np.delete(image_psf,1,0) image_psf = np.delete(image_psf,1,1) #Donwload the PSF. This is the same operation as the download function pixels = image_psf.astype(np.float32) tiff = Image.fromarray(pixels) deconv_path = os.path.join(imagepath, "%s%s_C%s_%03d_%03d.tif" % (imageId,"PSF",c,0,0)) tiff.save(deconv_path)