1{
2 "cells": [
3  {
4   "cell_type": "markdown",
5   "metadata": {},
6   "source": [
7    "Let us go through a full worked example.  Here we have a Tipsy SPH dataset.  By general\n",
8    "inspection, we see that there are stars present in the dataset, since\n",
9    "there are fields with field type: `Stars` in the `ds.field_list`. Let's look \n",
10    "at the `derived_field_list` for all of the `Stars` fields. "
11   ]
12  },
13  {
14   "cell_type": "code",
15   "execution_count": null,
16   "metadata": {
17    "collapsed": false
18   },
19   "outputs": [],
20   "source": [
21    "import yt\n",
22    "import numpy as np\n",
23    "\n",
24    "ds = yt.load(\"TipsyGalaxy/galaxy.00300\")\n",
25    "for field in ds.derived_field_list:\n",
26    "    if field[0] == 'Stars':\n",
27    "        print (field)"
28   ]
29  },
30  {
31   "cell_type": "markdown",
32   "metadata": {},
33   "source": [
34    "We will filter these into young stars and old stars by masking on the ('Stars', 'creation_time') field. \n",
35    "\n",
36    "In order to do this, we first make a function which applies our desired cut.  This function must accept two arguments: `pfilter` and `data`.  The first argument is a `ParticleFilter` object that contains metadata about the filter its self.  The second argument is a yt data container.\n",
37    "\n",
38    "Let's call \"young\" stars only those stars with ages less 5 million years.  Since Tipsy assigns a very large `creation_time` for stars in the initial conditions, we need to also exclude stars with negative ages. \n",
39    "\n",
40    "Conversely, let's define \"old\" stars as those stars formed dynamically in the simulation with ages greater than 5 Myr.  We also include stars with negative ages, since these stars were included in the simulation initial conditions.\n",
41    "\n",
42    "We make use of `pfilter.filtered_type` so that the filter definition will use the same particle type as the one specified in the call to `add_particle_filter` below.  This makes the filter definition usable for arbitrary particle types.  Since we're only filtering the `\"Stars\"` particle type in this example, we could have also replaced `pfilter.filtered_type` with `\"Stars\"` and gotten the same result."
43   ]
44  },
45  {
46   "cell_type": "code",
47   "execution_count": null,
48   "metadata": {
49    "collapsed": false
50   },
51   "outputs": [],
52   "source": [
53    "def young_stars(pfilter, data):\n",
54    "    age = data.ds.current_time - data[pfilter.filtered_type, \"creation_time\"]\n",
55    "    filter = np.logical_and(age.in_units('Myr') <= 5, age >= 0)\n",
56    "    return filter\n",
57    "\n",
58    "def old_stars(pfilter, data):\n",
59    "    age = data.ds.current_time - data[pfilter.filtered_type, \"creation_time\"]\n",
60    "    filter = np.logical_or(age.in_units('Myr') >= 5, age < 0)\n",
61    "    return filter"
62   ]
63  },
64  {
65   "cell_type": "markdown",
66   "metadata": {},
67   "source": [
68    "Now we define these as particle filters within the yt universe with the\n",
69    "`add_particle_filter()` function."
70   ]
71  },
72  {
73   "cell_type": "code",
74   "execution_count": null,
75   "metadata": {
76    "collapsed": false
77   },
78   "outputs": [],
79   "source": [
80    "yt.add_particle_filter(\"young_stars\", function=young_stars, filtered_type='Stars', requires=[\"creation_time\"])\n",
81    "\n",
82    "yt.add_particle_filter(\"old_stars\", function=old_stars, filtered_type='Stars', requires=[\"creation_time\"])"
83   ]
84  },
85  {
86   "cell_type": "markdown",
87   "metadata": {},
88   "source": [
89    "Let us now apply these filters specifically to our dataset.\n",
90    "\n",
91    "Let's double check that it worked by looking at the derived_field_list for any new fields created by our filter."
92   ]
93  },
94  {
95   "cell_type": "code",
96   "execution_count": null,
97   "metadata": {
98    "collapsed": false
99   },
100   "outputs": [],
101   "source": [
102    "ds.add_particle_filter('young_stars')\n",
103    "ds.add_particle_filter('old_stars')\n",
104    "\n",
105    "for field in ds.derived_field_list:\n",
106    "    if \"young_stars\" in field or \"young_stars\" in field[1]:\n",
107    "        print (field)"
108   ]
109  },
110  {
111   "cell_type": "markdown",
112   "metadata": {},
113   "source": [
114    "We see all of the new `young_stars` fields as well as the 4 deposit fields.  These deposit fields are `mesh` fields generated by depositing particle fields on the grid.  Let's generate a couple of projections of where the young and old stars reside in this simulation by accessing some of these new fields."
115   ]
116  },
117  {
118   "cell_type": "code",
119   "execution_count": null,
120   "metadata": {
121    "collapsed": false
122   },
123   "outputs": [],
124   "source": [
125    "p = yt.ProjectionPlot(ds, 'z', [('deposit', 'young_stars_cic'), ('deposit', 'old_stars_cic')], width=(40, 'kpc'), center='m')\n",
126    "p.set_figure_size(5)\n",
127    "p.show()"
128   ]
129  },
130  {
131   "cell_type": "markdown",
132   "metadata": {},
133   "source": [
134    "We see that young stars are concentrated in regions of active star formation, while old stars are more spatially extended."
135   ]
136  }
137 ],
138 "metadata": {
139  "kernelspec": {
140   "display_name": "Python 3",
141   "language": "python",
142   "name": "python3"
143  },
144  "language_info": {
145   "codemirror_mode": {
146    "name": "ipython",
147    "version": 3
148   },
149   "file_extension": ".py",
150   "mimetype": "text/x-python",
151   "name": "python",
152   "nbconvert_exporter": "python",
153   "pygments_lexer": "ipython3",
154   "version": "3.5.1"
155  }
156 },
157 "nbformat": 4,
158 "nbformat_minor": 0
159}
160