# of gamma along the required axis, to calculate the observed synchrotron # map. This integration is performed by the trapezoidal rule. To normalise # the calculated synchrotron map, divide by the number of pixels along the # z-axis. Note the array is ordered by (z,y,x)! # NOTE: Set dx to whatever the pixel spacing is sync_arr_z = np.trapz(mag_perp_gamma_z, dx = 1.0, axis = int_axis) /\ np.shape(mag_perp)[0] # Now that the synchrotron maps have been produced, we need to save the # produced maps as a FITS file # Create a primary HDU to contain the synchrotron data pri_hdu = fits.PrimaryHDU(sync_arr_z) # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr_z, pri_hdu.header, data_loc + 'synint_z' +\ '_gam{}'.format(gamma) + '.fits') if 'y' in line_o_sight: # Calculate the magnitude of the magnetic field perpendicular to the line of # sight, which is just the square root of the sum of the x and z component # magnitudes squared. mag_perp = np.sqrt( np.power(mag_x_data, 2.0) + np.power(mag_z_data, 2.0) ) # Construct a variable which tells the script which axis we need to # integrate along to calculate the synchrotron maps. Since the line of sight # is the y axis, we need to integrate along axis 1. int_axis = 1 # Create a Numpy array to hold the calculated synchrotron emission map sync_arr_y = np.zeros((np.shape(mag_perp)[1],np.shape(mag_perp)[2]))
# Calculate all of the first order spatial derivatives that we need dQ_dy, dQ_dx, dU_dy, dU_dx = calc_Sto_1Diff(StoQ, StoU, pix_sep = dl) # Calculate all of the second order spatial derivatives that we need d2Q_dy2, d2Q_dydx, d2Q_dx2, d2U_dy2, d2U_dydx, d2U_dx2 =\ calc_Sto_2Diff(dQ_dy, dQ_dx, dU_dy, dU_dx, pix_sep = dl) #------------------------- Polarisation Angle ------------------------------ # Check to see if we need to calculate the polarisation angle if 'Angle' in diag_list: # Calculate the observed polarisation angle for this Stokes Q and U polar_angle = calc_Polar_Angle(StoQ, StoU) # Save the polarisation angle array mat2FITS_Image(polar_angle, StoQ_hdr, data_loc + 'PolarAngle_' +\ emis_mech + '.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Polarisation angle calculated' #----------------------- Polarisation Gradient ----------------------------- # Check to see if we need to calculate the polarisation gradient if 'Grad' in diag_list: # Calculate the observed polarisation gradient for this Stokes Q and U polar_grad = calc_Polar_Grad(dQ_dy, dQ_dx, dU_dy, dU_dx) # Save the polarisation gradient array mat2FITS_Image(polar_grad, StoQ_hdr, data_loc + 'PolarGrad_' +\ emis_mech + '.fits', clobber = True)
#------------- Maximum Radial Component Directional Derivative ------------- # Calculate the maximum value of the radial component of the directional # derivative at each pixel of the image, using the Stokes Q and U values # and their derivatives rad_direc_amp = calc_Rad_Direc_Amp(Sto_Q, Sto_U, dQ_dy, dQ_dx, dU_dy, dU_dx) # Print a message to the screen to show that the maximum of the radial # component of the directional derivative has been calculated successfully. print 'Maximum Radial Component Direc Deriv calculated successfully.' # Convert the matrix of maximum radial component values into a FITS file, # using the header information of the CGPS data. Also save the FITS file # that is produced by the function. rad_direc_amp_FITS = mat2FITS_Image(rad_direc_amp, cgps_Q_hdr,\ data_loc + 'Rad_Direc_Amp_{}_smooth2_{}.fits'.format(save_append,\ final_res_array[i])) # Print a message to the screen to show that the FITS file was produced and # saved successfully. print 'FITS file successfully saved for the radial component of the '\ + 'directional derivative.' #----------- Maximum Tangential Component Directional Derivative ----------- # Calculate the maximum value of the tangential component of the directional # derivative at each pixel of the image, using the Stokes Q and U values # and their derivatives tang_direc_amp = calc_Tang_Direc_Amp(Sto_Q, Sto_U, dQ_dy, dQ_dx, dU_dy, dU_dx) # Print a message to the screen to show that the maximum of the tangential
print 'Mach number maps calculated' # Now that the Mach number maps have been produced, we need to save the # produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the sonic Mach number data pri_hdu_sonic = fits.PrimaryHDU(los_sonic) # Create a primary HDU to contain the Alfvenic Mach data pri_hdu_alf = fits.PrimaryHDU(los_alf) # Save the produced sonic Mach number map as a FITS file mat2FITS_Image(los_sonic, pri_hdu_sonic.header, data_loc + 'los_av_sonic_' +\ line_o_sight + '.fits', clobber = True) # Save the produced Alfvenic Mach number map as a FITS file mat2FITS_Image(los_alf, pri_hdu_alf.header, data_loc + 'los_av_alf_' +\ line_o_sight + '.fits', clobber = True) # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() vel_x_fits.close() vel_y_fits.close() vel_z_fits.close() dens_fits.close() # Print a message to state that the FITS file was saved successfully
# Print a message to the screen to show that everything is going smoothly print 'Stokes parameters successfully extracted from data.' # Extract values from the S-PASS header that specify the separation between # pixels along the x and y directions in degrees dx = np.absolute(spass_hdr['CDELT1']) dy = np.absolute(spass_hdr['CDELT2']) # Calculate the polarisation intensity images for both data sets spass_pol_inten = np.sqrt(np.power(spass_Q_data,2.0)\ + np.power(spass_U_data,2.0)) urum_pol_inten = np.sqrt(np.power(urum_Q_data,2.0)\ + np.power(urum_U_data,2.0)) # Save the polarisation intensity images for both data sets mat2FITS_Image(spass_pol_inten, spass_hdr, save_loc +\ 'spass_pol_inten.fits', clobber = True) mat2FITS_Image(urum_pol_inten, urum_hdr, save_loc +\ 'urum_pol_inten.fits', clobber = True) #---------------------- Curvature Calculations SPASS --------------------------- # Calculate the first order spatial derivatives of Stokes Q and U for the # spass data sp_dQ_dy, sp_dQ_dx, sp_dU_dy, sp_dU_dx =\ calc_Sto_1Diff(spass_Q_data, spass_U_data, pix_sep = dy) # Calculate all of the second order spatial derivatives of Stokes Q and U for # the spass data sp_d2Q_dy2, sp_d2Q_dydx, sp_d2Q_dx2, sp_d2U_dy2, sp_d2U_dydx, sp_d2U_dx2 =\ calc_Sto_2Diff(sp_dQ_dy, sp_dQ_dx, sp_dU_dy, sp_dU_dx, pix_sep = dy)
# Open up the FITS file fits_file = fits.open(cgps_loc + direc_name + fits_file_list[i]) # Obtain the header from the FITS file fits_hdr = fits_file[0].header # Obtain the data from the FITS file fits_data = fits_file[0].data # Change the CRVAL1 value to the required value fits_hdr['CRVAL1'] = crval1 # Change the CRVAL2 value to the required value fits_hdr['CRVAL2'] = crval2 # Change the CRPIX1 value to the required value fits_hdr['CRPIX1'] = crpix1_arr[i] # Change the CRPIX2 value to the required value fits_hdr['CRPIX2'] = crpix2_arr[i] # Check to see if there is an EQUINOX keyword in the FITS file if 'EQUINOX' in fits_hdr: # In this case there is an EQUINOX keyword, so delete it del fits_hdr['EQUINOX'] # Save the new FITS file with the modified header mat2FITS_Image(fits_data, fits_hdr, cgps_loc + output_direc + fits_file_list[i]) # Print a message to the screen to say the FITS file has been made print "{} made successfully.".format(fits_file_list[i]) # Close the FITS file to save memory fits_file.close()
# Specify what the third axis is pri_hdu_StoQ.header['CTYPE3'] = 'Spec-ind' # Add header keywords to describe the line of sight, frequency, # pixel size, density, velocity scale, and magnetic field scale for # Stokes Q pri_hdu_StoQ.header['SIM'] = (save_sim, 'simulation used') pri_hdu_StoQ.header['LOS'] = (int_axis, '0-z, 1-y, 2-x') pri_hdu_StoQ.header['FREQ'] = (freq, 'observing frequency (Hz)') pri_hdu_StoQ.header['PIX-SIZE'] = (dl, 'size of each pixel (pc)') pri_hdu_StoQ.header['DENSITY'] = (n_e, 'density scaling (cm^-3)') pri_hdu_StoQ.header['VELSCALE'] = (v_0, 'velocity scaling (m s^-1)') pri_hdu_StoQ.header['MAGSCALE'] = (B_0, 'magnetic field scaling (mu G)') # Save the produced Stokes Q and U arrays as FITS files mat2FITS_Image(StoQ, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_StoQ_specind_' + emis_mech + '.fits', clobber = True) mat2FITS_Image(StoU, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_StoU_specind_' + emis_mech + '.fits', clobber = True) # Save the produced polarised intensity and polarisation angle as FITS files mat2FITS_Image(pol_inten, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_pol_inten_specind_' + emis_mech + '.fits', clobber = True) mat2FITS_Image(pol_angle, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_pol_angle_specind_' + emis_mech + '.fits', clobber = True) # Close all of the fits files, to save memory dens_fits.close() magx_fits.close() magy_fits.close() magz_fits.close()
# Extract the data for Stokes Q, as a memory map StoQ = StoQ_fits[0].data # Extract the header for Stokes Q StoQ_hdr = StoQ_fits[0].header # Change the value for the CRPIX1 keyword, to give the correct reference # pixel for the new array StoQ_hdr['CRPIX1'] = -332.00 # Extract the portion of the Stokes Q image that we are interested in newQ = StoQ[:,:,2909:3983] # Save the selected region of the Stokes Q image as a new FITS file mat2FITS_Image(newQ, StoQ_hdr, data_loc +\ 'GALFACTS_' + 'S1_chanavg_subset_Q' + '.fits', clobber = True) # Close the Stokes Q fits file, and anything related to it, to free memory StoQ_fits.close() del newQ del StoQ # Open the FITS file that contains Stokes U, as a memory map, so that we don't # load it all in at once. StoU_fits = fits.open(data_loc + 'GALFACTS_S1_0263_4023_10chanavg_U.fits',\ memmap = True) # Extract the data for Stokes U, as a memory map StoU = StoU_fits[0].data # Extract the header for Stokes U
if i == 0: # Set the return slice to be 0 return_slice = 0 else: # For all other cases, we need to return the second slice of the # array return_slice = 1 # Put this slice into the storage array storage_arr[i] = rot_meas[return_slice] # Change the header to reflect what is being saved StoQ_hdr['OBJECT'] = 'GALFACTS_S1 Rot Meas' # Save the rotation measure mat2FITS_Image(storage_arr, StoQ_hdr, data_loc +\ 'RotMeas_S1_chanavg_subset.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Rotation measure calculated' #----------------------- Wavelength Gradient --------------------------- # Check to see if we need to calculate the wavelength gradient if 'Wav_Grad' in diag_list: # Iterate over the slices of the Stokes Q and U arrays for i in range(num_slice): # Extract the current Stokes Q slice from the full array, as well as # the slices immediately before and after this, if they exist StoQ_slice = StoQ[max(0,i-1):min(i+2,num_slice)] # Extract the current Stokes U slice from the full array, as well as
# integrate along to calculate the map of projected magnetic field. # Since the line of sight is the x axis, we need to integrate along axis 2. int_axis = 2 # Integrate the magnetic field strength along the required axis. This # integration is performed by the trapezoidal rule. To normalise # the calculated map, divide by the number of pixels along the # z-axis. Note the array is ordered by (z,y,x)! # NOTE: Set dx to whatever the pixel spacing is mag_proj = np.trapz(mag_amp, dx = 1.0, axis = int_axis) /\ np.shape(mag_amp)[0] # Now that the projected magnetic field map has been produced, we need to # save the produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the map of projected magnetic field pri_hdu = fits.PrimaryHDU(mag_proj) # Save the produced map of the projected magnetic field as a FITS file mat2FITS_Image(mag_proj, pri_hdu.header, data_loc + 'mag_proj_' +\ line_o_sight + '.fits') # Print a message to state that the FITS file was saved successfully print 'FITS file of projected magnetic field saved successfully' # All of the required maps have been saved, so print a message stating that # the script has finished print 'All projected magnetic field calculated successfully'
# integrate along to calculate the map of projected magnetic field. # Since the line of sight is the x axis, we need to integrate along axis 2. int_axis = 2 # Integrate the magnetic field strength along the required axis. This # integration is performed by the trapezoidal rule. To normalise # the calculated map, divide by the number of pixels along the # z-axis. Note the array is ordered by (z,y,x)! # NOTE: Set dx to whatever the pixel spacing is mag_proj = np.trapz(mag_amp, dx = 1.0, axis = int_axis) /\ np.shape(mag_amp)[0] # Now that the projected magnetic field map has been produced, we need to # save the produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the map of projected magnetic field pri_hdu = fits.PrimaryHDU(mag_proj) # Save the produced map of the projected magnetic field as a FITS file mat2FITS_Image(mag_proj, pri_hdu.header, data_loc + 'mag_proj_' +\ line_o_sight + '.fits') # Print a message to state that the FITS file was saved successfully print 'FITS file of projected magnetic field saved successfully' # All of the required maps have been saved, so print a message stating that # the script has finished print 'All projected magnetic field calculated successfully'
# Bryan's division_mat[j,i] = my_data[j,i] - B_value # Print a message to the screen to show when 50 columns have been computed if (i+1)%50 == 0: # The number of columns completed is a multiple of 50, so print a # message to the screen print '{} columns completed'.format(i+1) # When the code reaches this point, both for loops have completed, and the # division matrix is filled with values. # Convert the matrix of divided polarisation gradient values into a FITS file, # using the header information of my data. Also save the FITS file that is # produced by the function. division_FITS = mat2FITS_Image(division_mat, my_hdr,\ data_loc + 'sgps_subtract_polar_fix_unit.fits') # Print a message to the screen to show that the FITS file was produced and # saved successfully. print 'FITS file successfully saved for the divided polarisation gradients.' # Create an image of the divided polarisation gradient values # using aplpy and the produced FITS file. This image is automatically # saved using the given filename. fits2aplpy(division_FITS, data_loc + 'sgps_subtract_polar_fix_unit.png', \ colour = 'RdBu') # Print a message to the screen to show that the image of the divided # polarisation gradient values has been successfully produced and saved. print 'Image of the divided polarisation gradients successfully saved.\n'
# Calculate the maximum value of the radial component of the directional # derivative at each pixel of the image, using the Stokes Q and U values # and their derivatives rad_direc_amp = calc_Rad_Direc_Amp(Sto_Q, Sto_U, dQ_dy, dQ_dx, dU_dy, dU_dx) # Print a message to the screen to show that the maximum of the radial # component of the directional derivative has been calculated successfully. print 'Maximum Radial Component Direc Deriv calculated successfully.' # Convert the matrix of maximum radial component values into a FITS file, # using the header information of the CGPS data. Also save the FITS file # that is produced by the function. rad_direc_amp_FITS = mat2FITS_Image(rad_direc_amp, cgps_Q_hdr,\ data_loc + 'Rad_Direc_Amp_{}_smooth2_{}.fits'.format(save_append,\ final_res_array[i])) # Print a message to the screen to show that the FITS file was produced and # saved successfully. print 'FITS file successfully saved for the radial component of the '\ + 'directional derivative.' #----------- Maximum Tangential Component Directional Derivative ----------- # Calculate the maximum value of the tangential component of the directional # derivative at each pixel of the image, using the Stokes Q and U values # and their derivatives tang_direc_amp = calc_Tang_Direc_Amp(Sto_Q, Sto_U, dQ_dy, dQ_dx, dU_dy, dU_dx)
def calc_sparse_stats(input_files, output_filenames, stat_list, box_halfwidths,\ all_fits_info = True): ''' Description This function calculates local statistics for some pixels in an image, that are sparsely distributed throughout the image, using the data in surrounding pixels. The selected pixels will be located on a rectangular grid, and the spacing between the pixels is determined by the size of the box used to calculate statistics, so that the input map is sampled as a rate greater than the Nyquist frequency. The statistics that are calculated can be specified in the stat_list variable. All of these statistics will be calculated for each input image. Multiple input files can be provided, and statistics will be calculated for each image. Maps of the produced statistics will be saved using the given output filenames. Required Input input_files - An array of strings, where each string specifies the directory and filename of the FITS image to calculate statistics for. Local statistics are calculated for each file provided in this array. output_filenames - An array of strings, where each string specifies the directory and filename to use when saving a FITS file image of the produced statistic map. An image is saved for each input file, and each statistic. This array needs to be the same length as input_files. Each FITS file that is saved will have the type of statistic appended to the output filename provided. The given strings should not have the .fits extension present, as this is added in the function. stat_list - An array of strings, where each string specifies a statistic that is to be calculated locally for each input image. Allowed values are 'mean', 'stdev',skewness' and 'kurtosis'. box_halfwidths - The half-widths of the box to use when calculating the local statistics, in pixels. This is an array of positive integers greater than or equal to 1. This array must have the same length as input_files. Pixels selected for the evaluation of statistics are separated by half of the box half-width. all_fits_info - A boolean value, if True, then all CDELT and CRPIX header info is present in the simulations, and will be used in the code. If False, then placeholder information will be used. Output 0 - An error occurred, possibly due to inappropriate input values 1 - Function ran to completion, and saved FITS images of the calculated statistics maps successfully. ''' # Check to see that the number of output filenames matches the number of # input filenames if len(input_files) != len(output_filenames): # In this case the number of output filenames does not match the number # input filenames, so the code cannot proceed. Print an error message # to say what has happened print 'ERROR: Number of input files and output filenames are different' # The code should not proceed in this case, so return 0 return 0 # Check to see that the number of box halfwidth values equals the number # of input filenames if len(input_files) != len(box_halfwidths): # In this case the number of box halfwidths to use does not match the # number of input filenames, so the code cannot proceed. Print an # error message to say what has happened. print 'ERROR: Number of input files and box halfwidths are different' # The code should not proceed in this case, so return 0 return 0 # Create a list of valid strings that can be given to the stat_list variable valid_stats = ['mean', 'stdev', 'skewness', 'kurtosis'] # Check to see that valid statistics were provided if len(list(set(valid_stats).intersection(stat_list))) == 0: # In this case the array of strings given to the function does not # provide any valid statistics to calculate, so print an error message # to the screen print 'ERROR: No valid statistics provided to the function' # The code should not proceed in this case, so return 0 return 0 # Check to see that the values given for the box halfwidths are positive # integers greater than or equal to 1 if np.any(box_halfwidths < 1): # In this case a value given for the box halfwidth is invalid, so # print an error message to the screen print 'ERROR: At least one of the values for box half-width is invalid' # The code should not proceed in this case, so return to 0 return 0 # Loop over the given input files, so that we can calculate statistics for # each one for i in range(len(input_files)): # Print a message to show that calculations are starting for the current # input file print 'Calculations starting for {}'.format(input_files[i]) # Open the CGPS FITS file for the current resolution fits_file = fits.open(input_files[i]) # Obtain the header of the primary HDU for the data fits_hdr = fits_file[0].header # Extract the data from the FITS file, which is held in the primary HDU fits_data = fits_file[0].data # Print a message to the screen saying that the data was successfully # extracted print 'CGPS data successfully extracted from the FITS file.' # Extract the number of pixels along the horizontal axis of the image num_pix_horiz = fits_hdr['NAXIS1'] # Extract the number of pixels along the vertical axis of the image num_pix_vert = fits_hdr['NAXIS2'] # If all header information is present, use the information there if all_fits_info == True: # Extract the size of each pixel from the header. This is the length of # each side of the pixel (assumed to be square), in degrees. pix_size_deg = fits_hdr['CDELT2'] # Calculate where the reference pixel is relative to the top left # hand corner of the image horiz_centre_loc = np.absolute(fits_hdr['CDELT1'] * fits_hdr['CRPIX1']) vert_centre_loc = np.absolute(fits_hdr['CDELT2'] * fits_hdr['CRPIX2']) elif all_fits_info == False: # If all header information is not present, use placeholder information # Set the size of each pixel from the header, which is just 1 pix_size_deg = 1.0 # Calculate where the reference pixel is relative to the top left # hand corner of the image horiz_centre_loc = np.absolute(pix_size_deg * num_pix_horiz / 2.0) vert_centre_loc = np.absolute(pix_size_deg * num_pix_vert / 2.0) # Create a new header object, that will become the header for the # statistics map that is produced stats_hdr = fits_hdr # Calculate the spacing between the grid points that will be used to # calculate local statistics. The floor is taken just to make sure it # is an integer. grid_space = int(np.floor(box_halfwidths[i] / 2)) # Calculate the number of grid points to place along the horizontal axis # A ceiling is taken to make sure we get the right integer number of # grid points to use num_grid_horiz = int(np.ceil(num_pix_horiz / grid_space)) # Calculate the number of grid points to place along the vertical axis # A ceiling is taken to make sure we get the right integer number of # grid points to use num_grid_vert = int(np.ceil(num_pix_vert / grid_space)) # Construct an array, where each entry gives the index value along the # horizontal axis of the grid points horiz_grid_indices = grid_space * np.array(range(num_grid_horiz)) # Construct an array, where each entry gives the index value along the # vertical axis of the grid points vert_grid_indices = grid_space * np.array(range(num_grid_vert)) # At this point the grid has been constructed, and we just need to # modify some of the FITS header values so that the constructed # statistics maps can be saved # Change the NAXIS keywords, that specify how many pixels are along # each axis of the image stats_hdr['NAXIS1'] = num_grid_horiz stats_hdr['NAXIS2'] = num_grid_vert # If all header information is present, use the information there if all_fits_info == True: # Change the CDELT keywords, that specify the spacing between pixels # in degrees stats_hdr['CDELT1'] = stats_hdr['CDELT1'] * grid_space stats_hdr['CDELT2'] = stats_hdr['CDELT2'] * grid_space # Change the CRPIX keywords, that specify which pixel is the reference # pixel in the image stats_hdr['CRPIX1'] = np.absolute( horiz_centre_loc / stats_hdr['CDELT1']) + 1 stats_hdr['CRPIX2'] = np.absolute(vert_centre_loc / stats_hdr['CDELT2']) elif all_fits_info == False: # If all header information is not present, use placeholder information # Change the CDELT keywords, that specify the spacing between pixels # in degrees stats_hdr['CDELT1'] = pix_size_deg * grid_space stats_hdr['CDELT2'] = pix_size_deg * grid_space # Change the CRPIX keywords, that specify which pixel is the reference # pixel in the image stats_hdr['CRPIX1'] = np.absolute( horiz_centre_loc / stats_hdr['CDELT1']) + 1 stats_hdr['CRPIX2'] = np.absolute(vert_centre_loc / stats_hdr['CDELT2']) # Create a dictionary that will hold the arrays corresponding to each # statistic stat_dict = {} # Create new numpy arrays, that have the same size as the input array. # These will be used to store the calculated local statistics. The # arrays are stored in a dictionary, with each statistic having its own # array for stat in stat_list: # Assign an empty array to the current statistic. Note that the data # type is 32-bit float, since all of the input arrays have that data # type stat_dict[stat] = np.zeros((num_grid_vert,num_grid_horiz)\ , dtype = np.float64) # Loop over all of the pixels at which we will evaluate statistics, # starting by looping over each row for j in range(num_grid_vert): # Loop over all of the pixels in this row for k in range(num_grid_horiz): # Extract the value of the data at the current pixel pix_value = fits_data[vert_grid_indices[j], horiz_grid_indices[k]] # Calculate the index of the uppermost pixels to be included in # the local box. Note that the minus sign is because Python # indexes so that the pixels highest in the image have the # lowest index value upper_index = vert_grid_indices[j] - box_halfwidths[i] # Calculate the index of the lowermost pixels to be included in # the local box lower_index = vert_grid_indices[j] + box_halfwidths[i] # Calculate the index of the rightmost pixels to be included in # the local box right_index = horiz_grid_indices[k] + box_halfwidths[i] # Calculate the index of the leftmost pixels to be included in # the local box left_index = horiz_grid_indices[k] - box_halfwidths[i] # Check that the index of the uppermost pixel to include in the # local box is valid, i.e. not negative if upper_index < 0: # In this case the value of the upper index doesn't make # sense, so reset it to zero upper_index = 0 # Check that the index of the leftmost pixel to include in the # local box is valid, i.e. not negative if left_index < 0: # In this case the value of the left index doesn't make # sense, so reset it to zero left_index = 0 # Check that the index of the lowermost pixel to include in the # local box is valid, i.e. that it does not extend beyond the # boundaries of the image if lower_index >= num_pix_vert: # In this case the value of the lower index doesn't make # sense, so reset it to the largest possible index for the # vertical axis lower_index = num_pix_vert - 1 # Check that the index of the rightmost pixel to include in the # local box is valid, i.e. that it does not extend beyond the # boundaries of the image if right_index >= num_pix_horiz: # In this case the value of the lower index doesn't make # sense, so reset it to the largest possible index for the # horizontal axis right_index = num_pix_horiz - 1 # Extract the data in the local box around the current # pixel we are studying local_data = fits_data[upper_index:lower_index+1,\ left_index:right_index+1] # Flatten the local data into a one-dimensional array local_data_flat = local_data.flatten() # Find where all of the NaN values are in the local data NaN_position = np.isnan(local_data_flat) # Extract the values in the local data that are not NaN local_data_no_nan =\ local_data_flat[np.logical_not(NaN_position)] # Sort the local data from smallest to largest local_data_sorted = np.sort(local_data_no_nan) # Truncate the data array to the desired range local_data_trunc = local_data_sorted[\ int(np.floor(0*len(local_data_sorted))):\ int(np.floor(0.99*len(local_data_sorted)))] # # If we are at a desired pixel of the statistics map, then # # produce a histogram of the truncated data values, and save it. # if j==26 and (k>= 101 and k<=125): # # We are at a desired pixel, so save an image of the # # histogram at this pixel # hist_plot(local_data_trunc, output_filenames[i] +\ # '_hist_{}_{}.png'.format(j,k), 'png', 'Polar Gradient',\ # 'PDF Polar Grad x={} y={}'.format(k,j), bins=20 ) # Check that most of the data in the box is not NaN if (len(local_data_flat) / 2.0) > len(local_data_no_nan): # In this case more than half of the data is NaN, so # record NaN for any statistics that are to be calculated for stat in stat_list: (stat_dict[stat])[j, k] = float('nan') else: # Check to see if the mean of the local area needs to be # calculated if 'mean' in stat_list: # Calculate the mean of the local data that has had # the NaN values removed, and store it in the # corresponding array (stat_dict['mean'])[j,k] =\ np.mean(local_data_trunc, dtype = np.float64) # Check to see if the standard deviation of the local area # needs to be calculated if 'stdev' in stat_list: # Calculate the standard deviation of the local data # that has had the NaN values removed, and store it in # the corresponding array (stat_dict['stdev'])[j,k] =\ np.std(local_data_trunc, dtype = np.float64) # Check to see if the skewness of the local area needs to be # calculated if 'skewness' in stat_list: # Calculate the skewness of the local data that has had # the NaN values removed, and store it in the # corresponding array (stat_dict['skewness'])[j,k] =\ stats.skew(local_data_trunc) # Check to see if the kurtosis of the local area needs to be # calculated if 'kurtosis' in stat_list: # Calculate the kurtosis of the local data that has had # the NaN values removed, and store it in the # corresponding array (stat_dict['kurtosis'])[j,k] =\ stats.kurtosis(local_data_trunc) # When the code reaches this point, all of the required # statistics have been calculated for this pixel # When the code reaches this point, statistics have been calculated # for all of the pixels in this row # Every 20 rows, print out a message to show where the code is up to if (j + 1) % 20 == 0: # Another 20 rows have been completed, so print a message print '{} rows calculated'.format(j + 1) # When the code reaches this point, statistics have been calculated for # all of the pixels, for this particular value of the final resolution # Next, we want to save the produced maps of the local statistics # Loop over all of the statistics that were calculated for stat in stat_list: # Convert the matrix of values for this statistic into a FITS file, # and save the result using the same header as the input CGPS data. # The FITS file is saved in the same location as the CGPS data stat_FITS = mat2FITS_Image(stat_dict[stat], stats_hdr,\ output_filenames[i] + '_{}_sparse'.format(stat) + '.fits') # Print a message to the screen, to show that a FITS file was # produced for the current statistic print 'FITS file saved for {}'.format(stat) # At this point, all FITS files have been saved for the required # statistics, so print a message to the screen about this print 'All FITS files saved for {}'.format(input_files[i]) # When the code reaches this point, all of the FITS files have been saved # Print a message stating this print 'All FITS files saved successfully' # Since the code has run successfully, return 1 return 1
# # Save the projected Alfvenic Mach number image as a FITS file, # # using the same header as was created for synchrotron intensity # mat2FITS_Image(los_sonic, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ # los_loc + 'Mean_Sonic_Mach.fits', clobber = True) #---------------------- Projected V Field Amplitude ------------------------ # Calculate the velocity field amplitude at each pixel V_amp = np.sqrt(np.power(vel_para,2.0) + np.power(vel_perp,2.0)) # Average the amplitude of the velocity field along the line of sight V_amp_proj = np.mean(V_amp, axis = int_axis, dtype = np.float64) # Save the projected velocity field image as a FITS file, using the # same header as was created for synchrotron intensity mat2FITS_Image(V_amp_proj, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ los_loc + 'V_amp_projected.fits', clobber = True) #------------------------- Projected V Parallel ---------------------------- # Integrate the velocity field parallel to the line of sight along the # line of sight V_para_proj = np.mean(vel_para, axis = int_axis, dtype = np.float64) # Save the projected parallel velocity field image as a FITS file, using the # same header as was created for synchrotron intensity mat2FITS_Image(V_para_proj, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ los_loc + 'V_para_projected.fits', clobber = True) #--------------------- Projected V Perpendicular --------------------------- # Integrate the velocity field perpendicular to the line of sight along the
# Calculate all of the first order spatial derivatives that we need dQ_dy, dQ_dx, dU_dy, dU_dx = calc_Sto_1Diff(StoQ, StoU, pix_sep = pix_size_deg) # Calculate all of the second order spatial derivatives that we need d2Q_dy2, d2Q_dydx, d2Q_dx2, d2U_dy2, d2U_dydx, d2U_dx2 =\ calc_Sto_2Diff(dQ_dy, dQ_dx, dU_dy, dU_dx, pix_sep = pix_size_deg) #---------------------- Polarisation Intensity ------------------------- # Check to see if we need to calculate the polarisation intensity if 'Inten' in diag_list: # Calculate the polarisation intensity for this Stokes Q and U polar_inten = calc_Polar_Inten(StoQ, StoU) # Save the polarisation intensity mat2FITS_Image(polar_inten, StoQ_hdr, data_loc +\ 'PolarInten_' + 'S3_average' + '.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Polarisation intensity calculated' #------------------------- Polarisation Angle ------------------------------ # Check to see if we need to calculate the polarisation angle if 'Angle' in diag_list: # Calculate the observed polarisation angle for this Stokes Q and U polar_angle = calc_Polar_Angle(StoQ, StoU) # Save the polarisation angle array mat2FITS_Image(polar_angle, StoQ_hdr, data_loc + 'PolarAngle_' +\ 'S3_average' + '.fits', clobber = True)
pri_hdu.header['CRPIX3'] = 1 # Add a header keyword to the HDU header, specifying the value of gamma # at the reference pixel pri_hdu.header['CRVAL3'] = 1.0 # Add a header keyword to the HDU header, specifying the increment in gamma # along each slice of the array pri_hdu.header['CDELT3'] = 0.5 # Add a header keyword to the HDU header, describing what the third axis is pri_hdu.header['CTYPE3'] = 'Gamma ' if line_o_sight == 'y': # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4y_' +\ 'rot_{}'.format(rot_ang_arr[j]) + '.fits') elif line_o_sight == 'z': # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4_' +\ 'rot_{}'.format(rot_ang_arr[j]) + '.fits') # Print a message to state that the FITS file was saved successfully print 'FITS file of synchrotron maps saved successfully {}'.format(rot_ang_arr[j]) # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() # Print a message to state that the FITS file was saved successfully print 'FITS file of synchrotron maps saved successfully {}'.format(sim)
pri_hdu.header['CRPIX3'] = 1 # Add a header keyword to the HDU header, specifying the value of gamma # at the reference pixel pri_hdu.header['CRVAL3'] = 1.0 # Add a header keyword to the HDU header, specifying the increment in gamma # along each slice of the array pri_hdu.header['CDELT3'] = 0.5 # Add a header keyword to the HDU header, describing what the third axis is pri_hdu.header['CTYPE3'] = 'Gamma ' if line_o_sight == 'y': # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4y_' +\ 'rot_{}'.format(rot_ang_arr[j]) + '.fits') elif line_o_sight == 'z': # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4_' +\ 'rot_{}'.format(rot_ang_arr[j]) + '.fits') # Print a message to state that the FITS file was saved successfully print 'FITS file of synchrotron maps saved successfully {}'.format( rot_ang_arr[j]) # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() # Print a message to state that the FITS file was saved successfully
# Add header keywords to describe the line of sight, frequency, # spectral index, pixel size, density, velocity scale, and magnetic # field scale for Stokes U pri_hdu_StoU.header['SIM'] = (save_sim_arr[i], 'simulation used') pri_hdu_StoU.header['LOS'] = (int_axis, '0-z, 1-y, 2-x') pri_hdu_StoU.header['FREQ'] = (freq_backlit, 'observing frequency (Hz)') pri_hdu_StoU.header['SPEC-IND'] = (spec_ind, 'spectral index') pri_hdu_StoU.header['PIX-SIZE'] = (dl, 'size of each pixel (pc)') pri_hdu_StoU.header['DENSITY'] = (n_e, 'density scaling (cm^-3)') pri_hdu_StoU.header['VELSCALE'] = (v_0, 'velocity scaling (m s^-1)') pri_hdu_StoU.header['MAGSCALE'] = (B_0, 'magnetic field scaling (mu G)') # Save the produced Stokes Q and U images as FITS files mat2FITS_Image(StoQ, pri_hdu_StoQ.header, save_loc + save_sim_arr[i] + \ los_loc + 'StoQ_' + 'backlit' + '.fits', clobber = True) mat2FITS_Image(StoU, pri_hdu_StoU.header, save_loc + save_sim_arr[i] + \ los_loc + 'StoU_' + 'backlit' + '.fits', clobber = True) elif 'internal' in emis_mech: # In this case we need to produce cubes of Stokes Q and U for the case # when the emission is generated within the simulation cube, over a # range of frequencies # Create empty arrays, that will be used to contain the Stokes Q and U # maps created at each frequency StoQ = np.zeros((len(freq_internal), dens_data.shape[1],\ dens_data.shape[2]), dtype = np.float32) StoU = np.zeros((len(freq_internal), dens_data.shape[1],\ dens_data.shape[2]), dtype = np.float32)
# # Save the projected Alfvenic Mach number image as a FITS file, # # using the same header as was created for synchrotron intensity # mat2FITS_Image(los_sonic, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ # los_loc + 'Mean_Sonic_Mach.fits', clobber = True) #---------------------- Projected V Field Amplitude ------------------------ # Calculate the velocity field amplitude at each pixel V_amp = np.sqrt(np.power(vel_para, 2.0) + np.power(vel_perp, 2.0)) # Average the amplitude of the velocity field along the line of sight V_amp_proj = np.mean(V_amp, axis=int_axis, dtype=np.float64) # Save the projected velocity field image as a FITS file, using the # same header as was created for synchrotron intensity mat2FITS_Image(V_amp_proj, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ los_loc + 'V_amp_projected.fits', clobber = True) #------------------------- Projected V Parallel ---------------------------- # Integrate the velocity field parallel to the line of sight along the # line of sight V_para_proj = np.mean(vel_para, axis=int_axis, dtype=np.float64) # Save the projected parallel velocity field image as a FITS file, using the # same header as was created for synchrotron intensity mat2FITS_Image(V_para_proj, pri_hdu_I.header, save_loc + save_sim_arr[i] + \ los_loc + 'V_para_projected.fits', clobber = True) #--------------------- Projected V Perpendicular --------------------------- # Integrate the velocity field perpendicular to the line of sight along the
# Extract the data for Stokes Q, as a memory map StoQ = StoQ_fits[0].data # Extract the header for Stokes Q StoQ_hdr = StoQ_fits[0].header # Change the value for the CRPIX1 keyword, to give the correct reference # pixel for the new array StoQ_hdr['CRPIX1'] = -332.00 # Extract the portion of the Stokes Q image that we are interested in newQ = StoQ[:, :, 2909:3983] # Save the selected region of the Stokes Q image as a new FITS file mat2FITS_Image(newQ, StoQ_hdr, data_loc +\ 'GALFACTS_' + 'S1_chanavg_subset_Q' + '.fits', clobber = True) # Close the Stokes Q fits file, and anything related to it, to free memory StoQ_fits.close() del newQ del StoQ # Open the FITS file that contains Stokes U, as a memory map, so that we don't # load it all in at once. StoU_fits = fits.open(data_loc + 'GALFACTS_S1_0263_4023_10chanavg_U.fits',\ memmap = True) # Extract the data for Stokes U, as a memory map StoU = StoU_fits[0].data # Extract the header for Stokes U
# Print a message to the screen to show that everything is going smoothly print 'Stokes parameters successfully extracted from data.' # Extract values from the S-PASS header that specify the separation between # pixels along the x and y directions in degrees dx = np.absolute(spass_hdr['CDELT1']) dy = np.absolute(spass_hdr['CDELT2']) # Calculate the polarisation intensity images for both data sets spass_pol_inten = np.sqrt(np.power(spass_Q_data,2.0)\ + np.power(spass_U_data,2.0)) urum_pol_inten = np.sqrt(np.power(urum_Q_data,2.0)\ + np.power(urum_U_data,2.0)) # Save the polarisation intensity images for both data sets mat2FITS_Image(spass_pol_inten, spass_hdr, save_loc +\ 'spass_pol_inten.fits', clobber = True) mat2FITS_Image(urum_pol_inten, urum_hdr, save_loc +\ 'urum_pol_inten.fits', clobber = True) #---------------------- Curvature Calculations SPASS --------------------------- # Calculate the first order spatial derivatives of Stokes Q and U for the # spass data sp_dQ_dy, sp_dQ_dx, sp_dU_dy, sp_dU_dx =\ calc_Sto_1Diff(spass_Q_data, spass_U_data, pix_sep = dy) # Calculate all of the second order spatial derivatives of Stokes Q and U for # the spass data sp_d2Q_dy2, sp_d2Q_dydx, sp_d2Q_dx2, sp_d2U_dy2, sp_d2U_dydx, sp_d2U_dx2 =\ calc_Sto_2Diff(sp_dQ_dy, sp_dQ_dx, sp_dU_dy, sp_dU_dx, pix_sep = dy)
# the second mask first_mask = np.zeros(np.shape(Q_data), dtype = bool) second_mask = np.zeros(np.shape(Q_data), dtype = bool) # Run the generate mask function on Stokes Q, to create a mask that covers # all of the sources detected in Stokes Q first_mask, second_mask = generate_mask(catalogue = Q_srclist, mask1 =\ first_mask, mask2 = second_mask, image_loc = Sto_Q_file,\ thresh1 = thresh1, thresh2 = thresh2) # Run the generate mask function on Stokes U, to create a mask that covers # all of the sources detected in Stokes U, in addition to Stokes Q first_mask, second_mask = generate_mask(catalogue = U_srclist, mask1 =\ first_mask, mask2 = second_mask, image_loc = Sto_U_file,\ thresh1 = thresh1, thresh2 = thresh2) # Cast the two masks into floats, so that they can be saved as FITS images first_mask = first_mask.astype(np.int) second_mask = second_mask.astype(np.int) # Save the mask created with the first threshold as a FITS file first_FITS = mat2FITS_Image(first_mask, Q_hdr,\ data_loc + 'combined_mask_{}_thr_{}.fits'.format(mosaic_area, thresh1)) # Save the mask created with the second threshold as a FITS file second_FITS = mat2FITS_Image(second_mask, Q_hdr,\ data_loc + 'combined_mask_{}_thr_{}.fits'.format(mosaic_area, thresh2)) # At this point the required masks have been saved as FITS files, so print a # message saying that the program completed successfully print 'Masks successfully saved as FITS files'
# Specify what the third axis is pri_hdu_StoQ.header['CTYPE3'] = 'Spec-ind' # Add header keywords to describe the line of sight, frequency, # pixel size, density, velocity scale, and magnetic field scale for # Stokes Q pri_hdu_StoQ.header['SIM'] = (save_sim, 'simulation used') pri_hdu_StoQ.header['LOS'] = (int_axis, '0-z, 1-y, 2-x') pri_hdu_StoQ.header['FREQ'] = (freq, 'observing frequency (Hz)') pri_hdu_StoQ.header['PIX-SIZE'] = (dl, 'size of each pixel (pc)') pri_hdu_StoQ.header['DENSITY'] = (n_e, 'density scaling (cm^-3)') pri_hdu_StoQ.header['VELSCALE'] = (v_0, 'velocity scaling (m s^-1)') pri_hdu_StoQ.header['MAGSCALE'] = (B_0, 'magnetic field scaling (mu G)') # Save the produced Stokes Q and U arrays as FITS files mat2FITS_Image(StoQ, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_StoQ_specind_' + emis_mech + '.fits', clobber = True) mat2FITS_Image(StoU, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_StoU_specind_' + emis_mech + '.fits', clobber = True) # Save the produced polarised intensity and polarisation angle as FITS files mat2FITS_Image(pol_inten, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_pol_inten_specind_' + emis_mech + '.fits', clobber = True) mat2FITS_Image(pol_angle, pri_hdu_StoQ.header, save_loc + save_sim + '_' + \ line_o_sight + '_pol_angle_specind_' + emis_mech + '.fits', clobber = True) # Close all of the fits files, to save memory dens_fits.close() magx_fits.close() magy_fits.close() magz_fits.close()
print 'Mach number maps calculated' # Now that the Mach number maps have been produced, we need to save the # produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the sonic Mach number data pri_hdu_sonic = fits.PrimaryHDU(los_sonic) # Create a primary HDU to contain the Alfvenic Mach data pri_hdu_alf = fits.PrimaryHDU(los_alf) # Save the produced sonic Mach number map as a FITS file mat2FITS_Image(los_sonic, pri_hdu_sonic.header, data_loc + 'los_av_sonic_' +\ line_o_sight + '.fits', clobber = True) # Save the produced Alfvenic Mach number map as a FITS file mat2FITS_Image(los_alf, pri_hdu_alf.header, data_loc + 'los_av_alf_' +\ line_o_sight + '.fits', clobber = True) # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() vel_x_fits.close() vel_y_fits.close() vel_z_fits.close() dens_fits.close() # Print a message to state that the FITS file was saved successfully
pri_hdu_StoQ.header['MAGSCALE'] = (B_0, 'magnetic field scaling (mu G)') # Add header keywords to describe the line of sight, frequency, # spectral index, pixel size, density, velocity scale, and magnetic # field scale for Stokes U pri_hdu_StoU.header['SIM'] = (save_sim_arr[i], 'simulation used') pri_hdu_StoU.header['LOS'] = (int_axis, '0-z, 1-y, 2-x') pri_hdu_StoU.header['FREQ'] = (freq_backlit, 'observing frequency (Hz)') pri_hdu_StoU.header['SPEC-IND'] = (spec_ind, 'spectral index') pri_hdu_StoU.header['PIX-SIZE'] = (dl, 'size of each pixel (pc)') pri_hdu_StoU.header['DENSITY'] = (n_e, 'density scaling (cm^-3)') pri_hdu_StoU.header['VELSCALE'] = (v_0, 'velocity scaling (m s^-1)') pri_hdu_StoU.header['MAGSCALE'] = (B_0, 'magnetic field scaling (mu G)') # Save the produced Stokes Q and U images as FITS files mat2FITS_Image(StoQ, pri_hdu_StoQ.header, save_loc + save_sim_arr[i] + \ los_loc + 'StoQ_' + 'backlit' + '.fits', clobber = True) mat2FITS_Image(StoU, pri_hdu_StoU.header, save_loc + save_sim_arr[i] + \ los_loc + 'StoU_' + 'backlit' + '.fits', clobber = True) elif 'internal' in emis_mech: # In this case we need to produce cubes of Stokes Q and U for the case # when the emission is generated within the simulation cube, over a # range of frequencies # Create empty arrays, that will be used to contain the Stokes Q and U # maps created at each frequency StoQ = np.zeros((len(freq_internal), dens_data.shape[1],\ dens_data.shape[2]), dtype = np.float32) StoU = np.zeros((len(freq_internal), dens_data.shape[1],\ dens_data.shape[2]), dtype = np.float32)
# Calculate all of the first order spatial derivatives that we need dQ_dy, dQ_dx, dU_dy, dU_dx = calc_Sto_1Diff(StoQ, StoU, pix_sep=dl) # Calculate all of the second order spatial derivatives that we need d2Q_dy2, d2Q_dydx, d2Q_dx2, d2U_dy2, d2U_dydx, d2U_dx2 =\ calc_Sto_2Diff(dQ_dy, dQ_dx, dU_dy, dU_dx, pix_sep = dl) #------------------------- Polarisation Angle ------------------------------ # Check to see if we need to calculate the polarisation angle if 'Angle' in diag_list: # Calculate the observed polarisation angle for this Stokes Q and U polar_angle = calc_Polar_Angle(StoQ, StoU) # Save the polarisation angle array mat2FITS_Image(polar_angle, StoQ_hdr, data_loc + 'PolarAngle_' +\ emis_mech + '.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Polarisation angle calculated' #----------------------- Polarisation Gradient ----------------------------- # Check to see if we need to calculate the polarisation gradient if 'Grad' in diag_list: # Calculate the observed polarisation gradient for this Stokes Q and U polar_grad = calc_Polar_Grad(dQ_dy, dQ_dx, dU_dy, dU_dx) # Save the polarisation gradient array mat2FITS_Image(polar_grad, StoQ_hdr, data_loc + 'PolarGrad_' +\ emis_mech + '.fits', clobber = True)
if i == 0: # Set the return slice to be 0 return_slice = 0 else: # For all other cases, we need to return the second slice of the # array return_slice = 1 # Put this slice into the storage array storage_arr[i] = rot_meas[return_slice] # Change the header to reflect what is being saved StoQ_hdr['OBJECT'] = 'GALFACTS_S1 Rot Meas' # Save the rotation measure mat2FITS_Image(storage_arr, StoQ_hdr, data_loc +\ 'RotMeas_S1_chanavg_subset.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Rotation measure calculated' #----------------------- Wavelength Gradient --------------------------- # Check to see if we need to calculate the wavelength gradient if 'Wav_Grad' in diag_list: # Iterate over the slices of the Stokes Q and U arrays for i in range(num_slice): # Extract the current Stokes Q slice from the full array, as well as # the slices immediately before and after this, if they exist StoQ_slice = StoQ[max(0, i - 1):min(i + 2, num_slice)] # Extract the current Stokes U slice from the full array, as well as
# the second mask first_mask = np.zeros(np.shape(Q_data), dtype=bool) second_mask = np.zeros(np.shape(Q_data), dtype=bool) # Run the generate mask function on Stokes Q, to create a mask that covers # all of the sources detected in Stokes Q first_mask, second_mask = generate_mask(catalogue = Q_srclist, mask1 =\ first_mask, mask2 = second_mask, image_loc = Sto_Q_file,\ thresh1 = thresh1, thresh2 = thresh2) # Run the generate mask function on Stokes U, to create a mask that covers # all of the sources detected in Stokes U, in addition to Stokes Q first_mask, second_mask = generate_mask(catalogue = U_srclist, mask1 =\ first_mask, mask2 = second_mask, image_loc = Sto_U_file,\ thresh1 = thresh1, thresh2 = thresh2) # Cast the two masks into floats, so that they can be saved as FITS images first_mask = first_mask.astype(np.int) second_mask = second_mask.astype(np.int) # Save the mask created with the first threshold as a FITS file first_FITS = mat2FITS_Image(first_mask, Q_hdr,\ data_loc + 'combined_mask_{}_thr_{}.fits'.format(mosaic_area, thresh1)) # Save the mask created with the second threshold as a FITS file second_FITS = mat2FITS_Image(second_mask, Q_hdr,\ data_loc + 'combined_mask_{}_thr_{}.fits'.format(mosaic_area, thresh2)) # At this point the required masks have been saved as FITS files, so print a # message saying that the program completed successfully print 'Masks successfully saved as FITS files'
# along the third axis pri_hdu.header['CRPIX3'] = 1 # Add a header keyword to the HDU header, specifying the value of gamma # at the reference pixel pri_hdu.header['CRVAL3'] = 1.0 # Add a header keyword to the HDU header, specifying the increment in gamma # along each slice of the array pri_hdu.header['CDELT3'] = 0.5 # Add a header keyword to the HDU header, describing what the third axis is pri_hdu.header['CTYPE3'] = 'Gamma ' # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4' +\ line_o_sight + '.fits') # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() # Print a message to state that the FITS file was saved successfully print 'FITS file of synchrotron maps saved successfully {}'.format(simul_arr[i]) # # Now we wish to compare our calculated maps with Blakesley's. To do this, # # we will cycle through all of the synchrotron maps that have been calculated, # # and for each a plot will be produced of the difference between my map # # of synchrotron emission and Blakesley's. I will also print out the maximum # # difference between the maps. # for i in range(len(gamma_arr)):
print 'Polarisation gradient map calculated' # Now that the polarisation gradient map has been produced, we need to save the # produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the rotation measure data pri_hdu_RM = fits.PrimaryHDU(RM_image) # Create a primary HDU to contain the polarisation gradient data pri_hdu_gradP = fits.PrimaryHDU(gradP) # Save the produced rotation measure map as a FITS file mat2FITS_Image(RM_image, pri_hdu_RM.header, data_loc + 'rot_meas_' +\ line_o_sight + '.fits', clobber = True) # Save the produced polarisation gradient map as a FITS file mat2FITS_Image(gradP, pri_hdu_gradP.header, data_loc + 'polar_grad_' +\ line_o_sight + '.fits', clobber = True) # Close all of the fits files, to save memory mag_fits.close() dens_fits.close() # Print a message to state that the FITS file was saved successfully print 'FITS file of gradient map saved successfully {}'.format(simul_arr[i]) # All of the required maps have been saved, so print a message stating that # the script has finished print 'All gradient maps calculated successfully'
# Find the entries of the array where the measured angle was in the fourth # quadrant, but it is supposed to be in the third quadrant third_quad = np.logical_and(theta_cos_entries, double_theta_sin < 0) # For entries that are supposed to be in the second quadrant, adjust the # value of the measured angle double_theta_sin[second_quad] = np.pi - double_theta_sin[second_quad] # For entries that are supposed to be in the third quadrant, adjust the # value of the measured angle double_theta_sin[ third_quad] = -1.0 * np.pi - double_theta_sin[third_quad] # Calculate the angle for which the mixed derivative is maximised, # at each pixel mix_max_ang = np.rad2deg(0.5 * double_theta_sin) # Save the produced angle image as a FITS file mat2FITS_Image(mix_max_ang, pol_angle_hdr, data_loc +\ 'MixMaxAng_backlit.fits', clobber = True) #--------------------------------------------------------------------------- # Print a message to state that the FITS files were saved successfully print 'FITS files of projected quantities saved successfully {}'.\ format(simul_arr[i]) # All of the required maps have been saved, so print a message stating that # the script has finished print 'All projected diagnostic maps calculated successfully'
-1087.00000, 2113.00000, 1313.00000, 513.00000, -287.00000, -1087.00000]) # Loop over all of the FITS files that need to be modified for i in range(len(fits_file_list)): # Open up the FITS file fits_file = fits.open(cgps_loc + direc_name + fits_file_list[i]) # Obtain the header from the FITS file fits_hdr = fits_file[0].header # Obtain the data from the FITS file fits_data = fits_file[0].data # Change the CRVAL1 value to the required value fits_hdr['CRVAL1'] = crval1 # Change the CRVAL2 value to the required value fits_hdr['CRVAL2'] = crval2 # Change the CRPIX1 value to the required value fits_hdr['CRPIX1'] = crpix1_arr[i] # Change the CRPIX2 value to the required value fits_hdr['CRPIX2'] = crpix2_arr[i] # Save the new FITS file with the modified header mat2FITS_Image(fits_data, fits_hdr, cgps_loc + output_direc + fits_file_list[i]) # Print a message to the screen to say the FITS file has been made print "{} made successfully.".format(fits_file_list[i]) # Close the FITS file to save memory fits_file.close()
def calc_local_stats(input_files, output_filenames, stat_list, box_halfwidths): ''' Description This function calculates statistics for each pixel in an image, using the data in surrounding pixels. The statistics that are calculated can be specified in the stat_list variable. All of these statistics will be calculated for each input image. Multiple input files can be provided, and statistics will be calculated for each image. Maps of the produced statistics will be saved using the given output filenames. Required Input input_files - An array of strings, where each string specifies the directory and filename of the FITS image to calculate statistics for. Local statistics are calculated for each file provided in this array. output_filenames - An array of strings, where each string specifies the directory and filename to use when saving a FITS file image of the produced statistic map. An image is saved for each input file, and each statistic. This array needs to be the same length as input_files. Each FITS file that is saved will have the type of statistic appended to the output filename provided. The given strings should not have the .fits extension present, as this is added in the function. stat_list - An array of strings, where each string specifies a statistic that is to be calculated locally for each input image. Allowed values are 'skewness' and 'kurtosis'. box_halfwidths - The half-widths of the box to use when calculating the local statistics, in pixels. This is an array of positive integers greater than or equal to 1. This array must have the same length as input_files. Output 0 - An error occurred, possibly due to inappropriate input values 1 - Function ran to completion, and saved FITS images of the calculated statistics maps successfully. ''' # Check to see that the number of output filenames matches the number of # input filenames if len(input_files) != len(output_filenames): # In this case the number of output filenames does not match the number # input filenames, so the code cannot proceed. Print an error message # to say what has happened print 'ERROR: Number of input files and output filenames are different' # The code should not proceed in this case, so return 0 return 0 # Check to see that the number of box halfwidth values equals the number # of input filenames if len(input_files) != len(box_halfwidths): # In this case the number of box halfwidths to use does not match the # number of input filenames, so the code cannot proceed. Print an # error message to say what has happened. print 'ERROR: Number of input files and box halfwidths are different' # The code should not proceed in this case, so return 0 return 0 # Create a list of valid strings that can be given to the stat_list variable valid_stats = ['skewness', 'kurtosis'] # Check to see that valid statistics were provided if len(list(set(valid_stats).intersection(stat_list))) == 0: # In this case the array of strings given to the function does not # provide any valid statistics to calculate, so print an error message # to the screen print 'ERROR: No valid statistics provided to the function' # The code should not proceed in this case, so return 0 return 0 # Check to see that the values given for the box halfwidths are positive # integers greater than or equal to 1 if np.any(box_halfwidths < 1): # In this case a value given for the box halfwidth is invalid, so # print an error message to the screen print 'ERROR: At least one of the values for box half-width is invalid' # The code should not proceed in this case, so return to 0 return 0 # Loop over the given input files, so that we can calculate statistics for # each one for i in range(len(input_files)): # Print a message to show that calculations are starting for the current # input file print 'Calculations starting for {}'.format(input_files[i]) # Open the CGPS FITS file for the current resolution fits_file = fits.open(input_files[i]) # Obtain the header of the primary HDU for the data fits_hdr = fits_file[0].header # Extract the data from the FITS file, which is held in the primary HDU fits_data = fits_file[0].data # Print a message to the screen saying that the data was successfully # extracted print 'CGPS data successfully extracted from the FITS file.' # Create a dictionary that will hold the arrays corresponding to each # statistic stat_dict = {} # Create new numpy arrays, that have the same size as the input array. # These will be used to store the calculated local statistics. The # arrays are stored in a dictionary, with each statistic having its own # array for stat in stat_list: # Assign an empty array to the current statistic. Note that the data # type is 32-bit float, since all of the input arrays have that data # type stat_dict[stat] = np.zeros(np.shape(fits_data), dtype=np.float32) # Extract the size of each pixel from the header. This is the length of # each side of the pixel (assumed to be square), in degrees. pix_size_deg = fits_hdr['CDELT2'] # Extract the number of pixels along the horizontal axis of the image num_pix_horiz = fits_hdr['NAXIS1'] # Extract the number of pixels along the vertical axis of the image num_pix_vert = fits_hdr['NAXIS2'] # Loop over all of the pixels in the dataset, starting by looping over # each row for j in range(num_pix_vert): # Loop over all of the pixels in this row for k in range(num_pix_horiz): # Extract the value of the data at the current pixel pix_value = fits_data[j, k] # Calculate the index of the uppermost pixels to be included in # the local box. Note that the minus sign is because Python # indexes so that the pixels highest in the image have the # lowest index value upper_index = j - box_halfwidths[i] # Calculate the index of the lowermost pixels to be included in # the local box lower_index = j + box_halfwidths[i] # Calculate the index of the rightmost pixels to be included in # the local box right_index = k + box_halfwidths[i] # Calculate the index of the leftmost pixels to be included in # the local box left_index = k - box_halfwidths[i] # Check that the index of the uppermost pixel to include in the # local box is valid, i.e. not negative if upper_index < 0: # In this case the value of the upper index doesn't make # sense, so reset it to zero upper_index = 0 # Check that the index of the leftmost pixel to include in the # local box is valid, i.e. not negative if left_index < 0: # In this case the value of the left index doesn't make # sense, so reset it to zero left_index = 0 # Check that the index of the lowermost pixel to include in the # local box is valid, i.e. that it does not extend beyond the # boundaries of the image if lower_index >= num_pix_vert: # In this case the value of the lower index doesn't make # sense, so reset it to the largest possible index for the # vertical axis lower_index = num_pix_vert - 1 # Check that the index of the rightmost pixel to include in the # local box is valid, i.e. that it does not extend beyond the # boundaries of the image if right_index >= num_pix_horiz: # In this case the value of the lower index doesn't make # sense, so reset it to the largest possible index for the # horizontal axis right_index = num_pix_horiz - 1 # Check to see if the value of the data at this pixel is NaN if np.isnan(pix_value): # In this case the pixel is NaN, so set the corresponding # pixel in all of the statistics arrays to NaN as well for stat in stat_list: (stat_dict[stat])[j, k] = float('nan') else: # In this case the pixel is not NaN, and so we can calculate # local statistics at this point # Extract the data in the local box around the current # pixel we are studying local_data = fits_data[upper_index:lower_index+1,\ left_index:right_index+1] # Check to see if the skewness of the local area needs to be # calculated if 'skewness' in stat_list: # Flatten the local data into a one-dimensional array local_data_flat = local_data.flatten() # Find where all of the NaN values are in the local data NaN_position = np.isnan(local_data_flat) # Extract the values in the local data that are not NaN local_data_no_nan =\ local_data_flat[np.logical_not(NaN_position)] # Calculate the skewness of the local data that has had # the NaN values removed, and store it in the # corresponding array (stat_dict['skewness'])[j,k] =\ stats.skew(local_data_no_nan) elif 'kurtosis' in stat_list: # Flatten the local data into a one-dimensional array local_data_flat = local_data.flatten() # Find where all of the NaN values are in the local data NaN_position = np.isnan(local_data_flat) # Extract the values in the local data that are not NaN local_data_no_nan =\ local_data_flat[np.logical_not(NaN_position)] # Calculate the kurtosis of the local data that has had # the NaN values removed, and store it in the # corresponding array (stat_dict['kurtosis'])[j,k] =\ stats.kurtosis(local_data_no_nan) # When the code reaches this point, all of the required # statistics have been calculated for this pixel # When the code reaches this point, statistics have been calculated # for all of the pixels in this row # Every 100 rows, print out a message to show where the code is up to if (j + 1) % 100 == 0: # Another 100 rows have been completed, so print a message print '{} rows calculated'.format(j + 1) # When the code reaches this point, statistics have been calculated for # all of the pixels, for this particular value of the final resolution # Next, we want to save the produced maps of the local statistics # Loop over all of the statistics that were calculated for stat in stat_list: # Convert the matrix of values for this statistic into a FITS file, # and save the result using the same header as the input CGPS data. # The FITS file is saved in the same location as the CGPS data stat_FITS = mat2FITS_Image(stat_dict[stat], fits_hdr,\ output_filenames[i] + '_{}'.format(stat) + '.fits') # Print a message to the screen, to show that a FITS file was # produced for the current statistic print 'FITS file saved for {}'.format(stat) # At this point, all FITS files have been saved for the required # statistics, so print a message to the screen about this print 'All FITS files saved for {}'.format(input_files[i]) # When the code reaches this point, all of the FITS files have been saved # Print a message stating this print 'All FITS files saved successfully' # Since the code has run successfully, return 1 return 1
# along the third axis pri_hdu.header['CRPIX3'] = 1 # Add a header keyword to the HDU header, specifying the value of gamma # at the reference pixel pri_hdu.header['CRVAL3'] = 1.0 # Add a header keyword to the HDU header, specifying the increment in gamma # along each slice of the array pri_hdu.header['CDELT3'] = 0.5 # Add a header keyword to the HDU header, describing what the third axis is pri_hdu.header['CTYPE3'] = 'Gamma ' # Save the produced synchrotron maps as a FITS file mat2FITS_Image(sync_arr, pri_hdu.header, data_loc + 'synint_p1-4' +\ line_o_sight + '.fits') # Close all of the fits files, to save memory mag_x_fits.close() mag_y_fits.close() mag_z_fits.close() # Print a message to state that the FITS file was saved successfully print 'FITS file of synchrotron maps saved successfully {}'.format( simul_arr[i]) # # Now we wish to compare our calculated maps with Blakesley's. To do this, # # we will cycle through all of the synchrotron maps that have been calculated, # # and for each a plot will be produced of the difference between my map # # of synchrotron emission and Blakesley's. I will also print out the maximum # # difference between the maps.
print 'Polarisation gradient map calculated' # Now that the polarisation gradient map has been produced, we need to save the # produced map as a FITS file # To do this, we need to make a FITS header, so that anyone using the FITS # file in the future will know what gamma values were used # Create a primary HDU to contain the rotation measure data pri_hdu_RM = fits.PrimaryHDU(RM_image) # Create a primary HDU to contain the polarisation gradient data pri_hdu_gradP = fits.PrimaryHDU(gradP) # Save the produced rotation measure map as a FITS file mat2FITS_Image(RM_image, pri_hdu_RM.header, data_loc + 'rot_meas_' +\ line_o_sight + '.fits', clobber = True) # Save the produced polarisation gradient map as a FITS file mat2FITS_Image(gradP, pri_hdu_gradP.header, data_loc + 'polar_grad_' +\ line_o_sight + '.fits', clobber = True) # Close all of the fits files, to save memory mag_fits.close() dens_fits.close() # Print a message to state that the FITS file was saved successfully print 'FITS file of gradient map saved successfully {}'.format( simul_arr[i]) # All of the required maps have been saved, so print a message stating that # the script has finished
# Bryan's division_mat[j, i] = my_data[j, i] - B_value # Print a message to the screen to show when 50 columns have been computed if (i + 1) % 50 == 0: # The number of columns completed is a multiple of 50, so print a # message to the screen print '{} columns completed'.format(i + 1) # When the code reaches this point, both for loops have completed, and the # division matrix is filled with values. # Convert the matrix of divided polarisation gradient values into a FITS file, # using the header information of my data. Also save the FITS file that is # produced by the function. division_FITS = mat2FITS_Image(division_mat, my_hdr,\ data_loc + 'sgps_subtract_polar_fix_unit.fits') # Print a message to the screen to show that the FITS file was produced and # saved successfully. print 'FITS file successfully saved for the divided polarisation gradients.' # Create an image of the divided polarisation gradient values # using aplpy and the produced FITS file. This image is automatically # saved using the given filename. fits2aplpy(division_FITS, data_loc + 'sgps_subtract_polar_fix_unit.png', \ colour = 'RdBu') # Print a message to the screen to show that the image of the divided # polarisation gradient values has been successfully produced and saved. print 'Image of the divided polarisation gradients successfully saved.\n'
# Calculate all of the first order spatial derivatives that we need dQ_dy, dQ_dx, dU_dy, dU_dx = calc_Sto_1Diff(StoQ, StoU, pix_sep=pix_size_deg) # Calculate all of the second order spatial derivatives that we need d2Q_dy2, d2Q_dydx, d2Q_dx2, d2U_dy2, d2U_dydx, d2U_dx2 =\ calc_Sto_2Diff(dQ_dy, dQ_dx, dU_dy, dU_dx, pix_sep = pix_size_deg) #---------------------- Polarisation Intensity ------------------------- # Check to see if we need to calculate the polarisation intensity if 'Inten' in diag_list: # Calculate the polarisation intensity for this Stokes Q and U polar_inten = calc_Polar_Inten(StoQ, StoU) # Save the polarisation intensity mat2FITS_Image(polar_inten, StoQ_hdr, data_loc +\ 'PolarInten_' + 'S3_average' + '.fits', clobber = True) # Print a message to say the diagnostic has been calculated print 'Polarisation intensity calculated' #------------------------- Polarisation Angle ------------------------------ # Check to see if we need to calculate the polarisation angle if 'Angle' in diag_list: # Calculate the observed polarisation angle for this Stokes Q and U polar_angle = calc_Polar_Angle(StoQ, StoU) # Save the polarisation angle array mat2FITS_Image(polar_angle, StoQ_hdr, data_loc + 'PolarAngle_' +\ 'S3_average' + '.fits', clobber = True)