[Yt-svn] yt-commit r798 - in trunk: doc/source scripts yt yt/raven

mturk at wrangler.dreamhost.com mturk at wrangler.dreamhost.com
Wed Sep 24 06:43:19 PDT 2008


Author: mturk
Date: Wed Sep 24 06:43:17 2008
New Revision: 798
URL: http://yt.spacepope.org/changeset/798

Log:
* Updated version number in sphinx conf
* Added a bunch of convenience functions to 'iyt' -- all of which will be
  documented
* Minor change to the 'hop_plot' function in yt/mods.py, but that will likely
  get moved into recipes (see below)
* Added import for FixedResolution in raven/__init__.py
* Added FITS export and "open in DS9" options to the FixedResolutionBuffer
  objects.  These require pyfits and numdisplay, respectively
* Started a new "RecipeBook" sub-module, featuring a not-quite-complete
  implementation of Generic Functions, so that you can defined a recipe and it
  will, if it knows how, generate any keyword arguments it thinks you need.
  Right now it's very simple, as I had very simple needs, and only does
  mass-enclosed plots, which in the past have been a bit sticky.  Expect this
  to expand, and be a better, higher-level entry point.

As a note on that last point -- lately I've added several new high-level
interfaces.  I'm going to play around a bit, see how they shake out, talk to
people that might use them, and ultimately strip back to only a few.  I think
these will be the recipe book, which will cover any number of single verb-like
things you want to do, and the IPython interface.




Added:
   trunk/yt/recipes.py
Modified:
   trunk/doc/source/conf.py
   trunk/scripts/iyt
   trunk/yt/mods.py
   trunk/yt/raven/FixedResolution.py
   trunk/yt/raven/__init__.py

Modified: trunk/doc/source/conf.py
==============================================================================
--- trunk/doc/source/conf.py	(original)
+++ trunk/doc/source/conf.py	Wed Sep 24 06:43:17 2008
@@ -48,9 +48,9 @@
 # other places throughout the built documents.
 #
 # The short X.Y version.
-version = '1.0'
+version = '1.5'
 # The full version, including alpha/beta/rc tags.
-release = '1.0'
+release = '1.5-alpha'
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:

Modified: trunk/scripts/iyt
==============================================================================
--- trunk/scripts/iyt	(original)
+++ trunk/scripts/iyt	Wed Sep 24 06:43:17 2008
@@ -18,4 +18,238 @@
     code.interact(doc, None, namespace)
     sys.exit()
 
-IPython.Shell.IPShellMatplotlib(user_ns=namespace).mainloop(sys_exit=1,banner=doc)
+ip_shell = IPython.Shell.IPShellMatplotlib(user_ns=namespace)
+
+# The rest is a modified version of the IPython default profile code
+
+""" User configuration file for IPython
+
+This is a more flexible and safe way to configure ipython than *rc files
+(ipythonrc, ipythonrc-pysh etc.)
+
+This file is always imported on ipython startup. You can import the
+ipython extensions you need here (see IPython/Extensions directory).
+
+Feel free to edit this file to customize your ipython experience.
+
+Note that as such this file does nothing, for backwards compatibility.
+Consult e.g. file 'ipy_profile_sh.py' for an example of the things 
+you can do here.
+
+See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
+description on what you could do here.
+"""
+
+# Most of your config files and extensions will probably start with this import
+
+#import IPython.ipapi
+ip = ip_shell.IP.getapi()
+
+# You probably want to uncomment this if you did %upgrade -nolegacy
+# import ipy_defaults    
+
+import os   
+import glob
+import itertools
+
+def main():   
+
+    # uncomment if you want to get ipython -p sh behaviour
+    # without having to use command line switches  
+    # import ipy_profile_sh
+
+    # Configure your favourite editor?
+    # Good idea e.g. for %edit os.path.isfile
+
+    #import ipy_editors
+    
+    # Choose one of these:
+    
+    #ipy_editors.scite()
+    #ipy_editors.scite('c:/opt/scite/scite.exe')
+    #ipy_editors.komodo()
+    #ipy_editors.idle()
+    # ... or many others, try 'ipy_editors??' after import to see them
+    
+    # Or roll your own:
+    #ipy_editors.install_editor("c:/opt/jed +$line $file")
+    
+    
+    o = ip.options
+    # An example on how to set options
+    #o.autocall = 1
+    o.system_verbose = 0
+    
+    #import_all("os sys")
+    #execf('~/_ipython/ns.py')
+
+
+    # -- prompt
+    # A different, more compact set of prompts from the default ones, that
+    # always show your current location in the filesystem:
+
+    #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
+    #o.prompt_in2 = r'.\D: '
+    #o.prompt_out = r'[\#] '
+    
+    # Try one of these color settings if you can't read the text easily
+    # autoexec is a list of IPython commands to execute on startup
+    #o.autoexec.append('%colors LightBG')
+    #o.autoexec.append('%colors NoColor')
+    #o.autoexec.append('%colors Linux')
+    
+    # for sane integer division that converts to float (1/2 == 0.5)
+    #o.autoexec.append('from __future__ import division')
+    
+    # For %tasks and %kill
+    #import jobctrl 
+    
+    # For autoreloading of modules (%autoreload, %aimport)    
+    #import ipy_autoreload
+    
+    # For winpdb support (%wdb)
+    #import ipy_winpdb
+    
+    # For bzr completer, requires bzrlib (the python installation of bzr)
+    #ip.load('ipy_bzr')
+    
+    # Tab completer that is not quite so picky (i.e. 
+    # "foo".<TAB> and str(2).<TAB> will work). Complete 
+    # at your own risk!
+    #import ipy_greedycompleter
+    
+from UserDict import UserDict
+class ParameterFileDict(UserDict):
+    def __init__(self):
+        # We accept no contributions
+        UserDict.__init__(self)
+        self._key_numbers = {}
+        self._nn = 0
+    def __setitem__(self, key, value):
+        if isinstance(key, int): raise KeyError
+        UserDict.__setitem__(self, key, value)
+        self._key_numbers[self._nn] = key
+        self._nn += 1
+    def __getitem__(self, key):
+        if isinstance(key, int):
+            return self[self._key_numbers[key]]
+        return UserDict.__getitem__(self, key)
+    def __iter__(self):
+        return itertools.chain(self.data.iterkeys(),
+                        self._key_numbers.iterkeys())
+    def __repr__(self):
+        s = "{" + ", \n ".join(
+                [" '(%s, %s)': %s" % (i, self._key_numbers[i], self[i])
+                    for i in sorted(self._key_numbers)]) + "}"
+        return s
+    def has_key(self, key):
+        return self.data.has_key(key) or self._key_numbers.has_key(key)
+    def keys(self):
+        return self.data.key(key) + self._key_numbers.key(key)
+
+pfs = ParameterFileDict()
+pcs = []
+ip.user_ns['pf'] = None
+ip.user_ns['pfs'] = pfs
+ip.user_ns['pc'] = None
+ip.user_ns['pcs'] = pcs
+ip.ex("from yt.mods import *")
+
+def do_pfall(self, arg):
+    if arg.strip() == "": arg = 0
+    for i in range(int(arg)+1):
+        for f in glob.glob("".join(["*/"]*i) + "*.hierarchy" ):
+            #print i, f
+            fn = f[:-10]
+            # Make this a bit smarter
+            ip.user_ns['pfs'][fn] = EnzoStaticOutput(fn)
+    ip.ex("print pfs")
+
+ip.expose_magic("pfall", do_pfall)
+
+def _parse_pf(arg):
+    if arg.strip() == "":
+        if ip.user_ns.get('pf', None) is not None:
+            return ip.user_ns['pf']
+        elif len(pfs) > 0:
+            return pfs[0]
+    else:
+        if pfs.has_key(arg):
+            return pfs[arg]
+        if pfs.has_key(int(arg)):
+            return pfs[int(arg)]
+        return EnzoStaticOutput(arg)
+    raise KeyError
+        
+def do_slice(self, arg):
+    pc = None
+    if len(arg.split()) == 3:
+        pfn, field, axis = arg.split()
+        pf = _parse_pf(arg.split()[0])
+    elif len(arg.split()) == 2:
+        field, axis = arg.split()
+        pf = _parse_pf("")
+        if ip.user_ns.get('pc', None) is not None and \
+           ip.user_ns['pc'].parameter_file is pf:
+            pf = ip.user_ns['pc']
+    else:
+        print "Need either two or three arguments."
+        return
+    axis = int(axis)
+    if pc is None: pc = PlotCollectionInteractive(pf)
+    pc.add_slice(field, axis)
+    print "Setting pcs[%s] = New PlotCollection" % len(pcs)
+    ip.user_ns['pcs'].append(pc)
+    if ip.user_ns.get('pc', None) is None: ip.user_ns['pc'] = pc
+    return pc
+
+ip.expose_magic("pcslicer", do_slice)
+
+def do_width(self, arg):
+    if ip.user_ns.get("pc", None) is None:
+        print "No 'pc' defined"
+        return
+    if len(arg.split()) == 2:
+        w, u = arg.split()
+    else:
+        w, u = arg, '1'
+    ip.user_ns['pc'].set_width(float(w), u)
+ip.expose_magic("width", do_width)
+
+def do_zoom(self, arg):
+    if ip.user_ns.get("pc", None) is None:
+        print "No 'pc' defined"
+        return
+    pc = ip.user_ns['pc']
+    w = None
+    for p in pc:
+        if hasattr(p, 'width'): w = p.width
+    if w is None: print "No zoomable plots defined"
+    w /= float(arg)
+    pc.set_width(w, '1')
+ip.expose_magic("zoom", do_zoom)
+    
+def do_setup_pf(self, arg):
+    if pfs.has_key(arg): ip.user_ns['pf'] = pfs[arg]
+    iarg = -1
+    try:
+        iarg = int(arg)
+    except ValueError: pass
+    if pfs.has_key(iarg): ip.user_ns['pf'] = pfs[iarg]
+    print ip.user_ns['pf']
+    
+ip.expose_magic("gpf", do_setup_pf)
+
+# some config helper functions you can use 
+def import_all(modules):
+    """ Usage: import_all("os sys") """ 
+    for m in modules.split():
+        ip.ex("from %s import *" % m)
+        
+def execf(fname):
+    """ Execute a file in user namespace """
+    ip.ex('execfile("%s")' % os.path.expanduser(fname))
+
+#main()
+
+ip_shell.mainloop(sys_exit=1,banner=doc)

