.. _example_basic: Basic Example ============= The most fundamental use for `LUCI` is to read in an HDF5 file and fit a region of the data cube. In this tutorial, we will outline how to do just that. If you want to see the complete example code, please see the bottom of the page. This is also available as a jupyter notebook (complete with output) under *Exmples/BasicExamples.ipynb* in the main Luci repository. You can download the example data using the following command: .. code-block:: bash wget -O NGC6946_SN3.hdf5 https://ws.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/data/pub/CFHT/2307000z.hdf5?RUNID=xc9le6u8llecp7fp This will download the hdf5 file for SN3 (R~400) NGC 6946. The file is just under 900 Mb, so the download may take a while. Note you may need to change the name of the HDF5 file to `NGC6946_SN3.merged.cm1.1.0`. The region files used in the examples can be found in the 'Examples/regions' folder. To run the examples, place these region files in the same directory as the hdf5 file. We should start by import the appropriate modules. .. code-block:: python import sys sys.path.insert(0, '/the/path/to/LUCI/') import LuciBase as Luci import LUCI.LuciPlotting as lplt Remember that '/the/path/to/LUCI/' is the full path to the directory where you cloned LUCI from github. For example, yours may look like '/home/carterrhea/LUCI/'. We will also be highlighting the built in plotting functions found in `LUCI/LuciPlotting.py`. All the region files can be found in 'Examples/regions'. The next step is to load/read the HDF5 data cube. To do this we **invoke** LUCI by initiating an instance of her along with the proper parameters. First we define the correct parameters: 1. luci_path = /the/path/to/LUCI/ # Path to Luci 2. cube_dir = '/path/to/data/cube' # Path to data cube 3. cube_name = 'name_of_data_cube' # don't add .hdf5 extension 4. object_name = 'name_of_object' 5. redshift = 0.01 # Redshift of object 6. resolution = 5000 # Resolution of the ML reference spectrum For example: .. code-block:: python #Set Parameters # Using Machine Learning Algorithm for Initial Guess Luci_path = '/home/carterrhea/Documents/LUCI/' cube_dir = '/home/carterrhea/Documents/LUCI_test' # Path to data cube cube_name = 'NGC6946_SN3' # don't add .hdf5 extension object_name = 'NGC6946' redshift = 0.000133 # Redshift of M33 resolution = 1000 Although the first three arguments are rather self explanatory, it is worth discussing the others. The redshift is provided so that we can shift x-axis of the spectra to the rest-frame. As discussed, this enables better fitting. The redshift of an object can be found at `http://cdsportal.u-strasbg.fr/ `_ . The `resolution` is the resolution of the reference spectrum that will be used for the initial fit estimates. Although this was previously described, I'll remind you that you can find more information at `https://sitelle-signals.github.io/Pamplemousse/index.html `_. The Luci directory contains already a handful differing resolutions (R ~ 1000, 1800, 2000, 2500, 3000, 3500, 4000 ,4500, 5000, 7000). If you require a different resolution for your work, please send me an email at carter.rhea@umontreal.ca. Note that `ML_bool=True` by default. If you do not wish to use the machine learning methodology to estimate the initial values for the velocity, broadening, and amplitude of the line, please simply include the argument `ML_bool=False`. .. code-block:: python # Not Using Machine Learning Algorithm for Initial Guess Luci_path = '/media/carterrhea/carterrhea/SIGNALS/LUCI/' cube_dir = '/media/carterrhea/carterrhea/M33' # Path to data cube cube_name = 'M33_Field7_SN3.merged.cm1.1.0' # don't add .hdf5 extension object_name = 'M33_Field7' redshift = -0.0006 # Redshift of M33 resolution = 5000 ML_bool = False With these parameters set, we can invoke `LUCI` with the following command: .. code-block:: python cube = Luci(luci_path, cube_dir+'/'+cube_name, cube_dir, object_name, redshift, resolution, ML_bool) This reads the HDF5 file, transforms the data cube into a 3d numpy array, and updates the header to be of an appropriate form. It also reads in the machine learning reference spectrum (we need the x-axis for interpolation purposes) and creates the x-axis for the uninterpolated cube. Note that the first argument is the full path to the cube and the second argument is the full path to the output directory (i.e. the output files will be located at cube_dir+'/Luci/'; the 'Luci' at the end is appended by the code itself). .. code-block:: python cube.create_deep_image() We can quickly make a *deep image* by collapsing (summing) the spectral axis. At last, we can fit a region of the cube. There are three functions for fitting the cube: `fit_cube`, `fit_entire_cube`, and `fit_region`. The first option, `fit_cube`, fits a rectangular region of the cube and is invoked by calling: .. code-block:: python vel_map, broad_map, flux_map, ampls_map = cube.fit_cube(line_list, fit_function, vel_rel, sigma_rel, x_min, x_max, y_min, y_max) line_list is a list of lines to fit (e.x. ['Halpha']), fit function is the fitting function to be used (e.x. 'gaussian'), and the remaining arguments are the x and y bounds (respectively) of the bounding box. The vel_rel parameter describes the relational constraints between the lines. For example, if we are fitting three lines and we want the velocities of the second and third lines to be tied to one another, we would simply set vel_rel=[1,2,2]. If we wanted all the lines tied, then we would put [1,1,1]. The sigma_rel parameter functions in the exact same way except it affects the broadening (velocity dispersion) of the lines. For example if we want to fit the three lines in SN3 with all their parameters tied together in a small region, we would do: .. code-block:: python vel_map, broad_map, flux_map, ampls_map = cube.fit_cube(['Halpha', 'NII6548', 'NII6583', 'SII6716', 'SII6731'], 'gaussian', [1,1,1,1,1], [1,1,1,1,1], 500, 1100, 700, 1300) This final command fits the regions and saves the velocity, velocity dispersion (broadening), amplitude, flux, and fit statistic (chi-squared) maps in the output directory defined above. Additionally, it returns the velocity, velocity dispersion, flux, and fit statistics maps for plotting purposes. To fit the entire cube, we would simply run the following instead: .. code-block:: python vel_map, broad_map, flux_map, ampls_map = cube.fit_entire_cube(line_list, fit_function) Or we can fit an entire region .. code-block:: python vel_map, broad_map, flux_map, ampls_map = cube.fit_region(line_list, fit_function, region_file) where `region_file` is the path to the ds9 region file save in **fk5** coordinates. If you wish to activate the Bayesian MCMC implementation, simply add `bayes_bool=True` to any of the fit functions described above. Additionally, **binning** can be applied by adding the `binning` argument to any of the above fit functions. For example, we can bin 2x2 regions as such: .. code-block:: python vel_map, broad_map, flux_map, ampls_map = cube.fit_cube(['Halpha'], 'gaussian', 1300, 1400, 550, 650, binning=2) And with those few lines, we have read in our data cube, created a *deep image* and fit the cube. We can now visualize our fits with our specialized plotting functionality: .. code-block:: python lplt.plot_map(vel_map, 'velocity', cube_dir) The `LUCI.LuciPlotting.plot_map` function takes the map of interest, the name of the map (either 'velocity', 'broadening', or 'flux'), and the output directory as arguments. Of course, we can also use simply `matplotlib` plotting functionality as well. `LUCI` also has the abilitiy to restrict the wavelength region over which the fit is performed. So, for instance, if you only wish to fit Halpha and the NII-doublet, you can set restrict the wavelength to be between 15000 and 15250 cm^-1^ by adding two arguments to your fit function: `spec_min` and `spec_max`. Note that these values need to be in wavenumber. We have seen, in some cases of low signal-to-noise, that adding this restriction helps the fit algorithm. For clarity, we reproduce the commands required to obtain fits here: .. code-block:: python Luci_path = '/media/carterrhea/carterrhea/SIGNALS/LUCI/' # Path to Luci cube_dir = '/media/carterrhea/carterrhea/M33' # Path to data cube cube_name = 'M33_Field7_SN3.merged.cm1.1.0' # don't add .hdf5 extension object_name = 'M33_Field7' redshift = -0.0006 # Redshift of M33 resolution = 5000 cube = Luci(cube_dir+'/'+cube_name, cube_dir, object_name, redshift, ML_ref, ML_model) cube.create_deep_image() vel_map, broad_map, flux_map, ampls_map = cube.fit_cube(['Halpha', 'NII6548', 'NII6583', 'SII6716', 'SII6731'], 'gaussian', [1,1,1,1,1], [1,1,1,1,1], 500, 1100, 700, 1300)