[cig-commits] r11830 - in cs/portal/trunk/seismo/SeismoWebPortal: . templates/SeismoWebPortal

leif at geodynamics.org leif at geodynamics.org
Fri Apr 18 14:51:28 PDT 2008


Author: leif
Date: 2008-04-18 14:51:28 -0700 (Fri, 18 Apr 2008)
New Revision: 11830

Modified:
   cs/portal/trunk/seismo/SeismoWebPortal/gmt.py
   cs/portal/trunk/seismo/SeismoWebPortal/models.py
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/event_detail.html
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/source_detail.html
   cs/portal/trunk/seismo/SeismoWebPortal/views.py
Log:
Cache images generated using GMT.


Modified: cs/portal/trunk/seismo/SeismoWebPortal/gmt.py
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/gmt.py	2008-04-18 19:26:37 UTC (rev 11829)
+++ cs/portal/trunk/seismo/SeismoWebPortal/gmt.py	2008-04-18 21:51:28 UTC (rev 11830)
@@ -3,16 +3,17 @@
 import os
 import shutil
 
-from os.path import join
+from os.path import join, isdir
 from popen2 import Popen3
 from tempfile import mkdtemp, TemporaryFile
-from django.http import Http404
+from django.http import HttpResponse, Http404
+from django.shortcuts import get_object_or_404
 
 
 gmt_bin = "/home/leif/opt/gmt/bin"
 
 
-def psmeca(cmt):
+def psmeca(cmt, filename, args):
 
     # Create a temporary directory and 'cd' there, so that '.gmt*'
     # files get cleaned-up.
@@ -22,7 +23,7 @@
     os.putenv("LD_LIBRARY_PATH", "/home/leif/opt/netCDF/lib")
 
     # Spawn 'psmeca' to draw the beachball.
-    child = Popen3([join(gmt_bin, "psmeca"), '-R0/10/0/10', '-Jx1', '-G255/0/0', '-M', '-Sm1.1', '-L2', '-K', '-V', '-P'])
+    child = Popen3([join(gmt_bin, "psmeca"), '-R0/10/0/10', '-Jx1', '-G255/0/0', '-L2', '-K', '-V', '-P'] + args)
     print >>child.tochild, "3 5 0 %f %f %f %f %f %f 1 0 0" % (
         cmt.Mrr, cmt.Mtt, cmt.Mpp, cmt.Mrt, cmt.Mrp, cmt.Mtp)
     child.tochild.close()
@@ -39,20 +40,18 @@
         raise Http404
 
     # Convert the PostScript to a GIF file.
-    gif = join(workdir, "beachball.gif")
     spawn("/usr/bin/convert",
           '+antialias',
           '-fill', '#00F', '-draw', 'color 0,0 floodfill', '-transparent', '#00F',
           '-trim', '+repage',
-          ps, gif)
+          ps, filename)
 
-    gif = open(gif, 'r')
     shutil.rmtree(workdir)
 
-    return gif
+    return
 
 
-def stationsMap(stationList):
+def stationsMap(stationList, filename):
     # Based on:
     #  globe_fig_CIG.pl
     #  Carl Tape
@@ -155,16 +154,15 @@
     os.chdir(owd)
     
     # Convert the PostScript to a JPG file.
-    jpg = join(workdir, "map.jpg")
-    spawn("/usr/bin/convert", '-trim', '+repage', psfile, jpg)
+    spawn("/usr/bin/convert", '-trim', '+repage', psfile, filename)
 
-    jpg = open(jpg, 'r')
     shutil.rmtree(workdir)
 