Modified: trunk/yt/mods.py
==============================================================================
--- trunk/yt/mods.py	(original)
+++ trunk/yt/mods.py	Wed Sep 24 06:43:17 2008
@@ -146,16 +146,18 @@
     for s in inspect.stack()[1:]:
         if 'pf' in s[0].f_locals:
             __pf = s[0].f_locals['pf']
+            if isinstance(__pf, types.StringTypes):
+                __pf = EnzoStaticOutput(__pf)
             mylog.info("Obtained parameter file %s", __pf)
             return __pf
     
-def hop_plot():
-    pf = _get_current_pf()
-    pc = PlotCollection(pf, center=[0.5,0.5,0.5])
-    center = (pf["DomainRightEdge"]-pf["DomainLeftEdge"])/2.0
-    hop_output = hop.HopList(pf.h.sphere(center, 1.0/pf["1"]))
-    hop_output.write_out("%s.hop" % pf)
+def hop_plot(my_pf = None):
+    if my_pf is None: my_pf = _get_current_pf()
+    pc = PlotCollection(my_pf, center=[0.5,0.5,0.5])
+    center = (my_pf["DomainRightEdge"]-my_pf["DomainLeftEdge"])/2.0
+    hop_output = hop.HopList(my_pf.h.sphere(center, 1.0/my_pf["1"]))
+    hop_output.write_out("%s.hop" % my_pf)
     for ax in range(3):
         pc.add_projection("Density", ax).add_callback(
                             HopCircleCallback(hop_output, ax))
-    pc.save("%s_hop" % pf)
+    pc.save("%s_hop" % my_pf)

Modified: trunk/yt/raven/FixedResolution.py
==============================================================================
--- trunk/yt/raven/FixedResolution.py	(original)
+++ trunk/yt/raven/FixedResolution.py	Wed Sep 24 06:43:17 2008
@@ -72,6 +72,34 @@
         dpy = (self.bounds[3]-self.bounds[2])/self.buff_size[1]
         return distance/dpy
 
