In this notebook, you will learn the common core functionality across many of the Marvin Tools. This includes the basics of accessing and handling MaNGA data from different locations, as well as a beginners guide of interacting with data via the core tools of Cubes and Maps. Much of this information can be found in the Getting Started section of the Marvin documentation.
Marvin Tools provides the core functionality for accessing MaNGA data with Marvin. At the lowest level they are class wrappers around data products or elements (datacubes, maps, and spaxels). Their purpose is to provide a more natural way to interact with the data, unconstrained by specific data storage architectures such as files or databases, or by data location such as a laptop or remote server.
All Marvin Tools are built off a set of common core functionalities and features, and thus behave in very similar ways. There are four main classes provided in Marvin: the Cube
, the RSS
, the Maps
, and the ModelCube
.
We will start by focusing on a Marvin Cube to demonstrate the common features and handling of Marvin Tools. Everything discussed here also applies to any of the other available Marvin Tools listed above.
Let's start by importing the Marvin Cube class.
In [13]:
from marvin.tools import Cube
You may see the info message No release version set. Setting default to DR15
. The default data release Marvin uses is DR15. For this tutorial, we will be using DR15 data so there is no need to do anything further. In general, to change which release Marvin uses, we can use the Marvin config.setRelease
method on the config
object.
In [14]:
from marvin import config
# set the release to DR15
config.setRelease("DR15")
Let's instantiate our first cube, for galaxy with plate-IFU designation 8485-1901. Each marvin tool takes a string id input and can one of: a string filepath and name, a plate-IFU designation, or a manga-ID designation. Marvin will attempt to identify the input format and properly load the target data.
In [18]:
# instantiate a cube for 8485-1901
cube = Cube('8485-1901')
cube
Out[18]:
Once instantiated, each marvin tool indicates a mode and a data-origin. Note that mode="local"
and data_origin="file"
. This indicates that we have accessed a file from our local filesystem. Our cube now has a filename
attribute indicating its location on disk.
In [20]:
# print the local filename
cube.filename
Out[20]:
What if we won't have the MaNGa data products for our target of interest? We can specify the plateifu or mangaid of the target and Marvin will access it remotely. Let's open a cube for 8485-1902.
In [132]:
remote_cube = Cube('8485-1902')
remote_cube
Out[132]:
Now note that mode="remote"
and data_origin="api"
. This indicates the cube has been remotely loaded using the built-in Marvin API. By specifying an input plateifu or mangaid, marvin will always first try to access the data locally, and then fall back to remote access. You can also explicitly load a file using the filename
keyword argument.
In [23]:
# Explicitly load a cube from a file on disk
filename = '/Users/Brian/Work/sdss/sas/dr15/manga/spectro/redux/v2_4_3/8485/stack/manga-8485-1901-LOGCUBE.fits.gz'
cube = Cube(filename=filename)
cube
Out[23]:
In [42]:
print('Target Coordindates:', cube.ra, cube.dec)
print('Header:')
# access the PRIMARY header for the current object
cube.header
Out[42]:
In [43]:
# show the WCS for the current object
cube.wcs
Out[43]:
In [47]:
# look up the cube datmaodel
datamodel = cube.datamodel
datamodel
Out[47]:
The datamodel for a cube contains 3 datacube extensions and 2 spectral extensions. Let's look at them more closely.
In [62]:
# see what datacubes are available
print('Datacubes:')
datamodel.datacubes
Out[62]:
In [63]:
# see what additional spectral extensions are available
print('Spectra:')
datamodel.spectra
Out[63]:
This tells us that this cube has three associated 3D datacubes, flux
, dispersion
, and dispersion_prepixel
, and two associated spectra, spectral_resolution
and spectral_resolution_prepixel
, as well as their associated units. The description
attribute provides information on what the extension is.
In [64]:
print('Flux description:', datamodel.datacubes.flux.description)
print('Spectral Resolution description:', datamodel.spectra.spectral_resolution.description)
The names of each of the datacubes and spectral extensions are available as object attributes and can be used to access the associated data quantity. Let's access the flux
for our current cube.
In [66]:
flux = cube.flux
flux
Out[66]:
The flux is represented as a 3D array with units. We can also access the inverse variance and the mask using flux.ivar
and flux.mask
, respectively. Marvin uses Astropy quantities to represent all internal multidimensional data, e.g. 3-d datacube and 2-d map arrays, or 1-d spectral data.
All marvin arrays can be sliced to extract subsets of data. Slices of datacubes produce new datacubes. Slices of spectra produce new spectra. A single slice from a datacube extracts a spectrum. Each spectrum can be easily displayed with its plot
attribute.
In [81]:
# create a small datacube subset in a 10x10 pixel region around the center of the target
central_pixel = int(cube.flux.shape[1]/2)
lo = central_pixel - 5
hi = central_pixel + 5
subset = flux[:, lo:hi, lo:hi]
subset
Out[81]:
In [84]:
# extract a single spectrum and display it
spectrum = flux[:, 16, 17]
spectrum
Out[84]:
In [85]:
spectrum.plot(show_std=True)
Out[85]:
For a given target galaxy, there are many associated MaNGA Data Products from both the reduction and analysis pipelines. Marvin seamlessly connects these together so you don't have to access them individually. Let's access the DAP Maps objects associated with our cube. To do so we use the getMaps
method on cube
. All instances have getXXX
methods that allow you to access associated data objects for a given target.
In [87]:
# access the Maps object from our cube
maps = cube.getMaps()
maps
Out[87]:
When accessing associated objects, Marvin also smartly determines whether to open the file locally or remotely grab it over the API. In our case, the mode is local and data_origin is file. DAP Maps have different bintypes. The default binning is HYB10, a hybrid binning scheme to S/N~10. To load a different bintype, use the bintype
keyword argument in the cube.getMaps
method.
A Maps
behaves very similarly to a Cube
and everything we have discussed above will still work. Instead of datacubes and spectra, a Maps
object contains a set of 2D quantities called Map
, each one of them representing a different property measured by the DAP. One can get a full list of all the properties available using the datamodel.
In [88]:
# look at the datamodel for the maps
maps.datamodel
Out[88]:
Note that some properties such as spx_skycoo
have multiple channels (in this case the on-sky
x
and y
coordinates). To access the individual property, simply combine the property name and the channel name with an underscore, i.e. spx_skycoo_on_sky_x
. As before, we can get more information about a property using the description
attribute.
In [91]:
print('spx_skycoo_on_sky_x: ', maps.datamodel.spx_skycoo_on_sky_x.description)
More information about Marvin datamodels can be found here. See the DR15 Datamodel for a full description of the available datamodels for DR15.
We can retrieve the map associated to a specific property directly from the Maps instance. For example, let’s get the Hα emission line flux (fitted by a Gaussian). As Map
quantities are similar to DataCube
, we can easily plot the 2d map.
In [101]:
# grab the map of H-alpha emission line flux
ha = maps.emline_gflux_ha_6564
ha
Out[101]:
In [100]:
# plot the H-alpha map
fig, ax = ha.plot()
Note that the plot
method returns the matplotlib Figure
and Axes
for the plot. We can use those to modify or save the plot. Marvin plotting routines try to select the best parameters, colour maps, and dynamic ranges. You can modify those by passing extra arguments to plot. You can learn more in the Map plotting section. We will talk about the Map class in detail in Working with Astropy Quantities and in Map.
Remember that all associated objects are connected together. They can be accessed either from within an object instance or loaded independently from the class itself. From within an instance, the core tools, Maps
, RSS
, and ModelCube
are available using the getXXX
methods, as well as additional auxillary tools and object data, such as Image
.
In [145]:
# load the same Maps object by itself
from marvin.tools import Maps
my_maps = Maps('8485-1901')
my_maps
# get the stellar velocity map
stvel = my_maps.stellar_velocity
In [146]:
# load an auxilliary tool, the gri color image of the target galaxy using the Marvin Image tool
# get the Image of the galaxy and plot it
image = cube.getImage()
image.plot()
Out[146]:
In [114]:
# look at the overall cube quality flags
cube.quality_flag
Out[114]:
In this case the MANGA_DRP3QUAL maskbit does not have any bit activated, which means the data is safe to use. See the Maskbits section for more information on how to interact with Marvin Maskbits.
The targeting flags highlight the targeting bits set for this galaxy and tell you which sample the target belongs to.
In [115]:
# look at the targeting flags for this galaxy
cube.target_flags
Out[115]:
Note that in this case the galaxy belongs to the secondary sample from the final target selection (SECONDARY_v1_2_0
) as well as to the secondary samples from several commissioning target selections. The galaxy does not have any ancillary bit (manga_target3). An manga_target3 bit set indicates the target belongs to one of the MaNGA Ancillary programs.
For each target we can also access additional catalog data: the associated parameters from the NASA Sloan Atlas, and the DAPall file. The NSA catalog contains measured global galaxy photometric and shape profile information, while the DAPall catalog contains aggregrate statistics as measured by the MaNGA DAP pipeline. NSA properties are available on all Marvin objects under the nsa
attribute. DAPall properties are available on all Marvin Maps
and Modelcube
objects.
In [125]:
# look at the NSA properties for this galaxy from the cube instance
nsa = cube.nsa
nsa
Out[125]:
In [126]:
# look at the DAP all properties from the maps instance
maps.dapall
Out[126]:
SDSS members produce Value-Added Catalogs (VACS) of MaNGA products. These products can be incorporated into Marvin. Any incorporated VACS in Marvin are contained in the vacs
attribute attached to each tool. More information on VACs in Marvin can be found here. Currently the MaNGA-HI VAC for DR15 has been contributed into Marvin. Let's take a look at it.
In [147]:
# access the available VACs for this object
vacs = cube.vacs
vacs
Out[147]:
vacs is a container (list) of all names of the vacs contributed into Marvin. These names are dottable to access to vac data. These contributed custom products can be of any format chosen by the VAC owner, a Python class, a dictionary, an array, etc.
In [153]:
# access the mangahi vac
hi = vacs.mangahi
print(hi)
print('data type:', type(hi))
# access any HI data available for 8485-1901
hi.data
Out[153]:
While Marvin allows you to access data remotely, frequently you will find that you want to download the file associated to an object so that you can access it more quickly in the future. We can do that using the download
method attached to all marvin core tools. Let’s try to load a cube that we know we do not have in out hard drive, and download it.
In [133]:
# Check our remote cube we loaded earlier
remote_cube
Out[133]:
In [134]:
# download the remote cube
# remote_cube.download()
In [136]:
# loading the cube a second time loads it from the new file
new_cube = Cube('8485-1902')
new_cube
Out[136]:
Each tool contains a download
method to download that individual file. If you want to download a list of targets in bulk, you can use the downloadList
utility function. This function uses the built-in Python product sdss_access
to download files from the Utah SAS. downloadList
accepts as input a list of target ids, e.g. plateifus or mangaids. The dltype
keyword indicates the type of file you wish to download. The default file is cube
. Let's use the utility function to download a list of DAP MAPS files for three targets.
In [139]:
from marvin.utils.general import downloadList
# create a list of target ids
plateifus = ['8485-1901', '8485-1902', '7443-1901']
# download the DAP 2d MAPS files for these targets
# dllist = downloadList(plateifus, dltype='maps')
All of the core Marvin Galaxy Tools have the ability to extract one ore more Spaxel
objects. Spaxel
objects are special Marvin objects to make it easier to deal with individual spaxels in galaxies and access their properties. See the Getting Started with Spaxels for more information on how to interact with Spaxels
. We can either use the standard array slicing notation (0-indexed, origin of coordinates in the lower left corner of the array)
In [140]:
# extract the spaxel at array index x=10, y=15
spaxel = cube[15, 10]
spaxel
Out[140]:
or we can use getSpaxel
method, which accepts multiple arguments. Note that by default, (x, y) coordinates passed to getSpaxel
are measured from the center of the array.
In [142]:
# get the spaxel at the center of the target galaxy
central_spaxel = cube.getSpaxel(x=0, y=0)
central_spaxel
Out[142]:
In [144]:
# we can plot the spectrum of the spaxel
spaxel.flux.plot()
Out[144]:
In [ ]:
In [ ]: