def find_cc(lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position=[0, 0], e_L=0, theta_L=0, shear=0, theta_shear=0, gravlens_params={}, caustic_CC_file='crit.txt', gravlens_input_file='gravlens_CC_input.txt', grid_factor=5., grid_factor2=3., max_iter_number=20, min_n_lines=200, gridhi1_CC_factor=2., accept_res_limit=2E-4): """ Determines the caustics and critical curves (CC) for a single component lens model. Uses an iterative procedure to determine the grid size and the minimum number of points on the curves. The CC size may vary considerably depending on the lens-source configuration. Because of this, we developed an iterative method to find the CC, that involves the size of the grid used by gravlens (gridhi1). The initial value of gridhi1 must be an upper limit for the size of the CC, and find_cc will try to find the CC. Each time gravlens can't find the CC, we lower gridhi1 by a factor of grid_factor (=5), in order to increase precision. This continues on until gravlens finds the CC or the number of iterations, max_iter_number (=20), is reached. After finding the CC, if the file is composed of less than min_n_lines (=200) lines, the code redefines gridhi1 to gridhi1/grid_factor2 (grid_factor2=3), usually increasing the number of points. With this first determination of the CC, the code uses its scale (gridhi1_CC_factor(=2) times the distance of the furthest CC point to the lens center) to reobtain the CC with the apropriate value for the grid, ensuring best precision. If the CC were not found after these attempts, this function returns "False" and an error message. If all caustic points have coordinates < accept_res_limit (=2E-4), a warning message will be generated, meaning that the precision of gravlens (limited by the number of digits in the output file) is being reached. Example: x_caustic, y_caustic, x_CC, y_CC, gravlens_config = find_cc('nfw',1,1,0,0) Input: - lens_model <str> : lens name (see gravlens manual table 3.1) - mass_scale <float> : mass scale of the lens - "parameter 1" - model_param_8 <float> : misc. lens parameter - often scale radio (depends on the lens model) - model_param_9 <float> : misc. lens parameter - often scale radio (depends on the lens model) - model_param_10 <float> : misc. lens parameter - often a power law index (depends on the lens model) - galaxy_position <list> : [x,y] position of the lens - e_L <float> : lens ellipticity (default=0) - theta_L <float> : lens position angle (in degrees) with respect to the vertical (counterclockwise) - shear <float> : external shear amplitude - theta_shear <float> : external shear direction (in degrees) - gravlens_params <dic> : contains the keys and values of the gravlens configuration (see default parameters at function set_gravlens_default,inside lens_parameters) - caustic_CC_file <str> : name of the output file with the caustic and CC positions - gravlens_input_file <str> : name of the input file used to run gravlens - grid_factor <float> : used in the iteration to find the critical curves. Each time no curves were found, the grid size is divided by grid_factor - min_n_lines <int> : minimum number of lines demanded in the CC file to decrease the grid by grid_factor_2 - grid_factor2 <float> : if the CC file is composed of less than min_n_lines, the code divides the grid size by grid_factor2 - max_iter_number <int> : maximum number of time the grid size will be divided by grid_factor - gridhi1_CC_factor <float> : the final size of the grid will be gridhi1_CC_factor * (the furthest CC point) - accept_res_limit <float> : if the furthest CC point is closer than accept_res_limit from the lens center, display a warning about lack of precision in determining the curves Output: - <list> : [x_caustic, ycaustic], with x_caustic and ycaustic being the lists with the caustic coordinates - <list> : [x_CC, y_CC], with x_CC and y_CC being the lists with the CC coordinates - <dict> : all configuration variables used for running gravlens (including gridhi1) - <str> : name of the file with the caustic and CC positions ('caustic_CC_file') - <str> : name of the input file used to run gravlens (gravlens_input_file) """ inputlens, setlens, gravlens_params_updated = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params ) # inputlens is the gravlens input (sets general parameters and the lens parameters) # setlens is the gravlens input line that concerns the lens (ex: nfw 1 0 ...) logging.debug( 'Determined the strings that defines the mass model in gravlens through the \'lens_parameters\' function' ) #-------------------------------------- #----------------------------- os.system('rm -f %s' % caustic_CC_file) # if the file previously exists, delete it critcurves(inputlens, caustic_CC_file, gravlens_input_file) # gets the critical curves (crit.txt file) logging.debug( 'Got the critical curves (%s file) with function \"critcurves\"' % caustic_CC_file) #----------------------------- # ITERATION ON gridhi1 (TO GET BETTER RESOLUTION ON CC) counter = 0 while os.path.isfile( './' + caustic_CC_file ) == False and counter < max_iter_number: # looks for the C.C. file (crit.txt) - if this file does not exist, add a note to arccatalog and quit gravlens_params_updated['gridhi1'] = float( gravlens_params_updated['gridhi1']) / grid_factor # gridhi1 /= 5. lens_par_out = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params_updated ) # inputlens is the gravlens input (sets general parameters and the lens parameters) inputlens, setlens, gravlens_params_updated = lens_par_out critcurves( inputlens, caustic_CC_file, gravlens_input_file) # gets the critical curves (crit.txt file) counter += 1 logging.debug('(Number of iterations on gridhi1 = %d)' % (counter)) if os.path.isfile( './' + caustic_CC_file ) == False: # looks for the C.C. file (crit.txt) - if this file does not exist, returns 'False' logging.error( 'Gravlens could not determine the caustics and critical curves. Try changing the input units (for example, from arcseconds to miliarcsecond), because gravlens outputs the critical curves with only 6 digits. The grid size used was %f and it was obtained through %d iteration.' % (float(gravlens_params_updated['gridhi1']), counter)) return False if len( open('./' + caustic_CC_file).readlines() ) < min_n_lines: # these correspond to critical cases when the CC have too few points. gravlens_params_updated['gridhi1'] = float( gravlens_params_updated['gridhi1']) / grid_factor2 # gridhi1 /= 3. lens_par_out = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params_updated ) # inputlens is the gravlens input (sets general parameters and the lens parameters) inputlens, setlens, gravlens_params_updated = lens_par_out critcurves( inputlens, caustic_CC_file, gravlens_input_file) # gets the critical curves (crit.txt file) x1, y1, u1, v1 = np.loadtxt( caustic_CC_file, usecols=(0, 1, 2, 3), unpack=True) # CC_x, CC_y, caustic_x, caustic_y #----------------------------------------------------------------------------------------------------------- # redefine gridhi1 according to the CC size index_CC = np.argmax( x1**2 + y1**2 ) # it is not necessary to use the lens center since we want the furthest point anyway logging.debug( 'The CC furthest point is at (%s, %s), a distance %s of the origin .' % (x1[index_CC], y1[index_CC], (x1[index_CC]**2 + y1[index_CC]**2)**0.5)) gravlens_params_updated['gridhi1'] = gridhi1_CC_factor * ( (x1[index_CC]**2 + y1[index_CC]**2)**0.5) #----------------------------------------------------------------------------------------------------------- # get CC with best value for the grid lens_par_out = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params_updated ) # inputlens is the gravlens input (sets general parameters and the lens parameters) inputlens, setlens, gravlens_params_updated = lens_par_out logging.debug('gridhi1 = %f and number of iterations on gridhi1 = %d' % (float(gravlens_params_updated['gridhi1']), counter)) critcurves(inputlens, caustic_CC_file, gravlens_input_file) # gets the critical curves (crit.txt file) x1, y1, u1, v1 = np.loadtxt( caustic_CC_file, usecols=(0, 1, 2, 3), unpack=True) # CC_x, CC_y, caustic_x, caustic_y # index_CC = np.argmax(x1**2 + y1**2) # logging.debug( 'The CC furthest point is at (%s, %s), a distance %s of the origin .' % (x1[index_CC], y1[index_CC], (x1[index_CC]**2 + y1[index_CC]**2)**0.5 ) ) # check if the precision is ok (gravlens outputs coordinates with only 6 decimal places) if max(max(np.abs(u1)), max(np.abs(v1))) < accept_res_limit: logging.warning( 'The caustics seem to be determined with low resolution') return x1, y1, u1, v1, gravlens_params_updated
def lensing(lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params, dimpix, source_centers, source_model, ref_magzpt, reference_band, base_name='sbmap', nover_max=3): """ Lenses sources for the given lens model. The lensing is performed with the gravlens software, using command SBmap2. Input: - lens_model <str> : Lens name (see gravlens manual table 3.1) - mass_scale <float> : Mass scale of the lens - "parameter 1" - model_param_8 <float> : misc. lens parameter - often scale radio (depends on the lens model) - model_param_9 <float> : misc. lens parameter - often scale radio (depends on the lens model) - model_param_10 <float> : misc. lens parameter - often a power law index (depends on the lens model) - galaxy_position <list> : [x,y] position of the lens - e_L <float> : lens ellipticity (ellipticity = 1 - q, where 0<q<=1 is the axial ratio) - theta_L <float> : lens position angle (in degrees) with respect to the vertical (counterclockwise) - shear <float> : external shear amplitude - theta_shear <float> : external shear direction (in degrees) - gravlens_params <dic> : Contains the keys and values of the gravlens configuration , dimpix, source_centers, source_model, - ref_magzpt <float> : The zero point magnitude to be used. It only affects the source fluxes. - reference_band <str> : - base_name <str> : - nover_max <int> : Output: - image_names <list> : """ inputlens, setlens, same_gravlens_params = lens_parameters(lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params) half_frame_size = gravlens_params['gridhi1'] Npix = int( (2.*half_frame_size) / dimpix ) image_names = [] f199 = open('sersicinput.txt', 'w') f199.write(inputlens) for i in range (0,len(source_centers)): source_type = source_model[i]['source_type'] # type of the source (can be 'sersic' or 'uniform') f199.write('setsource 1\n') # Nover increase resolution if the source is smaller than the pixel nover = source_model[i]['nover'] while source_model[i]['rs'] < dimpix/nover and nover < nover_max: nover += 1 source_model[i]['nover'] = nover # ------------------------------------------------------------------- if source_type == 'sersic': # determine 'totalsourceplaneflux', according to the source magnitude totalsourceplaneflux = 10**((2./5)*(ref_magzpt - source_model[i]['mag'])) f199.write('%s %f %.6f %.6f %f %f %.6f 0 %f macro\n' % (source_type, totalsourceplaneflux, source_centers[i][0], source_centers[i][1], source_model[i]['es'], source_model[i]['thetas'], source_model[i]['rs'], source_model[i]['ns'] ) ) # sersic/uniform F x y e PA halflightr nothing nS macro/micro if source_type == 'uniform': # fix 'totalsourceplaneflux' to 1 totalsourceplaneflux = 1 f199.write('%s %f %.6f %.6f %f %f %.6f 0 0 macro\n' % (source_type, totalsourceplaneflux, source_centers[i][0], source_centers[i][1], source_model[i]['es'], source_model[i]['thetas'], source_model[i]['rs'] ) ) # sersic/uniform F x y e PA halflightr nothing macro/micro #------------------------------------------------------------------------ f199.write('0 0 0 0 0 0 0 0\n') image_names.append('%s%05d_%s.fits' % (base_name, i, reference_band) ) f199.write('SBmap2 %0.9f %0.9f %d %0.9f %0.9f %d %d %s 3\n' % (-half_frame_size, half_frame_size, Npix, -half_frame_size, half_frame_size, Npix, nover, image_names[-1]) ) # <x lo> <hi> <# steps> <y lo> <hi> <# steps> <Nover> <file> <outtype> logging.debug( "The source %d is centered at %s and its properties are %s" % (i+1, source_centers[i] ,str(source_model) ) ) f199.close() if len(source_centers) > 0: logging.info( "gravlens is lensing %d finite source(s) (this may take several minutes depending on the resolution)..." % len(source_centers) ) status = os.system('gravlens sersicinput.txt > /dev/null') logging.debug('Executed gravlens to lens the finite sources and returned status %s' % str(status) ) else: logging.info( "There were no sources to be lensed" ) return image_names, half_frame_size
def lens_point_sources(x, y, lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position=(0, 0), e_L=0, theta_L=0, shear=0, theta_shear=0, gravlens_params={}, gravlens_input_file='findimg_input.txt', gravlens_output_file='findimg_out.txt', keep_files=False): """ Computes the positions of point images from a list of point sources. Input: - x [float,...] : x coordinates of the point sources - y [float,...] : y coordinates of the point sources - lens_model str : Lens name (see gravlens manual table 3.1) - mass_scale float : Mass scale of the lens - "parameter 1" - model_param_8 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_9 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_10 float : misc. lens parameter - often a power law index (depends on the lens model) - galaxy_position [float,float] : [x,y] position of the lens - e_L float : lens ellipticity (ellipticity = 1 - q, where 0<q<=1 is the axial ratio) - theta_L float : lens position angle (in degrees) with respect to the vertical (counterclockwise) - shear float : external shear amplitude - theta_shear float : external shear direction (in degrees) - gravlens_params dict : contains the keys and values of the gravlens configuration (see default parameters at function set_gravlens_default,inside lens_parameters) - gravlens_input_file str : name of the input file for gravlens - gravlens_output_file str : name of the output file generated by gravlens (with the point images' info) - keep_files bool : 'True' to keep gravlens input and output files and 'False' to delete them Output: - x_img [ [float,...],... ] : x coordinates of the point images. It has the same size of the input 'x', but each element of x_img has the n images of the corresponding source (n>=1) - y_img [ [float,...],... ] : y coordinates of the point images. Same shape of x_img - magnification [ [float,...],... ] : magnifications (mu_t*mu_r) of corresponding images. Same shape of x_img - time_delay [ [float,...],... ] : time delay of each image. Same shape of x_img - out_file [str,...] : list of gravlens output files with the images' parameters """ inputlens, setlens, gravlens_params_updated = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params) # run gravlens to get the images ======================================================== f = open(gravlens_input_file, 'w') f.write(inputlens) out_file = [] for i in range(len(x)): out_file.append(gravlens_output_file[:-4] + '_' + str(i) + gravlens_output_file[-4:]) f.write('findimg %0.6f %0.6f %s \n' % (x[i], y[i], out_file[-1])) f.close() os.system('gravlens %s > /dev/null' % (gravlens_input_file)) # now we have 'len(x)' files with the images information (pos, magnification, time delay) #======================================================================================== # we now read the files ======================================================== x_img, y_img, magnification, time_delay = [], [], [], [] for i in range(len(x)): # len(x) = len(out_file) img_properties = np.loadtxt(out_file[i], comments='#', skiprows=1, unpack=True) # , ndmin=4 if len( img_properties ) == 0: # in the case no images were found (means that the grid is not big enough) x_img.append([]) y_img.append([]) magnification.append([]) time_delay.append([]) else: x_img.append( list(np.array(img_properties[0], ndmin=1)) ) # I transform to list so sum(x_img, []) will flatten this list y_img.append( list(np.array(img_properties[1], ndmin=1)) ) # I transform to list so sum(y_img, []) will flatten this list magnification.append(img_properties[2]) time_delay.append(img_properties[3]) # ============================================================================== if keep_files == False: os.system('rm -f %s %s' % (gravlens_input_file, gravlens_output_file[:-4] + '*.' + gravlens_output_file[-3:])) return x_img, y_img, magnification, time_delay, out_file
def select_source_positions( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position=[0., 0.], e_L=0, theta_L=0, shear=0, theta_shear=0, gravlens_params={}, src_density_or_number=10, minimum_distortion=0., control_rhombus=2., caustic_CC_file='crit.txt', gravlens_input_file='gravlens_CC_input.txt', rad_curves_file='lens_curves_rad.dat', tan_curves_file='lens_curves_tan.dat', curves_plot='crit-caust_curves.png', show_plot=0, write_to_file=0, max_delta_count=20, delta_increment=1.1, grid_factor=5., grid_factor2=3., max_iter_number=20, min_n_lines=200, gridhi1_CC_factor=2., accept_res_limit=2E-4, gravlens_mag_input_file='gravlens_magtensor_in.txt', gravlens_mag_output_file='gravlens_magtensor_out.txt', keep_mag_files=False, gravlens_img_input_file='findimg_input.txt', gravlens_img_output_file='findimg_out.txt', keep_img_files=False): """ Determines the source centers that are candidates to generate an arc. The sources are sampled in a rectangle near the tangential caustic and lensed. The sorces with at least one image with |mu_t/mu_r| > minimum_distortion are selected, together with its images and properties. If src_density_or_number is a float (and therefore a density), the number of sources is given by np.random.poisson(rectangle_area*src_density_or_number ) Input: - lens_model str : Lens name (see gravlens manual table 3.1) - mass_scale float : Mass scale of the lens - "parameter 1" - model_param_8 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_9 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_10 float : misc. lens parameter - often a power law index (depends on the lens model) - galaxy_position [float,float] : [x,y] position of the lens - e_L float : lens ellipticity (ellipticity = 1 - q, where 0<q<=1 is the axial ratio) - theta_L float : lens position angle (in degrees) with respect to the vertical (counterclockwise) - shear float : external shear amplitude - theta_shear float : external shear direction (in degrees) - gravlens_params dict : contains the keys and values of the gravlens configuration (see default parameters at function set_gravlens_default,inside lens_parameters) - src_density_or_number int/float : if int, it is the number of point sources to be sampled. If it is a float it is the source density - minimum_distortion float : the minimum ratio |mu_t/mu_r| at least one image of a source must have to the source be selected - control_rhombus - caustic_CC_file str : name of the output file with the caustic and CC positions - gravlens_input_file str : name of the input file used to run gravlens - rad_curves_file str : name of the file containing the radial curves (optional - see write_to_file) - tan_curves_file str : name of the file containing the radial curves (optional - see write_to_file) - curves_plot str : the name of the generated plot file (including the extension, ex. 'curves_plot.png'). To see the extensions available see matplotlib.pyplot help (default='crit_curves.png'). If curves_plot=0 means no plots. - show_plot int : use 0 for 'no screen display' (default) and 1 for display on the screen. - write_to_file int : Option to write the curves to a file (see rad_curves_file and tan_curves_file ). The default is 0, meaning not to write to a file. - delta_increment float : - grid_factor float : used in the iteration to find the critical curves. Each time no curves were found, the grid size is divided by grid_factor - grid_factor2 float : if the CC file is composed of less than min_n_lines, the code divides the grid size by grid_factor2 - max_iter_number int : maximum number of time the grid size will be divided by grid_factor - min_n_lines int : minimum number of lines demanded in the CC file to decrease the grid by grid_factor_2 - gridhi1_CC_factor float : the final size of the grid will be gridhi1_CC_factor * (the furthest CC point) - accept_res_limit float : if the furthest CC point is closer than accept_res_limit from the lens center, display a warning about lack of precision in determining the curves - gravlens_mag_input_file str : name of the input file for gravlens (magnification tensor) - gravlens_mag_output_file str : name of the output file generated by gravlens (magnification tensor) - keep_mag_files bool : 'True' to keep gravlens input and output files (magnification tensor files) and 'False' to delete them - gravlens_img_input_file str : name of the input file for gravlens (point images) - gravlens_img_output_file str : name of the output file generated by gravlens (point images) - keep_img_files bool : 'True' to keep gravlens input and output files (point images) and 'False' to delete them Output: - x_src_f [float,...] : x coordinates of the selected point sources - y_src_f [float,...] : y coordinates of the selected point sources - x_img_f [ [float,...],... ] : x coordinates of the point images. It has the same size of x_src_f, but each element of x_img_f has the n images of the corresponding source (n>=1) - y_img_f [ [float,...],... ] : x coordinates of the point images. Same shape of x_img_f - image_distortions [[float,float],...] : each pair has respectively the tangential and radial distortions [mu_t,mu_r] of the selected sources """ # find and separate critical curves out_run_find_cc = run_find_cc(lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params, caustic_CC_file, gravlens_input_file, rad_curves_file, tan_curves_file, curves_plot=0, show_plot=show_plot, write_to_file=write_to_file, max_delta_count=max_delta_count, delta_increment=delta_increment, grid_factor=grid_factor, grid_factor2=grid_factor2, max_iter_number=max_iter_number, min_n_lines=min_n_lines, gridhi1_CC_factor=gridhi1_CC_factor, accept_res_limit=accept_res_limit) logging.info( 'Ran pipelines.find_cc.run and obtained and separated the caustic and critical curves' ) rad_CC_x, rad_CC_y, tan_CC_x, tan_CC_y, rad_caustic_x, rad_caustic_y, tan_caustic_x, tan_caustic_y = out_run_find_cc #---------------------------------------------------------- #------------ call compute_deformation_rhombus --------------------------- xlosango, ylosango = compute_deformation_rhombus(float(theta_L), tan_caustic_x, tan_caustic_y, control_rhombus) #--------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------------------- x_vert_1, y_vert_1 = min(xlosango), min( ylosango) # vert_1 : lower left corner x_vert_2, y_vert_2 = max(xlosango), max( ylosango) # vert_2 : upper right corner logging.debug( 'The sources will be randomly generated in the range [%s,%s] (x direction) and [%s,%s] (y direction).' % (str(x_vert_1), str(x_vert_2), str(y_vert_1), str(y_vert_2))) rectangle_area = (x_vert_1 - x_vert_2) * (y_vert_1 - y_vert_2 ) # deltaX*deltaY # if src_density_or_number is a float, it is a density, if it is a integer it is the number of sources if type(src_density_or_number) == int: nsources = src_density_or_number if type(src_density_or_number) == float: nsources = np.random.poisson(rectangle_area * src_density_or_number) logging.debug('Number of point sources generated = %d' % nsources) #----------------------------------------------------------------------------------------------------------- # redefine gridhi1 tan_CC_x = np.array(tan_CC_x) tan_CC_y = np.array(tan_CC_y) index = np.argmax(tan_CC_x**2 + tan_CC_y**2) image_plane_factor = float(gridhi1_CC_factor) gravlens_params['gridhi1'] = image_plane_factor * ( (tan_CC_x[index]**2 + tan_CC_y[index]**2)**0.5) inputlens, setlens, gravlens_params = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params) #----------------------------------------------------------------------------------------------------------- source_positions_output = source_positions( nsources, [x_vert_1, x_vert_2], [y_vert_1, y_vert_2], minimum_distortion, lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params, gravlens_mag_input_file, gravlens_mag_output_file, keep_mag_files, gravlens_img_input_file, gravlens_img_output_file, keep_img_files) while source_positions_output == False: gravlens_params['gridhi1'] = float(gravlens_params['gridhi1']) * 1.15 logging.debug('loop in source_positions: gridhi1 = %f' % float(gravlens_params['gridhi1'])) inputlens, setlens, gravlens_params = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params) source_positions_output = source_positions( nsources, [x_vert_1, x_vert_2], [y_vert_1, y_vert_2], minimum_distortion, lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params, gravlens_mag_input_file, gravlens_mag_output_file, keep_mag_files, gravlens_img_input_file, gravlens_img_output_file, keep_img_files) logging.debug('gridhi1 = %s' % float(gravlens_params['gridhi1'])) x_src_f, y_src_f, x_img_f, y_img_f, image_distortions = source_positions_output logging.debug( 'Selected positions for finite sources. Coordinates x: %s. Coordinates y: %s' % (str(x_src_f), str(y_src_f))) logging.debug( 'Images of the point sources. Coordinates x: %s. Coordinates y: %s' % (str(x_img_f), str(y_img_f))) logging.debug('Corresponding mu_t and mu_r for each image: %s' % str(image_distortions)) img_x_plot, img_y_plot = sum(x_img_f, []), sum(y_img_f, []) plot_cc(tan_caustic_x, tan_caustic_y, rad_caustic_x, rad_caustic_y, tan_CC_x, tan_CC_y, rad_CC_x, rad_CC_y, curves_plot, show_plot=0, src_x=x_src_f, src_y=y_src_f, img_x=img_x_plot, img_y=img_y_plot) return x_src_f, y_src_f, x_img_f, y_img_f, image_distortions
def get_distortions(x, y, lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position=(0, 0), e_L=0, theta_L=0, shear=0, theta_shear=0, gravlens_params={}, gravlens_input_file='gravlens_magtensor_in.txt', gravlens_output_file='gravlens_magtensor_out.txt', keep_files=False): """ Computes the tangential and radial local distortions for a list of (image plane) points. Input: - x [float,...] : x coordinates of the points the local distortions will be calculated - y [float,...] : y coordinates of the points the local distortions will be calculated - lens_model str : Lens name (see gravlens manual table 3.1) - mass_scale float : Mass scale of the lens - "parameter 1" - model_param_8 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_9 float : misc. lens parameter - often scale radio (depends on the lens model) - model_param_10 float : misc. lens parameter - often a power law index (depends on the lens model) - galaxy_position [float,float] : [x,y] position of the lens - e_L <float> : lens ellipticity (ellipticity = 1 - q, where 0<q<=1 is the axial ratio) - theta_L <float> : lens position angle (in degrees) with respect to the vertical (counterclockwise) - shear <float> : external shear amplitude - theta_shear <float> : external shear direction (in degrees) - gravlens_params dict : contains the keys and values of the gravlens configuration (see default parameters at function set_gravlens_default,inside lens_parameters) - gravlens_input_file str : name of the input file for gravlens - gravlens_output_file str : name of the output file generated by gravlens (with the magnification tensor) - keep_files bool : 'True' to keep gravlens input and output files and 'False' to delete them Output: - distortions [[float,float],...] : each pair has respectively the tangential and radial distortions [mu_t,mu_r] of the corresponding input point (x_i,y_i) """ inputlens, setlens, gravlens_params_updated = lens_parameters( lens_model, mass_scale, model_param_8, model_param_9, model_param_10, galaxy_position, e_L, theta_L, shear, theta_shear, gravlens_params) f = open(gravlens_input_file, 'w') f.write(inputlens) for i in range(len(x)): f.write('magtensor %0.9f %0.9f \n' % (x[i], y[i])) f.close() os.system('gravlens %s > %s' % (gravlens_input_file, gravlens_output_file)) f = open(gravlens_output_file, 'r').readlines() nlinha = len(f) - 6 * len( x ) # I am using this to get the matrix elements without worrying about the number of lines the file has (which depends on the number of parameters of gravlens we modify). 'nlinha' is the number of lines that DON'T contain the output data of magtensor distortions = [] for i in range(len(x)): # calculates the magnifications at each point a11 = float(f[nlinha + i * 6].split()[0]) # element 11 of the mag tensor a12 = float(f[nlinha + i * 6].split()[1]) # element 12 (=21) of the mag tensor a22 = float(f[nlinha + i * 6 + 1].split()[1]) # element 22 of the mag tensor mu_t = (((a11 + a22) / 2.) / (a11 * a22 - a12**2) - ((((a22 - a11) / 2.)**2 + a12**2)**0.5) / (abs(a11 * a22 - a12**2)))**(-1) mu_r = (((a11 + a22) / 2.) / (a11 * a22 - a12**2) + ((((a22 - a11) / 2.)**2 + a12**2)**0.5) / (abs(a11 * a22 - a12**2)))**(-1) distortions.append([mu_t, mu_r]) if keep_files == False: os.system('rm -f %s %s' % (gravlens_input_file, gravlens_output_file)) return distortions