+    def export_fits(self, filename_prefix, fields = None):
+        """
+        This will export a set of FITS images of either the fields specified
+        or all the fields already in the object.  The output filenames are
+        *filename_prefix* plus an underscore plus the name of the field.
+
+        This requires the *pyfits* module, which is a standalone module
+        provided by STSci to interface with FITS-format files.
+        """
+        import pyfits
+        if filename_prefix.endswith('.fits'): filename_prefix=filename_prefix[:-5]
+        if fields is None: fields = self.data.keys()
+        for field in fields:
+            hdu = pyfits.PrimaryHDU(self[field])
+            hdu.writeto("%s_%s.fits" % (filename_prefix, field))
+
+    def open_in_ds9(self, field, take_log=True):
+        """
+        This will open a given field in DS9.  This requires the *numdisplay*
+        package, which is a simple download from STSci.  Furthermore, it
+        presupposed that it can connect to DS9 -- that is, that DS9 is already open.
+        """
+        import numdisplay
+        numdisplay.open()
+        if take_log: data=na.log10(self[field])
+        else: data=self[field]
+        numdisplay.display(data)
+
 class AnnuliProfiler(object):
     def __init__(self, fixed_buffer, center, num_bins, min_radius, max_radius):
         """

Modified: trunk/yt/raven/__init__.py
==============================================================================
--- trunk/yt/raven/__init__.py	(original)
+++ trunk/yt/raven/__init__.py	Wed Sep 24 06:43:17 2008
@@ -61,6 +61,7 @@
 be = PlotTypes
 
 from Callbacks import *
+from FixedResolution import *
 
 color_maps = matplotlib.cm.cmapnames + raven_colormaps.keys()
 default_cmap = ytcfg.get("raven", "colormap")

Added: trunk/yt/recipes.py
==============================================================================
--- (empty file)
+++ trunk/yt/recipes.py	Wed Sep 24 06:43:17 2008
@@ -0,0 +1,127 @@
+"""
+Helpful recipes to make tasty AMR desserts
+
+Author: Matthew Turk <matthewturk at gmail.com>
+Affiliation: KIPAC/SLAC/Stanford
+Homepage: http://yt.enzotools.org/
+License:
+  Copyright (C) 2007-2008 Matthew Turk.  All Rights Reserved.
+
+  This file is part of yt.
+
+  yt is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+# Named imports
+import yt.lagos as lagos
+import yt.raven as raven
+from yt.funcs import *
+import numpy as na
+import os.path, inspect, types
+from functools import wraps
+from yt.logger import ytLogger as mylog
+
+def _fix_pf(pf):
+    if isinstance(pf, lagos.StaticOutput): return pf
+    if os.path.exists("%s.hierarchy" % pf):
+        return lagos.EnzoStaticOutput(pf)
+    elif pf.endswith(".hierarchy"):
+        return lagos.EnzoStaticOutput(pf[:-10])
+    # JS will have to implement the Orion one
+
+__pf_centers = {}
+def _fix_center(pf, center):
+    if center is not None and iterable(center):
+        center = na.array(center)
+    else:
+        if pf['CurrentTimeIdentifier'] in __pf_centers:
+            center = __pf_centers[pf['CurrentTimeIdentifier']]
+        else:
+            center = pf.h.find_max("Density")[1]
+            __pf_centers[pf['CurrentTimeIdentifier']] = center
+    return center
+
+def _fix_radius(pf, radius):
+    if radius is not None:
+        if iterable(radius):
+            return radius[0] / pf[radius[1]]
+        return radius
+    mylog.info("Setting radius to be 0.1 of the box size")
+    # yt-generalization : needs to be changed to 'unitary'
+    return 0.1 / pf["1"]
+
+def _fix_axis(pf, axis):
+    if axis is None:
+        raise ValueError("You need to specify an Axis!")
+    elif isinstance(axis, types.IntType) and (0 <= x <= 2):
+        return axis
+    elif isinstance(axis, types.StringTypes) and \
+         axis.upper() in 'XYZ':
+        return 'XYZ'.find(axis.upper())
+    else:
+        raise ValueError("Invalid Axis specified.")
+
+
+_arg_fixer = {
+                'center' : (True, _fix_center),
+                'radius' : (True, _fix_radius),
+                'axis' : (True, _fix_axis),
+             }
+
+def fix_plot_args(plot_func):
+    @wraps(plot_func)
+    def call_func(self, pf, **kwargs):
+        pf = _fix_pf(pf)
+        fkwargs = inspect.getargspec(plot_func)[0]
+        for arg in fkwargs:
+            if arg in _arg_fixer:
+                needs, fixer = _arg_fixer[arg]
+                if arg in kwargs:
+                    kwargs[arg] = fixer(pf, kwargs[arg])
+                elif needs:
+                    kwargs[arg] = fixer(pf, None)
+        retval = plot_func(self, pf, **kwargs)
+        if 'filename' in kwargs and 'filename' in fkwargs:
+            retval.save(kwargs['filename'])
+        return retval
+    return call_func
+
+which_pc = raven.PlotCollection
+
+# to add:
+#   zoom movies
+
+class _RecipeBook(object):
+
+    @fix_plot_args
+    def mass_enclosed_radius(self, pf, center=None, radius=None, radius_unit="Radiuspc",
+                             filename = None):
+        pc = which_pc(pf, center=center)
+        p = pc.add_profile_sphere(radius, '1', 
+                                  [radius_unit, "CellMassMsun"],
+                                  accumulation=True, weight=None)
+        return pc
+
+    @fix_plot_args
+    def mass_enclosed_field(self, pf, field="Density", center=None, radius=None,
+                            weight="CellMassMsun", filename = None):
+        pc = which_pc(pf, center=center)
+        p = pc.add_profile_sphere(radius, '1', 
+                                  ["Radius", "CellMassMsun"],
+                                  accumulation=True, weight=None)
+        p.switch_z(field, weight=weight)
+        p.switch_x("CellMassMsun")
+        return pc
+
+RecipeBook = _RecipeBook()



More information about the yt-svn mailing list