├── pip-requirements.txt
├── tutorials
├── vo
│ ├── README.rst
│ └── conesearch_tutorial.ipynb
├── UVES
│ ├── CaII-1.png
│ ├── CaII-2.png
│ ├── CaII-3.png
│ ├── CaII.png
│ ├── CaII-lines-all.png
│ └── CaII-lines-one.png
├── FITS-header
│ ├── input_file.fits
│ └── FITS-header.ipynb
├── Plot-Catalog
│ ├── simple_table.csv
│ ├── Young-Objects-Compilation.csv
│ └── plot-catalog.ipynb
├── FITS-tables
│ └── FITS-tables.ipynb
├── FITS-images
│ └── FITS-images.ipynb
└── Quantities
│ └── Quantities.ipynb
├── html
├── images
│ └── astropy_word_32.png
└── css
│ ├── style.css
│ └── docs.css
├── .gitignore
├── README.md
├── DEPLOY.md
├── deploy
├── templates
├── index_template.html
├── astropy.tpl
└── matplotlibrc
├── CONTRIBUTING.md
└── prepare_deploy.py
/pip-requirements.txt:
--------------------------------------------------------------------------------
1 | IPython>=2.0
2 | astropy>=0.3
3 |
--------------------------------------------------------------------------------
/tutorials/vo/README.rst:
--------------------------------------------------------------------------------
1 | This directory contains tutorials related to `astropy.vo` package.
2 |
--------------------------------------------------------------------------------
/tutorials/UVES/CaII-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII-1.png
--------------------------------------------------------------------------------
/tutorials/UVES/CaII-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII-2.png
--------------------------------------------------------------------------------
/tutorials/UVES/CaII-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII-3.png
--------------------------------------------------------------------------------
/tutorials/UVES/CaII.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII.png
--------------------------------------------------------------------------------
/html/images/astropy_word_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/html/images/astropy_word_32.png
--------------------------------------------------------------------------------
/tutorials/UVES/CaII-lines-all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII-lines-all.png
--------------------------------------------------------------------------------
/tutorials/UVES/CaII-lines-one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/UVES/CaII-lines-one.png
--------------------------------------------------------------------------------
/tutorials/FITS-header/input_file.fits:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwcraig/astropy-tutorials/master/tutorials/FITS-header/input_file.fits
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ipynb_checkpoints/
2 | html/
3 | runipy-*
4 | IPython-*
5 | tutorials/*/_run_*
6 | tutorials/*/*.fits
7 | tutorials/*/*.pdf
8 | tutorials/*/*.png
--------------------------------------------------------------------------------
/tutorials/Plot-Catalog/simple_table.csv:
--------------------------------------------------------------------------------
1 | # name,ra,dec
2 | BLG100,17:51:00.0,-29:59:48
3 | BLG101,17:53:40.2,-29:49:52
4 | BLG102,17:56:20.2,-29:30:51
5 | BLG103,17:56:20.2,-30:06:22
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Tutorials
2 | =========
3 |
4 | This repository contains tutorials for the [Astropy](http://astropy.org)
5 | project (also on [github](https://github.com/astropy/astropy)).
6 |
7 | Running Tutorials
8 | -----------------
9 |
10 | To run the tutorials, you need ipython installed. If you have IPython 2.0, you
11 | can just start the notebook server in this directory:
12 |
13 | ipython notebook --matplotlib=inline
14 |
15 | But if you have an older version, you first need to `cd` into the appropriate
16 | subdirectory before starting that command.
17 |
18 | The tutorials are initially empty of any output. You can run them by pressing
19 | "Run All" under the "Cell" menu in the ipython notebook.
20 |
21 | Dependencies
22 | ------------
23 |
24 | To deploy the notebooks, you will need:
25 |
26 | * IPython
27 | * Astropy
28 | * runipy
29 | * pandoc
30 |
31 | _Note, all except pandoc can be pip installed. To install pandoc, follow the instructions here: http://johnmacfarlane.net/pandoc/installing.html_.
32 |
--------------------------------------------------------------------------------
/DEPLOY.md:
--------------------------------------------------------------------------------
1 | Deploying
2 | =========
3 |
4 | All notebooks in this repository aren't necessarily live. They have to be 'published' in order to appear on the main astropy tutorials web page. To mark a tutorial as published, you must edit the notebook metadata set the published key to `true`. For example, if I wanted to publish the Quantities tutorial, I would edit the notebook metadata for `tutorials/Quantities/Quantities.ipynb` to include a line `"published": true`.
5 |
6 | Once a tutorial is marked as published, the automated deploy script will find the corresponding notebook file, convert it to HTML, and include it in a push to the gh-pages branch of the repository. Only repository admins can deploy because it requires direct commit rights to the main `astropy-tutorials` repository.
7 |
8 | To actually deploy the tutorials, just run the deploy script:
9 |
10 | ./deploy
11 |
12 | and follow the prompts. By default, the script takes the tutorials in the master branch, runs them, converts them to HTML, and pushes to the `gh-pages` branch. __If you have any uncomitted changes in your master branch the deploy script will wipe them!__
13 |
14 | Test deploy
15 | -----------
16 |
17 | If you'd instead like to test running and converting the notebooks, use the `prepare_deploy.py`script. You can run the notebook files with:
18 |
19 | python prepare_deploy.py run
20 |
21 | and convert them with:
22 |
23 | python prepare_deploy.py convert
24 |
25 | or combine the commands:
26 |
27 | python prepare_deploy.py run convert
28 |
29 | The converted html files will appear in the `html` path.
--------------------------------------------------------------------------------
/deploy:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | GH_PAGESBRANCH=gh-pages
4 | GH_REMOTE=origin
5 |
6 | # get current git branch name - should throw an error if in a detached state
7 | current_branch_name="$(git symbolic-ref --short HEAD)"
8 |
9 | echo "*****************************************************************"
10 | echo "WARNING! This script will remove the local gh-pages branch,"
11 | echo "build the notebook files into HTML, then push to remote gh-pages"
12 | echo "located here: $GH_REMOTE/gh-pages."
13 | echo
14 | echo "Make sure you have no uncommitted changes in your current branch"
15 | echo "as these may be overwritten!"
16 | echo
17 | read -p "Are you sure you want to do this? [y/N] " -n 1 -r
18 | echo
19 | if [[ $REPLY =~ ^[Yy]$ ]]
20 | then
21 | # first run the notebooks
22 | OUTPUT=`python prepare_deploy.py run`
23 | if [[ $OUTPUT == *ERROR* ]]
24 | then
25 | echo "Error running notebook files!";
26 | exit;
27 | fi
28 |
29 | # then convert the notebooks to HTML
30 | OUTPUT=`python prepare_deploy.py convert`
31 | if [[ $OUTPUT == *ERROR* ]]
32 | then
33 | echo "Error converting notebook files to HTML!";
34 | exit;
35 | fi
36 |
37 | # remove the old $GH_PAGESBRANCH branch
38 | OUTPUT=`git branch -D $GH_PAGESBRANCH`
39 | if [[ $OUTPUT == *fatal* ]]
40 | then
41 | echo "Error deleting branch '$GH_PAGESBRANCH'.";
42 | exit;
43 | fi
44 |
45 | # Create a new "orphaned" branch -- we don't need history for
46 | # the built products
47 | git checkout --orphan $GH_PAGESBRANCH
48 |
49 | # Copy the built files to a tmp location
50 | cp -R html _tmp
51 |
52 | # This will delete all of the git-managed files here
53 | git rm -rf .
54 |
55 | # Now copy the html back into here
56 | cp -R _tmp/* .
57 | rm -rf _tmp
58 |
59 | git add *.html
60 | git add images
61 | git add css
62 | git commit -m "Generated from sources"
63 |
64 | read -p "Would you like to preview the rendered HTML? [y/N] " -n 1 -r
65 | if [[ $REPLY =~ ^[Yy]$ ]]; then
66 | echo "\n\n"
67 | open index.html
68 | else
69 | echo "\n"
70 | fi
71 |
72 | read -p "Are you sure you want to push to the remote branch '$GH_PAGESBRANCH'? [y/N] " -n 1 -r
73 | if [[ $REPLY =~ ^[Yy]$ ]]; then
74 | echo "\n"
75 | echo "Pushing to $GH_PAGESBRANCH"
76 | git push -f $GH_REMOTE $GH_PAGESBRANCH
77 |
78 | git checkout -f $current_branch_name
79 | git clean -f
80 | git branch -D $GH_PAGESBRANCH
81 | else
82 | echo "\n"
83 | echo "You're now in an orphaned test deploy branch."
84 | echo "To get back to normal you can run the following:"
85 | echo " git checkout -f $current_branch_name"
86 | echo " git clean -f"
87 | echo " git branch -D $GH_PAGESBRANCH"
88 | fi
89 | fi
90 |
--------------------------------------------------------------------------------
/templates/index_template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Astropy Tutorials
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 | Astropy Tutorials
33 | The tutorials on this site walk through some typical software tasks and demonstrate the features in Astropy sub-packages in the context of a story or standard workflow. See the Astropy documentation for a structured view of the functionality within the Astropy project.
34 |
35 |
36 |
37 |
38 |
39 | List of Tutorials
40 |
43 |
44 |
45 |
46 |
47 |
48 | Contributing
49 |
50 | We welcome feedback and improvements to these tutorials via the Astropy Tutorials repo on Github . If you find a typo or would like to clarify some text, please either create an issue or make the change yourself and then submit a pull request directly to the repository . Questions and/or comments about the tutorials are welcome on the astropy-dev mailing list.
51 |
52 | If you are interested in contributing an ipython notebook as a tutorial, please check the README or contact the developer list . Also, if you have an idea for a tutorial or a tutorial request, please post to the developer list . If you would like to contribute to this effort, but need some inspiration, check out the open issues . This is a collaborative effort and we are looking for contributions and ideas from users like you!
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/templates/astropy.tpl:
--------------------------------------------------------------------------------
1 | {%- extends 'full.tpl' -%}
2 |
3 | {% block header %}
4 |
5 |
6 | {title}
7 |
8 | {{ super() }}
9 |
10 |
11 |
12 |
13 |
14 | {%- endblock header %}
15 |
16 | {% block body %}
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Author: {author}
34 | Edit on Github
35 | Date Created: {date}
36 |
37 |
38 |
39 | {{ super() }}
40 |
41 |
42 |
43 |
44 |
45 |
63 |
Please enable JavaScript to view the comments powered by Disqus.
64 |
65 |
66 |
67 |
68 |
70 |
86 |
87 | {%- endblock body %}
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing
2 | ============
3 |
4 | Overview
5 | --------
6 |
7 | Each tutorial is essentially an [IPython notebook](http://ipython.org/notebook.html)
8 | file. The notebooks are each saved in a separate directory within the `tutorials`
9 | subdirectory in this project. Let's look in [FITS-Header]
10 | (https://github.com/astropy/astropy-tutorials/tree/master/tutorials/FITS-Header)
11 | as an example. There is a single IPython notebook file that contains the text
12 | and code for the tutorial, and a FITS file used in the tutorial. The notebook
13 | file is automatically run and converted into a static HTML page ([example]
14 | (http://tutorials.astropy.org/FITS-header.html)), which is then displayed in
15 | the tutorial listing on http://tutorials.astropy.org. Each tutorial notebook
16 | file also contains metadata about the tutorial such as the author's name, month
17 | and year it was written, and any other information that should be associated
18 | with the tutorial.
19 |
20 | Procedure
21 | ---------
22 |
23 | If you are unfamiliar with git, you should first get familiar with git and
24 | github. There are a number of resources available for learning git, but a good
25 | place to start is with the [github interactive tutorial](http://try.github.io/).
26 | You should also get familiar with using pull requests and forks on github:
27 | https://help.github.com/articles/using-pull-requests
28 |
29 | To create and contribute a new tutorial, you will first need to fork the
30 | astropy-tutorials repository on github and clone this fork locally to your
31 | machine (replace with your github username)::
32 |
33 | git clone git@github.com:/astropy-tutorials.git
34 |
35 | Next, create a branch in your local repository with the name of the tutorial
36 | you'd like to contribute. Let's imagine we're adding a tutorial to demonstrate
37 | spectral line fitting -- we might call it `Spectral-Line-Fitting`:
38 |
39 | git checkout -b Spectral-Line-Fitting
40 |
41 | Next we'll create a new directory in `tutorials/` with the same name as the
42 | branch:
43 |
44 | mkdir tutorials/Spectral-Line-Fitting
45 |
46 | All files used by the tutorial -- e.g., example data files, the IPython
47 | notebook file itself -- should go in this directory. Now you can start writing
48 | the tutorial! Simply change directories into this new path and start up an
49 | IPython notebook server:
50 |
51 | cd tutorials/Spectral-Line-Fitting
52 | ipython notebook --matplotlib inline
53 |
54 | Create a new notebook file, and write away! Remember to place any extra files
55 | used by the tutorial in the directory with the notebook file, and place them
56 | under git version control.
57 |
58 | You will also need to edit the notebook file metadata. The metadata contains
59 | any extra information about the tutorial you may want to add. The metadata
60 | must contain, at minimum, the following fields:
61 |
62 | - link_name (the name of the link which will appear in the list of tutorials)
63 | - author
64 | - date (month year, e.g. 'July 2013')
65 |
66 | An example of one of these files can be found [here]
67 | (https://github.com/adrn/astropy-tutorials/blob/master/tutorials/FITS-Header/FITS-header.ipynb).
68 |
69 | When you feel like your tutorial is complete, push your local branch up to your
70 | fork of the repository on github (by default, named 'origin'):
71 |
72 | git push origin Spectral-Line-Fitting
73 |
74 | Then you will file a pull request against the main `astropy-tutorials`
75 | repository for review.
76 |
77 |
78 | Data Files
79 | ----------
80 |
81 | ### For tutorial authors
82 |
83 | If your tutorial includes large data files (where large means >~ 1 MB), we
84 | don't want them in the astropy/astropy-tutorials git repository, as that will
85 | drastically slow down cloning the repository. Instead, we encourage use of the
86 | `astropy.utils.download_files` function, and will host data files on the
87 | http://data.astropy.org server. To make this easy, use the following procedure
88 | when you have large data files.
89 |
90 | * When writing your tutorial, just include the files in your tutorial's
91 | directory (e.g., ``tutorials/My-tutorial-name/mydatafile.fits``). Those who
92 | are reviewing your tutorial will have to download them, but they would need
93 | them anyway, so it's ok. _IMPORTANT_: when you add or modify data files, make
94 | sure the only thing in that commit involves the data files. That is, do
95 | _not_ edit your notebook and add/change data files in the same commit. This
96 | will make it much easier to remove the data files when your tutorial is
97 | actually merged.
98 |
99 | * To actually access your data files in the notebook, do something like this at
100 | the top of the notebook:
101 |
102 | from astropy.utils.data import download_file
103 |
104 | tutorialpath = ''
105 | mydatafilename1 = download_file(tutorialpath + 'mydatafile1.fits', cache=True)
106 | mydatafilename2 = download_file(tutorialpath + 'mydatafile2.dat', cache=True)
107 |
108 | And then use them like this:
109 |
110 | fits.open(mydatafilename1)
111 | ...
112 | with open(mydatafilename2) as f:
113 | ...
114 |
115 | If you do this, the only change necessary on merging your notebook will be to
116 | set `tutorialpath` to
117 | ``'http://data.astropy.org/tutorials/My-tutorial-name/'``.
118 |
119 |
120 | ### For repository maintainers
121 |
122 | If this above procedure is followed, you only need to do these steps when merging your pull request:
123 |
124 | 1. Do ``git rebase -i`` and delete the commits that include the data files
125 | 2. Upload the data files to http://data.astropy.org/tutorials/My-tutorial-name/
126 | 3. Update the `tutorialpath` variable.
127 |
--------------------------------------------------------------------------------
/html/css/style.css:
--------------------------------------------------------------------------------
1 | /* Ripped from the main astropy website with some modifications*/
2 | /* http://meyerweb.com/eric/tools/css/reset/
3 | v2.0 | 20110126
4 | License: none (public domain)
5 | */
6 |
7 | /* HTML5 display-role reset for older browsers */
8 | article, aside, details, figcaption, figure,
9 | footer, header, hgroup, menu, nav, section {
10 | display: block;
11 | }
12 | body {
13 | line-height: 1;
14 | }
15 | ol, ul {
16 | list-style: none;
17 | }
18 | blockquote, q {
19 | quotes: none;
20 | }
21 | blockquote:before, blockquote:after,
22 | q:before, q:after {
23 | content: '';
24 | content: none;
25 | }
26 | table {
27 | border-collapse: collapse;
28 | border-spacing: 0;
29 | }
30 |
31 | body{
32 | line-height: 1.25em;
33 | font-size: 16px;
34 | color:#333;
35 | font-family: 'Open Sans', sans-serif;
36 | }
37 |
38 | #wrapper{
39 | margin:0 auto;
40 | max-width:960px;
41 | padding:0 10px;
42 | min-width: 320px; /* min-width of whole site */
43 | }
44 |
45 | a{
46 | color: #FF5000;
47 | text-decoration: none;
48 | }
49 | a, svg{
50 | -webkit-transition: all 0.3s ease;
51 | -moz-transition: all 0.3s ease;
52 | -o-transition: all 0.3s ease;
53 | -ms-transition: all 0.3s ease;
54 | transition: all 0.3s ease;
55 | }
56 |
57 | a:hover{
58 | color:#333;
59 | }
60 |
61 | h1{
62 | font-size: 28px;
63 | font-weight: bold;
64 | margin-top: 10px;
65 | margin-bottom: 20px;
66 | }
67 |
68 | h2{
69 | font-size: 24px;
70 | margin-bottom: 10px;
71 | }
72 |
73 | h3{
74 | font-size: 20px;
75 | margin: 20px 0px 10px 0px;
76 |
77 | }
78 |
79 | p{
80 | margin-bottom: 10px;
81 | margin-top: 10px;
82 | line-height: 1.5em;
83 | }
84 |
85 | strong{
86 | font-weight: bold;
87 |
88 | }
89 |
90 | section{
91 | border-bottom: 1px #efefef solid;
92 | padding: 20px 0 20px;
93 | clear: both;
94 | }
95 |
96 | section:first-of-type{
97 | margin-top:42px;
98 | }
99 |
100 | section:last-of-type{
101 | border-bottom: 0px;
102 | }
103 |
104 | section *:last-child{
105 | margin-bottom: 0px;
106 | }
107 |
108 | ul li{
109 | list-style-type: square;
110 | list-style-position: outside;
111 | list-style-color: #FF5000;
112 | line-height: 1.5em;
113 | margin-bottom:0.5em;
114 | margin-left: 30px;
115 | }
116 |
117 | ul li:last-child{
118 | margin-bottom: 0px;
119 | }
120 |
121 | cite{
122 | font-family: monospace;
123 | }
124 |
125 | pre{
126 | background-color: #f5f5f5;
127 | border: 1px solid #ddd;
128 | padding: 10px;
129 | color: black;
130 | font-family: Monaco, Andale Mono, Courier New, monospace;
131 | webkit-border-radius: 3px;
132 | -moz-border-radius: 3px;
133 | border-radius: 3px;
134 | margin-bottom: 5px;
135 | }
136 |
137 | .button{
138 | padding: 8px;
139 | display: inline-block;
140 | background-image: -webkit-gradient(
141 | linear,
142 | left top,
143 | left bottom,
144 | color-stop(0, #FC9468),
145 | color-stop(0.89, #FF5100)
146 | );
147 | background-image: -o-linear-gradient(bottom, #FC9468 0%, #FF5100 89%);
148 | background-image: -moz-linear-gradient(bottom, #FC9468 0%, #FF5100 89%);
149 | background-image: -webkit-linear-gradient(bottom, #FC9468 0%, #FF5100 89%);
150 | background-image: -ms-linear-gradient(bottom, #FC9468 0%, #FF5100 89%);
151 | background-image: linear-gradient(to bottom, #FC9468 0%, #FF5100 89%);
152 | }
153 |
154 | a.button, .button a{
155 | color: white;
156 | }
157 |
158 |
159 | p .button{
160 | padding-top:0px;
161 | padding-bottom:0px;
162 | padding-right:4px;
163 | padding-left:4px;
164 | }
165 |
166 | .button:hover{
167 | cursor: pointer;
168 | background-image: -webkit-gradient(
169 | linear,
170 | left top,
171 | left bottom,
172 | color-stop(0, #FFA47D),
173 | color-stop(1, #FF7D45)
174 | );
175 | background-image: -o-linear-gradient(bottom, #FFA47D 0%, #FF7D45 100%);
176 | background-image: -moz-linear-gradient(bottom, #FFA47D 0%, #FF7D45 100%);
177 | background-image: -webkit-linear-gradient(bottom, #FFA47D 0%, #FF7D45 100%);
178 | background-image: -ms-linear-gradient(bottom, #FFA47D 0%, #FF7D45 100%);
179 | background-image: linear-gradient(to bottom, #FFA47D 0%, #FF7D45 100%);
180 | }
181 |
182 |
183 | .right{
184 | float: right;
185 | }
186 |
187 | /* nav */
188 | nav{
189 | line-height: 42px;
190 | position:absolute;
191 | left:0px;
192 | top:0px;
193 | width:100%;
194 | background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #222222),color-stop(0.89, #333333));
195 | background-image: -o-linear-gradient(bottom, #222222 0%, #333333 89%);
196 | background-image: -moz-linear-gradient(bottom, #222222 0%, #333333 89%);
197 | background-image: -webkit-linear-gradient(bottom, #222222 0%, #333333 89%);
198 | background-image: -ms-linear-gradient(bottom, #222222 0%, #333333 89%);
199 | background-image: linear-gradient(to bottom, #222222 0%, #333333 89%);
200 | }
201 |
202 | nav > *{
203 | display:inline-block;
204 | vertical-align:top;
205 | }
206 |
207 | nav img{
208 | float: left;
209 | margin-left: 20px;
210 | margin-top: 5px;
211 | }
212 |
213 | nav ul{
214 | max-width:960px;
215 | margin: 0;
216 | padding: 0;
217 | }
218 |
219 | nav ul li{
220 | display:inline;
221 | list-style: none;
222 | display: block;
223 | margin: 0;
224 | }
225 |
226 | nav li a, nav li a:link{
227 | color:#fff;
228 | font-size: 22px;
229 | font-weight: 300;
230 | }
231 | nav li a:hover{
232 | color:#FF5000;
233 | }
234 |
235 | nav li a.active{
236 | color:#FF5000;
237 | }
238 |
239 | nav .pull-right{
240 | float: right;
241 | margin-right:10px;
242 | }
243 |
244 |
245 | /*
246 | IPython overrides
247 | */
248 |
249 | /* Tweaks to make a bit more responsive in conjuction with astropy scheme */
250 |
251 | @media (max-width: 355px) {
252 |
253 | #wrapper {
254 | padding-left: 0px;
255 | padding-right: 0px;
256 | }
257 |
258 | body {
259 | padding-left: 0px;
260 | padding-right: 0px;
261 | }
262 |
263 | .text_cell_render {
264 | padding-left: 0px;
265 | padding-right: 0px;
266 | }
267 |
268 | }
269 |
270 | .container {
271 | max-width: 900px;
272 | font-size: 12pt;
273 | }
274 |
275 | .tutorials li {
276 | padding-top: 10px;
277 | padding-bottom: 10px;
278 | margin-bottom: 0;
279 | }
280 |
281 |
282 | /*
283 | Notebook styling
284 | */
285 |
286 | #notebook p {
287 | font-size: 16px;
288 | line-height: 20px;
289 | }
290 |
291 | #notebook code, pre{
292 | padding:0 3px 2px;
293 | font-family: monospace;
294 | word-wrap: break-word;
295 | }
296 |
297 | #notebook pre {
298 | font-size:14px;
299 | line-height: 17px;
300 | }
301 |
--------------------------------------------------------------------------------
/tutorials/FITS-header/FITS-header.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "astropy-tutorials": {
4 | "author": "Adrian M. Price-Whelan ",
5 | "date": "July 2013",
6 | "description": "Demonstrates how to read in, edit a FITS header, and then write it back out to disk using astropy.io.fits.",
7 | "link_name": "Editing a FITS header",
8 | "name": "",
9 | "published": true
10 | },
11 | "signature": "sha256:cf2d708df4d0fc7ef4323fb110d8ea45860df205fa6ce40acbebecf1819821eb"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "heading",
20 | "level": 1,
21 | "metadata": {},
22 | "source": [
23 | "Edit a FITS header"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "This tutorial describes how to read in, edit a FITS header, and then write \n",
31 | "it back out to disk. For this example we're going to change the `OBJECT` \n",
32 | "keyword.\n",
33 | "\n",
34 | "This tutorial uses [astropy.io.fits](http://docs.astropy.org/en/latest/io/fits/index.html), \n",
35 | "which was formerly released separately as `pyfits`. If you have used \n",
36 | "`pyfits` to manipulate FITS files then you may already be familiar \n",
37 | "with the features and syntax of the package. We start by importing\n",
38 | "the subpackage into our local namespace, and allows us to access the\n",
39 | "functions and classes as `fits.name_of_function()`. For example, \n",
40 | "to access the `getdata()` function, we _don't_ have to do \n",
41 | "`astropy.io.fits.getdata()` and can instead simple use `fits.getdata()`.\n",
42 | "You may run across old documentation or tutorials that use the name \n",
43 | "`pyfits`. Such examples will begin with `import pyfits` and then \n",
44 | "the command `fits.getdata()` (for example) would be written as \n",
45 | "`pyfits.getdata()`."
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "collapsed": false,
51 | "input": [
52 | "from astropy.io import fits"
53 | ],
54 | "language": "python",
55 | "metadata": {},
56 | "outputs": []
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "metadata": {},
61 | "source": [
62 | "``astropy.io.fits`` provides a lot of flexibility for reading FITS \n",
63 | "files and headers, but most of the time the convenience functions are\n",
64 | "the easiest way to access the data. ``fits.getdata()`` reads just the \n",
65 | "data from a FITS file, but with the `header=True` keyword argument will\n",
66 | "also read the header. "
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "collapsed": false,
72 | "input": [
73 | "data, header = fits.getdata(\"input_file.fits\", header=True)"
74 | ],
75 | "language": "python",
76 | "metadata": {},
77 | "outputs": []
78 | },
79 | {
80 | "cell_type": "markdown",
81 | "metadata": {},
82 | "source": [
83 | "There is also a dedicated function for reading just the \n",
84 | "header:"
85 | ]
86 | },
87 | {
88 | "cell_type": "code",
89 | "collapsed": false,
90 | "input": [
91 | "hdu_number = 0\n",
92 | "fits.getheader('input_file.fits', hdu_number)"
93 | ],
94 | "language": "python",
95 | "metadata": {},
96 | "outputs": []
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "but `getdata()` can get both the data and the header, so it is a useful \n",
103 | "command to remember. Since the primary HDU of a FITS file must contain image data, \n",
104 | "the data is now stored in a ``numpy`` array. The header is stored in an \n",
105 | "object that acts like a standard Python dictionary. "
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "collapsed": false,
111 | "input": [
112 | "print(type(data))\n",
113 | "print(header[\"NAXIS\"])"
114 | ],
115 | "language": "python",
116 | "metadata": {},
117 | "outputs": []
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "Now let's change the header to give it the correct object:"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "collapsed": false,
129 | "input": [
130 | "header['OBJECT'] = \"M31\""
131 | ],
132 | "language": "python",
133 | "metadata": {},
134 | "outputs": []
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {},
139 | "source": [
140 | "Finally, we have to write out the FITS file. Again, the convenience \n",
141 | "function for this is the most useful command to remember:"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "collapsed": false,
147 | "input": [
148 | "fits.writeto('output_file.fits', data, header, clobber=True)"
149 | ],
150 | "language": "python",
151 | "metadata": {},
152 | "outputs": []
153 | },
154 | {
155 | "cell_type": "markdown",
156 | "metadata": {},
157 | "source": [
158 | "That's it; you're done!"
159 | ]
160 | },
161 | {
162 | "cell_type": "markdown",
163 | "metadata": {},
164 | "source": [
165 | "Two common more complicated cases are worth mentioning (but if your needs \n",
166 | "are much more complex, you should consult the full documentation). \n",
167 | "\n",
168 | "The first complication is that the FITS file you're examining and \n",
169 | "editing might have multiple HDU's (extensions), in which case you can \n",
170 | "specify the extension like this:"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "collapsed": false,
176 | "input": [
177 | "data,header = fits.getdata(\"input_file.fits\", ext=1, header=True)"
178 | ],
179 | "language": "python",
180 | "metadata": {},
181 | "outputs": []
182 | },
183 | {
184 | "cell_type": "markdown",
185 | "metadata": {},
186 | "source": [
187 | "This will get you the data and header associated with the index=1 extension \n",
188 | "in the FITS file. Without specifying a number, getdata() will get the \n",
189 | "0th extension (equivalent to saying `ext=0`)."
190 | ]
191 | },
192 | {
193 | "cell_type": "markdown",
194 | "metadata": {},
195 | "source": [
196 | "Another useful tip is if you want to overwrite an existing FITS \n",
197 | "file. By default, writeto() won't let you do this, so you need to \n",
198 | "explicitly give it permission using the `clobber` keyword argument:"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "collapsed": false,
204 | "input": [
205 | "fits.writeto('output_file.fits', data, header, clobber=True)"
206 | ],
207 | "language": "python",
208 | "metadata": {},
209 | "outputs": []
210 | },
211 | {
212 | "cell_type": "heading",
213 | "level": 2,
214 | "metadata": {},
215 | "source": [
216 | "Exercise"
217 | ]
218 | },
219 | {
220 | "cell_type": "markdown",
221 | "metadata": {},
222 | "source": [
223 | "Read in the file you just wrote, and add three header keywords:\n",
224 | "\n",
225 | "1. 'RA' for the Right Ascension of M31\n",
226 | "2. 'DEC' for the Declination of M31\n",
227 | "3. 'RADECSRC' with text indicating where you found the RA/Dec (web URL, textbook name, your photographic memory, etc.).\n",
228 | "\n",
229 | "then write the updated header back out to a new file. "
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "collapsed": false,
235 | "input": [],
236 | "language": "python",
237 | "metadata": {},
238 | "outputs": []
239 | }
240 | ],
241 | "metadata": {}
242 | }
243 | ]
244 | }
--------------------------------------------------------------------------------
/prepare_deploy.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding: utf-8
3 |
4 | """ Build all notebook files into HTML pages. """
5 |
6 | from __future__ import division, print_function
7 |
8 | # Standard library
9 | import os
10 | import re
11 | import sys
12 | import shutil
13 |
14 | # protect for 2.* vs. 3.*
15 | try:
16 | import configparser
17 | cp = configparser
18 | except ImportError:
19 | import ConfigParser
20 | cp = ConfigParser
21 |
22 | from astropy import log as logger
23 | from IPython.nbformat.current import read, write
24 |
25 | # A template for the index page
26 | with open("templates/index_template.html") as f:
27 | INDEX_TEMPLATE = f.read()
28 |
29 | def walk_through_tutorials(only_published=True, selected_nb_re=None):
30 | """ Generator for walking through the tutorials directory structure.
31 | This returns tuples of (full_tutorial_path, tutorial_name) for
32 | each tutorial. If published is set to True, this will only return
33 | the published tutorials.
34 | """
35 | nbre = re.compile(selected_nb_re) if selected_nb_re else None
36 |
37 | current_directory = os.getcwd()
38 | tutorials_base = os.path.join(current_directory,'tutorials')
39 |
40 | if not os.path.exists(tutorials_base):
41 | err = ("Can't find 'tutorials' path! You must run this script from the"
42 | " top-level astropy-tutorials directory.")
43 | raise IOError(err)
44 |
45 | # walk through each directory in tutorials/ to find all .ipynb file
46 | for tutorial_name in os.listdir(tutorials_base):
47 | tutorial_path = os.path.join(tutorials_base, tutorial_name)
48 | if not os.path.isdir(tutorial_path):
49 | # skip files / things that are not directories
50 | continue
51 |
52 | for filename in os.listdir(tutorial_path):
53 | base,ext = os.path.splitext(filename)
54 |
55 | if ext.lower() == ".ipynb" and "checkpoint" not in base:
56 | full_filename = os.path.join(tutorial_path, filename)
57 | notebook = read(open(full_filename), 'json')
58 | is_published = notebook['metadata']['astropy-tutorials'].get('published', False)
59 | if not is_published and only_published:
60 | continue
61 |
62 | if nbre and nbre.match(base) is None:
63 | continue
64 |
65 | yield full_filename,notebook
66 |
67 | def run_notebooks(selected_nb_re=None):
68 | """ Run the tutorial notebooks. """
69 | from runipy.notebook_runner import NotebookRunner
70 |
71 | _orig_path = os.getcwd()
72 |
73 | # walk through each directory in tutorials/ to find all .ipynb file
74 | for tutorial_filename,nb in walk_through_tutorials(only_published=True,
75 | selected_nb_re=selected_nb_re):
76 | path,filename = os.path.split(tutorial_filename)
77 |
78 | if filename.startswith("_run_"):
79 | continue
80 |
81 | logger.info("Running tutorial: {}".format(filename))
82 |
83 | # notebook file
84 | output_filename = os.path.join(path,"_run_{}"
85 | .format(filename))
86 |
87 | # prepend _run_ to the notebook names to create new files
88 | # so the user isn't left with a bunch of modified files.
89 | os.chdir(path)
90 | r = NotebookRunner(nb, mpl_inline=True)
91 | r.run_notebook(skip_exceptions=True)
92 | write(r.nb, open(output_filename, 'w'), 'json')
93 |
94 | os.chdir(_orig_path)
95 |
96 | def convert_notebooks(selected_nb_re=None):
97 | """ Convert the tutorials (IPython notebook files) located in tutorials/*
98 | into static HTML pages.
99 | """
100 | from IPython.nbconvert.nbconvertapp import NbConvertApp
101 |
102 | current_directory = os.getcwd()
103 | html_base = os.path.join(current_directory,"html")
104 | if not os.path.exists(html_base):
105 | os.mkdir(html_base)
106 | template_path = os.path.join(current_directory, 'templates')
107 |
108 | app = NbConvertApp()
109 | app.initialize(argv=[]) # hack
110 | app.export_format = 'html'
111 | app.config.Exporter.template_path = ['templates', template_path]
112 | app.config.Exporter.template_file = 'astropy'
113 |
114 | # walk through each directory in tutorials/ to find all .ipynb file
115 | index_list = []
116 | re_str = ('_run_' + selected_nb_re) if selected_nb_re else None
117 | for tutorial_filename,nb in walk_through_tutorials(only_published=True,
118 | selected_nb_re=re_str):
119 | path,filename = os.path.split(tutorial_filename)
120 | if not filename.startswith("_run_"):
121 | continue
122 |
123 | # remove _run_ from base filename
124 | base = os.path.splitext(filename)[0]
125 | cleanbase = base.lstrip("_run_")
126 |
127 | app.output_base = os.path.join(html_base,cleanbase)
128 | app.notebooks = [os.path.join(path,filename)]
129 | app.start()
130 |
131 | # HACK to set title and other things in rendered notebook
132 | html_filename = "{}.html".format(os.path.join(html_base,cleanbase))
133 | with open(html_filename, 'rb') as f:
134 | html_file_data = f.read()
135 |
136 | with open(html_filename, 'wb') as f:
137 | html_file_data = html_file_data.decode("utf-8")
138 | html_file_data = html_file_data.replace("{title}",nb['metadata']['astropy-tutorials']['link_name'])
139 | html_file_data = html_file_data.replace("{author}",nb['metadata']['astropy-tutorials']['author'])
140 | html_file_data = html_file_data.replace("{date}",nb['metadata']['astropy-tutorials']['date'])
141 | html_file_data = html_file_data.replace("{abspageurl}","{}".format(cleanbase))
142 | html_file_data = html_file_data.replace("{pageurl}","{}.html".format(cleanbase))
143 | f.write(html_file_data.encode("utf8"))
144 |
145 | index_listing = dict()
146 | index_listing["link_path"] = "{}.html".format(cleanbase)
147 | index_listing["link_name"] = nb['metadata']['astropy-tutorials']['link_name']
148 | index_listing["description"] = nb['metadata']['astropy-tutorials']['description']
149 | index_list.append(index_listing)
150 |
151 | # Make an index of all notes
152 | entries = []
153 | for page in sorted(index_list, key=lambda x: x['link_name']): # sort on tutorial name
154 | entry_html = ""
155 | entry_html += "{0[link_name]} ".format(page)
156 | entry_html += "{0[description]} ".format(page)
157 | entry_html += " "
158 | entries.append(entry_html)
159 |
160 | with open(os.path.join(current_directory,'html','index.html'), 'w') as f:
161 | f.write(INDEX_TEMPLATE.format(entries='\n'.join(entries)))
162 |
163 |
164 | if __name__ == "__main__":
165 | from argparse import ArgumentParser
166 |
167 | # Define parser object
168 | parser = ArgumentParser(description="Prepare the tutorials for deployment.")
169 | parser.add_argument("-v", "--verbose", action="store_true", dest="verbose",
170 | default=False, help="Be chatty! (default = False)")
171 | parser.add_argument("-q", "--quiet", action="store_true", dest="quiet",
172 | default=False, help="Be quiet! (default = False)")
173 | parser.add_argument("-n", "--nameregex", default=None,
174 | help="A regular expression to select the names of the "
175 | "notebooks to be processed. If not given, all "
176 | "notebooks will be used.")
177 |
178 | parser.add_argument('action', nargs='+', choices=['run', 'convert'],
179 | help='The action(s) to take when running the script. '
180 | '"run" means to just run the notebooks, while '
181 | '"convert" will use nbconvert to turn them to '
182 | 'convert them to HTML.')
183 |
184 | args = parser.parse_args()
185 |
186 | # Set logger level based on verbose flags
187 | if args.verbose:
188 | logger.setLevel('DEBUG')
189 | elif args.quiet:
190 | logger.setLevel('ERROR')
191 | else:
192 | logger.setLevel('INFO')
193 |
194 | for action in args.action:
195 | if action == 'run':
196 | run_notebooks(args.nameregex)
197 | elif action == 'convert':
198 | convert_notebooks(args.nameregex)
199 |
--------------------------------------------------------------------------------
/tutorials/FITS-tables/FITS-tables.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "astropy-tutorials": {
4 | "author": "Lia R. Corrales ",
5 | "date": "January 2014",
6 | "description": "astropy.utils.data to download the file, astropy.io.fits to open and view the file, matplotlib for making both 1D and 2D histograms of the data.",
7 | "link_name": "Viewing and manipulating data from FITS tables",
8 | "name": "",
9 | "published": true
10 | },
11 | "signature": "sha256:a70c090b1d7a9465e61834c7995c5ccfb99827bcab5fda45ee037c39b8f16b73"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "code",
20 | "collapsed": false,
21 | "input": [
22 | "import numpy as np\n",
23 | "\n",
24 | "# Set up matplotlib and use a nicer set of plot parameters\n",
25 | "%config InlineBackend.rc = {}\n",
26 | "import matplotlib\n",
27 | "matplotlib.rc_file(\"../../templates/matplotlibrc\")\n",
28 | "import matplotlib.pyplot as plt\n",
29 | "%matplotlib inline"
30 | ],
31 | "language": "python",
32 | "metadata": {},
33 | "outputs": []
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": [
39 | "The following line is needed to download the example FITS files used in this tutorial."
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "collapsed": false,
45 | "input": [
46 | "from astropy.utils.data import download_file"
47 | ],
48 | "language": "python",
49 | "metadata": {},
50 | "outputs": []
51 | },
52 | {
53 | "cell_type": "heading",
54 | "level": 1,
55 | "metadata": {},
56 | "source": [
57 | "Viewing and manipulating data from FITS tables"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "collapsed": false,
63 | "input": [
64 | "from astropy.io import fits"
65 | ],
66 | "language": "python",
67 | "metadata": {},
68 | "outputs": []
69 | },
70 | {
71 | "cell_type": "markdown",
72 | "metadata": {},
73 | "source": [
74 | "FITS files can often contain large amount of multi-dimensional data and tables. In this particular example, I will open a FITS file with information from Chandra's HETG-S instrument."
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "collapsed": false,
80 | "input": [
81 | "event_filename = download_file( 'http://data.astropy.org/tutorials/FITS-tables/chandra_events.fits', cache=True )"
82 | ],
83 | "language": "python",
84 | "metadata": {},
85 | "outputs": []
86 | },
87 | {
88 | "cell_type": "heading",
89 | "level": 2,
90 | "metadata": {},
91 | "source": [
92 | "Opening the FITS file and viewing table contents"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "Since the file is big, I will open with `memmap=True` to prevent RAM storage issues."
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "collapsed": false,
105 | "input": [
106 | "pha_list = fits.open(event_filename, memmap=True)"
107 | ],
108 | "language": "python",
109 | "metadata": {},
110 | "outputs": []
111 | },
112 | {
113 | "cell_type": "code",
114 | "collapsed": false,
115 | "input": [
116 | "pha_list.info()"
117 | ],
118 | "language": "python",
119 | "metadata": {},
120 | "outputs": []
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {},
125 | "source": [
126 | "I'm interested in reading EVENTS, which contains information about each X-ray photon that hit the detector."
127 | ]
128 | },
129 | {
130 | "cell_type": "markdown",
131 | "metadata": {},
132 | "source": [
133 | "To find out what information the table contains, I will print the column names."
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "collapsed": false,
139 | "input": [
140 | "print(pha_list[1].columns)"
141 | ],
142 | "language": "python",
143 | "metadata": {},
144 | "outputs": []
145 | },
146 | {
147 | "cell_type": "markdown",
148 | "metadata": {},
149 | "source": [
150 | "Now I'll load the data into a separate variable."
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "collapsed": false,
156 | "input": [
157 | "pha_data = pha_list[1].data"
158 | ],
159 | "language": "python",
160 | "metadata": {},
161 | "outputs": []
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "metadata": {},
166 | "source": [
167 | "We can extract data from the table by referencing the column name."
168 | ]
169 | },
170 | {
171 | "cell_type": "markdown",
172 | "metadata": {},
173 | "source": [
174 | "For example, I'll make a histogram for the energy of each photon, giving us a sense for the spectrum (folded with the detector's efficiency)."
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "collapsed": false,
180 | "input": [
181 | "NBINS = 500\n",
182 | "energy_hist = plt.hist(pha_data['energy'], NBINS)"
183 | ],
184 | "language": "python",
185 | "metadata": {},
186 | "outputs": []
187 | },
188 | {
189 | "cell_type": "heading",
190 | "level": 2,
191 | "metadata": {},
192 | "source": [
193 | "Making a 2-D histogram with some table data"
194 | ]
195 | },
196 | {
197 | "cell_type": "markdown",
198 | "metadata": {},
199 | "source": [
200 | "I will make an image of the zeroth order with a 2-D histogram of the angular coordinates in the table."
201 | ]
202 | },
203 | {
204 | "cell_type": "markdown",
205 | "metadata": {},
206 | "source": [
207 | "First, I create a boolean mask to isolate the zeroth order events"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "collapsed": false,
213 | "input": [
214 | "i_zero = pha_data['tg_m'] == 0"
215 | ],
216 | "language": "python",
217 | "metadata": {},
218 | "outputs": []
219 | },
220 | {
221 | "cell_type": "heading",
222 | "level": 3,
223 | "metadata": {},
224 | "source": [
225 | "Method 1: Use numpy to make a 2-D histogram and imshow to display it"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {},
231 | "source": [
232 | "This method allowed me to create an image without stretching"
233 | ]
234 | },
235 | {
236 | "cell_type": "code",
237 | "collapsed": false,
238 | "input": [
239 | "NBINS = (100,100)\n",
240 | "\n",
241 | "img_zero, yedges, xedges = np.histogram2d(pha_data['tg_r'][i_zero], pha_data['tg_d'][i_zero], NBINS)\n",
242 | "\n",
243 | "extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]\n",
244 | "\n",
245 | "plt.imshow(img_zero, extent=extent, interpolation='nearest', cmap='gist_yarg', origin='lower')\n",
246 | "\n",
247 | "plt.xlabel('tg_d [degrees]')\n",
248 | "plt.ylabel('tg_r [degrees]')\n",
249 | "\n",
250 | "# To see more color maps\n",
251 | "# http://wiki.scipy.org/Cookbook/Matplotlib/Show_colormaps"
252 | ],
253 | "language": "python",
254 | "metadata": {},
255 | "outputs": []
256 | },
257 | {
258 | "cell_type": "heading",
259 | "level": 3,
260 | "metadata": {},
261 | "source": [
262 | "Method 2: Use hist2d with a log-normal color scheme"
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "collapsed": false,
268 | "input": [
269 | "from matplotlib.colors import LogNorm"
270 | ],
271 | "language": "python",
272 | "metadata": {},
273 | "outputs": []
274 | },
275 | {
276 | "cell_type": "code",
277 | "collapsed": false,
278 | "input": [
279 | "NBINS = (100,100)\n",
280 | "img_zero_mpl = plt.hist2d(pha_data['tg_r'][i_zero], pha_data['tg_d'][i_zero], NBINS, cmap='jet', norm=LogNorm())\n",
281 | "\n",
282 | "cbar = plt.colorbar(ticks=[1.0,3.0,6.0])\n",
283 | "cbar.ax.set_yticklabels(['1','3','6'])\n",
284 | "\n",
285 | "plt.xlabel('tg_r [degrees]')\n",
286 | "plt.ylabel('tg_d [degrees]')"
287 | ],
288 | "language": "python",
289 | "metadata": {},
290 | "outputs": []
291 | },
292 | {
293 | "cell_type": "heading",
294 | "level": 2,
295 | "metadata": {},
296 | "source": [
297 | "Close the FITS file"
298 | ]
299 | },
300 | {
301 | "cell_type": "code",
302 | "collapsed": false,
303 | "input": [
304 | "pha_list.close()"
305 | ],
306 | "language": "python",
307 | "metadata": {},
308 | "outputs": []
309 | },
310 | {
311 | "cell_type": "heading",
312 | "level": 2,
313 | "metadata": {},
314 | "source": [
315 | "Exercises"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {},
321 | "source": [
322 | "Make a scatter plot of the same data you histogrammed above. The [plt.scatter](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.scatter) function is your friend for this. Why might you want to use this instead of hist2d?"
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "collapsed": false,
328 | "input": [],
329 | "language": "python",
330 | "metadata": {},
331 | "outputs": []
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "metadata": {},
336 | "source": [
337 | "Try the same with the [plt.hexbin](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hexbin) plotting function. Which do you think looks better for this kind of data?"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "collapsed": false,
343 | "input": [],
344 | "language": "python",
345 | "metadata": {},
346 | "outputs": []
347 | },
348 | {
349 | "cell_type": "markdown",
350 | "metadata": {},
351 | "source": [
352 | "Try making the same, but without sub-selecting on `'i_zero'`. Which plots help you better understand the data now? What if you try `'x'` and `'y'` instead of `'tg_r'` and `'tg_d'`?"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "collapsed": false,
358 | "input": [],
359 | "language": "python",
360 | "metadata": {},
361 | "outputs": []
362 | }
363 | ],
364 | "metadata": {}
365 | }
366 | ]
367 | }
--------------------------------------------------------------------------------
/tutorials/Plot-Catalog/Young-Objects-Compilation.csv:
--------------------------------------------------------------------------------
1 | ,,,,2MASS Photometry,,,,,,WISE Photometry,,,,,,,,Spectra,,,,Astrometry,,,,,,,,,,,
2 | Name,Designation,RA,Dec,Jmag,J_unc,Hmag,H_unc,Kmag,K_unc,W1,W1_unc,W2,W2_unc,W3,W3_unc,W4,W4_unc,Spectral Type,Spectra (FITS),Opt Spec Refs,NIR Spec Refs,pm_ra (mas),pm_ra_unc,pm_dec (mas),pm_dec_unc,pi (mas),pi_unc,radial velocity (km/s),rv_unc,Astrometry Refs,Discovery Refs,Group/Age,Note
3 | ,00 04 02.84 -64 10 35.6,1.01201,-64.18,15.79,0.07,14.83,0.07,14.01,0.05,13.37,0.03,12.94,0.03,12.18,0.24,9.16,null,L1γ,,Kirkpatrick et al. 2010,,,,,,,,,,,Kirkpatrick et al. 2010,,
4 | PC 0025+04,00 27 41.97 +05 03 41.7,6.92489,5.06,16.19,0.09,15.29,0.10,14.96,0.12,14.62,0.04,14.14,0.05,12.24,null,8.89,null,M9.5β,,Mould et al. 1994,,0.0105,0.0004,-0.0008,0.0003,,,,,Faherty et al. 2009,Schneider et al. 1991,,
5 | ,00 32 55.84 -44 05 05.8,8.23267,-44.08,14.78,0.04,13.86,0.03,13.27,0.04,12.82,0.03,12.49,0.03,11.73,0.19,9.29,null,L0γ,,Cruz et al. 2009,,0.1178,0.0043,-0.0916,0.0043,38.4,4.8,,,Faherty et al. 2012,Reid et al. 2008,,
6 | ,00 37 43.06 -58 46 22.9,9.42942,-58.77,15.37,0.05,14.26,0.05,13.59,0.05,13.13,0.03,12.74,0.03,12.56,0.38,9.32,null,L0γ,,Cruz et al. 2009,,0.049,0.01,-0.051,0.02,,,,,Faherty et al. 2009,Reid et al. 2008,,
7 | ,00 45 21.43 +16 34 44.6,11.33929,16.58,13.06,0.02,12.06,0.04,11.37,0.02,10.77,0.02,10.39,0.02,9.74,0.04,8.42,0.26,L2β,,Cruz et al. 2009,Wilson et al. 2003,0.385,0.017,-0.026,0.012,,,,,Faherty et al. 2009,Wilson et al. 2003,,
8 | ,Empire,,,13.8,,13.1,,12.5,,12.07,0.03,11.64,0.02,11.14,0.18,9.02,null,M9β,,Reid et al. 2008,Wilson et al. 2003,0.098,0.022,-0.051,0.01,,,,,Faherty et al. 2009,Wilson et al. 2003,,
9 | ,Flatiron,,,16.4,0.1,15.2,,14.4,,13.68,0.03,13.20,0.03,11.99,null,8.48,null,L2γ,,Cruz et al. in prep,Cruz et al. in prep,0.044,0.024,-0.082,0.024,,,,,Faherty et al. 2009,Cruz et al. in prep,,
10 | ,Liberty,,,15.1,,14.2,,13.4,,13.03,0.03,12.62,0.03,11.80,0.19,9.22,null,L1β,,Cruz et al. in prep,Cruz et al. in prep,0.08,0.017,-0.062,0.02,,,,,Faherty et al. 2009,Cruz et al. 2003,,
11 | ,01 24 45.99 -57 45 37.9,21.19163,-57.76,16.31,0.11,15.06,0.09,14.32,0.09,13.77,0.03,13.34,0.03,12.45,0.31,8.91,null,L0γ,,Cruz et al. 2009,,-0.003,0.01,0.018,0.019,,,,,Faherty et al. 2009,Reid et al. 2008,,
12 | ,01 26 21.09 +14 28 05.7,21.52750,14.47,17.10,,16.20,,15.30,,14.24,0.03,13.70,0.04,12.38,null,9.13,null,L4:γ,,Cruz et al. in prep,Metchev et al. 2008,,,,,,,,,,Metchev08,,
13 | ,01 41 58.23 -46 33 57.4,25.49263,-46.57,14.83,0.04,13.88,0.03,13.10,0.03,12.55,0.02,12.17,0.02,11.92,0.21,9.24,null,L0γ,,Cruz et al. 2009,Kirkpatrick et al. 2006,0.104,0.017,-0.026,0.024,,,,,Faherty et al. 2009,Kirkpatrick06,,
14 | ,Williamsburg,,,15.0,,14.1,,13.5,,13.00,0.03,12.65,0.03,11.93,0.20,9.36,null,L0γ,,Cruz et al. in prep,Cruz et al. in prep,0.064,0.016,-0.039,0.019,,,,,Faherty et al. 2009,Cruz et al. in prep,,
15 | SSSPM J0222-5412,02 21 54.94 -54 12 05.4,35.47892,-54.20,13.90,0.03,13.22,0.03,12.67,0.03,12.33,0.02,11.96,0.02,11.44,0.12,9.48,null,M9β,,Reid et al. 2008,,0.136,0.01,-0.01,0.017,,,,,Faherty et al. 2009,Lodieu05,,
16 | ,02 23 54.64 -58 15 06.7,35.97767,-58.25,15.07,0.05,14.00,0.04,13.42,0.04,12.82,0.02,12.43,0.02,11.64,0.15,9.47,null,L0γ,,Cruz et al. 2009,,0.134,0.01,0.005,0.019,,,,,Faherty et al. 2009,Reid et al. 2008,,
17 | ,02 25 19.47 -58 37 29.5,36.33113,-58.62,13.74,0.03,13.06,0.03,12.56,0.03,12.23,0.02,11.93,0.02,11.99,0.19,9.22,null,M9β,,Reid et al. 2008,,0.085,0.01,-0.03,0.018,,,,,Faherty et al. 2009,Reid et al. 2008,,
18 | ,02 34 00.93 -64 42 06.8,38.50388,-64.70,15.33,0.06,14.44,0.06,13.85,0.07,13.25,0.03,12.91,0.03,12.62,0.28,9.49,null,L0γ,,Kirkpatrick et al. 2010,,,,,,,,,,,Kirkpatrick et al. 2010,,
19 | ,02 41 11.5 -03 26 58,40.29797,-3.45,15.80,0.07,14.81,0.05,14.04,0.05,13.64,0.03,13.26,0.03,12.77,0.42,9.00,null,L0γ,,Cruz et al. 2009,,,,,,,,,,,Cruz et al. 2007,,
20 | ,02 53 59.7 +32 06 37,43.49917,32.11,13.62,0.02,12.93,0.02,12.55,0.03,12.32,0.03,12.13,0.02,11.81,0.25,8.51,null,M7:β,,Cruz et al. 2003,,,,,,,,,,,Cruz et al. 2003,,
21 | ,03 03 20.42 -73 12 30.0,45.83510,-73.21,16.14,0.11,15.10,0.09,14.32,0.08,13.78,0.03,13.35,0.03,12.29,0.17,9.34,0.34,L2γ,,Kirkpatrick et al. 2010,,,,,,,,,,,Kirkpatrick et al. 2010,,
22 | ,03 23 10.02 -46 31 23.7,50.79175,-46.52,15.39,0.07,14.32,0.06,13.70,0.05,13.08,0.02,12.67,0.02,11.94,0.16,9.18,null,L0γ,,Cruz et al. 2009,,0.06,0.013,-0.01,0.019,,,,,Faherty et al. 2009,Reid et al. 2008,,
23 | ,Brooklyn,,,16.1,,14.7,,13.9,,13.0,0.0,12.4,0.0,12.2,0.2,9.7,null,L5β,,Cruz et al. in prep,,0.108,0.014,-0.146,0.015,,,,,Faherty et al. 2009,Cruz et al. 2003,,
24 | LP 944- 20/BRI 0337-3535,03 39 35.2 -35 25 44,54.89674,-35.43,10.73,0.02,10.02,0.02,9.55,0.02,9.13,0.02,8.81,0.02,8.27,0.02,8.00,0.11,M9β,,KHI97,Geballe et al. 2002,0.324,0.0076,0.2959,0.0075,,,,,Faherty et al. 2009,Luyten 1979 (NLTT)**,,
25 | ,03 55 23.37 +11 33 43.7,58.84738,11.56,14.05,0.02,12.53,0.03,11.53,0.02,10.53,0.02,9.94,0.02,9.29,0.04,8.32,null,L5γ,,Cruz et al. 2009,Cruz et al. in prep,0.218,0.005,-0.626,0.005,122,13,,,Faherty et al. 2013,Reid et al. 2008,,
26 | DENIS J0357-4417,03 57 26.95 -44 17 30.5AB,59.36229,-44.29,14.37,0.03,13.53,0.03,12.91,0.03,12.48,0.02,12.09,0.02,11.60,0.08,9.32,null,L0β,,Cruz et al. 2009,Cruz et al. in prep,0.064,0.013,-0.02,0.019,,,,,Faherty et al. 2009,Bouy et al. 2003,,resolved spectra in Martin et al. 2006
27 | ,04 06 26.77 -38 12 10.2,61.61156,-38.20,16.77,0.13,15.71,0.10,15.11,0.12,14.45,0.03,14.10,0.04,12.52,null,9.10,null,L0γ,,Kirkpatrick et al. 2010,Kirkpatrick et al. 2010,,,,,,,,,,Kirkpatrick et al. 2010,,
28 | ,04 21 07.2 -63 06 02,65.28003,-63.10,15.57,0.05,14.28,0.04,13.45,0.04,12.56,0.02,12.14,0.02,11.60,0.10,9.25,null,L5γ,,Cruz et al. 2009,,0.146,0.008,0.191,0.018,,,,,Faherty et al. 2009,Cruz et al. 2007,,
29 | DENIS J043627.8-411446,04 36 27.8 -41 14 46,69.11621,-41.25,13.10,0.03,12.43,0.02,12.05,0.03,11.74,0.02,11.46,0.02,11.11,0.08,9.18,null,M8β,,Cruz et al. 2007,Cruz et al. in prep,0.073,0.012,0.013,0.016,,,,,Faherty et al. 2009,Phan-Bao et al. 2003,,
30 | SDSS 0443+0002,04 43 37.6 +00 02 05,70.90670,0.03,12.51,0.03,11.80,0.02,11.22,0.02,10.83,0.02,10.48,0.02,10.03,0.05,8.42,null,M9γ,,Cruz et al. 2007,Cruz et al. in prep,0.028,0.014,-0.099,0.014,,,,,Faherty et al. 2009,Hawley et al. 2002,,
31 | ,05 01 24.06 -00 10 45.2,75.35025,-0.18,14.98,0.04,13.71,0.03,12.96,0.04,12.05,0.02,11.52,0.02,10.95,0.11,9.17,null,L4γ,,Cruz et al. 2009,,0.1824,0.0043,-0.1327,0.0042,76.4,4.8,,,Faherty et al. 2012,Reid et al. 2008,,
32 | ,Broadway,,,15.4,,14.1,,13.2,,12.4,0.0,11.9,0.0,11.3,0.1,9.1,null,L5γ,,Kirkpatrick et al. in prep,Cruz et al. in prep,-0.028,0.016,0.099,0.018,,,,,Faherty et al. 2009,Cruz et al. 2003,,
33 | ,Queens,,,15.2,,14.2,,13.6,,13.0,0.0,12.7,0.0,12.6,0.3,9.2,null,L1γ,,Cruz et al. in prep,Cruz et al. in prep,0.0286,0.0042,-0.016,0.004,21.4,6.9,,,Faherty et al. 2012,Cruz et al. 2007,,
34 | ,05 34 15.94 -06 31 39.7,83.56645,-6.53,16.05,0.08,15.37,0.10,14.94,0.10,14.79,0.04,14.26,0.06,11.59,null,8.27,0.30,M8γ,,Kirkpatrick et al. 2010,Kirkpatrick et al. 2010,,,,,,,,,,Kirkpatrick et al. 2010,,
35 | ,Manhattan,,,15.7,,14.6,,13.8,,13.3,0.0,12.8,0.0,12.6,0.4,9.2,null,L2γ,,Cruz et al. in prep,,0.0246,0.0053,-0.0306,0.005,25.6,9.4,,,Faherty et al. 2012,Cruz et al. 2007,,
36 | ,06 08 52.8 -27 53 58,92.22016,-27.90,13.60,0.03,12.90,0.03,12.37,0.03,11.98,0.02,11.62,0.02,11.31,0.11,9.09,null,M8.5γ,,Rice et al. 2010,Rice et al. 2010,0.0089,0.0035,0.0107,0.0035,32,3.6,,,Faherty et al. 2012,Cruz et al. 2003,,
37 | ,06 52 48.51 -57 41 37.6,103.20213,-57.69,13.63,0.03,12.97,0.02,12.45,0.02,12.15,0.02,11.86,0.02,11.04,0.05,9.60,0.37,M8β,,Reid et al. 2008,,0.001,0.0034,0.0292,0.0033,31.3,3.2,,,Faherty et al. 2012,Reid et al. 2008,,
38 | ,07 12 37.86 -61 55 52.8,108.15775,-61.93,15.30,0.06,14.39,0.04,13.67,0.05,12.99,0.02,12.63,0.02,11.48,0.10,9.51,null,L1β,,Cruz et al. 2009,,-0.0357,0.0049,0.0791,0.0048,22.9,9.1,,,Faherty et al. 2012,Cruz et al. 2009,,
39 | ,Bronx,,,13.4,,12.6,,12.1,,11.76,0.02,11.40,0.02,10.76,0.10,8.72,null,M9γ,,Cruz et al. 2007,Cruz et al. in prep,-0.048,0.019,-0.089,0.019,,,,,Faherty et al. 2009,Cruz et al. 2007,,
40 | ,10 22 04.89 +02 00 47.7,155.52038,2.01,14.10,0.03,13.40,0.03,12.90,0.03,12.61,0.03,12.34,0.03,11.97,0.41,8.53,null,M9β,,Reid et al. 2008,,-0.1562,0.0066,-0.429,0.0068,26.4,11.5,,,Faherty et al. 2012,Reid et al. 2008,,
41 | ,10 22 48.21 +58 25 45.3,155.70088,58.43,13.50,0.03,12.64,0.03,12.16,0.03,11.76,0.02,11.50,0.02,11.20,0.11,9.13,null,L1β,,Cruz et al. 2009,,-0.36,0.1,-0.78,0.09,,,,,Faherty et al. 2009,Reid et al. 2008,,
42 | SSSPM 1102-3431,11 02 09.83 -34 30 35.5,165.54097,-34.51,13.03,0.02,12.36,0.02,11.89,0.02,11.44,0.02,10.79,0.02,9.39,0.03,8.02,0.19,M8.5γ,,Scholz et al. 2005,,-0.033,0.012,-0.024,0.015,,,,,Faherty et al. 2009,Scholz et al. 2005,,
43 | DENIS-P J115442.2-340039,Chelsea,,,14.1,,13.3,,12.8,,12.35,0.02,12.04,0.02,11.37,0.11,9.55,null,L0β,,Cruz et al. in prep,Cruz et al. in prep,-0.161,0.013,0.004,0.015,,,,,Faherty et al. 2009,Bouy et al. 2003,,
44 | ,14 11 21.3 -21 19 50,212.83879,-21.33,12.44,0.02,11.83,0.03,11.33,0.02,11.08,0.02,10.82,0.02,10.65,0.07,8.81,null,M9β,,Cruz et al. 2003,Kendall et al. 2004,-0.03,0.2,0.09,0.2,,,,,Faherty et al. 2009,Kendall et al. 2004,,
45 | ,Soho,,,14.5,,13.4,,12.6,,11.9,0.0,11.5,0.0,10.8,0.1,9.0,null,L4:β,,Reid et al. 2008,Cruz et al. in prep,0.262,0.022,-0.12,0.022,,,,,Faherty et al. 2009,Wilson et al. 2003,,
46 | ,Nolita,,,15.9,,14.8,,14.0,,13.2,0.0,12.7,0.0,11.4,0.2,8.8,null,L4γ,,Cruz et al. in prep,Cruz et al. in prep,0.032,0.019,-0.061,0.02,,,,,Faherty et al. 2009,Cruz et al. in prep,,
47 | ,15 47 47.19 -24 23 49.3,236.94663,-24.40,13.97,0.03,13.27,0.03,12.74,0.03,12.41,0.03,12.11,0.03,12.11,null,8.74,null,M9γ,,Reid et al. 2008,,-0.133,0.015,-0.122,0.016,,,,,Faherty et al. 2009,Reid et al. 2008,,
48 | ,15 51 52.37 +09 41 14.8,237.96821,9.69,16.32,0.11,15.11,0.07,14.31,0.06,13.60,0.03,13.12,0.03,12.68,0.48,9.16,null,L4γ,,Cruz et al. in prep,,-0.07,0.022,-0.05,0.022,,,,,Faherty et al. 2009,Reid et al. 2008,,
49 | ,15 52 59.06 +29 48 48.5,238.24608,29.81,13.48,0.03,12.61,0.03,12.02,0.03,11.54,0.02,11.21,0.02,10.66,0.05,9.00,null,L0β,,Cruz et al. 2009,,-0.157,0.02,-0.051,0.02,,,,,Faherty et al. 2009,Wilson et al. 2003,,
50 | ,15 57 50.11 -29 52 43.1,239.45881,-29.88,16.32,0.12,15.45,0.10,14.85,0.11,14.44,0.04,14.07,0.06,12.15,0.34,8.67,null,M9δ,,Kirkpatrick et al. 2010,Kirkpatrick et al. 2010,,,,,,,,,,Kirkpatrick et al. 2010,,
51 | ,16 15 42.5 +49 53 21,243.92723,49.89,16.79,0.14,15.33,0.10,14.31,0.07,13.20,0.02,12.62,0.02,12.13,0.13,9.31,null,L4γ,,Cruz et al. in prep,Geissler et al. 2011,,,,,,,,,,Cruz et al. 2007,,
52 | ,Greenwich,,,14.4,,13.6,,13.0,,12.6,0.0,12.2,0.02,11.66,0.15,9.33,null,L0γ,,Cruz et al. in prep,,-0.053,0.011,-0.036,0.016,,,,,Faherty et al. 2009,Cruz et al. 2007,,
53 | ,17 26 00.0 +15 38 19,261.50029,15.64,15.67,0.07,14.47,0.05,13.66,0.05,13.07,0.03,12.69,0.03,11.56,0.16,9.31,null,L3.5γ,,Cruz et al. 2009,,-0.031,0.013,-0.048,0.014,,,,,Faherty et al. 2009,Kirkpatrick et al. 2000,,
54 | ,19 35 55.95 -28 46 34.3,293.98312,-28.78,13.95,0.03,13.18,0.02,12.71,0.03,12.35,0.03,11.91,0.03,10.52,0.08,8.64,null,M9γ,,Reid et al. 2008,,,,,,,,,,,Reid et al. 2008,,
55 | ,19 56 47.00 -75 42 27.0,299.19583,-75.71,16.15,0.10,15.04,0.10,14.23,0.07,13.69,0.03,13.25,0.03,12.68,null,9.17,null,L0γ,,Cruz et al. 2009,,,,,,,,,,,Reid et al. 2008,,
56 | DENIS-P J200048.3-752306,20 00 48.41 -75 23 07.0,300.20171,-75.39,12.73,0.03,11.97,0.03,11.51,0.03,11.11,0.02,10.80,0.02,10.55,0.07,8.55,null,M9γ,,Reid et al. 2008,,,,,,,,,,,,,
57 | ,Rockefeller,,,15.3,,14.2,,13.4,,12.5,0.0,12.1,0.03,11.44,0.21,8.82,null,L5β,,Cruz et al. in prep,Cruz et al. in prep,-0.098,0.013,-0.105,0.014,,,,,Faherty et al. 2009,Cruz et al. 2007,,
58 | ,20 13 51.52 -28 06 02.0,303.46467,-28.10,14.24,0.03,13.46,0.03,12.94,0.03,12.53,0.03,12.16,0.03,11.88,0.28,8.66,null,M9γ,,Cruz et al. in prep,,,,,,,,,,,Reid et al. 2008,,
59 | ,21 26 50.40 -81 40 29.3,321.71000,-81.67,15.54,0.06,14.41,0.05,13.55,0.04,12.91,0.02,12.47,0.02,11.89,0.16,9.36,null,L3γ,,Cruz et al. 2009,,,,,,,,,,,Reid et al. 2008,,
60 | ,Tribeca,,,16.4,0.1,15.0,,14.1,,13.37,0.03,12.92,0.03,12.05,0.32,8.43,null,L4β,,Cruz et al. in prep,,,,,,,,,,,Cruz et al. in prep,,
61 | ,Harlem,,,15.5,,14.4,,13.6,,12.82,0.02,12.38,0.03,11.89,0.22,9.26,null,L4γ,,Cruz et al. in prep,,0.111,0.013,-0.182,0.018,,,,,Faherty et al. 2009,K00,,
62 | ,22 08 13.63 +29 21 21.5,332.05679,29.36,15.80,0.09,14.79,0.07,14.15,0.07,13.35,0.03,12.89,0.03,12.58,0.39,9.30,null,L3γ,,Cruz et al. 2009,,0.111,0.014,-0.011,0.014,,,,,Faherty et al. 2009,Kirkpatrick et al. 2000,,
63 | ,22 13 44.9 -21 36 07,333.43715,-21.60,15.38,0.04,14.40,0.06,13.76,0.04,13.23,0.03,12.83,0.03,11.55,0.20,9.07,null,L0γ,,Cruz et al. 2009,,0.06,0.011,-0.063,0.017,,,,,Faherty et al. 2009,Cruz et al. 2007,,
64 | SDSS 2249+0044,22 49 53.45 +00 44 04.6,342.47273,0.73,16.59,0.12,15.42,0.11,14.36,0.07,13.58,0.03,13.14,0.05,11.28,null,7.69,null,L4γ,,Cruz et al. in prep,Geballe et al. 2002,0.075,0.018,0.026,0.018,,,,,Faherty et al. 2009,Geballe et al. 2002,,Binary: Allers et al. 2010
65 | ,Chinatown,,,15.8,,14.7,,14.0,,13.55,0.03,13.10,0.03,11.67,0.23,8.59,null,L0γ,,Cruz et al. in prep,,,,,,,,,,,Cruz et al. in prep,,
66 | ,23 22 52.99 -61 51 27.5,350.72079,-61.86,15.55,0.06,14.54,0.06,13.86,0.04,13.24,0.03,12.84,0.03,12.68,0.39,9.38,null,L2γ,,Cruz et al. 2009,,,,,,,,,,,Reid et al. 2008,,
--------------------------------------------------------------------------------
/tutorials/FITS-images/FITS-images.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "astropy-tutorials": {
4 | "author": "Lia R. Corrales ",
5 | "date": "January 2014",
6 | "description": "Demonstrates use of astropy.utils.data to download data; astropy.io.fits to open the file; matplotlib to view the image with different color scales and stretches and to make histrograms. Also includes method for simple image stacking.",
7 | "link_name": "Viewing and manipulating FITS images",
8 | "name": "",
9 | "published": true
10 | },
11 | "signature": "sha256:192ee736cce2ddffa26e398414e46e7e86754ff8a48a191ccf3434e6b2ea963d"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "code",
20 | "collapsed": false,
21 | "input": [
22 | "import numpy as np\n",
23 | "\n",
24 | "# Set up matplotlib and use a nicer set of plot parameters\n",
25 | "%config InlineBackend.rc = {}\n",
26 | "import matplotlib\n",
27 | "matplotlib.rc_file(\"../../templates/matplotlibrc\")\n",
28 | "import matplotlib.pyplot as plt\n",
29 | "%matplotlib inline"
30 | ],
31 | "language": "python",
32 | "metadata": {},
33 | "outputs": []
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": [
39 | "The following line is needed to download the example FITS files used here."
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "collapsed": false,
45 | "input": [
46 | "from astropy.utils.data import download_file"
47 | ],
48 | "language": "python",
49 | "metadata": {},
50 | "outputs": []
51 | },
52 | {
53 | "cell_type": "heading",
54 | "level": 1,
55 | "metadata": {},
56 | "source": [
57 | "Viewing and manipulating FITS images"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "collapsed": false,
63 | "input": [
64 | "from astropy.io import fits"
65 | ],
66 | "language": "python",
67 | "metadata": {},
68 | "outputs": []
69 | },
70 | {
71 | "cell_type": "code",
72 | "collapsed": false,
73 | "input": [
74 | "image_file = download_file('http://data.astropy.org/tutorials/FITS-images/HorseHead.fits', cache=True )"
75 | ],
76 | "language": "python",
77 | "metadata": {},
78 | "outputs": []
79 | },
80 | {
81 | "cell_type": "heading",
82 | "level": 2,
83 | "metadata": {},
84 | "source": [
85 | "Opening FITS files and loading the image data"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "I will open the FITS file and find out what it contains."
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "collapsed": false,
98 | "input": [
99 | "hdu_list = fits.open(image_file)\n",
100 | "hdu_list.info()"
101 | ],
102 | "language": "python",
103 | "metadata": {},
104 | "outputs": []
105 | },
106 | {
107 | "cell_type": "markdown",
108 | "metadata": {},
109 | "source": [
110 | "Generally the image information is located in the PRIMARY block. The blocks are numbered and can be accessed by indexing hdu_list."
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "collapsed": false,
116 | "input": [
117 | "image_data = hdu_list[0].data"
118 | ],
119 | "language": "python",
120 | "metadata": {},
121 | "outputs": []
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "You data is now stored as a 2-D numpy array. Want to know the dimensions of the image? Just look at the `shape` of the array."
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "collapsed": false,
133 | "input": [
134 | "print(type(image_data))\n",
135 | "print(image_data.shape)"
136 | ],
137 | "language": "python",
138 | "metadata": {},
139 | "outputs": []
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {},
144 | "source": [
145 | "At this point, we can just close the FITS file. We have stored everything we wanted to a variable."
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "collapsed": false,
151 | "input": [
152 | "hdu_list.close()"
153 | ],
154 | "language": "python",
155 | "metadata": {},
156 | "outputs": []
157 | },
158 | {
159 | "cell_type": "heading",
160 | "level": 3,
161 | "metadata": {},
162 | "source": [
163 | "SHORTCUT"
164 | ]
165 | },
166 | {
167 | "cell_type": "markdown",
168 | "metadata": {},
169 | "source": [
170 | "If you don't need to examine the FITS header, you can call `fits.getdata` to bypass the previous steps."
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "collapsed": false,
176 | "input": [
177 | "image_data = fits.getdata(image_file)\n",
178 | "print(type(image_data))\n",
179 | "print(image_data.shape)"
180 | ],
181 | "language": "python",
182 | "metadata": {},
183 | "outputs": []
184 | },
185 | {
186 | "cell_type": "heading",
187 | "level": 2,
188 | "metadata": {},
189 | "source": [
190 | "Viewing the image data and getting basic statistics"
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "collapsed": false,
196 | "input": [
197 | "plt.imshow(image_data, cmap='gray')\n",
198 | "plt.colorbar()\n",
199 | "\n",
200 | "# To see more color maps\n",
201 | "# http://wiki.scipy.org/Cookbook/Matplotlib/Show_colormaps"
202 | ],
203 | "language": "python",
204 | "metadata": {},
205 | "outputs": []
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "Let's get some basic statistics about our image"
212 | ]
213 | },
214 | {
215 | "cell_type": "code",
216 | "collapsed": false,
217 | "input": [
218 | "print('Min:', np.min(image_data))\n",
219 | "print('Max:', np.max(image_data))\n",
220 | "print('Mean:', np.mean(image_data))\n",
221 | "print('Stdev:', np.std(image_data))"
222 | ],
223 | "language": "python",
224 | "metadata": {},
225 | "outputs": []
226 | },
227 | {
228 | "cell_type": "heading",
229 | "level": 3,
230 | "metadata": {},
231 | "source": [
232 | "Plotting a histogram"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {},
238 | "source": [
239 | "To make a histogram with `matplotlib.pyplot.hist()`, I need to cast the data from a 2-D to array to something one dimensional."
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {},
245 | "source": [
246 | "In this case, I am using the iterable python object `img_data.flat`."
247 | ]
248 | },
249 | {
250 | "cell_type": "code",
251 | "collapsed": false,
252 | "input": [
253 | "print(type(image_data.flat))"
254 | ],
255 | "language": "python",
256 | "metadata": {},
257 | "outputs": []
258 | },
259 | {
260 | "cell_type": "code",
261 | "collapsed": false,
262 | "input": [
263 | "NBINS = 1000\n",
264 | "histogram = plt.hist(image_data.flat, NBINS)"
265 | ],
266 | "language": "python",
267 | "metadata": {},
268 | "outputs": []
269 | },
270 | {
271 | "cell_type": "heading",
272 | "level": 3,
273 | "metadata": {},
274 | "source": [
275 | "Displaying the image with a logarithmic scale"
276 | ]
277 | },
278 | {
279 | "cell_type": "markdown",
280 | "metadata": {},
281 | "source": [
282 | "Want to use a logarithmic color scale? To do so we need to load the `LogNorm` object from `matplotlib`."
283 | ]
284 | },
285 | {
286 | "cell_type": "code",
287 | "collapsed": false,
288 | "input": [
289 | "from matplotlib.colors import LogNorm"
290 | ],
291 | "language": "python",
292 | "metadata": {},
293 | "outputs": []
294 | },
295 | {
296 | "cell_type": "code",
297 | "collapsed": false,
298 | "input": [
299 | "plt.imshow(image_data, cmap='gray', norm=LogNorm())\n",
300 | "\n",
301 | "# I chose the tick marks based on the histogram above\n",
302 | "cbar = plt.colorbar(ticks=[5.e3,1.e4,2.e4])\n",
303 | "cbar.ax.set_yticklabels(['5,000','10,000','20,000'])"
304 | ],
305 | "language": "python",
306 | "metadata": {},
307 | "outputs": []
308 | },
309 | {
310 | "cell_type": "heading",
311 | "level": 2,
312 | "metadata": {},
313 | "source": [
314 | "Basic image math: image stacking"
315 | ]
316 | },
317 | {
318 | "cell_type": "markdown",
319 | "metadata": {},
320 | "source": [
321 | "You can perform math with the image data like any other numpy array. In this particular example, I will stack several images of M13 taken with a ~10'' telescope."
322 | ]
323 | },
324 | {
325 | "cell_type": "markdown",
326 | "metadata": {},
327 | "source": [
328 | "I open a series of FITS files and store the data in a list, which I've named `image_concat`."
329 | ]
330 | },
331 | {
332 | "cell_type": "code",
333 | "collapsed": false,
334 | "input": [
335 | "image_list = [ download_file('http://data.astropy.org/tutorials/FITS-images/M13_blue_000'+n+'.fits', cache=True ) \\\n",
336 | " for n in ['1','2','3','4','5'] ]\n",
337 | "\n",
338 | "# The long way\n",
339 | "image_concat = []\n",
340 | "for image in image_list:\n",
341 | " image_concat.append(fits.getdata(image))\n",
342 | " \n",
343 | "# The short way\n",
344 | "#image_concat = [ fits.getdata(image) for image in IMAGE_LIST ]"
345 | ],
346 | "language": "python",
347 | "metadata": {},
348 | "outputs": []
349 | },
350 | {
351 | "cell_type": "markdown",
352 | "metadata": {},
353 | "source": [
354 | "Now I'll stack the images by summing my concatenated list."
355 | ]
356 | },
357 | {
358 | "cell_type": "code",
359 | "collapsed": false,
360 | "input": [
361 | "# The long way\n",
362 | "final_image = np.zeros(shape=image_concat[0].shape)\n",
363 | "\n",
364 | "for image in image_concat:\n",
365 | " final_image += image\n",
366 | "\n",
367 | "# The short way\n",
368 | "#final_image = np.sum(image_concat, axis=0)"
369 | ],
370 | "language": "python",
371 | "metadata": {},
372 | "outputs": []
373 | },
374 | {
375 | "cell_type": "markdown",
376 | "metadata": {},
377 | "source": [
378 | "I'm going to show the image, but I want to decide on the best stretch. To do so I'll plot a histogram of the data."
379 | ]
380 | },
381 | {
382 | "cell_type": "code",
383 | "collapsed": false,
384 | "input": [
385 | "image_hist = plt.hist(final_image.flat, 1000)"
386 | ],
387 | "language": "python",
388 | "metadata": {},
389 | "outputs": []
390 | },
391 | {
392 | "cell_type": "markdown",
393 | "metadata": {},
394 | "source": [
395 | "I'll use the keywords `vmin` and `vmax` to set limits on the color scaling for `imshow`."
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "collapsed": false,
401 | "input": [
402 | "plt.imshow(final_image, cmap='gray', vmin=2.e3, vmax=3.e3)\n",
403 | "plt.colorbar()"
404 | ],
405 | "language": "python",
406 | "metadata": {},
407 | "outputs": []
408 | },
409 | {
410 | "cell_type": "heading",
411 | "level": 2,
412 | "metadata": {},
413 | "source": [
414 | "Writing image data to a FITS file"
415 | ]
416 | },
417 | {
418 | "cell_type": "markdown",
419 | "metadata": {},
420 | "source": [
421 | "This is easy to do with the `writeto()` method."
422 | ]
423 | },
424 | {
425 | "cell_type": "markdown",
426 | "metadata": {},
427 | "source": [
428 | "You will receive an error if the file you are trying to write already exists. That's why I've set `clobber=True`."
429 | ]
430 | },
431 | {
432 | "cell_type": "code",
433 | "collapsed": false,
434 | "input": [
435 | "outfile = 'stacked_M13_blue.fits'\n",
436 | "\n",
437 | "hdu = fits.PrimaryHDU(final_image)\n",
438 | "hdu.writeto(outfile, clobber=True)"
439 | ],
440 | "language": "python",
441 | "metadata": {},
442 | "outputs": []
443 | },
444 | {
445 | "cell_type": "heading",
446 | "level": 2,
447 | "metadata": {},
448 | "source": [
449 | "Exercises"
450 | ]
451 | },
452 | {
453 | "cell_type": "markdown",
454 | "metadata": {},
455 | "source": [
456 | "Determine the mean, median, and standard deviation of a part of the stacked M13 image where there is *not* light from M13. Use those statistics with a sum over the part of the image that includes M13 to estimate the total light in this image from M13."
457 | ]
458 | },
459 | {
460 | "cell_type": "code",
461 | "collapsed": false,
462 | "input": [],
463 | "language": "python",
464 | "metadata": {},
465 | "outputs": []
466 | },
467 | {
468 | "cell_type": "markdown",
469 | "metadata": {},
470 | "source": [
471 | "Show the image of the Horsehead Nebula, but in to units of *surface brightness* (magnitudes per square arcsecond).\n",
472 | "(Hint: the *physical* size of the image is 15x15 arcminutes.)"
473 | ]
474 | },
475 | {
476 | "cell_type": "code",
477 | "collapsed": false,
478 | "input": [],
479 | "language": "python",
480 | "metadata": {},
481 | "outputs": []
482 | },
483 | {
484 | "cell_type": "markdown",
485 | "metadata": {},
486 | "source": [
487 | "Now write out the image you just created, preserving the header the original image had, but add a keyword 'UNITS' with the value 'mag per sq arcsec'.\n",
488 | "(Hint: you may need to read the [astropy.io.fits](http://docs.astropy.org/en/stable/io/fits/index.html) documentation if you're not sure how to include both the header and the data)"
489 | ]
490 | },
491 | {
492 | "cell_type": "code",
493 | "collapsed": false,
494 | "input": [],
495 | "language": "python",
496 | "metadata": {},
497 | "outputs": []
498 | }
499 | ],
500 | "metadata": {}
501 | }
502 | ]
503 | }
--------------------------------------------------------------------------------
/tutorials/vo/conesearch_tutorial.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": "",
4 | "signature": "sha256:25f3f22fe7ed00491c4f02dc43cb5321bcc84711f81ea92cf243c0bd29c1d95b",
5 | "astropy-tutorials": {
6 | "author": "P. L. Lim",
7 | "date": "March 2015",
8 | "link_name": "VO Conesearch",
9 | "name": "",
10 | "published": false,
11 | "description" : "..."
12 | }
13 | },
14 | "nbformat": 3,
15 | "nbformat_minor": 0,
16 | "worksheets": [
17 | {
18 | "cells": [
19 | {
20 | "cell_type": "heading",
21 | "level": 1,
22 | "metadata": {},
23 | "source": [
24 | "VO Simple Cone Search Tutorial"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {},
30 | "source": [
31 | "This tutorial requires `astropy` 1.0 or greater because the coordinate systems API changed in v1.0 (see https://github.com/astropy/astropy-APEs/blob/master/APE5.rst), although the `vo` package was introduced in v0.3. Cone Search allows you to query a catalog of astronomical sources and obtain those that lie within a cone of a given radius around the given position. For more information on Cone Search, see http://docs.astropy.org/en/stable/vo/conesearch.html."
32 | ]
33 | },
34 | {
35 | "cell_type": "code",
36 | "collapsed": false,
37 | "input": [
38 | "# Python 3 compatibility; See https://docs.python.org/2/library/__future__.html\n",
39 | "from __future__ import absolute_import, division, print_function\n",
40 | "\n",
41 | "# Built-in Python library\n",
42 | "import time\n",
43 | "import warnings\n",
44 | "\n",
45 | "# Third-party software\n",
46 | "import numpy as np\n",
47 | "\n",
48 | "# Astropy\n",
49 | "import astropy\n",
50 | "from astropy import coordinates as coord\n",
51 | "from astropy import units as u\n",
52 | "from astropy.utils import data\n",
53 | "from astropy.vo import conf\n",
54 | "from astropy.vo.client import conesearch, vos_catalog\n",
55 | "\n",
56 | "# Do NOT proceed if printed version number is less than 1.0\n",
57 | "assert astropy.version.major >= 1, 'Astropy version is older than 1.0!'\n",
58 | "\n",
59 | "# This instructs iPython Notebook to plot within this browser,\n",
60 | "# instead of separate windows\n",
61 | "%matplotlib inline"
62 | ],
63 | "language": "python",
64 | "metadata": {},
65 | "outputs": []
66 | },
67 | {
68 | "cell_type": "markdown",
69 | "metadata": {},
70 | "source": [
71 | "It might be useful to list the available Cone Search catalogs first. By default, catalogs that pass nightly validation are included. Validation is hosted by Space Telescope Science Institute (STScI)."
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "collapsed": false,
77 | "input": [
78 | "conesearch.list_catalogs()"
79 | ],
80 | "language": "python",
81 | "metadata": {},
82 | "outputs": []
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {},
87 | "source": [
88 | "Next, let's pick an astronomical object of interest. For example, M31."
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "collapsed": false,
94 | "input": [
95 | "c = coord.SkyCoord.from_name('M31', frame='icrs')\n",
96 | "print(c)"
97 | ],
98 | "language": "python",
99 | "metadata": {},
100 | "outputs": []
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {},
105 | "source": [
106 | "By default, a basic Cone Search goes through the list of catalogs and *stops* at the first one that returns non-empty VO table. Let's search for objects within 0.1 degree around M31. You will see a lot of warnings that were generated by VO table parser but ignored by Cone Search service validator. VO compliance enforced by Cone Search providers is beyond the control of `astropy.vo` package."
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "collapsed": false,
112 | "input": [
113 | "result = conesearch.conesearch(c, 0.1 * u.degree)"
114 | ],
115 | "language": "python",
116 | "metadata": {},
117 | "outputs": []
118 | },
119 | {
120 | "cell_type": "code",
121 | "collapsed": false,
122 | "input": [
123 | "print('First non-empty table returned by', result.url)\n",
124 | "print('Number of rows is', result.nrows)"
125 | ],
126 | "language": "python",
127 | "metadata": {},
128 | "outputs": []
129 | },
130 | {
131 | "cell_type": "markdown",
132 | "metadata": {},
133 | "source": [
134 | "Extract metadata of this Cone Search catalog."
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "collapsed": false,
140 | "input": [
141 | "my_db = vos_catalog.get_remote_catalog_db(conf.conesearch_dbname)\n",
142 | "my_cat = my_db.get_catalog_by_url(result.url)\n",
143 | "print(my_cat.dumps())"
144 | ],
145 | "language": "python",
146 | "metadata": {},
147 | "outputs": []
148 | },
149 | {
150 | "cell_type": "markdown",
151 | "metadata": {},
152 | "source": [
153 | "If you have a favorite catalog in mind, you can also perform Cone Search only on that catalog. A list of available catalogs can be obtained by calling `conesearch.list_catalogs()`, as mentioned above."
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "collapsed": false,
159 | "input": [
160 | "result = conesearch.conesearch(\n",
161 | " c, 0.1 * u.degree, catalog_db='The USNO-A2.0 Catalogue (Monet+ 1998) 1')"
162 | ],
163 | "language": "python",
164 | "metadata": {},
165 | "outputs": []
166 | },
167 | {
168 | "cell_type": "code",
169 | "collapsed": false,
170 | "input": [
171 | "print('Number of rows is', result.nrows)"
172 | ],
173 | "language": "python",
174 | "metadata": {},
175 | "outputs": []
176 | },
177 | {
178 | "cell_type": "markdown",
179 | "metadata": {},
180 | "source": [
181 | "Let's explore the 3 rows of astronomical objects found within 0.1 degree of M31 in the given catalog and sort them by increasing distance. For this example, the VO table has 4 columns:\n",
182 | "\n",
183 | "* `_r` = Angular distance (in degrees) between object and M31\n",
184 | "* `_RAJ2000` = Right ascension of the object (epoch=J2000)\n",
185 | "* `_DEJ2000` = Declination of the object (epoch=J2000)\n",
186 | "* `USNO-A2.0` = Catalog ID of the object\n",
187 | "\n",
188 | "Note that column names, meanings, order, etc. might vary from catalog to catalog."
189 | ]
190 | },
191 | {
192 | "cell_type": "code",
193 | "collapsed": false,
194 | "input": [
195 | "data_array = result.array.data\n",
196 | "print(data_array)"
197 | ],
198 | "language": "python",
199 | "metadata": {},
200 | "outputs": []
201 | },
202 | {
203 | "cell_type": "code",
204 | "collapsed": false,
205 | "input": [
206 | "col_names = data_array.dtype.names\n",
207 | "print(col_names)"
208 | ],
209 | "language": "python",
210 | "metadata": {},
211 | "outputs": []
212 | },
213 | {
214 | "cell_type": "code",
215 | "collapsed": false,
216 | "input": [
217 | "distance = data_array['_r']\n",
218 | "sorted_indices = np.argsort(distance)\n",
219 | "sorted_data_array = data_array[sorted_indices]\n",
220 | "print(sorted_data_array)"
221 | ],
222 | "language": "python",
223 | "metadata": {},
224 | "outputs": []
225 | },
226 | {
227 | "cell_type": "markdown",
228 | "metadata": {},
229 | "source": [
230 | "You can also convert the distance to arcseconds."
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "collapsed": false,
236 | "input": [
237 | "distance_field = result.get_field_by_id('_r')\n",
238 | "print('Field title:', distance_field.title)\n",
239 | "print('Unit is', distance_field.unit)"
240 | ],
241 | "language": "python",
242 | "metadata": {},
243 | "outputs": []
244 | },
245 | {
246 | "cell_type": "code",
247 | "collapsed": false,
248 | "input": [
249 | "distance_arcsec = (distance * distance_field.unit).to(u.arcsec)\n",
250 | "for d_deg, d_arcsec in zip(distance, distance_arcsec):\n",
251 | " print(d_deg, 'deg converted to', d_arcsec)"
252 | ],
253 | "language": "python",
254 | "metadata": {},
255 | "outputs": []
256 | },
257 | {
258 | "cell_type": "markdown",
259 | "metadata": {},
260 | "source": [
261 | "What if you want *all* the results from *all* the catalogs? And you also want to suppress all the VO table warnings and informational messages?\n",
262 | "\n",
263 | "__Warning: This can be time and resource intensive.__"
264 | ]
265 | },
266 | {
267 | "cell_type": "code",
268 | "collapsed": false,
269 | "input": [
270 | "with warnings.catch_warnings():\n",
271 | " warnings.simplefilter('ignore')\n",
272 | " all_results = conesearch.search_all(c, 0.1 * u.degree, verbose=False)"
273 | ],
274 | "language": "python",
275 | "metadata": {},
276 | "outputs": []
277 | },
278 | {
279 | "cell_type": "code",
280 | "collapsed": false,
281 | "input": [
282 | "for url, tab in all_results.items():\n",
283 | " print(url, 'returned', tab.nrows, 'rows')"
284 | ],
285 | "language": "python",
286 | "metadata": {},
287 | "outputs": []
288 | },
289 | {
290 | "cell_type": "code",
291 | "collapsed": false,
292 | "input": [
293 | "my_favorite_result = all_results['http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=I/220&']\n",
294 | "print(my_favorite_result.array.data.dtype.names)\n",
295 | "print(my_favorite_result.array.data)"
296 | ],
297 | "language": "python",
298 | "metadata": {},
299 | "outputs": []
300 | },
301 | {
302 | "cell_type": "heading",
303 | "level": 3,
304 | "metadata": {},
305 | "source": [
306 | "Asynchronous Searches"
307 | ]
308 | },
309 | {
310 | "cell_type": "markdown",
311 | "metadata": {},
312 | "source": [
313 | "Asynchronous versions (i.e., search will run in the background) of `conesearch()` and `search_all()` are also available. Result can be obtained using the asynchronous instance's `get()` method that returns the result upon completion or after a given `timeout` value in seconds."
314 | ]
315 | },
316 | {
317 | "cell_type": "code",
318 | "collapsed": false,
319 | "input": [
320 | "async_search = conesearch.AsyncConeSearch(\n",
321 | " c, 0.1 * u.degree, catalog_db='The USNO-A2.0 Catalogue (Monet+ 1998) 1')\n",
322 | "print('Am I running?', async_search.running())\n",
323 | "\n",
324 | "time.sleep(3)\n",
325 | "print('After 3 seconds. Am I done?', async_search.done())\n",
326 | "print()\n",
327 | "\n",
328 | "result = async_search.get(timeout=30)\n",
329 | "print('Number of rows returned is', result.nrows)"
330 | ],
331 | "language": "python",
332 | "metadata": {},
333 | "outputs": []
334 | },
335 | {
336 | "cell_type": "code",
337 | "collapsed": false,
338 | "input": [
339 | "async_search_all = conesearch.AsyncSearchAll(c, 0.1 * u.degree)\n",
340 | "print('Am I running?', async_search_all.running())\n",
341 | "print('Am I done?', async_search_all.done())\n",
342 | "print()\n",
343 | "\n",
344 | "all_results = async_search_all.get(timeout=30)\n",
345 | "for url, tab in all_results.items():\n",
346 | " print(url, 'returned', tab.nrows, 'rows')"
347 | ],
348 | "language": "python",
349 | "metadata": {},
350 | "outputs": []
351 | },
352 | {
353 | "cell_type": "heading",
354 | "level": 3,
355 | "metadata": {},
356 | "source": [
357 | "Estimating the Search Time"
358 | ]
359 | },
360 | {
361 | "cell_type": "markdown",
362 | "metadata": {},
363 | "source": [
364 | "Let's predict the run time of performing Cone Search on `http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&` with a radius of 0.5 degrees. For now, the prediction assumes a very simple linear model, which might or might not reflect the actual trend.\n",
365 | "\n",
366 | "For this exercise, web query timeout should be temporarily increased to 30 seconds. This might take a while."
367 | ]
368 | },
369 | {
370 | "cell_type": "code",
371 | "collapsed": false,
372 | "input": [
373 | "with warnings.catch_warnings():\n",
374 | " warnings.simplefilter('ignore')\n",
375 | " with data.conf.set_temp('remote_timeout', 30):\n",
376 | " t_est, n_est = conesearch.predict_search(\n",
377 | " 'http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&',\n",
378 | " c, 0.5 * u.degree, verbose=False, plot=True)"
379 | ],
380 | "language": "python",
381 | "metadata": {},
382 | "outputs": []
383 | },
384 | {
385 | "cell_type": "code",
386 | "collapsed": false,
387 | "input": [
388 | "print('Predicted run time is', t_est, 'seconds')\n",
389 | "print('Predicted number of rows is', n_est)"
390 | ],
391 | "language": "python",
392 | "metadata": {},
393 | "outputs": []
394 | },
395 | {
396 | "cell_type": "markdown",
397 | "metadata": {},
398 | "source": [
399 | "Let's get the actual run time and number of rows to compare with the prediction above. Since the predicted run time is longer than default timeout, we have to temporarily set the timeout to 60 seconds. This might take a while.\n",
400 | "\n",
401 | "As you will see, the prediction is not spot on, but it is not too shabby (at least, not when I tried it). Note that both predicted and actual run time results also depend on network latency and responsiveness of the service provider."
402 | ]
403 | },
404 | {
405 | "cell_type": "code",
406 | "collapsed": false,
407 | "input": [
408 | "with data.conf.set_temp('remote_timeout', 60):\n",
409 | " t_real, tab = conesearch.conesearch_timer(\n",
410 | " c, 0.5 * u.degree,\n",
411 | " catalog_db='http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&',\n",
412 | " verbose=False)"
413 | ],
414 | "language": "python",
415 | "metadata": {},
416 | "outputs": []
417 | },
418 | {
419 | "cell_type": "code",
420 | "collapsed": false,
421 | "input": [
422 | "print('Actual run time is', t_real, 'seconds')\n",
423 | "print('Actual number of rows is', tab.nrows)"
424 | ],
425 | "language": "python",
426 | "metadata": {},
427 | "outputs": []
428 | }
429 | ],
430 | "metadata": {}
431 | }
432 | ]
433 | }
--------------------------------------------------------------------------------
/tutorials/Plot-Catalog/plot-catalog.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "astropy-tutorials": {
4 | "author": "Adrian M. Price-Whelan and Kelle Cruz ",
5 | "date": "July 2013",
6 | "description": "Demonstrates use of astropy.io.ascii for reading and writing ASCII data, astropy.coordinates and astropy.units for converting RA (as a sexagesimal angle) to decimal degrees, and matplotlib for making a color-magnitude diagram and on-sky locations in a mollweide projection.",
7 | "link_name": "Read and plot catalog information from a text file",
8 | "name": "",
9 | "published": true
10 | },
11 | "signature": "sha256:d8377959a9a80bb857cffd95a033224627c9005df5668385ca7518acb38f2bec"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "code",
20 | "collapsed": false,
21 | "input": [
22 | "import numpy as np\n",
23 | "\n",
24 | "# Set up matplotlib and use a nicer set of plot parameters\n",
25 | "%config InlineBackend.rc = {}\n",
26 | "import matplotlib\n",
27 | "matplotlib.rc_file(\"../../templates/matplotlibrc\")\n",
28 | "import matplotlib.pyplot as plt\n",
29 | "%matplotlib inline"
30 | ],
31 | "language": "python",
32 | "metadata": {},
33 | "outputs": []
34 | },
35 | {
36 | "cell_type": "heading",
37 | "level": 1,
38 | "metadata": {},
39 | "source": [
40 | "Read in catalog information from a text file and plot some parameters"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {},
46 | "source": [
47 | "Astropy provides functionality for reading in and manipulating tabular\n",
48 | "data through the `astropy.table` subpackage. An additional set of\n",
49 | "tools for reading and writing ASCII data are provided with the\n",
50 | "`astropy.io.ascii` subpackage, but fundamentally use the classes and\n",
51 | "methods implemented in `astropy.table`.\n",
52 | "\n",
53 | "We'll start by importing the `ascii` subpackage:"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "collapsed": false,
59 | "input": [
60 | "from astropy.io import ascii"
61 | ],
62 | "language": "python",
63 | "metadata": {},
64 | "outputs": []
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "metadata": {},
69 | "source": [
70 | "For many cases, it is sufficient to use the `ascii.read('filename')` \n",
71 | "function as a black box for reading data from table-formatted text \n",
72 | "files. By default, this function will try to figure out how your \n",
73 | "data is formatted/delimited (by default, `guess=True`). For example, \n",
74 | "if your data are:\n",
75 | "\n",
76 | " # name,ra,dec\n",
77 | " BLG100,17:51:00.0,-29:59:48\n",
78 | " BLG101,17:53:40.2,-29:49:52\n",
79 | " BLG102,17:56:20.2,-29:30:51\n",
80 | " BLG103,17:56:20.2,-30:06:22\n",
81 | " ...\n",
82 | "\n",
83 | "(see _simple_table.csv_)\n",
84 | "\n",
85 | "`ascii.read()` will return a `Table` object:"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "collapsed": false,
91 | "input": [
92 | "tbl = ascii.read(\"simple_table.csv\")\n",
93 | "tbl"
94 | ],
95 | "language": "python",
96 | "metadata": {},
97 | "outputs": []
98 | },
99 | {
100 | "cell_type": "markdown",
101 | "metadata": {},
102 | "source": [
103 | "The header names are automatically parsed from the top of the file,\n",
104 | "and the delimiter is inferred from the rest of the file -- awesome! \n",
105 | "We can access the columns directly from their names as 'keys' of the\n",
106 | "table object:"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "collapsed": false,
112 | "input": [
113 | "tbl[\"ra\"]"
114 | ],
115 | "language": "python",
116 | "metadata": {},
117 | "outputs": []
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "If we want to then convert the first RA (as a sexagesimal angle) to\n",
124 | "decimal degrees, for example, we can pluck out the first (0th) item in\n",
125 | "the column and use the `coordinates` subpackage to parse the string:"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "collapsed": false,
131 | "input": [
132 | "import astropy.coordinates as coord\n",
133 | "import astropy.units as u\n",
134 | "\n",
135 | "first_row = tbl[0] # get the first (0th) row\n",
136 | "ra = coord.Angle(first_row[\"ra\"], unit=u.hour) # create an Angle object\n",
137 | "ra.degree # convert to degrees"
138 | ],
139 | "language": "python",
140 | "metadata": {},
141 | "outputs": []
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "metadata": {},
146 | "source": [
147 | "Now let's look at a case where this breaks, and we have to specify some\n",
148 | "more options to the `read()` function. Our data may look a bit messier::\n",
149 | "\n",
150 | " ,,,,2MASS Photometry,,,,,,WISE Photometry,,,,,,,,Spectra,,,,Astrometry,,,,,,,,,,,\n",
151 | " Name,Designation,RA,Dec,Jmag,J_unc,Hmag,H_unc,Kmag,K_unc,W1,W1_unc,W2,W2_unc,W3,W3_unc,W4,W4_unc,Spectral Type,Spectra (FITS),Opt Spec Refs,NIR Spec Refs,pm_ra (mas),pm_ra_unc,pm_dec (mas),pm_dec_unc,pi (mas),pi_unc,radial velocity (km/s),rv_unc,Astrometry Refs,Discovery Refs,Group/Age,Note\n",
152 | " ,00 04 02.84 -64 10 35.6,1.01201,-64.18,15.79,0.07,14.83,0.07,14.01,0.05,13.37,0.03,12.94,0.03,12.18,0.24,9.16,null,L1\u03b3,,Kirkpatrick et al. 2010,,,,,,,,,,,Kirkpatrick et al. 2010,,\n",
153 | " PC 0025+04,00 27 41.97 +05 03 41.7,6.92489,5.06,16.19,0.09,15.29,0.10,14.96,0.12,14.62,0.04,14.14,0.05,12.24,null,8.89,null,M9.5\u03b2,,Mould et al. 1994,,0.0105,0.0004,-0.0008,0.0003,,,,,Faherty et al. 2009,Schneider et al. 1991,,,00 32 55.84 -44 05 05.8,8.23267,-44.08,14.78,0.04,13.86,0.03,13.27,0.04,12.82,0.03,12.49,0.03,11.73,0.19,9.29,null,L0\u03b3,,Cruz et al. 2009,,0.1178,0.0043,-0.0916,0.0043,38.4,4.8,,,Faherty et al. 2012,Reid et al. 2008,,\n",
154 | " ...\n",
155 | "\n",
156 | "(see _Young-Objects-Compilation.csv_)"
157 | ]
158 | },
159 | {
160 | "cell_type": "markdown",
161 | "metadata": {},
162 | "source": [
163 | "If we try to just use `ascii.read()` on this data, it fails to parse the names out, and the column names become `col` followed by the number of the column:"
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "collapsed": false,
169 | "input": [
170 | "tbl = ascii.read(\"Young-Objects-Compilation.csv\")\n",
171 | "tbl.colnames"
172 | ],
173 | "language": "python",
174 | "metadata": {},
175 | "outputs": []
176 | },
177 | {
178 | "cell_type": "markdown",
179 | "metadata": {},
180 | "source": [
181 | "What happened? The column names are just `col1`, `col2`, etc., the\n",
182 | "default names if `ascii.read()` is unable to parse out column\n",
183 | "names. We know it failed to read the column names, but also notice\n",
184 | "that the first row of data are strings -- something else went wrong!"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "collapsed": false,
190 | "input": [
191 | "tbl[0]"
192 | ],
193 | "language": "python",
194 | "metadata": {},
195 | "outputs": []
196 | },
197 | {
198 | "cell_type": "markdown",
199 | "metadata": {},
200 | "source": [
201 | "A few things are causing problems here. First, there are two header \n",
202 | "lines in the file and the header lines are not denoted by comment \n",
203 | "characters. The first line is actually some meta data that we don't\n",
204 | "care about, so we want to skip it. We can get around this problem by \n",
205 | "specifying the `header_start` keyword to the `ascii.read()` function. \n",
206 | "This keyword argument specifies the index of the row in the text file \n",
207 | "to read the column names from:"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "collapsed": false,
213 | "input": [
214 | "tbl = ascii.read(\"Young-Objects-Compilation.csv\", header_start=1)\n",
215 | "tbl.colnames"
216 | ],
217 | "language": "python",
218 | "metadata": {},
219 | "outputs": []
220 | },
221 | {
222 | "cell_type": "markdown",
223 | "metadata": {},
224 | "source": [
225 | "Great -- now the columns have the correct names, but there is still a\n",
226 | "problem: all of the columns have string data types, and the column\n",
227 | "names are still included as a row in the table. This is because by\n",
228 | "default the data are assumed to start on the second row (index=1). \n",
229 | "We can specify `data_start=2` to tell the reader that the data in\n",
230 | "this file actually start on the 3rd (index=2) row:"
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "collapsed": false,
236 | "input": [
237 | "tbl = ascii.read(\"Young-Objects-Compilation.csv\", header_start=1, data_start=2)"
238 | ],
239 | "language": "python",
240 | "metadata": {},
241 | "outputs": []
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "metadata": {},
246 | "source": [
247 | "Some of the columns have missing data, for example, some of the `RA` values are missing (denoted by -- when printed):"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "collapsed": false,
253 | "input": [
254 | "print(tbl['RA'])"
255 | ],
256 | "language": "python",
257 | "metadata": {},
258 | "outputs": []
259 | },
260 | {
261 | "cell_type": "markdown",
262 | "metadata": {},
263 | "source": [
264 | "This is called a __Masked column__ because some missing values are \n",
265 | "masked out upon display. If we want to use this numeric data, we have\n",
266 | "to tell `astropy` what to fill the missing values with. We can do this\n",
267 | "with the `.filled()` method. For example, to fill all of the missing\n",
268 | "values with `NaN`'s:"
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "collapsed": false,
274 | "input": [
275 | "tbl['RA'].filled(np.nan)"
276 | ],
277 | "language": "python",
278 | "metadata": {},
279 | "outputs": []
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {},
284 | "source": [
285 | "Let's recap what we've done so far, then make some plots with the\n",
286 | "data. Our data file has an extra line above the column names, so we\n",
287 | "use the `header_start` keyword to tell it to start from line 1 instead\n",
288 | "of line 0 (remember Python is 0-indexed!). We then used had to specify\n",
289 | "that the data starts on line 2 using the `data_start`\n",
290 | "keyword. Finally, we note some columns have missing values."
291 | ]
292 | },
293 | {
294 | "cell_type": "code",
295 | "collapsed": false,
296 | "input": [
297 | "data = ascii.read(\"Young-Objects-Compilation.csv\", header_start=1, data_start=2)"
298 | ],
299 | "language": "python",
300 | "metadata": {},
301 | "outputs": []
302 | },
303 | {
304 | "cell_type": "markdown",
305 | "metadata": {},
306 | "source": [
307 | "Now that we have our data loaded, let's plot a color-magnitude diagram."
308 | ]
309 | },
310 | {
311 | "cell_type": "markdown",
312 | "metadata": {},
313 | "source": [
314 | "Here we simply make a scatter plot of the J-K color on the x-axis\n",
315 | "against the J magnitude on the y-axis. We use a trick to flip the\n",
316 | "y-axis `plt.ylim(reversed(plt.ylim()))`. Called with no arguments,\n",
317 | "`plt.ylim()` will return a tuple with the axis bounds, \n",
318 | "e.g. (0,10). Calling the function _with_ arguments will set the limits \n",
319 | "of the axis, so we simply set the limits to be the reverse of whatever they\n",
320 | "were before. Using this `pylab`-style plotting is convenient for\n",
321 | "making quick plots and interactive use, but is not great if you need\n",
322 | "more control over your figures."
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "collapsed": false,
328 | "input": [
329 | "plt.scatter(data[\"Jmag\"] - data[\"Kmag\"], data[\"Jmag\"]) # plot J-K vs. J\n",
330 | "plt.ylim(reversed(plt.ylim())) # flip the y-axis\n",
331 | "plt.xlabel(\"$J-K_s$\", fontsize=20)\n",
332 | "plt.ylabel(\"$J$\", fontsize=20)"
333 | ],
334 | "language": "python",
335 | "metadata": {},
336 | "outputs": []
337 | },
338 | {
339 | "cell_type": "markdown",
340 | "metadata": {},
341 | "source": [
342 | "As a final example, we will plot the angular positions from the\n",
343 | "catalog on a 2D projection of the sky. Instead of using `pylab`-style\n",
344 | "plotting, we'll take a more object-oriented approach. We'll start by\n",
345 | "creating a `Figure` object and adding a single subplot to the\n",
346 | "figure. We can specify a projection with the `projection` keyword; in\n",
347 | "this example we will use a Mollweide projection. Unfortunately, it is \n",
348 | "highly non-trivial to make the matplotlib projection defined this way \n",
349 | "follow the celestial convention of longitude/RA increasing to the left. \n",
350 | "\n",
351 | "The axis object, `ax`, knows to expect angular coordinate\n",
352 | "values. An important fact is that it expects the values to be in\n",
353 | "_radians_, and it expects the azimuthal angle values to be between\n",
354 | "(-180\u00ba,180\u00ba). This is (currently) not customizable, so we have to\n",
355 | "coerce our RA data to conform to these rules! `astropy` provides a\n",
356 | "coordinate class for handling angular values, `astropy.coordinates.Angle`. \n",
357 | "We can convert our column of RA values to radians, and wrap the \n",
358 | "angle bounds using this class."
359 | ]
360 | },
361 | {
362 | "cell_type": "code",
363 | "collapsed": false,
364 | "input": [
365 | "import astropy.coordinates as coord\n",
366 | "ra = coord.Angle(data['RA'].filled(np.nan)*u.degree)\n",
367 | "ra = ra.wrap_at(180*u.degree)\n",
368 | "dec = coord.Angle(data['Dec'].filled(np.nan)*u.degree)"
369 | ],
370 | "language": "python",
371 | "metadata": {},
372 | "outputs": []
373 | },
374 | {
375 | "cell_type": "code",
376 | "collapsed": false,
377 | "input": [
378 | "fig = plt.figure(figsize=(8,6))\n",
379 | "ax = fig.add_subplot(111, projection=\"mollweide\")\n",
380 | "ax.scatter(ra.radian, dec.radian)"
381 | ],
382 | "language": "python",
383 | "metadata": {},
384 | "outputs": []
385 | },
386 | {
387 | "cell_type": "markdown",
388 | "metadata": {},
389 | "source": [
390 | "By default, matplotlib will add degree ticklabels, so let's change the\n",
391 | "horizontal (x) tick labels to be in units of hours, and display a grid"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "collapsed": false,
397 | "input": [
398 | "fig = plt.figure(figsize=(8,6))\n",
399 | "ax = fig.add_subplot(111, projection=\"mollweide\")\n",
400 | "ax.scatter(ra.radian, dec.radian)\n",
401 | "ax.set_xticklabels(['14h','16h','18h','20h','22h','0h','2h','4h','6h','8h','10h'])\n",
402 | "ax.grid(True)"
403 | ],
404 | "language": "python",
405 | "metadata": {},
406 | "outputs": []
407 | },
408 | {
409 | "cell_type": "markdown",
410 | "metadata": {},
411 | "source": [
412 | "We can save this figure as a PDF using the `savefig` function:"
413 | ]
414 | },
415 | {
416 | "cell_type": "code",
417 | "collapsed": true,
418 | "input": [
419 | "fig.savefig(\"map.pdf\")"
420 | ],
421 | "language": "python",
422 | "metadata": {},
423 | "outputs": []
424 | },
425 | {
426 | "cell_type": "heading",
427 | "level": 2,
428 | "metadata": {},
429 | "source": [
430 | "Exercises"
431 | ]
432 | },
433 | {
434 | "cell_type": "markdown",
435 | "metadata": {},
436 | "source": [
437 | "Make the map figures as just above, but color the points by the `'Kmag'` column of the table."
438 | ]
439 | },
440 | {
441 | "cell_type": "code",
442 | "collapsed": false,
443 | "input": [],
444 | "language": "python",
445 | "metadata": {},
446 | "outputs": []
447 | },
448 | {
449 | "cell_type": "markdown",
450 | "metadata": {},
451 | "source": [
452 | "Try making the maps again, but with each of the following projections: 'aitoff', 'hammer', 'lambert', and `None` (which is the same as not giving any projection). Do any of them make the data seem easier to understand?"
453 | ]
454 | },
455 | {
456 | "cell_type": "code",
457 | "collapsed": false,
458 | "input": [],
459 | "language": "python",
460 | "metadata": {},
461 | "outputs": []
462 | }
463 | ],
464 | "metadata": {}
465 | }
466 | ]
467 | }
--------------------------------------------------------------------------------
/templates/matplotlibrc:
--------------------------------------------------------------------------------
1 | ### MATPLOTLIBRC FORMAT
2 |
3 | # This is a sample matplotlib configuration file - you can find a copy
4 | # of it on your system in
5 | # site-packages/matplotlib/mpl-data/matplotlibrc. If you edit it
6 | # there, please note that it will be overridden in your next install.
7 | # If you want to keep a permanent local copy that will not be
8 | # over-written, place it in HOME/.matplotlib/matplotlibrc (unix/linux
9 | # like systems) and C:\Documents and Settings\yourname\.matplotlib
10 | # (win32 systems).
11 | #
12 | # This file is best viewed in a editor which supports python mode
13 | # syntax highlighting. Blank lines, or lines starting with a comment
14 | # symbol, are ignored, as are trailing comments. Other lines must
15 | # have the format
16 | # key : val # optional comment
17 | #
18 | # Colors: for the color values below, you can either use - a
19 | # matplotlib color string, such as r, k, or b - an rgb tuple, such as
20 | # (1.0, 0.5, 0.0) - a hex string, such as ff00ff or #ff00ff - a scalar
21 | # grayscale intensity such as 0.75 - a legal html color name, eg red,
22 | # blue, darkslategray
23 |
24 | #### CONFIGURATION BEGINS HERE
25 |
26 | # the default backend; one of GTK GTKAgg GTKCairo CocoaAgg FltkAgg
27 | # MacOSX QtAgg Qt4Agg TkAgg WX WXAgg Agg Cairo GDK PS PDF SVG Template
28 | # You can also deploy your own backend outside of matplotlib by
29 | # referring to the module name (which must be in the PYTHONPATH) as
30 | # 'module://my_backend'
31 | # backend : MacOSX
32 |
33 | # if you are runing pyplot inside a GUI and your backend choice
34 | # conflicts, we will automatically try and find a compatible one for
35 | # you if backend_fallback is True
36 | #backend_fallback: True
37 | interactive : True
38 | toolbar : toolbar2 # None | classic | toolbar2
39 | timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris
40 |
41 | # Where your matplotlib data lives if you installed to a non-default
42 | # location. This is where the matplotlib fonts, bitmaps, etc reside
43 | #datapath : /home/jdhunter/mpldata
44 |
45 |
46 | ### LINES
47 | # See http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.lines for more
48 | # information on line properties.
49 | lines.linewidth : 1.0 # line width in points
50 | #lines.linestyle : - # solid line
51 | # lines.color : purple
52 | #lines.marker : None # the default marker
53 | #lines.markeredgewidth : 0.5 # the line width around the marker symbol
54 | #lines.markersize : 6 # markersize, in points
55 | #lines.dash_joinstyle : miter # miter|round|bevel
56 | #lines.dash_capstyle : butt # butt|round|projecting
57 | #lines.solid_joinstyle : miter # miter|round|bevel
58 | #lines.solid_capstyle : projecting # butt|round|projecting
59 | lines.antialiased : True # render lines in antialised (no jaggies)
60 |
61 | ### PATCHES
62 | # Patches are graphical objects that fill 2D space, like polygons or
63 | # circles. See
64 | # http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.patches
65 | # information on patch properties
66 | patch.linewidth : 0.5 # edge width in points
67 | patch.facecolor : 348ABD # blue
68 | patch.edgecolor : eeeeee
69 | patch.antialiased : True # render patches in antialised (no jaggies)
70 |
71 | ### FONT
72 | #
73 | # font properties used by text.Text. See
74 | # http://matplotlib.sourceforge.net/api/font_manager_api.html for more
75 | # information on font properties. The 6 font properties used for font
76 | # matching are given below with their default values.
77 | #
78 | # The font.family property has five values: 'serif' (e.g. Times),
79 | # 'sans-serif' (e.g. Helvetica), 'cursive' (e.g. Zapf-Chancery),
80 | # 'fantasy' (e.g. Western), and 'monospace' (e.g. Courier). Each of
81 | # these font families has a default list of font names in decreasing
82 | # order of priority associated with them.
83 | #
84 | # The font.style property has three values: normal (or roman), italic
85 | # or oblique. The oblique style will be used for italic, if it is not
86 | # present.
87 | #
88 | # The font.variant property has two values: normal or small-caps. For
89 | # TrueType fonts, which are scalable fonts, small-caps is equivalent
90 | # to using a font size of 'smaller', or about 83% of the current font
91 | # size.
92 | #
93 | # The font.weight property has effectively 13 values: normal, bold,
94 | # bolder, lighter, 100, 200, 300, ..., 900. Normal is the same as
95 | # 400, and bold is 700. bolder and lighter are relative values with
96 | # respect to the current weight.
97 | #
98 | # The font.stretch property has 11 values: ultra-condensed,
99 | # extra-condensed, condensed, semi-condensed, normal, semi-expanded,
100 | # expanded, extra-expanded, ultra-expanded, wider, and narrower. This
101 | # property is not currently implemented.
102 | #
103 | # The font.size property is the default font size for text, given in pts.
104 | # 12pt is the standard value.
105 | #
106 | font.family : sans-serif
107 | #font.style : normal
108 | #font.variant : normal
109 | #font.weight : medium
110 | #font.stretch : normal
111 | # note that font.size controls default text sizes. To configure
112 | # special text sizes tick labels, axes, labels, title, etc, see the rc
113 | # settings for axes and ticks. Special text sizes can be defined
114 | # relative to font.size, using the following values: xx-small, x-small,
115 | # small, medium, large, x-large, xx-large, larger, or smaller
116 | font.size : 12.0
117 | # font.serif : Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
118 | font.sans-serif : Arial, Helvetica, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Avant Garde, sans-serif
119 | #font.cursive : Apple Chancery, Textile, Zapf Chancery, Sand, cursive
120 | #font.fantasy : Comic Sans MS, Chicago, Charcoal, Impact, Western, fantasy
121 | font.monospace : Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace
122 |
123 | ### TEXT
124 | # text properties used by text.Text. See
125 | # http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.text for more
126 | # information on text properties
127 |
128 | #text.color : black
129 |
130 | ### LaTeX customizations. See http://www.scipy.org/Wiki/Cookbook/Matplotlib/UsingTex
131 | #text.usetex : False # use latex for all text handling. The following fonts
132 | # are supported through the usual rc parameter settings:
133 | # new century schoolbook, bookman, times, palatino,
134 | # zapf chancery, charter, serif, sans-serif, helvetica,
135 | # avant garde, courier, monospace, computer modern roman,
136 | # computer modern sans serif, computer modern typewriter
137 | # If another font is desired which can loaded using the
138 | # LaTeX \usepackage command, please inquire at the
139 | # matplotlib mailing list
140 | #text.latex.unicode : False # use "ucs" and "inputenc" LaTeX packages for handling
141 | # unicode strings.
142 | #text.latex.preamble : # IMPROPER USE OF THIS FEATURE WILL LEAD TO LATEX FAILURES
143 | # AND IS THEREFORE UNSUPPORTED. PLEASE DO NOT ASK FOR HELP
144 | # IF THIS FEATURE DOES NOT DO WHAT YOU EXPECT IT TO.
145 | # preamble is a comma separated list of LaTeX statements
146 | # that are included in the LaTeX document preamble.
147 | # An example:
148 | # text.latex.preamble : \usepackage{bm},\usepackage{euler}
149 | # The following packages are always loaded with usetex, so
150 | # beware of package collisions: color, geometry, graphicx,
151 | # type1cm, textcomp. Adobe Postscript (PSSNFS) font packages
152 | # may also be loaded, depending on your font settings
153 |
154 | #text.dvipnghack : None # some versions of dvipng don't handle alpha
155 | # channel properly. Use True to correct
156 | # and flush ~/.matplotlib/tex.cache
157 | # before testing and False to force
158 | # correction off. None will try and
159 | # guess based on your dvipng version
160 |
161 | #text.markup : 'plain' # Affects how text, such as titles and labels, are
162 | # interpreted by default.
163 | # 'plain': As plain, unformatted text
164 | # 'tex': As TeX-like text. Text between $'s will be
165 | # formatted as a TeX math expression.
166 | # This setting has no effect when text.usetex is True.
167 | # In that case, all text will be sent to TeX for
168 | # processing.
169 |
170 | #text.hinting : True # If True, text will be hinted, otherwise not. This only
171 | # affects the Agg backend.
172 |
173 | # The following settings allow you to select the fonts in math mode.
174 | # They map from a TeX font name to a fontconfig font pattern.
175 | # These settings are only used if mathtext.fontset is 'custom'.
176 | # Note that this "custom" mode is unsupported and may go away in the
177 | # future.
178 | #mathtext.cal : cursive
179 | #mathtext.rm : serif
180 | #mathtext.tt : monospace
181 | #mathtext.it : serif:italic
182 | #mathtext.bf : serif:bold
183 | #mathtext.sf : sans
184 | #mathtext.fontset : cm # Should be 'cm' (Computer Modern), 'stix',
185 | # 'stixsans' or 'custom'
186 | #mathtext.fallback_to_cm : True # When True, use symbols from the Computer Modern
187 | # fonts when a symbol can not be found in one of
188 | # the custom math fonts.
189 |
190 | #mathtext.default : it # The default font to use for math.
191 | # Can be any of the LaTeX font names, including
192 | # the special name "regular" for the same font
193 | # used in regular text.
194 |
195 | ### AXES
196 | # default face and edge color, default tick sizes,
197 | # default fontsizes for ticklabels, and so on. See
198 | # http://matplotlib.sourceforge.net/api/axes_api.html#module-matplotlib.axes
199 | #axes.hold : True # whether to clear the axes by default on
200 | axes.facecolor : ffffff # axes background color
201 | axes.edgecolor : black # axes edge color
202 | axes.linewidth : 1 # edge linewidth
203 | axes.grid : True # display grid or not
204 | axes.titlesize : x-large # fontsize of the axes title
205 | axes.labelweight : bold
206 | axes.labelsize : large # fontsize of the x any y labels
207 | axes.labelcolor : black
208 | axes.axisbelow : True # whether axis gridlines and ticks are below
209 | # the axes elements (lines, text, etc)
210 | #axes.formatter.limits : -7, 7 # use scientific notation if log10
211 | # of the axis range is smaller than the
212 | # first or larger than the second
213 | #axes.unicode_minus : True # use unicode for the minus symbol
214 | # rather than hypen. See http://en.wikipedia.org/wiki/Plus_sign#Plus_sign
215 | axes.color_cycle : 348ABD, 7A68A6, A60628, 467821, CF4457, 188487, E24A33
216 | # E24A33 : orange
217 | # 7A68A6 : purple
218 | # 348ABD : blue
219 | # 188487 : turquoise
220 | # A60628 : red
221 | # CF4457 : pink
222 | # 467821 : green
223 |
224 |
225 |
226 |
227 | # color cycle for plot lines
228 | # as list of string colorspecs:
229 | # single letter, long name, or
230 | # web-style hex
231 |
232 | #polaraxes.grid : True # display grid on polar axes
233 | #axes3d.grid : True # display grid on 3d axes
234 |
235 | ### TICKS
236 | # see http://matplotlib.sourceforge.net/api/axis_api.html#matplotlib.axis.Tick
237 | xtick.major.size : 0 # major tick size in points
238 | xtick.minor.size : 0 # minor tick size in points
239 | xtick.major.pad : 6 # distance to major tick label in points
240 | xtick.minor.pad : 6 # distance to the minor tick label in points
241 | xtick.color : black # color of the tick labels
242 | #xtick.labelsize : medium # fontsize of the tick labels
243 | xtick.direction : in # direction: in or out
244 |
245 | ytick.major.size : 0 # major tick size in points
246 | ytick.minor.size : 0 # minor tick size in points
247 | ytick.major.pad : 6 # distance to major tick label in points
248 | ytick.minor.pad : 6 # distance to the minor tick label in points
249 | ytick.color : black # color of the tick labels
250 | #ytick.labelsize : medium # fontsize of the tick labels
251 | ytick.direction : in # direction: in or out
252 |
253 |
254 | ### GRIDS
255 | #grid.color : black # grid color
256 | #grid.linestyle : : # dotted
257 | #grid.linewidth : 0.5 # in points
258 |
259 | ### Legend
260 | legend.fancybox : True # if True, use a rounded box for the
261 | # legend, else a rectangle
262 | #legend.isaxes : True
263 | legend.numpoints : 1 # the number of points in the legend line
264 | #legend.fontsize : large
265 | #legend.pad : 0.0 # deprecated; the fractional whitespace inside the legend border
266 | #legend.borderpad : 0.5 # border whitspace in fontsize units
267 | #legend.markerscale : 1.0 # the relative size of legend markers vs. original
268 | # the following dimensions are in axes coords
269 | #legend.labelsep : 0.010 # the vertical space between the legend entries
270 | #legend.handlelen : 0.05 # the length of the legend lines
271 | #legend.handletextsep : 0.02 # the space between the legend line and legend text
272 | #legend.axespad : 0.02 # the border between the axes and legend edge
273 | #legend.shadow : False
274 |
275 | ### FIGURE
276 | # See http://matplotlib.sourceforge.net/api/figure_api.html#matplotlib.figure.Figure
277 | figure.figsize : 8, 6 # figure size in inches
278 | # figure.dpi : 150 # figure dots per inch
279 | figure.facecolor : 1.00 # figure facecolor; 0.75 is scalar gray
280 | figure.edgecolor : 0.0 # figure edgecolor
281 |
282 | # The figure subplot parameters. All dimensions are fraction of the
283 | # figure width or height
284 | #figure.subplot.left : 0.125 # the left side of the subplots of the figure
285 | #figure.subplot.right : 0.9 # the right side of the subplots of the figure
286 | #figure.subplot.bottom : 0.1 # the bottom of the subplots of the figure
287 | #figure.subplot.top : 0.9 # the top of the subplots of the figure
288 | #figure.subplot.wspace : 0.2 # the amount of width reserved for blank space between subplots
289 | figure.subplot.hspace : 0.5 # the amount of height reserved for white space between subplots
290 |
291 | ### IMAGES
292 | #image.aspect : equal # equal | auto | a number
293 | #image.interpolation : bilinear # see help(imshow) for options
294 | #image.cmap : jet # gray | jet etc...
295 | #image.lut : 256 # the size of the colormap lookup table
296 | #image.origin : upper # lower | upper
297 | #image.resample : False
298 |
299 | ### CONTOUR PLOTS
300 | #contour.negative_linestyle : dashed # dashed | solid
301 |
302 | ### Agg rendering
303 | ### Warning: experimental, 2008/10/10
304 | #agg.path.chunksize : 0 # 0 to disable; values in the range
305 | # 10000 to 100000 can improve speed slightly
306 | # and prevent an Agg rendering failure
307 | # when plotting very large data sets,
308 | # especially if they are very gappy.
309 | # It may cause minor artifacts, though.
310 | # A value of 20000 is probably a good
311 | # starting point.
312 | ### SAVING FIGURES
313 | #path.simplify : True # When True, simplify paths by removing "invisible"
314 | # points to reduce file size and increase rendering
315 | # speed
316 | #path.simplify_threshold : 0.1 # The threshold of similarity below which
317 | # vertices will be removed in the simplification
318 | # process
319 | #path.snap : True # When True, rectilinear axis-aligned paths will be snapped to
320 | # the nearest pixel when certain criteria are met. When False,
321 | # paths will never be snapped.
322 |
323 | # the default savefig params can be different from the display params
324 | # Eg, you may want a higher resolution, or to make the figure
325 | # background white
326 | savefig.dpi : 72 # figure dots per inch
327 | #savefig.facecolor : white # figure facecolor when saving
328 | #savefig.edgecolor : white # figure edgecolor when saving
329 | #savefig.extension : auto # what extension to use for savefig('foo'), or 'auto'
330 |
331 | #cairo.format : png # png, ps, pdf, svg
332 |
333 | # tk backend params
334 | #tk.window_focus : False # Maintain shell focus for TkAgg
335 |
336 | # ps backend params
337 | #ps.papersize : letter # auto, letter, legal, ledger, A0-A10, B0-B10
338 | #ps.useafm : False # use of afm fonts, results in small files
339 | #ps.usedistiller : False # can be: None, ghostscript or xpdf
340 | # Experimental: may produce smaller files.
341 | # xpdf intended for production of publication quality files,
342 | # but requires ghostscript, xpdf and ps2eps
343 | #ps.distiller.res : 6000 # dpi
344 | #ps.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
345 |
346 | # pdf backend params
347 | #pdf.compression : 6 # integer from 0 to 9
348 | # 0 disables compression (good for debugging)
349 | #pdf.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
350 |
351 | # svg backend params
352 | #svg.image_inline : True # write raster image data directly into the svg file
353 | #svg.image_noscale : False # suppress scaling of raster data embedded in SVG
354 | #svg.embed_char_paths : True # embed character outlines in the SVG file
355 |
356 | # docstring params
357 | #docstring.hardcopy = False # set this when you want to generate hardcopy docstring
358 |
359 | # Set the verbose flags. This controls how much information
360 | # matplotlib gives you at runtime and where it goes. The verbosity
361 | # levels are: silent, helpful, debug, debug-annoying. Any level is
362 | # inclusive of all the levels below it. If your setting is "debug",
363 | # you'll get all the debug and helpful messages. When submitting
364 | # problems to the mailing-list, please set verbose to "helpful" or "debug"
365 | # and paste the output into your report.
366 | #
367 | # The "fileo" gives the destination for any calls to verbose.report.
368 | # These objects can a filename, or a filehandle like sys.stdout.
369 | #
370 | # You can override the rc default verbosity from the command line by
371 | # giving the flags --verbose-LEVEL where LEVEL is one of the legal
372 | # levels, eg --verbose-helpful.
373 | #
374 | # You can access the verbose instance in your code
375 | # from matplotlib import verbose.
376 | #verbose.level : silent # one of silent, helpful, debug, debug-annoying
377 | #verbose.fileo : sys.stdout # a log filename, sys.stdout or sys.stderr
378 |
379 | # Event keys to interact with figures/plots via keyboard.
380 | # Customize these settings according to your needs.
381 | # Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '')
382 |
383 | keymap.fullscreen : f # toggling
384 | keymap.home : h, r, home # home or reset mnemonic
385 | keymap.back : left, c, backspace # forward / backward keys to enable
386 | keymap.forward : right, v # left handed quick navigation
387 | keymap.pan : p # pan mnemonic
388 | keymap.zoom : o # zoom mnemonic
389 | keymap.save : s # saving current figure
390 | keymap.grid : g # switching on/off a grid in current axes
391 | keymap.yscale : l # toggle scaling of y-axes ('log'/'linear')
392 | keymap.xscale : L, k # toggle scaling of x-axes ('log'/'linear')
393 | keymap.all_axes : a # enable all axes
394 |
--------------------------------------------------------------------------------
/html/css/docs.css:
--------------------------------------------------------------------------------
1 | /* Add additional stylesheets below
2 | -------------------------------------------------- */
3 | /*
4 | Bootstrap's documentation styles
5 | Special styles for presenting Bootstrap's documentation and examples
6 |
7 | Note: if you want to make specific modifications for the tutorials' notebooks,
8 | it's probably better to go into the style.css (look for the #notebook selectors).
9 | That way we can mostly keep them in one place.
10 | */
11 |
12 |
13 | /* Body and structure
14 | -------------------------------------------------- */
15 | body {
16 | position: relative;
17 | background-color: #fff;
18 | background-repeat: repeat-x;
19 | background-position: 0 40px;
20 | padding-top: 40px;
21 | }
22 |
23 |
24 | /* Tweak navbar brand link to be super sleek
25 | -------------------------------------------------- */
26 | .navbar-fixed-top .brand {
27 | padding-right: 0;
28 | padding-left: 0;
29 | margin-left: 20px;
30 | float: right;
31 | font-weight: bold;
32 | color: #000;
33 | text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.125);
34 | -webkit-transition: all .2s linear;
35 | -moz-transition: all .2s linear;
36 | transition: all .2s linear;
37 | }
38 | .navbar-fixed-top .brand:hover {
39 | text-decoration: none;
40 | }
41 |
42 |
43 | /* Space out sub-sections more
44 | -------------------------------------------------- */
45 | section {
46 | padding-top: 60px;
47 | }
48 |
49 | /* Faded out hr */
50 | hr.soften {
51 | height: 1px;
52 | margin: 54px 0;
53 | background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
54 | background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
55 | background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
56 | background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
57 | border: 0;
58 | }
59 |
60 |
61 | /* Jumbotrons
62 | -------------------------------------------------- */
63 | .jumbotron {
64 | position: relative;
65 | }
66 | .jumbotron h1 {
67 | margin-bottom: 9px;
68 | font-size: 81px;
69 | font-weight: bold;
70 | letter-spacing: -1px;
71 | line-height: 1;
72 | }
73 | .jumbotron p {
74 | margin-bottom: 18px;
75 | font-weight: 300;
76 | }
77 | .jumbotron .btn-large {
78 | font-size: 20px;
79 | font-weight: normal;
80 | padding: 14px 24px;
81 | margin-right: 10px;
82 | -webkit-border-radius: 6px;
83 | -moz-border-radius: 6px;
84 | border-radius: 6px;
85 | }
86 | .jumbotron .btn-large small {
87 | font-size: 14px;
88 | }
89 |
90 | /* Masthead (docs home) */
91 | .masthead {
92 | margin-bottom: 72px;
93 | }
94 | .masthead h1,
95 | .masthead p {
96 | text-align: center;
97 | }
98 | .masthead h1 {
99 | margin-bottom: 18px;
100 | }
101 | .masthead p {
102 | margin-left: 5%;
103 | margin-right: 5%;
104 | font-size: 30px;
105 | line-height: 36px;
106 | }
107 |
108 |
109 | /* Specific jumbotrons
110 | ------------------------- */
111 | /* supporting docs pages */
112 | .subhead {
113 | padding-bottom: 0;
114 | margin-bottom: 9px;
115 | }
116 | .subhead h1 {
117 | font-size: 54px;
118 | }
119 |
120 | /* Subnav */
121 | .subnav {
122 | width: 100%;
123 | height: 36px;
124 | background-color: #eeeeee; /* Old browsers */
125 | background-repeat: repeat-x; /* Repeat the gradient */
126 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* FF3.6+ */
127 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(100%,#eeeeee)); /* Chrome,Safari4+ */
128 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Chrome 10+,Safari 5.1+ */
129 | background-image: -ms-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* IE10+ */
130 | background-image: -o-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Opera 11.10+ */
131 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#eeeeee',GradientType=0 ); /* IE6-9 */
132 | background-image: linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* W3C */
133 | border: 1px solid #e5e5e5;
134 | -webkit-border-radius: 4px;
135 | -moz-border-radius: 4px;
136 | border-radius: 4px;
137 | }
138 | .subnav .nav {
139 | margin-bottom: 0;
140 | }
141 | .subnav .nav > li > a {
142 | margin: 0;
143 | padding-top: 11px;
144 | padding-bottom: 11px;
145 | border-left: 1px solid #f5f5f5;
146 | border-right: 1px solid #e5e5e5;
147 | -webkit-border-radius: 0;
148 | -moz-border-radius: 0;
149 | border-radius: 0;
150 | }
151 | .subnav .nav > .active > a,
152 | .subnav .nav > .active > a:hover {
153 | padding-left: 13px;
154 | color: #777;
155 | background-color: #e9e9e9;
156 | border-right-color: #ddd;
157 | border-left: 0;
158 | -webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
159 | -moz-box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
160 | box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
161 | }
162 | .subnav .nav > .active > a .caret,
163 | .subnav .nav > .active > a:hover .caret {
164 | border-top-color: #777;
165 | }
166 | .subnav .nav > li:first-child > a,
167 | .subnav .nav > li:first-child > a:hover {
168 | border-left: 0;
169 | padding-left: 12px;
170 | -webkit-border-radius: 4px 0 0 4px;
171 | -moz-border-radius: 4px 0 0 4px;
172 | border-radius: 4px 0 0 4px;
173 | }
174 | .subnav .nav > li:last-child > a {
175 | border-right: 0;
176 | }
177 | .subnav .dropdown-menu {
178 | -webkit-border-radius: 0 0 4px 4px;
179 | -moz-border-radius: 0 0 4px 4px;
180 | border-radius: 0 0 4px 4px;
181 | }
182 |
183 | /* Fixed subnav on scroll, but only for 980px and up (sorry IE!) */
184 | @media (min-width: 980px) {
185 | .subnav-fixed {
186 | position: fixed;
187 | top: 40px;
188 | left: 0;
189 | right: 0;
190 | z-index: 1020; /* 10 less than .navbar-fixed to prevent any overlap */
191 | border-color: #d5d5d5;
192 | border-width: 0 0 1px; /* drop the border on the fixed edges */
193 | -webkit-border-radius: 0;
194 | -moz-border-radius: 0;
195 | border-radius: 0;
196 | -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
197 | -moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
198 | box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
199 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); /* IE6-9 */
200 | }
201 | .subnav-fixed .nav {
202 | width: 938px;
203 | margin: 0 auto;
204 | padding: 0 1px;
205 | }
206 | .subnav .nav > li:first-child > a,
207 | .subnav .nav > li:first-child > a:hover {
208 | -webkit-border-radius: 0;
209 | -moz-border-radius: 0;
210 | border-radius: 0;
211 | }
212 | }
213 |
214 |
215 | /* Quick links
216 | -------------------------------------------------- */
217 | .bs-links {
218 | margin: 36px 0;
219 | }
220 | .quick-links {
221 | min-height: 30px;
222 | margin: 0;
223 | padding: 5px 20px;
224 | list-style: none;
225 | text-align: center;
226 | overflow: hidden;
227 | }
228 | .quick-links:first-child {
229 | min-height: 0;
230 | }
231 | .quick-links li {
232 | display: inline;
233 | margin: 0 8px;
234 | color: #999;
235 | }
236 | .quick-links .github-btn,
237 | .quick-links .tweet-btn,
238 | .quick-links .follow-btn {
239 | position: relative;
240 | top: 5px;
241 | }
242 |
243 |
244 | /* Marketing section of Overview
245 | -------------------------------------------------- */
246 | .marketing .row {
247 | margin-bottom: 9px;
248 | }
249 | .marketing h1 {
250 | margin: 36px 0 27px;
251 | font-size: 40px;
252 | font-weight: 300;
253 | text-align: center;
254 | }
255 | .marketing h2,
256 | .marketing h3 {
257 | font-weight: 300;
258 | }
259 | .marketing h2 {
260 | font-size: 22px;
261 | }
262 | .marketing p {
263 | margin-right: 10px;
264 | }
265 | .marketing .bs-icon {
266 | float: left;
267 | margin: 7px 10px 0 0;
268 | opacity: .8;
269 | }
270 | .marketing .small-bs-icon {
271 | float: left;
272 | margin: 4px 5px 0 0;
273 | }
274 |
275 |
276 |
277 | /* Footer
278 | -------------------------------------------------- */
279 | .footer {
280 | margin-top: 45px;
281 | padding: 35px 0 36px;
282 | border-top: 1px solid #e5e5e5;
283 | }
284 | .footer p {
285 | margin-bottom: 0;
286 | color: #555;
287 | }
288 |
289 |
290 |
291 | /* Special grid styles
292 | -------------------------------------------------- */
293 | .show-grid {
294 | margin-top: 10px;
295 | margin-bottom: 20px;
296 | }
297 | .show-grid [class*="span"] {
298 | background-color: #eee;
299 | text-align: center;
300 | -webkit-border-radius: 3px;
301 | -moz-border-radius: 3px;
302 | border-radius: 3px;
303 | min-height: 30px;
304 | line-height: 30px;
305 | }
306 | .show-grid:hover [class*="span"] {
307 | background: #ddd;
308 | }
309 | .show-grid .show-grid {
310 | margin-top: 0;
311 | margin-bottom: 0;
312 | }
313 | .show-grid .show-grid [class*="span"] {
314 | background-color: #ccc;
315 | }
316 |
317 |
318 | /* Render mini layout previews
319 | -------------------------------------------------- */
320 | .mini-layout {
321 | border: 1px solid #ddd;
322 | -webkit-border-radius: 6px;
323 | -moz-border-radius: 6px;
324 | border-radius: 6px;
325 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.075);
326 | -moz-box-shadow: 0 1px 2px rgba(0,0,0,.075);
327 | box-shadow: 0 1px 2px rgba(0,0,0,.075);
328 | }
329 | .mini-layout {
330 | height: 240px;
331 | margin-bottom: 20px;
332 | padding: 9px;
333 | }
334 | .mini-layout div {
335 | -webkit-border-radius: 3px;
336 | -moz-border-radius: 3px;
337 | border-radius: 3px;
338 | }
339 | .mini-layout .mini-layout-body {
340 | background-color: #dceaf4;
341 | margin: 0 auto;
342 | width: 70%;
343 | height: 240px;
344 | }
345 | .mini-layout.fluid .mini-layout-sidebar,
346 | .mini-layout.fluid .mini-layout-header,
347 | .mini-layout.fluid .mini-layout-body {
348 | float: left;
349 | }
350 | .mini-layout.fluid .mini-layout-sidebar {
351 | background-color: #bbd8e9;
352 | width: 20%;
353 | height: 240px;
354 | }
355 | .mini-layout.fluid .mini-layout-body {
356 | width: 77.5%;
357 | margin-left: 2.5%;
358 | }
359 |
360 |
361 | /* Popover docs
362 | -------------------------------------------------- */
363 | .popover-well {
364 | min-height: 160px;
365 | }
366 | .popover-well .popover {
367 | display: block;
368 | }
369 | .popover-well .popover-wrapper {
370 | width: 50%;
371 | height: 160px;
372 | float: left;
373 | margin-left: 55px;
374 | position: relative;
375 | }
376 | .popover-well .popover-menu-wrapper {
377 | height: 80px;
378 | }
379 | .large-bird {
380 | margin: 5px 0 0 310px;
381 | opacity: .1;
382 | }
383 |
384 |
385 | /* Download page
386 | -------------------------------------------------- */
387 | .download .page-header {
388 | margin-top: 36px;
389 | }
390 | .page-header .toggle-all {
391 | margin-top: 5px;
392 | }
393 |
394 | /* Space out h3s when following a section */
395 | .download h3 {
396 | margin-bottom: 5px;
397 | }
398 | .download-builder input + h3,
399 | .download-builder .checkbox + h3 {
400 | margin-top: 9px;
401 | }
402 |
403 | /* Fields for variables */
404 | .download-builder input[type=text] {
405 | margin-bottom: 9px;
406 | font-family: Menlo, Monaco, "Courier New", monospace;
407 | font-size: 12px;
408 | color: #d14;
409 | }
410 | .download-builder input[type=text]:focus {
411 | background-color: #fff;
412 | }
413 |
414 | /* Custom, larger checkbox labels */
415 | .download .checkbox {
416 | padding: 6px 10px 6px 25px;
417 | color: #555;
418 | background-color: #f9f9f9;
419 | -webkit-border-radius: 3px;
420 | -moz-border-radius: 3px;
421 | border-radius: 3px;
422 | cursor: pointer;
423 | }
424 | .download .checkbox:hover {
425 | color: #333;
426 | background-color: #f5f5f5;
427 | }
428 | .download .checkbox small {
429 | font-size: 12px;
430 | color: #777;
431 | }
432 |
433 | /* Variables section */
434 | #variables label {
435 | margin-bottom: 0;
436 | }
437 |
438 | /* Giant download button */
439 | .download-btn {
440 | margin: 36px 0 108px;
441 | }
442 | #download p,
443 | #download h4 {
444 | max-width: 50%;
445 | margin: 0 auto;
446 | color: #999;
447 | text-align: center;
448 | }
449 | #download h4 {
450 | margin-bottom: 0;
451 | }
452 | #download p {
453 | margin-bottom: 18px;
454 | }
455 | .download-btn .btn {
456 | display: block;
457 | width: auto;
458 | padding: 19px 24px;
459 | margin-bottom: 27px;
460 | font-size: 30px;
461 | line-height: 1;
462 | text-align: center;
463 | -webkit-border-radius: 6px;
464 | -moz-border-radius: 6px;
465 | border-radius: 6px;
466 | }
467 |
468 |
469 |
470 | /* Color swatches on LESS docs page
471 | -------------------------------------------------- */
472 | /* Sets the width of the td */
473 | .swatch-col {
474 | width: 30px;
475 | }
476 | /* Le swatch */
477 | .swatch {
478 | display: inline-block;
479 | width: 30px;
480 | height: 20px;
481 | margin: -6px 0;
482 | -webkit-border-radius: 3px;
483 | -moz-border-radius: 3px;
484 | border-radius: 3px;
485 | }
486 | /* For white swatches, give a border */
487 | .swatch-bordered {
488 | width: 28px;
489 | height: 18px;
490 | border: 1px solid #eee;
491 | }
492 |
493 |
494 | /* Misc
495 | -------------------------------------------------- */
496 |
497 | /* Make tables spaced out a bit more */
498 | h2 + table,
499 | h3 + table,
500 | h4 + table,
501 | h2 + .row {
502 | margin-top: 5px;
503 | }
504 |
505 | /* Example sites showcase */
506 | .example-sites img {
507 | max-width: 100%;
508 | margin: 0 auto;
509 | }
510 | .marketing-byline {
511 | font-size: 18px;
512 | font-weight: 300;
513 | line-height: 24px;
514 | color: #999;
515 | text-align: center;
516 | }
517 |
518 | .scrollspy-example {
519 | height: 200px;
520 | overflow: auto;
521 | position: relative;
522 | }
523 |
524 | /* Remove bottom margin on example forms in wells */
525 | form.well {
526 | padding: 14px;
527 | }
528 |
529 | /* Tighten up spacing */
530 | .well hr {
531 | margin: 18px 0;
532 | }
533 |
534 | /* Fake the :focus state to demo it */
535 | .focused {
536 | border-color: rgba(82,168,236,.8);
537 | -webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
538 | -moz-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
539 | box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
540 | outline: 0;
541 | }
542 |
543 | /* For input sizes, make them display block */
544 | .docs-input-sizes select,
545 | .docs-input-sizes input[type=text] {
546 | display: block;
547 | margin-bottom: 9px;
548 | }
549 |
550 | /* Icons
551 | ------------------------- */
552 | .the-icons {
553 | margin-left: 0;
554 | list-style: none;
555 | }
556 | .the-icons i:hover {
557 | background-color: rgba(255,0,0,.25);
558 | }
559 |
560 | /* Eaxmples page
561 | ------------------------- */
562 | .bootstrap-examples .thumbnail {
563 | margin-bottom: 9px;
564 | background-color: #fff;
565 | }
566 |
567 | /* Responsive table
568 | ------------------------- */
569 | .responsive-utilities th small {
570 | display: block;
571 | font-weight: normal;
572 | color: #999;
573 | }
574 | .responsive-utilities tbody th {
575 | font-weight: normal;
576 | }
577 | .responsive-utilities td {
578 | text-align: center;
579 | }
580 | .responsive-utilities td.is-visible {
581 | color: #468847;
582 | background-color: #dff0d8 !important;
583 | }
584 | .responsive-utilities td.is-hidden {
585 | color: #ccc;
586 | background-color: #f9f9f9 !important;
587 | }
588 |
589 | /* Responsive tests
590 | ------------------------- */
591 | .responsive-utilities-test {
592 | margin-top: 5px;
593 | margin-left: 0;
594 | list-style: none;
595 | overflow: hidden; /* clear floats */
596 | }
597 | .responsive-utilities-test li {
598 | position: relative;
599 | float: left;
600 | width: 25%;
601 | height: 43px;
602 | font-size: 14px;
603 | font-weight: bold;
604 | line-height: 43px;
605 | color: #999;
606 | text-align: center;
607 | border: 1px solid #ddd;
608 | -webkit-border-radius: 4px;
609 | -moz-border-radius: 4px;
610 | border-radius: 4px;
611 | }
612 | .responsive-utilities-test li + li {
613 | margin-left: 10px;
614 | }
615 | .responsive-utilities-test span {
616 | position: absolute;
617 | top: -1px;
618 | left: -1px;
619 | right: -1px;
620 | bottom: -1px;
621 | -webkit-border-radius: 4px;
622 | -moz-border-radius: 4px;
623 | border-radius: 4px;
624 | }
625 | .responsive-utilities-test span {
626 | color: #468847;
627 | background-color: #dff0d8;
628 | border: 1px solid #d6e9c6;
629 | }
630 |
631 |
632 | /* Responsive Docs
633 | -------------------------------------------------- */
634 | @media (max-width: 480px) {
635 |
636 | /* Change up some type stuff */
637 | h2 {
638 | margin-top: 27px;
639 | }
640 | h2 small {
641 | display: block;
642 | line-height: 18px;
643 | }
644 | h3 {
645 | margin-top: 18px;
646 | }
647 |
648 | /* icons */
649 | .marketing .bs-icon {
650 | margin: 0;
651 | }
652 |
653 | /* Adjust the jumbotron */
654 | .jumbotron h1,
655 | .jumbotron p {
656 | text-align: center;
657 | margin-right: 0;
658 | }
659 | .jumbotron h1 {
660 | font-size: 45px;
661 | margin-right: 0;
662 | }
663 | .jumbotron p {
664 | margin-right: 0;
665 | margin-left: 0;
666 | font-size: 18px;
667 | line-height: 24px;
668 | }
669 | .jumbotron .btn {
670 | display: block;
671 | font-size: 18px;
672 | padding: 10px 14px;
673 | margin: 0 auto 10px;
674 | }
675 | /* Masthead (home page jumbotron) */
676 | .masthead {
677 | padding-top: 0;
678 | }
679 |
680 | /* Don't space out quick links so much */
681 | .quick-links {
682 | margin: 40px 0 0;
683 | }
684 | /* hide the bullets on mobile since our horizontal space is limited */
685 | .quick-links .divider {
686 | display: none;
687 | }
688 |
689 | /* center example sites */
690 | .example-sites {
691 | margin-left: 0;
692 | }
693 | .example-sites > li {
694 | float: none;
695 | display: block;
696 | max-width: 280px;
697 | margin: 0 auto 18px;
698 | text-align: center;
699 | }
700 | .example-sites .thumbnail > img {
701 | max-width: 270px;
702 | }
703 |
704 | table code {
705 | white-space: normal;
706 | word-wrap: break-word;
707 | word-break: break-all;
708 | }
709 |
710 | /* Modal example */
711 | .modal-example .modal {
712 | position: relative;
713 | top: auto;
714 | right: auto;
715 | bottom: auto;
716 | left: auto;
717 | }
718 |
719 | }
720 |
721 |
722 | @media (max-width: 768px) {
723 |
724 | /* This was in the version copied from the main site, but it mucks up the ipython notebooks */
725 | /* Remove any padding from the body */
726 | /*body {
727 | padding-top: 0;
728 | }*/
729 |
730 | /* Jumbotron buttons */
731 | .jumbotron .btn {
732 | margin-bottom: 10px;
733 | }
734 |
735 | /* Subnav */
736 | .subnav {
737 | position: static;
738 | top: auto;
739 | z-index: auto;
740 | width: auto;
741 | height: auto;
742 | background: #fff; /* whole background property since we use a background-image for gradient */
743 | -webkit-box-shadow: none;
744 | -moz-box-shadow: none;
745 | box-shadow: none;
746 | }
747 | .subnav .nav > li {
748 | float: none;
749 | }
750 | .subnav .nav > li > a {
751 | border: 0;
752 | }
753 | .subnav .nav > li + li > a {
754 | border-top: 1px solid #e5e5e5;
755 | }
756 | .subnav .nav > li:first-child > a,
757 | .subnav .nav > li:first-child > a:hover {
758 | -webkit-border-radius: 4px 4px 0 0;
759 | -moz-border-radius: 4px 4px 0 0;
760 | border-radius: 4px 4px 0 0;
761 | }
762 |
763 | /* Popovers */
764 | .large-bird {
765 | display: none;
766 | }
767 | .popover-well .popover-wrapper {
768 | margin-left: 0;
769 | }
770 |
771 | /* Space out the show-grid examples */
772 | .show-grid [class*="span"] {
773 | margin-bottom: 5px;
774 | }
775 |
776 | /* Unfloat the back to top link in footer */
777 | .footer .pull-right {
778 | float: none;
779 | }
780 | .footer p {
781 | margin-bottom: 9px;
782 | }
783 |
784 | }
785 |
786 |
787 | @media (min-width: 480px) and (max-width: 768px) {
788 |
789 | /* Scale down the jumbotron content */
790 | .jumbotron h1 {
791 | font-size: 54px;
792 | }
793 | .jumbotron p {
794 | margin-right: 0;
795 | margin-left: 0;
796 | }
797 |
798 | }
799 |
800 |
801 | @media (min-width: 768px) and (max-width: 980px) {
802 |
803 | /* This was in the version copied from the main site, but it mucks up the ipython notebooks */
804 | /* Remove any padding from the body */
805 | /*body {
806 | padding-top: 0;
807 | }*/
808 |
809 | /* Scale down the jumbotron content */
810 | .jumbotron h1 {
811 | font-size: 72px;
812 | }
813 |
814 | }
815 |
816 |
817 | @media (max-width: 980px) {
818 |
819 | /* Unfloat brand */
820 | .navbar-fixed-top .brand {
821 | float: left;
822 | margin-left: 0;
823 | padding-left: 10px;
824 | padding-right: 10px;
825 | }
826 |
827 | /* Inline-block quick links for more spacing */
828 | .quick-links li {
829 | display: inline-block;
830 | margin: 5px;
831 | }
832 |
833 | }
834 |
835 |
836 | /* LARGE DESKTOP SCREENS */
837 | @media (min-width: 1210px) {
838 |
839 | /* Update subnav container */
840 | .subnav-fixed .nav {
841 | width: 1168px; /* 2px less to account for left/right borders being removed when in fixed mode */
842 | }
843 |
844 | }
845 |
--------------------------------------------------------------------------------
/tutorials/Quantities/Quantities.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "astropy-tutorials": {
4 | "author": "Ana Bonaca , Erik Tollerud , Jonathan Foster ",
5 | "date": "April 2014",
6 | "description": "Demonstrates use of the astropy.units, astropy.constants, and the Quantity object for calculating the mass of a galaxy from its velocity dispersion and determining masses of molecular clouds from CO intensity maps. Includes use of matplotlib for making a histogram and an image with a colorbar. Also includes good practices for using quantities in functions you might distribute to other people.",
7 | "link_name": "Using Astropy Quantities for astrophysical calculations",
8 | "name": "",
9 | "published": true
10 | },
11 | "signature": "sha256:38ee8db3d37d4a8736448b719739ab2e2cb961a302b20c696136b60bf1c27051"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "heading",
20 | "level": 1,
21 | "metadata": {},
22 | "source": [
23 | "Using Astropy Quantites for astrophysical calculations"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "In this tutorial we present some examples showing how astropy's `Quantity` object can make astrophysics calculations easier. The examples include calculating the mass of a galaxy from its velocity dispersion and determining masses of molecular clouds from CO intensity maps. We end with an example of good practices for using quantities in functions you might distribute to other people.\n",
31 | "\n",
32 | "For an in-depth discussion of `Quantity` objects, see the [astropy documentation section](http://docs.astropy.org/en/stable/units/quantity.html)."
33 | ]
34 | },
35 | {
36 | "cell_type": "heading",
37 | "level": 2,
38 | "metadata": {},
39 | "source": [
40 | "Preliminaries"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {},
46 | "source": [
47 | "We start by loading standard libraries and set up plotting for ipython notebooks."
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "collapsed": false,
53 | "input": [
54 | "#!/usr/bin/env python\n",
55 | "\n",
56 | "from __future__ import print_function, division\n",
57 | "\n",
58 | "import math\n",
59 | "import numpy as np\n",
60 | "import matplotlib.pyplot as plt\n",
61 | "\n",
62 | "# You shouldn't use the `seed` function in real science code, but we use it here for example purposes.\n",
63 | "# It makes the \"random\" number generator always give the same numbers wherever you run it.\n",
64 | "np.random.seed(12345)\n",
65 | "\n",
66 | "# Set up matplotlib and use a nicer set of plot parameters\n",
67 | "%config InlineBackend.rc = {}\n",
68 | "import matplotlib\n",
69 | "matplotlib.rc_file(\"../../templates/matplotlibrc\")\n",
70 | "import matplotlib.pyplot as plt\n",
71 | "%matplotlib inline"
72 | ],
73 | "language": "python",
74 | "metadata": {},
75 | "outputs": []
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {},
80 | "source": [
81 | "It is conventional to load the astropy `units` module as the variable `u`, demonstrated below. This will make working with `Quantity` objects much easier. \n",
82 | "\n",
83 | "Astropy also has a `constants` module, where typical physical constants are available. The constants are stored as objects of a subclass of `Quantity`, so they behave just like a `Quantity`. Here, we'll only need the gravitational constant `G`, Planck's constant `h`, and Boltzmann's constant, `k_B`."
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "collapsed": false,
89 | "input": [
90 | "import astropy.units as u\n",
91 | "from astropy.constants import G, h, k_B"
92 | ],
93 | "language": "python",
94 | "metadata": {},
95 | "outputs": []
96 | },
97 | {
98 | "cell_type": "heading",
99 | "level": 2,
100 | "metadata": {},
101 | "source": [
102 | "1. Galaxy mass"
103 | ]
104 | },
105 | {
106 | "cell_type": "markdown",
107 | "metadata": {},
108 | "source": [
109 | "In this first example, we will use `Quantity` objects to estimate a hypothetical galaxy's mass, given its half-light radius and radial velocities of stars in the galaxy."
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {},
115 | "source": [
116 | "Lets assume that we measured the half light radius of the galaxy to be 29 pc projected on the sky at the distance of the galaxy. This radius is often called the \"effective radius\", so we will store it as a `Quantity` object with the name `Reff`. The easiest way to create a `Quantity` object is just by multiplying the value with its unit. Units are accessed as u.\"unit\", in this case u.pc."
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "collapsed": false,
122 | "input": [
123 | "Reff = 29 * u.pc"
124 | ],
125 | "language": "python",
126 | "metadata": {},
127 | "outputs": []
128 | },
129 | {
130 | "cell_type": "markdown",
131 | "metadata": {},
132 | "source": [
133 | "A completely equivalent (but more verbose) way of doing the same thing is to use the `Quantity` object's initializer, demonstrated below. In general, the simpler form (above) is preferred, as it is closer to how such a quantity would actually be written in text. The initalizer form has more options, though, which you can learn about from the [astropy reference documentation on Quantity](http://docs.astropy.org/en/stable/api/astropy.units.quantity.Quantity.html)."
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "collapsed": false,
139 | "input": [
140 | "Reff = u.Quantity(29, unit=u.pc)"
141 | ],
142 | "language": "python",
143 | "metadata": {},
144 | "outputs": []
145 | },
146 | {
147 | "cell_type": "markdown",
148 | "metadata": {},
149 | "source": [
150 | "We can access the value and unit of a `Quantity` using the `value` and `unit` attributes."
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "collapsed": false,
156 | "input": [
157 | "print(\"\"\"Half light radius\n",
158 | "value: {0}\n",
159 | "unit: {1}\"\"\".format(Reff.value, Reff.unit))"
160 | ],
161 | "language": "python",
162 | "metadata": {},
163 | "outputs": []
164 | },
165 | {
166 | "cell_type": "markdown",
167 | "metadata": {},
168 | "source": [
169 | "The `value` and `unit` attributes can also be accessed within the print function."
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "collapsed": false,
175 | "input": [
176 | "print(\"\"\"Half light radius\n",
177 | "value: {0.value}\n",
178 | "unit: {0.unit}\"\"\".format(Reff))"
179 | ],
180 | "language": "python",
181 | "metadata": {},
182 | "outputs": []
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {},
187 | "source": [
188 | "Furthermore, we can convert the radius in parsecs to any other unit of length using the ``to()`` method. Here, we convert it to meters."
189 | ]
190 | },
191 | {
192 | "cell_type": "code",
193 | "collapsed": false,
194 | "input": [
195 | "print(\"{0:.3g}\".format(Reff.to(u.m)))"
196 | ],
197 | "language": "python",
198 | "metadata": {},
199 | "outputs": []
200 | },
201 | {
202 | "cell_type": "markdown",
203 | "metadata": {},
204 | "source": [
205 | "Next, we will first create a synthetic dataset of radial velocity measurements, assuming a normal distribution with a mean velocity of 206 km/s and a velocity dispersion of 4.3 km/s."
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "collapsed": false,
211 | "input": [
212 | "vmean = 206\n",
213 | "sigin = 4.3\n",
214 | "v = np.random.normal(vmean, sigin, 500)*u.km/u.s"
215 | ],
216 | "language": "python",
217 | "metadata": {},
218 | "outputs": []
219 | },
220 | {
221 | "cell_type": "code",
222 | "collapsed": false,
223 | "input": [
224 | "print(\"\"\"First 10 radial velocity measurements: \n",
225 | "{0}\n",
226 | "{1}\"\"\".format(v[:10], v.to(u.m/u.s)[:10]))"
227 | ],
228 | "language": "python",
229 | "metadata": {},
230 | "outputs": []
231 | },
232 | {
233 | "cell_type": "code",
234 | "collapsed": false,
235 | "input": [
236 | "plt.figure()\n",
237 | "plt.hist(v, bins=20, histtype=\"step\")\n",
238 | "plt.xlabel(\"Velocity (km/s)\")\n",
239 | "plt.ylabel(\"N\")"
240 | ],
241 | "language": "python",
242 | "metadata": {},
243 | "outputs": []
244 | },
245 | {
246 | "cell_type": "markdown",
247 | "metadata": {},
248 | "source": [
249 | "Next, we calculate the velocity dispersion of the galaxy. This demonstrates how you can perform basic operations like subtraction and division with `Quantity` objects, and also use them in standard numpy functions such as `mean()` and `size()`. They retain their units through these operations just as you would expect them to."
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "collapsed": false,
255 | "input": [
256 | "sigma = np.sqrt(np.sum((v - np.mean(v))**2) / np.size(v))\n",
257 | "print(\"Velocity dispersion: {0:.2f}\".format(sigma))"
258 | ],
259 | "language": "python",
260 | "metadata": {},
261 | "outputs": []
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {},
266 | "source": [
267 | "Note how we needed to use `numpy` square root function, because the resulting velocity dispersion quantity is a `numpy` array. If we used the python standard `math` library's `sqrt` function instead, we get an error."
268 | ]
269 | },
270 | {
271 | "cell_type": "code",
272 | "collapsed": false,
273 | "input": [
274 | "sigma_scalar = math.sqrt(np.sum((v - np.mean(v))**2) / np.size(v))"
275 | ],
276 | "language": "python",
277 | "metadata": {},
278 | "outputs": []
279 | },
280 | {
281 | "cell_type": "markdown",
282 | "metadata": {},
283 | "source": [
284 | "In general, you should only use `numpy` functions with `Quantity` objects, *not* the `math` equivalents, unless you are sure you understand the consequences."
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {},
290 | "source": [
291 | "Now for the actual mass calculation. If a galaxy is pressure-supported (for example, an elliptical or dwarf spheroidal galaxy), its mass within the stellar extent can be estimated using a straightforward formula: $M_{1/2}=4\\sigma^2 R_{eff}/G$. There are caveats to the use of this formula for science - see Wolf et al. 2010 for details. For demonstrating `Quantity`, just accept that this is often good enough. For the calculation we can just multiply the quantities together, and `astropy` will keep track of the units."
292 | ]
293 | },
294 | {
295 | "cell_type": "code",
296 | "collapsed": false,
297 | "input": [
298 | "M = 4*sigma**2*Reff/G\n",
299 | "M"
300 | ],
301 | "language": "python",
302 | "metadata": {},
303 | "outputs": []
304 | },
305 | {
306 | "cell_type": "markdown",
307 | "metadata": {},
308 | "source": [
309 | "The result is in a composite unit, so it's not really obvious it's a mass. However, it can be decomposed to cancel all of the length units ($km^2 pc/m^3$) using the decompose() method."
310 | ]
311 | },
312 | {
313 | "cell_type": "code",
314 | "collapsed": false,
315 | "input": [
316 | "M.decompose()"
317 | ],
318 | "language": "python",
319 | "metadata": {},
320 | "outputs": []
321 | },
322 | {
323 | "cell_type": "markdown",
324 | "metadata": {},
325 | "source": [
326 | "We can also easily express the mass in whatever form you like - solar masses are common in astronomy, or maybe you want the default SI and CGS units."
327 | ]
328 | },
329 | {
330 | "cell_type": "code",
331 | "collapsed": false,
332 | "input": [
333 | "print(\"\"\"Galaxy mass\n",
334 | "in solar units: {0:.3g}\n",
335 | "SI units: {1:.3g}\n",
336 | "CGS units: {2:.3g}\"\"\".format(M.to(u.Msun), M.si, M.cgs))"
337 | ],
338 | "language": "python",
339 | "metadata": {},
340 | "outputs": []
341 | },
342 | {
343 | "cell_type": "markdown",
344 | "metadata": {},
345 | "source": [
346 | "Or, if you want the log of the mass, you can just use ``np.log10`` as long as the logarithm's argument is dimensionless."
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "collapsed": false,
352 | "input": [
353 | "np.log10(M / u.Msun)"
354 | ],
355 | "language": "python",
356 | "metadata": {},
357 | "outputs": []
358 | },
359 | {
360 | "cell_type": "markdown",
361 | "metadata": {},
362 | "source": [
363 | "However, you can't take the log of something with units, as that is not mathematically sensible."
364 | ]
365 | },
366 | {
367 | "cell_type": "code",
368 | "collapsed": false,
369 | "input": [
370 | "np.log10(M)"
371 | ],
372 | "language": "python",
373 | "metadata": {},
374 | "outputs": []
375 | },
376 | {
377 | "cell_type": "heading",
378 | "level": 2,
379 | "metadata": {},
380 | "source": [
381 | "Exercises"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {},
387 | "source": [
388 | "Use `Quantity` and Kepler's law in the form given below to determine the (circular) orbital speed of the Earth around the sun in km/s. You should not have to look up an constants or conversion factors to do this calculation - it's all in `astropy.units` and `astropy.constants`.\n",
389 | "\n",
390 | "$$v = \\sqrt{\\frac{G M_{\\odot}}{r}}$$"
391 | ]
392 | },
393 | {
394 | "cell_type": "code",
395 | "collapsed": false,
396 | "input": [],
397 | "language": "python",
398 | "metadata": {},
399 | "outputs": []
400 | },
401 | {
402 | "cell_type": "markdown",
403 | "metadata": {},
404 | "source": [
405 | "There's a much easier way to figure out the velocity of the Earth using just two units or quantities. Do that and then compare to the Kepler's law answer (the easiest way is probably to compute the percentage difference, if any)."
406 | ]
407 | },
408 | {
409 | "cell_type": "code",
410 | "collapsed": false,
411 | "input": [],
412 | "language": "python",
413 | "metadata": {},
414 | "outputs": []
415 | },
416 | {
417 | "cell_type": "markdown",
418 | "metadata": {},
419 | "source": [
420 | "(Completely optional, but a good way to convince yourself of the value of Quantity:) Do the above calculations by hand - you can use a calculator (or python just for its arithmatic) but look up all the appropriate conversion factors and use paper-and-pencil approaches for keeping track of them all. Which one took longer?"
421 | ]
422 | },
423 | {
424 | "cell_type": "code",
425 | "collapsed": false,
426 | "input": [],
427 | "language": "python",
428 | "metadata": {},
429 | "outputs": []
430 | },
431 | {
432 | "cell_type": "heading",
433 | "level": 2,
434 | "metadata": {},
435 | "source": [
436 | "2. Molecular cloud mass"
437 | ]
438 | },
439 | {
440 | "cell_type": "markdown",
441 | "metadata": {},
442 | "source": [
443 | "In this second example, we will demonstrate how using `Quantity` objects can facilitate a full derivation of the total mass of a molecular cloud using radio observations of isotopes of Carbon Monoxide (CO)."
444 | ]
445 | },
446 | {
447 | "cell_type": "heading",
448 | "level": 4,
449 | "metadata": {},
450 | "source": [
451 | "Setting up the data cube"
452 | ]
453 | },
454 | {
455 | "cell_type": "markdown",
456 | "metadata": {},
457 | "source": [
458 | "Let's assume that we have mapped the inner part of a molecular cloud in the J=1-0 rotational transition of ${\\rm C}^{18}{\\rm O}$ and are interested in measuring its total mass. The measurement produced a data cube with RA and Dec as spatial coordiates and velocity as the third axis. Each voxel in this data cube represents the brightness temperature of the emission at that position and velocity. Furthermore, we will assume that we have an independent measurement of distance to the cloud $d=250$ pc and that the excitation temperature is known and constant throughout the cloud: $T_{ex}=25$ K."
459 | ]
460 | },
461 | {
462 | "cell_type": "code",
463 | "collapsed": false,
464 | "input": [
465 | "d = 250 * u.pc\n",
466 | "Tex = 25 * u.K"
467 | ],
468 | "language": "python",
469 | "metadata": {},
470 | "outputs": []
471 | },
472 | {
473 | "cell_type": "markdown",
474 | "metadata": {},
475 | "source": [
476 | "We will generate a synthetic dataset, assuming the cloud follows a Gaussian distribution in each of RA, Dec and velocity. We start by creating a 100x100x300 numpy array, such that the first coordinate is right ascension, the second is declination, and the third is velocity. We use the `numpy.meshgrid` function to create data cubes for each of the three coordinates, and then use them in the formula for a Gaussian to generate an array with the synthetic data cube. In this cube, the cloud is positioned at the center of the cube, with $\\sigma$ and the center in each dimension shown below. Note in particular that the $\\sigma$ for RA and Dec have different units from the center, but `astropy` automatically does the relevant conversions before computing the exponential."
477 | ]
478 | },
479 | {
480 | "cell_type": "code",
481 | "collapsed": false,
482 | "input": [
483 | "# Cloud's center\n",
484 | "cen_ra = 52.25 * u.deg\n",
485 | "cen_dec = 0.25 * u.deg\n",
486 | "cen_v = 15 * u.km/u.s\n",
487 | "\n",
488 | "# Cloud's size\n",
489 | "sig_ra = 3 * u.arcmin\n",
490 | "sig_dec = 4 * u.arcmin\n",
491 | "sig_v = 3 * u.km/u.s\n",
492 | "\n",
493 | "#1D coordinate quantities\n",
494 | "ra = np.linspace(52, 52.5, 100) * u.deg\n",
495 | "dec = np.linspace(0, 0.5, 100) * u.deg\n",
496 | "v = np.linspace(0, 30, 300) *u.km/u.s\n",
497 | "\n",
498 | "#this creates data cubes of size for each coordinate based on the dimensions of the other coordinates\n",
499 | "ra_cube, dec_cube, v_cube = np.meshgrid(ra, dec, v)\n",
500 | "\n",
501 | "data_gauss = np.exp(-0.5*((ra_cube-cen_ra)/sig_ra)**2 + \n",
502 | " -0.5*((dec_cube-cen_dec)/sig_dec)**2 + \n",
503 | " -0.5*((v_cube-cen_v)/sig_v)**2 )"
504 | ],
505 | "language": "python",
506 | "metadata": {},
507 | "outputs": []
508 | },
509 | {
510 | "cell_type": "markdown",
511 | "metadata": {},
512 | "source": [
513 | "The units of the exponential are dimensionless, so we multiply the data cube by K to get brightness temperature units. Radio astronomers use a rather odd set of units [K km/s] as of integrated intensity (that is, summing all the emission from a line over velocity). As an aside for experts, we're setting up our artificial cube on the main-beam temperature scale (T$_{\\rm MB}$) which is the closest we can normally get to the actual brightness temperature of our source."
514 | ]
515 | },
516 | {
517 | "cell_type": "code",
518 | "collapsed": false,
519 | "input": [
520 | "data = data_gauss * u.K"
521 | ],
522 | "language": "python",
523 | "metadata": {},
524 | "outputs": []
525 | },
526 | {
527 | "cell_type": "markdown",
528 | "metadata": {},
529 | "source": [
530 | "We will also need to know the width of each velocity bin and the size of each pixel, so we calculate that now."
531 | ]
532 | },
533 | {
534 | "cell_type": "code",
535 | "collapsed": false,
536 | "input": [
537 | "# Average pixel size\n",
538 | "# This is only right if dec ~ 0, because of the cos(dec) factor.\n",
539 | "dra = (ra.max() - ra.min()) / len(ra)\n",
540 | "ddec = (dec.max() - dec.min()) / len(dec)\n",
541 | "\n",
542 | "#Average velocity bin width\n",
543 | "dv = (v.max() - v.min()) / len(v)\n",
544 | "print(\"\"\"dra = {0}\n",
545 | "ddec = {1}\n",
546 | "dv = {2}\"\"\".format(dra.to(u.arcsec), ddec.to(u.arcsec), dv))"
547 | ],
548 | "language": "python",
549 | "metadata": {},
550 | "outputs": []
551 | },
552 | {
553 | "cell_type": "markdown",
554 | "metadata": {},
555 | "source": [
556 | "We are interested in the integrated intensity over all of the velocity channels, so we will create a 2D quantity array by summing our data cube along the velocity axis (multiplying by the velocity width of a pixel)."
557 | ]
558 | },
559 | {
560 | "cell_type": "code",
561 | "collapsed": false,
562 | "input": [
563 | "intcloud = np.sum(data*dv, axis=2)\n",
564 | "intcloud.unit"
565 | ],
566 | "language": "python",
567 | "metadata": {},
568 | "outputs": []
569 | },
570 | {
571 | "cell_type": "markdown",
572 | "metadata": {},
573 | "source": [
574 | "We can plot the 2D quantity using matplotlib's imshow function, by passing the quantity's value. Similarly, we can set the correct extent using the values of $x_i$ and $x_f$. Finally, we can set the colorbar label to have proper units."
575 | ]
576 | },
577 | {
578 | "cell_type": "code",
579 | "collapsed": false,
580 | "input": [
581 | "#Note that we display RA in the convential way by going from max to min\n",
582 | "plt.imshow(intcloud.value, \n",
583 | " origin='lower', \n",
584 | " extent=[ra.value.max(), ra.value.min(), dec.value.min(), dec.value.max()], \n",
585 | " cmap='hot', \n",
586 | " interpolation='nearest', \n",
587 | " aspect='equal')\n",
588 | "plt.colorbar().set_label(\"Intensity ({})\".format(intcloud.unit))\n",
589 | "plt.xlabel(\"RA (deg)\")\n",
590 | "plt.ylabel(\"Dec (deg)\");"
591 | ],
592 | "language": "python",
593 | "metadata": {},
594 | "outputs": []
595 | },
596 | {
597 | "cell_type": "heading",
598 | "level": 4,
599 | "metadata": {},
600 | "source": [
601 | "Measuring The Column Density of CO"
602 | ]
603 | },
604 | {
605 | "cell_type": "markdown",
606 | "metadata": {},
607 | "source": [
608 | "In order to calculate the mass of the molecular cloud, we need to measure its column density. A number of assumptions are required for the following calculation; the most important are that the emission is optically thin (typically true for ${\\rm C}^{18}{\\rm O}$) and that conditions of local thermodynamic equilibrium hold along the line of sight. In the case where the temperature is large compared to the separation in energy levels for a molecule and the source fills the main beam of the telescope, the total column density for ${\\rm C}^{13}{\\rm O}$ is\n",
609 | "\n",
610 | "$N=C \\frac{\\int T_B(V) dV}{1-e^{-B}}$\n",
611 | "\n",
612 | "where the constants $C$ and $B$ are given by:\n",
613 | "\n",
614 | "$C=3.0\\times10^{14} \\left(\\frac{\\nu}{\\nu_{13}}\\right)^2 \\frac{A_{13}}{A} {\\rm K^{-1} cm^{-2} \\, km^{-1} \\, s}$\n",
615 | "\n",
616 | "$B=\\frac{h\\nu}{k_B T}$\n",
617 | "\n",
618 | "(Rohlfs & Wilson \"Tools of Radio Astronomy\"). "
619 | ]
620 | },
621 | {
622 | "cell_type": "markdown",
623 | "metadata": {},
624 | "source": [
625 | "Here we have given an expression for $C$ scaled to the values for ${\\rm C}^{13}{\\rm O}$ ($\\nu_{13}$ and $A_{13}$). In order to use this relation for ${\\rm C}^{18}{\\rm O}$, we need to rescale the frequencies ${\\nu}$ and Einstein coefficients $A$. $C$ is in funny mixed units, but that's okay. We'll define it as a `Quantities` object and not have to worry about it. \n",
626 | "\n",
627 | "First, we look up the wavelength for these emission lines and store them as quantities. "
628 | ]
629 | },
630 | {
631 | "cell_type": "code",
632 | "collapsed": false,
633 | "input": [
634 | "lambda13 = 2.60076 * u.mm\n",
635 | "lambda18 = 2.73079 * u.mm"
636 | ],
637 | "language": "python",
638 | "metadata": {},
639 | "outputs": []
640 | },
641 | {
642 | "cell_type": "markdown",
643 | "metadata": {},
644 | "source": [
645 | "Since the wavelength and frequency of light are related using the speed of light, we can convert between them. However, doing so just using the to() method fails, as units of length and frequency are not convertible:"
646 | ]
647 | },
648 | {
649 | "cell_type": "code",
650 | "collapsed": false,
651 | "input": [
652 | "nu13 = lambda13.to(u.Hz)"
653 | ],
654 | "language": "python",
655 | "metadata": {},
656 | "outputs": []
657 | },
658 | {
659 | "cell_type": "markdown",
660 | "metadata": {},
661 | "source": [
662 | "Fortunately, `astropy` comes to the rescue by providing a feature called \"unit equivalencies\". Equivalencies provide a way to convert between two physically different units that are not normally equivalent, but in a certain context have a one-to-one mapping. For more on equivalencies, see the [equivalencies section of astropy's documentation](http://docs.astropy.org/en/stable/units/equivalencies.html).\n",
663 | "\n",
664 | "In this case, calling the ``astropy.units.spectral()`` function provides the equivalencies necessary to handle conversions between wavelength and frequency. To use it, provide the equivalencies to the `equivalencies` keyword of the ``to()`` call:"
665 | ]
666 | },
667 | {
668 | "cell_type": "code",
669 | "collapsed": false,
670 | "input": [
671 | "nu13 = lambda13.to(u.Hz, equivalencies=u.spectral())\n",
672 | "nu18 = lambda18.to(u.Hz, equivalencies=u.spectral())"
673 | ],
674 | "language": "python",
675 | "metadata": {},
676 | "outputs": []
677 | },
678 | {
679 | "cell_type": "markdown",
680 | "metadata": {},
681 | "source": [
682 | "Next, we look up Einstein coefficients (in units of s$^{-1}$), and calculate the ratios in constant $C$. Note how the ratios of frequency and Einstein coefficient units are dimensionless, so the unit of $C$ is unchanged."
683 | ]
684 | },
685 | {
686 | "cell_type": "code",
687 | "collapsed": false,
688 | "input": [
689 | "A13 = 7.4e-8 / u.s\n",
690 | "A18 = 8.8e-8 / u.s\n",
691 | "\n",
692 | "C = 3e14 * (nu18/nu13)**3 * (A13/A18) / (u.K * u.cm**2 * u.km *(1/u.s))\n",
693 | "C"
694 | ],
695 | "language": "python",
696 | "metadata": {},
697 | "outputs": []
698 | },
699 | {
700 | "cell_type": "markdown",
701 | "metadata": {},
702 | "source": [
703 | "Now we move on to calculate the constant $B$. This is given by the ratio of $\\frac{h\\nu}{k_B T}$, where $h$ is Planck's constant, $k_B$ is the Boltzmann's constant, $\\nu$ is the emission frequency, and $T$ is the excitation temperature. The constants were imported from `astropy.constants`, and the other two values are already calculated, so here we just take the ratio."
704 | ]
705 | },
706 | {
707 | "cell_type": "code",
708 | "collapsed": false,
709 | "input": [
710 | "B = h * nu18 / (k_B * Tex)"
711 | ],
712 | "language": "python",
713 | "metadata": {},
714 | "outputs": []
715 | },
716 | {
717 | "cell_type": "markdown",
718 | "metadata": {},
719 | "source": [
720 | "The units of $B$ are Hz s, which can be decomposed to a dimensionless unit if you actually care about it's value. Usually this is not necessary, though. Quantities are at their best if you just use them without worrying about intermediate units, and only convert at the very end when you want a final answer."
721 | ]
722 | },
723 | {
724 | "cell_type": "code",
725 | "collapsed": false,
726 | "input": [
727 | "print('{0}\\n{1}'.format(B, B.decompose()))"
728 | ],
729 | "language": "python",
730 | "metadata": {},
731 | "outputs": []
732 | },
733 | {
734 | "cell_type": "markdown",
735 | "metadata": {},
736 | "source": [
737 | "At this point we have all the ingredients to calculate the number density of $\\rm CO$ molecules in this cloud. We already integrated (summed) over the velocity channels above to show the integrated intensity map, but we'll do it again here for clarity. This gives us the column density of CO for each spatial pixel in our map. We can then print out the peak column column density."
738 | ]
739 | },
740 | {
741 | "cell_type": "code",
742 | "collapsed": false,
743 | "input": [
744 | "NCO = C * np.sum(data*dv, axis=2) / (1 - np.exp(-B))\n",
745 | "print(\"Peak CO column density: \")\n",
746 | "np.max(NCO)\n"
747 | ],
748 | "language": "python",
749 | "metadata": {},
750 | "outputs": []
751 | },
752 | {
753 | "cell_type": "heading",
754 | "level": 4,
755 | "metadata": {},
756 | "source": [
757 | "CO to Total Mass"
758 | ]
759 | },
760 | {
761 | "cell_type": "markdown",
762 | "metadata": {},
763 | "source": [
764 | "We are using CO as a tracer for the much more numerous H$_2$, the quantity we are actually trying to infer. Since most of the mass is in H$_2$, we calculate its column density by multiplying the CO column density with the (known/assumed) H$_2$/CO ratio."
765 | ]
766 | },
767 | {
768 | "cell_type": "code",
769 | "collapsed": false,
770 | "input": [
771 | "H2_CO_ratio = 5.9e6\n",
772 | "NH2 = NCO * H2_CO_ratio\n",
773 | "print(\"Peak H2 column density: \")\n",
774 | "np.max(NH2)"
775 | ],
776 | "language": "python",
777 | "metadata": {},
778 | "outputs": []
779 | },
780 | {
781 | "cell_type": "markdown",
782 | "metadata": {},
783 | "source": [
784 | "That's a peak column density of roughly 50 magnitudes of visual extinction (assuming the conversion between N$_{\\rm H_2}$ and A$_V$ from Bohlin et al. 1978), which seems reasonable for a molecular cloud."
785 | ]
786 | },
787 | {
788 | "cell_type": "markdown",
789 | "metadata": {},
790 | "source": [
791 | "We obtain the mass column density by multiplying the number column density by the mass of an individual H$_2$ molecule. "
792 | ]
793 | },
794 | {
795 | "cell_type": "code",
796 | "collapsed": false,
797 | "input": [
798 | "mH2 = 2 * 1.008 * u.Dalton #aka atomic mass unit/amu\n",
799 | "rho = NH2 * mH2"
800 | ],
801 | "language": "python",
802 | "metadata": {},
803 | "outputs": []
804 | },
805 | {
806 | "cell_type": "markdown",
807 | "metadata": {},
808 | "source": [
809 | "A final step in going from the column density to mass is summing up over the area area. If we do this in the straightforward way of length x width of a pixel, this area is then in units of ${\\rm deg}^2$."
810 | ]
811 | },
812 | {
813 | "cell_type": "code",
814 | "collapsed": false,
815 | "input": [
816 | "dap = dra * ddec\n",
817 | "print(dap)"
818 | ],
819 | "language": "python",
820 | "metadata": {},
821 | "outputs": []
822 | },
823 | {
824 | "cell_type": "markdown",
825 | "metadata": {},
826 | "source": [
827 | "Now comes an important subtlety: in the small angle approximation, multiplying the pixel area with the square of distance yields the cross-sectional area of the cloud that the pixel covers, in *physical* units, rather than angular units. So it is tempting to just multiply the area and the square of the distance."
828 | ]
829 | },
830 | {
831 | "cell_type": "code",
832 | "collapsed": false,
833 | "input": [
834 | "da = dap * d**2 # don't actually do it this way - use the version below instead!\n",
835 | "print(da)"
836 | ],
837 | "language": "python",
838 | "metadata": {},
839 | "outputs": []
840 | },
841 | {
842 | "cell_type": "code",
843 | "collapsed": false,
844 | "input": [
845 | "dap.to(u.steradian).value * d**2"
846 | ],
847 | "language": "python",
848 | "metadata": {},
849 | "outputs": []
850 | },
851 | {
852 | "cell_type": "markdown",
853 | "metadata": {},
854 | "source": [
855 | "But this is **wrong**, because `astropy.units` treats angles (and solid angles) as actual physical units, while the small-angle approximation assumes angles are dimensionless. So if you, e.g., try to convert to a different area unit, it will fail:"
856 | ]
857 | },
858 | {
859 | "cell_type": "code",
860 | "collapsed": false,
861 | "input": [
862 | "da.to(u.cm**2)"
863 | ],
864 | "language": "python",
865 | "metadata": {},
866 | "outputs": []
867 | },
868 | {
869 | "cell_type": "markdown",
870 | "metadata": {},
871 | "source": [
872 | "The solution is to use the `dimensionless_angles` equivalency, which allows angles to be treated as dimensionless. This makes it so that they will automatically convert to radians and become dimensionless when a conversion is needed."
873 | ]
874 | },
875 | {
876 | "cell_type": "code",
877 | "collapsed": false,
878 | "input": [
879 | "da = (dap * d**2).to(u.pc**2, equivalencies=u.dimensionless_angles())\n",
880 | "da"
881 | ],
882 | "language": "python",
883 | "metadata": {},
884 | "outputs": []
885 | },
886 | {
887 | "cell_type": "code",
888 | "collapsed": false,
889 | "input": [
890 | "da.to(u.cm**2)"
891 | ],
892 | "language": "python",
893 | "metadata": {},
894 | "outputs": []
895 | },
896 | {
897 | "cell_type": "markdown",
898 | "metadata": {},
899 | "source": [
900 | "Finally, multiplying the column density with the pixel area and summing over all the pixels gives us the cloud mass."
901 | ]
902 | },
903 | {
904 | "cell_type": "code",
905 | "collapsed": false,
906 | "input": [
907 | "M = np.sum(rho * da)\n",
908 | "M.decompose().to(u.solMass)"
909 | ],
910 | "language": "python",
911 | "metadata": {},
912 | "outputs": []
913 | },
914 | {
915 | "cell_type": "heading",
916 | "level": 2,
917 | "metadata": {},
918 | "source": [
919 | "Exercises"
920 | ]
921 | },
922 | {
923 | "cell_type": "markdown",
924 | "metadata": {},
925 | "source": [
926 | "The astro material was pretty heavy on that one, so lets focus on some associated statistics using `Quantity`'s array capabililities. Compute the median and mean of the `data` with the ``np.mean`` and ``np.median`` functions. Why are their values so different?"
927 | ]
928 | },
929 | {
930 | "cell_type": "code",
931 | "collapsed": false,
932 | "input": [],
933 | "language": "python",
934 | "metadata": {},
935 | "outputs": []
936 | },
937 | {
938 | "cell_type": "markdown",
939 | "metadata": {},
940 | "source": [
941 | "Similarly, compute the standard deviation and variance (if you don't know the relevant functions, look it up in the numpy docs or just type np. and a code cell). Do they have the units you expect?"
942 | ]
943 | },
944 | {
945 | "cell_type": "code",
946 | "collapsed": false,
947 | "input": [],
948 | "language": "python",
949 | "metadata": {},
950 | "outputs": []
951 | },
952 | {
953 | "cell_type": "heading",
954 | "level": 3,
955 | "metadata": {},
956 | "source": [
957 | "3. Using Quantities with Functions"
958 | ]
959 | },
960 | {
961 | "cell_type": "markdown",
962 | "metadata": {},
963 | "source": [
964 | "`Quantity` is also a useful tool if you plan to share some of your code, either with collaborators or the wider community. By writing functions that take `Quantity` objects instead of raw numbers or arrays, you can write code that is agnostic to the input unit. In this way, you may even be able to prevent [the destruction of Mars orbiters](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter#Cause_of_failure). Below, we provide a simple example."
965 | ]
966 | },
967 | {
968 | "cell_type": "markdown",
969 | "metadata": {},
970 | "source": [
971 | "Suppose you are working on an instrument, and the bigwig funding it asks for a function to give an analytic estimate of the response function. You determine from some tests it's basically a Lorentzian, but with a different scale along the two axes. Your first thought might be to do this:"
972 | ]
973 | },
974 | {
975 | "cell_type": "code",
976 | "collapsed": false,
977 | "input": [
978 | "def response_func(xinarcsec, yinarcsec):\n",
979 | " xscale = 0.9\n",
980 | " yscale = 0.85\n",
981 | " xfactor = 1 / (1 + xinarcsec/xscale)\n",
982 | " yfactor = 1 / (1 + yinarcsec/yscale)\n",
983 | " \n",
984 | " return xfactor * yfactor"
985 | ],
986 | "language": "python",
987 | "metadata": {},
988 | "outputs": []
989 | },
990 | {
991 | "cell_type": "markdown",
992 | "metadata": {},
993 | "source": [
994 | "You meant the inputs to be in arcsec, but you send that to your hapless collaborator, and they don't look closely and think the inputs are instead supposed to be in arcmin. So they do:"
995 | ]
996 | },
997 | {
998 | "cell_type": "code",
999 | "collapsed": false,
1000 | "input": [
1001 | "response_func(1.0, 1.2)"
1002 | ],
1003 | "language": "python",
1004 | "metadata": {},
1005 | "outputs": []
1006 | },
1007 | {
1008 | "cell_type": "markdown",
1009 | "metadata": {},
1010 | "source": [
1011 | "And now they tell all their friends how terrible the instrument is, because it's supposed to have arcsecond resolution, but your function clearly shows it can only resolve an arcmin at best. But you can solve this by requiring they pass in `Quantity` objects. The new function could simply be:"
1012 | ]
1013 | },
1014 | {
1015 | "cell_type": "code",
1016 | "collapsed": false,
1017 | "input": [
1018 | "def response_func(x, y):\n",
1019 | " xscale = 0.9 * u.arcsec\n",
1020 | " yscale = 0.85 * u.arcsec\n",
1021 | " xfactor = 1 / (1 + x/xscale)\n",
1022 | " yfactor = 1 / (1 + y/yscale)\n",
1023 | " \n",
1024 | " return xfactor * yfactor"
1025 | ],
1026 | "language": "python",
1027 | "metadata": {},
1028 | "outputs": []
1029 | },
1030 | {
1031 | "cell_type": "markdown",
1032 | "metadata": {},
1033 | "source": [
1034 | "And your collaborator now has to pay attention. If they just blindly put in a number they get an error:"
1035 | ]
1036 | },
1037 | {
1038 | "cell_type": "code",
1039 | "collapsed": false,
1040 | "input": [
1041 | "response_func(1.0, 1.2)"
1042 | ],
1043 | "language": "python",
1044 | "metadata": {},
1045 | "outputs": []
1046 | },
1047 | {
1048 | "cell_type": "markdown",
1049 | "metadata": {},
1050 | "source": [
1051 | "Which is their cue to provide the units explicitly:"
1052 | ]
1053 | },
1054 | {
1055 | "cell_type": "code",
1056 | "collapsed": false,
1057 | "input": [
1058 | "response_func(1.0*u.arcmin, 1.2*u.arcmin)"
1059 | ],
1060 | "language": "python",
1061 | "metadata": {},
1062 | "outputs": []
1063 | },
1064 | {
1065 | "cell_type": "markdown",
1066 | "metadata": {},
1067 | "source": [
1068 | "The funding agency is impressed at the resolution you achieved, and your instrument is saved. You now go on to win the Nobel Prize due to discoveries the instrument makes. And it was all because you used `Quantity` as the input of code you shared."
1069 | ]
1070 | },
1071 | {
1072 | "cell_type": "heading",
1073 | "level": 2,
1074 | "metadata": {},
1075 | "source": [
1076 | "Exercise"
1077 | ]
1078 | },
1079 | {
1080 | "cell_type": "markdown",
1081 | "metadata": {},
1082 | "source": [
1083 | "Write a function that computes the Keplerian velocity you worked out in section 1 (using `Quantity` input and outputs, of course), but allowing for an arbitrary mass and orbital radius. Try it with some reasonable numbers for satellites orbiting the Earth, a moon of Jupiter, or an extrasolar planet. Feel free to use wikipedia or similar for the masses and distances. "
1084 | ]
1085 | },
1086 | {
1087 | "cell_type": "code",
1088 | "collapsed": false,
1089 | "input": [],
1090 | "language": "python",
1091 | "metadata": {},
1092 | "outputs": []
1093 | }
1094 | ],
1095 | "metadata": {}
1096 | }
1097 | ]
1098 | }
--------------------------------------------------------------------------------