-    return jpg
+    return
 
 
 def wiggleMap(cmt,
+              filename,
               stationList = None,
               opt_a=None,
               opt_A=None,
@@ -280,7 +278,7 @@
     # syndir,synsuff -- plot synthetics SYNDIR/*synsuff correpsonding to datafiles
     if opt_S:
         syn_dir, syn_suff = opt_S
-        assert os.path.isdir(syn_dir), "No such directory: %s" % syn_dir
+        assert isdir(syn_dir), "No such directory: %s" % syn_dir
         plot_syn = True
     else:
         syn_dir, syn_suff = None, None
@@ -360,13 +358,11 @@
     os.chdir(owd)
     
     # Convert the PostScript to a JPG file.
-    jpg = join(workdir, "map.jpg")
-    spawn("/usr/bin/convert", '-trim', '+repage', PS_OUT, jpg)
+    spawn("/usr/bin/convert", '-trim', '+repage', PS_OUT, filename)
 
-    jpg = open(jpg, 'r')
     shutil.rmtree(workdir)
 
-    return jpg
+    return
 
 
 def plotWiggleMap(plot_nr, nr_of_plots,
@@ -613,3 +609,133 @@
     s = open("inFile", 'w')
     s.write(text)
     s.close()
+
+
+
+def serve(request, pathname, document_root):
+    from django.views.static import serve as staticServe
+    from os import makedirs
+    from views import intOr404
+    from models import Source, StationList
+    
+    try:
+        return staticServe(request, pathname, document_root)
+    except Http404:
+        pass
+
+    path = pathname.split('/')
+    if not path: raise Http404
+    name = path.pop(0)
+
+    if name == "beachballs":
+        dirname = join(document_root, name)
+        if not path: raise Http404
+        name = path.pop(0)
+
+        objId = intOr404(name)
+        source = get_object_or_404(Source, id=objId)
+        dirname = join(dirname, name)
+
+        if not path: raise Http404
+        name = path.pop(0)
+        if path: raise Http404
+
+        if name == "icon_large.gif":
+            args = ['-M', '-Sm1.1']
+        elif name == "icon_small.gif":
+            args = ['-M', '-Sm0.5']
+        elif name == "detail.gif":
+            args = ['-M', '-Sm4.0']
+        elif name == "proportional.gif":
+            args = ['-Sm1.0']
+        else:
+            raise Http404
+
+        if not isdir(dirname):
+            makedirs(dirname)
+        filename = join(dirname, name)
+
+        psmeca(source, filename, args)
+
+    elif name == "maps":
+        dirname = join(document_root, name)
+        if not path: raise Http404
+        name = path.pop(0)
+
+        if name == "stations":
+            dirname = join(dirname, name)
+            if not path: raise Http404
+            name = path.pop(0)
+
+            objId = intOr404(name)
+            stationList = get_object_or_404(StationList, id=objId)
+            dirname = join(dirname, name)
+
+            if not path: raise Http404
+            name = path.pop(0)
+            if path: raise Http404
+            
+            if name != "mercator.jpg":
+                raise Http404
+
+            if not isdir(dirname):
+                makedirs(dirname)
+            filename = join(dirname, name)
+
+            stationsMap(stationList, filename)
+            
+        elif name == "events":
+            dirname = join(dirname, name)
+            if not path: raise Http404
+            name = path.pop(0)
+
+            objId = intOr404(name)
+            source = get_object_or_404(Source, id=objId)
+            dirname = join(dirname, name)
+
+            if not path: raise Http404
+            name = path.pop(0)
+
+            if name == "stations":
+                dirname = join(dirname, name)
+
+                if not path: raise Http404
+                name = path.pop(0)
+            
+                objId = intOr404(name)
+                stationList = get_object_or_404(StationList, id=objId)
+                dirname = join(dirname, name)
+
+                if not path: raise Http404
+                name = path.pop(0)
+                if name != "global":
+                    raise Http404
+                dirname = join(dirname, name)
+
+                if not path: raise Http404
+                name = path.pop(0)
+                if path: raise Http404
+                
+                if name == "event.jpg":
+                    opts = dict()
+                elif name == "antipode.jpg":
+                    opts = dict(opt_A=True)
+                else:
+                    raise Http404
+
+                if not isdir(dirname):
+                    makedirs(dirname)
+                filename = join(dirname, name)
+
+                wiggleMap(source, filename, stationList, opt_m=True, **opts)
+
+            else:
+                raise Http404
+
+        else:
+            raise Http404
+
+    else:
+        raise Http404
+    
+    return staticServe(request, pathname, document_root)

Modified: cs/portal/trunk/seismo/SeismoWebPortal/models.py
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/models.py	2008-04-18 19:26:37 UTC (rev 11829)
+++ cs/portal/trunk/seismo/SeismoWebPortal/models.py	2008-04-18 21:51:28 UTC (rev 11830)
@@ -160,12 +160,18 @@
     def _getSingleSource(self):
         if not hasattr(self, '_singleSource'):
             if self.source_set.count() == 1:
-                self._singleSource = self.source_set.all()[0]
+                self._singleSource = self.firstSource
             else:
                 self._singleSource = None
         return self._singleSource
     singleSource = property(_getSingleSource)
 
+    def _getFirstSource(self):
+        if not hasattr(self, '_firstSource'):
+            self._firstSource = self.source_set.all()[0]
+        return self._firstSource
+    firstSource = property(_getFirstSource)
+
     def sources(self):
         return self.source_set.order_by('timeShift')
 
@@ -257,7 +263,7 @@
         return 2.0 * (log10(self.scalarSeismicMoment()) - 16.1)/3.0
 
     def beachball(self):
-        src = "%s/beachballs/%d.gif" % (config.root, self.id)
+        src = "%s/beachballs/%d/icon_large.gif" % (config.root, self.id)
         return '<img class="icon" src="%s">' % src
 
     def cmtSolutionText(self):

Modified: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/event_detail.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/event_detail.html	2008-04-18 19:26:37 UTC (rev 11829)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/event_detail.html	2008-04-18 21:51:28 UTC (rev 11830)
@@ -1,5 +1,5 @@
 
-<h2>{{ object }}</h2>
+<h2>{{ title }}</h2>
 
 <div class=toolbar>
     <a href="gearth.kml"><img src="{{root}}/pics/kml.icon.gif" title="View in Google Earth" alt="View in Google Earth"></a>
@@ -8,7 +8,7 @@
 
 {% if object.singleSource %}
 
-<p id=sourceBeachballMw>{{ object.singleSource.beachball }} M<sub>w</sub> &cong; {{ object.singleSource.momentMagnitude|stringformat:".2f" }}</p>
+<p id=sourceBeachballMw><img src="{{root}}/beachballs/{{object.singleSource.id}}/detail.gif"> M<sub>w</sub> &cong; {{ object.singleSource.momentMagnitude|stringformat:".2f" }}</p>
 
 <div class=cmtsolution>
     <h3><code>CMTSOLUTION</code></h3>

Modified: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/source_detail.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/source_detail.html	2008-04-18 19:26:37 UTC (rev 11829)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/source_detail.html	2008-04-18 21:51:28 UTC (rev 11830)
@@ -5,7 +5,7 @@
     [<a href="CMTSOLUTION.txt">download as text</a>]
 </div>
 
-<p id=sourceBeachballMw>{{ object.beachball }} M<sub>w</sub> &cong; {{ object.momentMagnitude|stringformat:".2f" }}</p>
+<p id=sourceBeachballMw><img src="{{root}}/beachballs/{{object.id}}/detail.gif"> M<sub>w</sub> &cong; {{ object.momentMagnitude|stringformat:".2f" }}</p>
 
 <div class=cmtsolution>
     <h3><code>CMTSOLUTION</code></h3>

Modified: cs/portal/trunk/seismo/SeismoWebPortal/views.py
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/views.py	2008-04-18 19:26:37 UTC (rev 11829)
+++ cs/portal/trunk/seismo/SeismoWebPortal/views.py	2008-04-18 21:51:28 UTC (rev 11830)
@@ -28,7 +28,9 @@
 from StringIO import StringIO
 
 
-static_media_root = os.environ.get("WEBPORTAL_MEDIA_ROOT")+'/static'
+STATIC_ROOT = os.path.join(os.path.dirname(__file__), "static")
+OUTPUT_ROOT = os.path.join(settings.MEDIA_ROOT, 'SeismoWebPortal', 'output')
+GMT_ROOT = os.path.join(settings.MEDIA_ROOT, 'SeismoWebPortal', 'gmt')
 
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -59,6 +61,7 @@
 
 def root(request, pathname):
     from django.views.static import serve as staticServe
+    from gmt import serve as gmtServe
 
     if config.root is None:
         if pathname:
@@ -88,7 +91,7 @@
 
     name = path.pop(0)
 
-    static = lambda request, path, desktop: staticServe(request, pathname, document_root = static_media_root)
+    static = lambda request, path, desktop: staticServe(request, pathname, document_root = STATIC_ROOT)
 
     index = Index({
         "login": login,
@@ -97,7 +100,6 @@
         "jobs": jobs, # accessed by daemon
         "output": output, # accessed by daemon
         "requests": requests, # accessed by daemon
-        "beachballs": beachballs,
         "designs": designs,
         "doc": static,
         "pics": static,
@@ -118,6 +120,8 @@
 
     openPrivateApps(request, desktop)
 
+    gmt = lambda request, path, desktop: gmtServe(request, pathname, document_root = GMT_ROOT)
+
     index = Index({
         "home": homeFolder,
         "shared": sharedFolder,
@@ -129,6 +133,8 @@
         "help": help,
         "readme": readme,
         "admin": admin,
+        "beachballs": gmt,
+        "maps": gmt,
         })
     privateView = index.get(name)
     if privateView:
@@ -213,9 +219,6 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
-OUTPUT_ROOT = os.path.join(settings.MEDIA_ROOT, 'SeismoWebPortal', 'output')
-
-
 def desktopFolder(request, desktop):
     url = config.root + "/"
     child = gui.ChildWindow(url, "View")
@@ -1503,7 +1506,6 @@
 def eventFiles(name, event, request):
     index = Index({
         "CMTSOLUTION.txt": (event_detail_cmtsolution_txt, (), dict(event = event)),
-        "beachball.gif": (beachball_gif, (), dict(event_id = event.id)),
         "gearth.kml": (event_detail_gearth, (), dict(object_id = event.id)),
         })
     call = index.get(name)
@@ -1530,6 +1532,7 @@
             view,
             object_id = event.id,
             queryset = Event.objects.all(),
+            extra_context = {'title': workspace.fsNode.name }
             )
 
     name = path.pop(0)
@@ -1600,7 +1603,6 @@
 
     index = Index({
         "CMTSOLUTION.txt": (cmtsolution_txt, (), dict(object_id = objId)),
-        "beachball.gif": (beachball_gif, (), dict(source_id = objId)),
         })
     view, args, kwds = index[name]
     return view(request, *args, **kwds)
@@ -1613,37 +1615,28 @@
     url += "maps/"
 
     if not path:
-        return  HttpResponseRedirect(url + "event/")
+        return  HttpResponseRedirect(url + "global/")
     
     name = path.pop(0)
-    if not name in ["event", "antipode"]:
+    if path or not name in ["global", "stations"]:
         raise Http404
-    
-    if not path:
-        title = name.capitalize()
-        mapsFolder.appendNode(gui.File("event", "Event", url = url + "event/"))
-        mapsFolder.appendNode(gui.File("antipode", "Antipode", url = url + "antipode/"))
-        appWindow.path.append(mapsFolder.index[name])
-        child = gui.ChildWindow(url, title)
-        child.content = gui.StaticContent(img(url + "%s/%s.jpg" % (name, name), width=506, height=506))
-        desktop.activeWindow.selectWindow(child)
-        return desktop
 
-    name = path.pop(0)
-    if path or not name in ["event.jpg", "antipode.jpg"]: raise Http404
-    
-    from gmt import wiggleMap
-    import shutil
+    mapsFolder.appendNode(gui.File("global", "Global", url = url + "global/"))
+    mapsFolder.appendNode(gui.File("stations", "Stations", url = url + "stations/"))
+    appWindow.path.append(mapsFolder.index[name])
+    child = gui.ChildWindow(url, "View")
 
-    opts = {
-        "event.jpg": dict(),
-        "antipode.jpg": dict(opt_A=True),
-        }[name]
-    stream = wiggleMap(event.singleSource, workspace.stations, opt_m=True, **opts)
-    response = HttpResponse(mimetype='image/jpeg')
-    shutil.copyfileobj(stream,  response)
-    stream.close()
-    return response
+    if name == "global":
+        mapRoot = "%s/maps/events/%d/stations/%d/global" % (config.root, event.firstSource.id, workspace.stations.id)
+        imgList = [img("%s/%s" % (mapRoot, jpg), width=506, height=506)
+                   for jpg in ["event.jpg", "antipode.jpg"]]
+    else:
+        mapUrl = "%s/maps/stations/%s/mercator.jpg" % (config.root, workspace.stations.id)
+        imgList = [img(mapUrl, width=547, height=657)]
+        
+    child.content = gui.StaticContent(' '.join(imgList))
+    desktop.activeWindow.selectWindow(child)
+    return desktop
 
 
 def openEventFinder(desktop):
@@ -1822,30 +1815,6 @@
                               )
 
 
-def beachballs(request, path, desktop):
-    name = path.pop(0)
-    source_id = intOr404(os.path.splitext(name)[0])
-    if path: raise Http404
-    return beachball_gif(request, source_id = source_id)
-
-
-def beachball_gif(request, event_id=None, source_id=None):
-    from gmt import psmeca
-    import shutil
-    
-    if event_id:
-        event = get_object_or_404(Event, id=event_id)
-        source = event.singleSource
-        if not Source:
-            raise Http404
-    else:
-        source = get_object_or_404(Source, id=source_id)
-    stream = psmeca(source)
-    response = HttpResponse(mimetype='image/gif')
-    shutil.copyfileobj(stream,  response)
-    stream.close()
-    return response
-
 def cmtsolution_txt(request, object_id):
     from models import Source
     source = get_object_or_404(Source, id=object_id)
@@ -1920,8 +1889,8 @@
 
     objId = stationList.id # Ouch!
 
-    view = gui.ChildWindow(url, "View")
-    map = gui.ChildWindow(url + "map/", "Map")
+    map = gui.ChildWindow(url, "Map")
+    list = gui.ChildWindow(url + "list/", "List")
     properties = gui.ChildWindow(url + "properties/", "Properties")
     menuBar = [
         gui.Menu("actionMenu", "actions", "Actions",
@@ -1929,17 +1898,23 @@
                   ]
                  ),
         ]
-    view.menuBar = properties.menuBar = menuBar
-    desktop.activeWindow.insertWindow(view)
+    map.menuBar = list.menuBar = properties.menuBar = menuBar
     desktop.activeWindow.insertWindow(map)
+    desktop.activeWindow.insertWindow(list)
     desktop.activeWindow.insertWindow(properties)
 
     if not path:
-        return object_detail(request, desktop, view, StationList.objects.all(), object_id = objId)
+        mapUrl = "%s/maps/stations/%s/mercator.jpg" % (config.root, objId)
+        map.content = gui.StaticContent(img(mapUrl, width=547, height=657))
+        desktop.activeWindow.selectWindow(map)
+        return desktop
 
     name = path.pop(0)
     if path: raise Http404
 
+    if name == "list":
+        return object_detail(request, desktop, list, StationList.objects.all(), object_id = objId)
+
     if name == "properties":
         objId = stationList.fsNode.id # Ouch!
         return update_object(request,
@@ -1951,18 +1926,10 @@
                              follow = FSNode.follow,
                              )
     
-    if name == "map":
-        map.content = gui.StaticContent(img(url + "map.jpg", width=547, height=657))
-        desktop.activeWindow.selectWindow(map)
-        return desktop
-
     if name == "delete":
         obj = get_object_or_404(StationList, id=objId)
         return moveObjectToTrash(obj, request, config.root + "/home/")
 
-    if name == "map.jpg":
-        return stations_map_jpg(stationList)
-
     index = Index({
         "stations.txt": stationlist_detail_txt,
         "gearth.kml": stationlist_detail_gearth,
@@ -2063,17 +2030,6 @@
                               **kwds)
 
 
-def stations_map_jpg(stationList):
-    from gmt import stationsMap
-    import shutil
-    
-    stream = stationsMap(stationList)
-    response = HttpResponse(mimetype='image/jpeg')
-    shutil.copyfileobj(stream,  response)
-    stream.close()
-    return response
-
-
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # Help
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



More information about the cig-commits mailing list