[Yt-svn] yt-commit r353 - trunk/doc

mturk at wrangler.dreamhost.com mturk at wrangler.dreamhost.com
Fri Jan 4 14:40:02 PST 2008


Author: mturk
Date: Fri Jan  4 14:40:00 2008
New Revision: 353
URL: http://yt.spacepope.org/changeset/353

Log:
Initial import into the trunk of the demo.html file.

Added:
   trunk/doc/demo.html

Added: trunk/doc/demo.html
==============================================================================
--- (empty file)
+++ trunk/doc/demo.html	Fri Jan  4 14:40:00 2008
@@ -0,0 +1,331 @@
+<HTML>
+<HEAD><TITLE>yt Demo</TITLE>
+<STYLE>
+body {
+    background-color: #000000;
+    font-family:'Helvetica Neue', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif;
+}
+#titlebar {
+   background-color: #66DD66;
+   font-size: 200%;
+   width: 759px;
+   margin: 0px;
+   padding: 10px 0px 10px 119px;
+   border: 1px solid #00FF00;
+}
+#navbar {
+    background-color: #FF6666;
+    position: fixed;
+    margin: 0px;
+    padding: 10px;
+    width: 98px;
+    border: 1px solid #FF0000;
+    font-size: 70%;
+
+}
+#navbar ul{
+    list-style-type:none;
+    padding: 0px;
+    margin: 0px;
+}
+#maincontent {
+    position: relative;
+    left: 120px;
+    top: 0px;
+    width:740px;
+    padding: 10px;
+    background-color: #AAAAAA;
+}
+#maincontent pre {
+    background-color: #8888CC;
+    padding: 5px;
+    border: 1px solid #000000;
+}
+</STYLE>
+<BODY>
+<div id="titlebar">
+A Demo of yt
+</div>
+<div id="navbar">
+<ul>
+    <li><a href="#getting-started">Getting Started</a></li>
+    <li><a href="#basic-objects">Basic Objects</a></li>
+    <li><a href="#derived-fields">Derived Fields</a></li>
+    <li><a href="#profiles">Profiles</a></li>
+    <li><a href="#automated-plotting">Automated Plotting</a></li>
+</ul>
+</div>
+<div id="maincontent">
+<p>This is a short little demo of how to use yt from the command line.
+Hope it helps!</p>
+
+<a id="getting-started"><h3>Getting Started</h3></a>
+
+<p>We start out by getting some stuff into our local namespace.
+The import command is how an external module gets loaded.  By default,
+it shows up as the module name itself.  But you can also import it as
+something else, which makes things easier...</p>
+
+<p>Lagos is our data-handler.  If you need to touch data, lagos will be your
+friend.</p>
+<pre>
+>>> import yt.lagos as lagos
+</pre>
+
+<p>We first instantiate a StaticOutput.  This is a pretty simple process - lagos
+will grab the parameter file that you give it, parse it, set up some handy
+units, and then return control to you.</p>
+<pre>
+>>> a = lagos.EnzoStaticOutput("/Users/matthewturk/Research/data/DataDir0036/DataDump0036")
+</pre>
+
+<p>But what good is just a parameter file?  What we really want is to be able to
+manipulate the grids, and all the fields stored in those grids.  Fortunately,
+we can access the hierarchy as either 'hierarchy' or 'h'.
+Let's start out by finding the location of the maximum Density.
+Note that here we use an inline-unpacking -- find_max returns two values,
+packed into a tuple, so we manually unpack them right here.</p>
+<pre>
+>>> v,c = a.h.find_max("Density")
+>>> print v
+>>> print c
+</pre>
+
+<p>The hierarchy object has some interesting methods that let us access the data
+in different ways.  Let's start by looking at the grids.</p>
+
+<pre>
+>>> my_grid = a.h.grids[0] # The root grid
+>>> print my_grid.dx, my_grid.ActiveDimensions # Some of the attributes
+</pre>
+
+<p>You might be asking yourself, how do I know what properties objects have?
+Python gives us a convenient mechanism for determining this:</p>
+
+<pre>
+>>> print dir(my_grid)
+</pre>
+
+<p>In general, a method or property that begins with '_' is not meant to be
+called directly, and '__' means that it definitely shouldn't be called by an
+external process.</p>
+
+<p>Now let's take a look at accessing the data fields inherent to the grid
+object.</p>
+
+<pre>
+>>> print my_grid["Density"]*my_grid["Temperature"]
+</pre>
+
+<a id="basic-objects"><h3>Basic Objects</h3></a>
+
+<p>What the code just did was access the grid files and then spit back the
+results of the read operations.  So we can access the fields pretty easily
+this way, but what about generating new fields from our existing fields?
+Well, that's just as easy!  And yt comes with many derived fields
+pre-defined, but from within a script you can also define your own.</p>
+
+<pre>
+>>> print my_grid["Entropy"]
+</pre>
+
+<p>Entropy is a derived field.  But how does it work?  Well, we have a built-in
+source-code inspector.</p>
+
+<pre>
+>>> print lagos.fieldInfo["Entropy"].get_source()
+</pre>
+
+<p>But what if we only want a couple values?  We can directly grab indices.</p>
+
+<pre>
+>>> print my_grid["Density"][0,10,4] # 0-indexed!
+</pre>
+
+<p>We can also slice, using the slice operator: ':'</p>
+
+<pre>
+>>> print my_grid["Density"][0,:,4]
+>>> print my_grid["Density"][0,2:4,4]
+</pre>
+
+<p>Okay, so now you've seen how to grab fields from a grid.  The thing about
+getting fields from a grid, though, is that it works the exact same way as
+all the other data types!  (Well, maybe not projection :)  So that raises the
+question, how do we get more data objects?  Well, the hierarchy is our friend
+here.  We can get slices, projections, spheres, rectangular prisms,
+fixed-resolution grids and cutting planes from the herarchy.
+
+<p>Let's start with a slice.  A slice needs some info, but how do we know what
+type?  Well, let's use 'help'!</p>
+<pre>
+>>> help(a.h.slice)
+</pre>
+
+<p>Looks like we need to feed it an axis, a coordinate, and maybe some fields
+and a center.  Axes are always done as numbers, with 0 = x, 1 = y, 2 = z.</p>
+<pre>
+>>> my_slice = a.h.slice(0, 0.5, "Density")  # We don't really need to pass the field!
+</pre>
+
+<p>Now let's test out getting new fields.</p>
+
+<pre>
+>>> print my_slice["Pressure"], my_slice["Density"]
+</pre>
+
+<p>Okay, so enough of the slices.  (Although they can do some more stuff, like
+shift around inside the domain, and so on and so forth.)</p>
+
+<p>Let's do a region.  This is a box with a left edge and a right edge, and a
+center.  (You need a center for some other calculations, not for getting the
+region.)  Let's get started by grabbing the ENTIRE domain.</p>
+<pre>
+>>> my_region = a.h.region([0.5,0.5,0.5], [0.0,0.0,0.0], [1.0,1.0,1.0])
+</pre>
+
+<a id="derived-fields"><h3>Derived Fields</h3></a>
+<p>Okay, now we have a region.  We can do stuff with this -- in fact, it has the
+same data-access protocol as a slice or a grid!  Plus, math on these things
+is pretty fast:</p>
+<pre>
+>>> electron_fraction = my_region["Electron_Density"]/my_region["Density"]
+</pre>
+<p>But the thing is, that one happens to be a derived field already:</p>
+<pre>
+>>> electron_fraction = my_region["Electron_Fraction"]
+</pre>
+<p>In fact, every "*_Density" field is automatically set up as a "_Fraction" field.
+But what other fields are available to us?</p>
+
+<pre>
+>>> print lagos.fieldInfo.keys()
+</pre>
+
+<p>There are LOTS!  Not only that, but you can set up your own fields, too,
+which then become available to all data-types. Here's a very simple example,
+where we just cube Density.</p>
+<pre>
+>>> def _DensityCubed(field, data):
+...     return data["Density"]**3.0
+...
+>>> def _ConvertDensityCubed(data):
+...     return 1.0
+...
+>>> # Now we have our field functions, and we just need to tell the fieldinfo
+>>> # object about it.
+>>> lagos.add_field("DensityCubed", function=_DensityCubed,
+...     convert_function= _ConvertDensityCubed, units=r"\rm{g}^3/\rm{cm}^9")
+</pre>
+<p>This last part might need some explanation.  Derived fields are composed of
+three main parts.  The first is the function that defines the field.  It always
+accepts two variables -- field, and data.  'Field' is the DerivedField and
+'data' is the data object.  Note that we stick to a pretty strict means of
+returning fields -- <i>everything is returned in cgs</i>!  This means that when
+we request "Density" from 'data' it is returned to us <i>already</i> in CGS, so we
+don't need to convert anything.</p>
+<p>The last part, the call to add_field, is the most crucial.  It creates a
+DerivedField object which will control the behavior of the derived field in a
+couple crucial ways -- what you see here includes the string used for the units,
+the string used for the name of the field, the functions that govern the
+creation and conversion of the fiels.  However, you can also use
+'validators' -- in fact, for some fields, you <i>should</i> use validators.</p>
+<p>Validators are the most powerful part of the derived field process, because
+they can allow you to require ghost zones, which will be automatically generated.
+Check the "AveragedDensity" and "DivV" fields in the source code for an example
+of this.</p>
+
+<a id="profiles"><h3>Profiles</h3></a>
+<p>Profiles are one of the more interesting data types.  They are a binned average
+of one or more variables, along one or two different dimensions.  For example,
+you could get an average temperature in Density and H2 Fraction space.  Or you could
+Look at the distribution of Volume through Density and Temperature space.  Or you could
+take the spherically-averaged Number Density and see how it changes with radius.</p>
+
+<p>In order to make a profile, we first need a data object we want to get the profile
+<i>from</i>.  This can be a sphere, a region, or even an extracted region.  We'll
+first take a look at doing a spherically-average profile of Temperature with Radius.</p>
+
+<pre>
+>>> sphere = a.h.sphere([0.5,0.5,0.5], 0.1/a["kpc"])
+>>> prof = lagos.BinnedProfile1D(sphere, 16, "Radiuskpc",
+                                 0.0001, 0.1, True, True)
+>>> prof.add_fields(["Density","Temperature"], weight="CellMassMsun")
+</pre>
+
+<p>Alright, again, a bit of explanation.  First, we get our sphere -- and in doing
+so, we tell it where the center is, and how big (in <i>code units</i>) we want it to be.
+(Note that in order to convert a number into some unit, we <i>divide</i> by the conversion
+factor for that unit.</p>
+<p>Once we have that data object, we can do anything with it.  (See above!)
+However, what we <i>want</i> to do is generate a profile.  So we create
+a profile object, telling it where to get the data, which field we want to bin by,
+the lower and upper bounds (in the units of that field), and whether we want those
+bins to be log spaced.  But, there's one more option -- the last one is the "lazy_reader"
+option.  This controls whether we load all the data at once (faster) or whether
+we grab it from each grid individually (slower, but more memory-conservative.) </p>
+<p> Once we have instantiated the profile object, we add fields to it.
+These fields are weighted by CellMassMsun, and we get back an average value for
+each bin in 'Radiuskpc'.  Now we can plot them, or inspect them, with simple
+data-access methods.  Additionally, you can feed them directly into pylab or matplotlib
+(neither of which we will cover in any length here) and plot them:</p>
+
+<pre>
+>>> print prof["Density"]
+>>> import pylab
+>>> pylab.loglog(prof["Radiuskpc"], prof["Density"])
+>>> pylab.xlabel(r"$\rm{Radius} (\rm{kpc})$")
+>>> pylab.ylabel(r"$\rm{Density} (\rm{g}/\rm{cm}^3)$")
+>>> pylab.savefig("my_profile.png")
+</pre>
+
+<p>Two-dimensional profiles are along the same lines.</p>
+
+<pre>
+>>> prof2d = lagos.BinnedProfile2D(sphere,
+...                 16, "Density", 1e-32, 1e-24, True,
+...                 16, "Temperature", 1e2, 1e5, True, True)
+>>> prof2d.add_fields("CellVolume", weight=None)
+>>> pylab.pcolormesh(prof2d["Density"], prof2d["Temperature"],
+...                  prof2d["CellVolume"].transpose())
+</pre>
+
+<a id="automated-plotting"><h3>Automated Plotting</h3></a>
+<p> So now we know how to get and manipulate most of the datatypes, but we
+still have to go through some processes to plot them manually.  However, yt has
+facilities for plotting slices, projections and profiles in much easier ways.</p>
+<p>The plotting tool is called 'raven' and it's organized around the idea of
+PlotCollection objects.  Each PlotCollection object is in some way thematically
+associated -- maybe they are all the same data, sliced along different axes, for instance.
+When you act on a PlotCollection, you act on all the plots that are part of that
+collection.  Each PlotCollection is associated with a single parameter file.
+</p>
+<pre>
+>>> import yt.raven as raven
+>>> pc = raven.PlotCollection(a)
+>>> pc.add_slice("Density", 0)
+>>> pc.add_slice("Density", 1)
+>>> pc.add_slice("Density", 2)
+>>> pc.set_width(15, 'kpc')
+>>> pc.save("somename_15kpc")
+</pre>
+<p>
+There's a lot in that little block of text.  First I add a slice (note that while
+we can feed it a pre-existing slice, it will also grab one automatically if we
+don't!) along each axis (0,1,2) in the field "Density".  Each time we
+add a plot to the PlotCollection, it is accessible as pc.plots[index] where 'index'
+is the 0-based index in order of addition.  Each plot object has a 'data' property,
+so if we wanted the EnzoSlice object, we can access it:
+</p>
+<pre>
+>>> print pc.plots[1].data
+</pre>
+<p>After we've created the plots above, we set the width to 15 kiloparsecs.
+Note that raven understands any length unit that the hierarchy has, so you
+can set to mpc, kpc, pc, au, km or cm.  Then we call save, and feed it a prefix --
+it takes care of adding some more information to the filename, so don't supply it
+a file suffix.  (It defaults to '.png')
+</p>
+
+</div>
+</BODY></HTML>



More information about the yt-svn mailing list