<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Creating AngularCatalogs and ImageMasks
Py2PAC has several ways to create AngularCatalogs and ImageMasks.  We'll start with ImageMasks since we need them in order to do anything meaningful with an AngularCatalog.
First, import the things that we'll need.
Step1:  Ways to create an ImageMask
There are three main ways to create an ImageMask in Py2PAC, all classmethods of ImageMask
Step2:  To see what the mask looks like, we generate some random points and plot them.
Step3:  Simple enough.  Note that if you manually change the completenesses in the ImageMask._mask, it will behave like from_array, which is to say "not the way you expect" (this is on the list of things to be fixed).   See the next section.
From array
Step4:  The main thing to note here is that the binning isn't even.  The mask also has a different orientation from the orientation of the array.  The origin is in the lower left, at the minimum RA and Dec.  To see this, we'll use a slightly different array to mask.
Step5:  This clearly shows that the origin is in the lower left and also illustrates how variable completeness would be implemented in this version of Py2PAC.  Again, this should be fixed so the bins are square (or at least rectangular) in future versions.
From FITS
Step6:  Ways to create an AngularCatalog
An AngularCatalog can be created either with externally generated RAs and Decs or with randomly generated RAs and Decs.  They can have an ImageMask of any kind.  We'll start with pre-existing RAs and Decs (we'll make some up) and then move on to the random_catalog class method.
AngularCatalogs from existing coordinates
For the purposes of this exercise, we'll just create a random sample of "galaxies."  For interest, we'll distribute them as a 2D Gaussian.
Step7:  Now we need to make this into an AngularCatalog with some image mask.  The options are to pass an already existing ImageMask instance or to give the constructor the location of a weight file from which to construct the mask.  
Pre-existing ImageMask
For this demonstration, we'll make a rectangular mask and pass it explicitly.
Step8:  The first plot shows all the data and the second shows just the data within the mask area (just to confirm that the mask is working).
Creating an ImageMask from FITS at the same time you create the AngularCatalog
You can also generate AngularCatalogs with ImageMask from FITS files with just the constructor.  For this, we need coordinates that are in the right place, so we'll just use the CANDELS galaxies.
Step9:  AngularCatalogs with randomly generated points
For testing purposes, AngularCatalog has a class method called random_catalog.  This method can be called with either ranges in RA and Dec or with an existing ImageMask.  The code below shows an AngularCatalog made both ways.
<ASSISTANT_TASK:>
Python Code:
import AngularCatalog_class as ac
import ImageMask_class as imclass
from astropy.io import fits
from astropy.io import ascii
import numpy as np
import numpy.random as rand
import matplotlib.pyplot as plt
%matplotlib inline 
plt.rcParams['figure.figsize'] = (10, 6)
Explanation: Creating AngularCatalogs and ImageMasks
Py2PAC has several ways to create AngularCatalogs and ImageMasks.  We'll start with ImageMasks since we need them in order to do anything meaningful with an AngularCatalog.
First, import the things that we'll need.
End of explanation
mask_from_ranges = imclass.ImageMask.from_ranges([0, 1], [0, 0.5])
Explanation: Ways to create an ImageMask
There are three main ways to create an ImageMask in Py2PAC, all classmethods of ImageMask:
from_ranges: Creates a rectangular image mask over a range in RA and Dec with equal completeness in all parts of the image.  Bug to be fixed: doesn't allow for negative RAs
from_array: This doesn't work the way it should at the moment because WCS is wonky.  This creates a rectangular image mask with the completeness in each cell defined by the value of an input array.  I show here how it currently malfunctions.  Eventually, this should be fixed.
from_FITS_weight_file: Reads in a weight map in FITS format and converts it to completeness=1 at points with weight above the 5th percentile and completeness=0 below.
From ranges: single completeness over a rectangular area
We'll make the simplest mask first.  The arguments to from_ranges are two arrays, the RA range first, then the Dec range, both in degrees.
End of explanation
#Generate the randoms
ra, dec, completeness = mask_from_ranges.generate_random_sample(1e4)
#Plot
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel("RA (deg)")
ax.set_ylabel("Dec (deg)")
ax.scatter(ra, dec)
Explanation: To see what the mask looks like, we generate some random points and plot them.
End of explanation
#Make the mask array
mask_array = np.identity(4)
print mask_array
#Make the ImageMask
mask_from_array = imclass.ImageMask.from_array(mask_array, [0,1], [0,1])
%%capture
## ^ Use to suppress lengthy output
#Generate randoms
ra, dec, completeness = mask_from_array.generate_random_sample(1e4)
#Plot the randoms
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel("RA (deg)")
ax.set_ylabel("Dec (deg)")
ax.scatter(ra, dec)
Explanation: Simple enough.  Note that if you manually change the completenesses in the ImageMask._mask, it will behave like from_array, which is to say "not the way you expect" (this is on the list of things to be fixed).   See the next section.
From array: Make a mask from a pre-existing array
WARNING: This method does not work the way it should.  I have included it solely to show how the function is broken.
The concept for this method is to make it so that an arbitrary array with elements that range from 0 to 1 can be used as an image mask.  However, at the present time, dividing the area into even bins doesn't work for reasons unbeknownst to me.  We'll make a mask from the identity matrix to illustrate the strangeness, but then show how uneven completeness works.
End of explanation
#Make the new array mask
mask_array2 = np.identity(4)
mask_array2[0,0] = 0.2
mask_array2[0, 3] = 0.2
print mask_array2
#Make the new mask
mask_from_array2 = imclass.ImageMask.from_array(mask_array2, [0,1], [0,1])
%%capture
## ^ Use to suppress lengthy output
#Generate randoms
ra2, dec2, completeness = mask_from_array2.generate_random_sample(1e4)
#Plot the randoms
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel("RA (deg)")
ax.set_ylabel("Dec (deg)")
ax.scatter(ra2, dec2)
Explanation: The main thing to note here is that the binning isn't even.  The mask also has a different orientation from the orientation of the array.  The origin is in the lower left, at the minimum RA and Dec.  To see this, we'll use a slightly different array to mask.
End of explanation
#Make the mask
weight_file = 'hlsp_candels_hst_wfc3_gs-tot-sect33_f160w_v1.0_wht.fits'
mask_from_fits = imclass.ImageMask.from_FITS_weight_file(weight_file)
%%capture
## ^ Use to suppress lengthy output
#Generate randoms
ra, dec, completeness = mask_from_fits.generate_random_sample(1e5)
#Plot the randoms
fig=plt.figure()
fig.set_size_inches(7,7)
ax=fig.add_subplot(111)
ax.set_xlabel("RA (deg)")
ax.set_ylabel("Dec (deg)")
ax.scatter(ra, dec)
Explanation: This clearly shows that the origin is in the lower left and also illustrates how variable completeness would be implemented in this version of Py2PAC.  Again, this should be fixed so the bins are square (or at least rectangular) in future versions.
From FITS: Make a mask from a FITS file
This function was written with the weight files from the CANDELS mosaics in mind.  In principle, it should work with any FITS image with lower values denoting lower exposure times.  The routine reads in the FITS file and finds the 5th percentile of the nonzero weight values from a random sample of 1e6 values on the image (to make computation time manageable).  Then, a mask is created that has completeness 1 above the 5th percentile and 0 below.  
This example uses a CANDELS tile weight file.  The file is too large to be included in the repository, so the file "hlsp_candels_hst_wfc3_gs-tot-sect33_f160w_v1.0_wht.fits" (found here) must be downloaded and placed in the examples folder.
End of explanation
#Make the RAs and Decs
ras = rand.normal(loc=0.5, scale=0.2, size=int(1e3))
decs = rand.normal(loc=0, scale=0.2, size=int(1e3))
plt.scatter(ras, decs)
Explanation: Ways to create an AngularCatalog
An AngularCatalog can be created either with externally generated RAs and Decs or with randomly generated RAs and Decs.  They can have an ImageMask of any kind.  We'll start with pre-existing RAs and Decs (we'll make some up) and then move on to the random_catalog class method.
AngularCatalogs from existing coordinates
For the purposes of this exercise, we'll just create a random sample of "galaxies."  For interest, we'll distribute them as a 2D Gaussian.
End of explanation
#Make the mask that we'll be using
immask = imclass.ImageMask.from_ranges([0.1, .9], [-0.4, 0.4])
#Make the catalog
cat = ac.AngularCatalog(ras, decs, image_mask=immask)
#Generate some randoms to showthe mask area
cat.generate_random_sample(number_to_make=2e4)
#Plot both the randoms and all the data (not just what's within the mask)
cat.scatterplot_points(sample="both", masked_data=False)
cat.scatterplot_points(sample="both", masked_data=True)
Explanation: Now we need to make this into an AngularCatalog with some image mask.  The options are to pass an already existing ImageMask instance or to give the constructor the location of a weight file from which to construct the mask.  
Pre-existing ImageMask
For this demonstration, we'll make a rectangular mask and pass it explicitly.
End of explanation
#Create an AngularCatalog with an ImageMask from a weight file
weight_file = 'hlsp_candels_hst_wfc3_gs-tot-sect33_f160w_v1.0_wht.fits'
data_file = "example_data.dat"
data = ascii.read(data_file)
#Only use the first 1000 points (it's random points, so it doesn't matter which 1000) to make
#an AngularCatalog (so we can see the randoms too on the plot)
cat_wt = ac.AngularCatalog(data['ra'][0:1000], data['dec'][0:1000], weight_file = weight_file)
cat_wt.generate_random_sample(number_to_make=1e4)
cat_wt.scatterplot_points(sample="both", masked_data=True)
Explanation: The first plot shows all the data and the second shows just the data within the mask area (just to confirm that the mask is working).
Creating an ImageMask from FITS at the same time you create the AngularCatalog
You can also generate AngularCatalogs with ImageMask from FITS files with just the constructor.  For this, we need coordinates that are in the right place, so we'll just use the CANDELS galaxies.
End of explanation
#Make the AngularCatalog with an existing image mask
immask = imclass.ImageMask.from_ranges([0.1, .9], [-0.4, 0.4])
rand_cat_1 = ac.AngularCatalog.random_catalog(1e3, image_mask = immask)
rand_cat_1.scatterplot_points(sample="data")
#Make the AngularCatalog over a rectangular area
rand_cat_1 = ac.AngularCatalog.random_catalog(1e3, ra_range=[0, 0.5], dec_range=[0, 0.5])
rand_cat_1.scatterplot_points(sample="data")
Explanation: AngularCatalogs with randomly generated points
For testing purposes, AngularCatalog has a class method called random_catalog.  This method can be called with either ranges in RA and Dec or with an existing ImageMask.  The code below shows an AngularCatalog made both ways.
End of explanation
<END_TASK>