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

leif at geodynamics.org leif at geodynamics.org
Fri Mar 28 16:16:31 PDT 2008


Author: leif
Date: 2008-03-28 16:16:30 -0700 (Fri, 28 Mar 2008)
New Revision: 11629

Added:
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_form.html
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_upload.html
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dgloberequest_form.html
Modified:
   cs/portal/trunk/seismo/SeismoWebPortal/models.py
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosparameters_form.html
   cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dglobeparameters_form.html
   cs/portal/trunk/seismo/SeismoWebPortal/views.py
Log:
More database refactoring: moved some items from parameters to
"request" objects.  Added the ability to upload Mineos model files.
Added missing 'station list' setting for Mineos parameters.


Modified: cs/portal/trunk/seismo/SeismoWebPortal/models.py
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/models.py	2008-03-28 22:02:26 UTC (rev 11628)
+++ cs/portal/trunk/seismo/SeismoWebPortal/models.py	2008-03-28 23:16:30 UTC (rev 11629)
@@ -437,13 +437,9 @@
     mesh = models.ForeignKey(Specfem3DGlobeMesh, limit_choices_to = userFSChoices)
     model = models.ForeignKey(Specfem3DGlobeModel, limit_choices_to = userFSChoices)
 
-    zero_half_duration = models.BooleanField(default=True)
-    
     #
     # specific information starts here
     #
-    record_length = models.FloatField(max_digits=19, decimal_places=10, core=True, default=20.0,
-                                      validator_list=[isValidRecordLength])
     receivers_can_be_buried = models.BooleanField(core=True)
     print_source_time_function = models.BooleanField(core=True)
     save_forward = models.BooleanField(core=True, default=False)
@@ -570,11 +566,35 @@
         return
     
 
+class MineosModel(models.Model):
+
+    fsNode = models.ForeignKey(FSNode, null=True)
+
+    # A Mineos model is a small (15-20K) text file.
+    data = models.TextField()
+
+    def __str__(self): return self.fsNode.name
+
+    def icon(self):
+        return '<img src="/specfem3dglobe/icons/model.gif">'
+
+    def save(self):
+        super(MineosModel, self).save()
+        if self.fsNode is None:
+            self.fsNode = FSNode.newNode(self)
+            super(MineosModel, self).save()
+        else:
+            self.fsNode.save() # touch
+        return
+
+
 class MineosParameters(models.Model):
 
     fsNode = models.ForeignKey(FSNode, null=True)
 
     catalog = models.ForeignKey(MineosModeCatalog, limit_choices_to = userFSChoices)
+    model = models.ForeignKey(MineosModel, limit_choices_to = userFSChoices)
+    stations = models.ForeignKey(StationList, limit_choices_to = userFSChoices)
 
     # jcom
     radial = models.BooleanField(default=True)
@@ -593,10 +613,6 @@
     
     step = models.FloatField(max_digits=19, decimal_places=10, default=1.0) # seconds
 
-    def nsamples(self):
-        from math import ceil
-        return int(ceil(self.record_length * 60.0 / self.step))
-
     #------------------------------------------------------------------------
 
     def __str__(self): return self.fsNode.name
@@ -615,19 +631,23 @@
 
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Request
+# Status
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
-class Request(models.Model):
-    
-    # CMTSOLUTION
-    event = models.ForeignKey(Event, limit_choices_to = userFSChoices)
+class Status(models.Model):
+    name = models.CharField(maxlength=100, primary_key=True)
 
-    parametersSpecfem3DGlobe = models.ForeignKey(Specfem3DGlobeParameters, null=True)
-    parametersMineos = models.ForeignKey(MineosParameters, null=True)
+    @classmethod
+    def get(cls, name):
+        status, created = cls.objects.get_or_create(name = name,
+                                                    defaults = dict(name = name))
+        return status
 
+    @classmethod
+    def new(cls):    return cls.get('new')
 
+
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # Runs, Jobs
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -635,25 +655,24 @@
 
 class Run(models.Model):
     # each request may have multiple runs
-    simulation = models.ForeignKey(Request)
+    contentType = models.ForeignKey(ContentType, db_index=True)
+    objectId = models.PositiveIntegerField(db_index=True)
+    request = models.GenericForeignKey(ct_field='contentType', fk_field='objectId')
 
-    status = models.CharField(maxlength=100)
+    status = models.ForeignKey(Status, db_index=True)
     started = models.DateTimeField(auto_now_add=True, editable=False)
     finished = models.DateTimeField(null=True, blank=True)
 
     class Admin:
-        list_display = ('simulation', 'status', 'started', 'finished')
+        list_display = ('status', 'started', 'finished')
 
-    def __str__(self):
-        return "%s r%d" % (self.simulation.name, self.id)
 
-
 class Job(models.Model):
     # each run may correspond to multiple jobs
     run = models.ForeignKey(Run)
     
     task = models.CharField(maxlength=100)
-    status = models.CharField(maxlength=100)
+    status = models.ForeignKey(Status, db_index=True)
     created = models.DateTimeField(auto_now_add=True, editable=False)
     started = models.DateTimeField(null=True, blank=True)
     finished = models.DateTimeField(null=True, blank=True)
@@ -677,6 +696,41 @@
 
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Requests
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+class Specfem3DGlobeRequest(models.Model):
+    
+    # CMTSOLUTION
+    event = models.ForeignKey(Event)
+
+    parameters = models.ForeignKey(Specfem3DGlobeParameters)
+    zero_half_duration = models.BooleanField(default=True)
+    record_length = models.FloatField(max_digits=19, decimal_places=10, core=True, default=20.0,
+                                      validator_list=[isValidRecordLength])
+
+    runs = models.GenericRelation(Run, db_index=True)
+    status = models.ForeignKey(Status, db_index=True)
+
+
+class MineosRequest(models.Model):
+    
+    event = models.ForeignKey(Event)
+
+    parameters = models.ForeignKey(MineosParameters)
+    record_length = models.FloatField(max_digits=19, decimal_places=10, core=True, default=20.0,
+                                      validator_list=[isValidRecordLength])
+
+    runs = models.GenericRelation(Run, db_index=True)
+    status = models.ForeignKey(Status, db_index=True)
+    
+    def nsamples(self):
+        from math import ceil
+        return int(ceil(self.record_length * 60.0 / self.parameters.step))
+
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # Registration
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Added: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_form.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_form.html	                        (rev 0)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_form.html	2008-03-28 23:16:30 UTC (rev 11629)
@@ -0,0 +1,17 @@
+<h2>{% if object %}edit {{ object }}{% else %}new model{% endif %}</h2>
+
+<form method="post" action="{{ action }}">
+
+    {% if form.has_errors %}
+    <p><span class=error>Please correct the following error{{ form.error_dict|pluralize }}.</span>
+    {% endif %}
+
+    {{ form.data }}
+
+    <div class=tab30ex>
+    <div>
+        <input class=submit type="submit" value="Save" />
+    </div>
+    </div> <!-- tab30ex -->
+
+</form>

Added: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_upload.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_upload.html	                        (rev 0)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosmodel_upload.html	2008-03-28 23:16:30 UTC (rev 11629)
@@ -0,0 +1,24 @@
+
+<h2>upload mineos model</h2>
+
+<form action="/specfem3dglobe/config/mineos/models/upload/" method="POST" enctype="multipart/form-data">
+
+    {% if form.has_errors %}
+    <p><span class=error>Please correct the following error{{ form.error_dict|pluralize }}.</span>
+    {% endif %}
+
+    <div class=tab30ex>
+
+    <div>
+        <label for="id_model" class=before>local file to upload</label>
+        {{ form.model }} {{ form.model_file }}
+        {% if form.model.errors %}<span class=error>{{ form.model.errors|join:", " }}</span>{% endif %}
+    </div>
+
+    <div>
+        <input class=submit type="submit" value="Upload">
+    </div>
+
+    </div> <!-- tab30ex -->
+
+</form>

Modified: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosparameters_form.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosparameters_form.html	2008-03-28 22:02:26 UTC (rev 11628)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/mineosparameters_form.html	2008-03-28 23:16:30 UTC (rev 11629)
@@ -7,29 +7,28 @@
     <p><span class=error>Please correct the following error{{ form.error_dict|pluralize }}.</span>
     {% endif %}
 
-{% if form.has_errors %}
-<dl class=error>
-    {% for f in form.error_dict.iteritems %}
-    <dt>{{ f.0 }}</dt>
-    <dd>
-        <ul class=error>
-        {% for e in f.1 %}
-            <li>{{ e }}</li>
-        {% endfor %}
-        </ul>
-    </dd>
-    {% endfor %}
-</dl>
-{% endif %}
+    <div class=tab30ex>
 
-    <p>1D synthetics are generated using the PREM earth model, both with and without an ocean.
-
     <div>
         <label for="id_catalog" class=before>catalog</label>
         {{ form.catalog }}
         {% if form.catalog.errors %}<span class=error>{{ form.catalog.errors|join:", " }}</span>{% endif %}
     </div>
 
+    <div>
+        <label for="id_model" class=before>model</label>
+        {{ form.model }}
+        {% if form.model.errors %}<span class=error>{{ form.model.errors|join:", " }}</span>{% endif %}
+    </div>
+
+    <div>
+        <label for="id_stations" class=before>station list</label>
+        {{ form.stations }}
+        {% if form.stations.errors %}<span class=error>{{ form.stations.errors|join:", " }}</span>{% endif %}
+    </div>
+
+    </div> <!-- tab30ex -->
+
     <fieldset><legend>oscillations</legend>
 
     <div class=checkbox>

Modified: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dglobeparameters_form.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dglobeparameters_form.html	2008-03-28 22:02:26 UTC (rev 11628)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dglobeparameters_form.html	2008-03-28 23:16:30 UTC (rev 11629)
@@ -11,16 +11,6 @@
 
     <input type="hidden" name="simulation_type" value="1">
 
-    <div class=checkbox>
-        {{ form.zero_half_duration }}
-        <label for="id_zero_half_duration" class=after>zero half duration</label>
-        {% if form.zero_half_duration.errors %}<span class=error>{{ form.zero_half_duration.errors|join:", " }}</span>{% endif %}
-    </div>
-
-    {% if help_visible %}
-    <dl class=help><dt>zero half duration</dt><dd>For point-source simulations, we recommend setting the source half-duration parameter <code>half duration</code> equal to zero, which corresponds to simulating a step source-time function, i.e., a moment-rate function that is a delta function. If <code>half duration</code> is not set to zero, the code will use a Gaussian (i.e., a signal with a shape similar to a 'smoothed triangle', as explained in Komatitsch and Tromp [2002a]) source-time function with half-width <code>half duration</code>. We prefer to run the solver with <code>half duration</code> set to zero and convolve the resulting synthetic seismograms in post-processing after the run, because this way it is easy to use a variety of source-time functions. Komatitsch and Tromp [2002a] determined that the noise generated in the simulation by using a step source time function may be safely filtered out afterward based upon a convolution with the desired source time function and/or low-pass filtering. Use the script <code>process_syn.pl</code> for this purpose by specifying the <code>-h</code> option (the <code>process_syn.pl</code> script can be found in the <a href="/specfem3dglobe/samples/UTILS.tar.gz">utilities package</a>). Alternatively, use signal-processing software packages such as <a href="http://www.llnl.gov/sac/">SAC</a>.<p>For finite fault simulations, it is usually not advisable to use a zero half duration and convolve afterwards, since the half duration is generally fixed by the finite fault model.</dd></dl>
-    {% endif %}
-
     <div>
         <label for="id_mesh" class=before>mesh</label>
         {{ form.mesh }}
@@ -33,16 +23,7 @@
         {% if form.model.errors %}<span class=error>{{ form.model.errors|join:", " }}</span>{% endif %}
     </div>
 
-    <div>
-        <label for="id_record_length" class=before>record length</label>
-        {{ form.record_length }} minutes
-        {% if form.record_length.errors %}<span class=error>{{ form.record_length.errors|join:", " }}</span>{% endif %}
-        {% if help_visible %}<span class=help>Choose the desired record length of the synthetic seismograms (in minutes). This controls the length of the numerical simulation, i.e., twice the record length requires twice as much CPU time. This must be 100 minutes or less for simulations run via the web.</span>{% endif %}
-    </div>
 
-
-    <fieldset><legend>stations</legend>
-
     <div>
         <label for="id_stations" class=before>station list</label>
         {{ form.stations }}
@@ -57,8 +38,6 @@
     </div>
 
 
-    </fieldset> <!-- stations -->
-
     {% if 0 %}
     <fieldset><legend>movie</legend>
 

Added: cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dgloberequest_form.html
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dgloberequest_form.html	                        (rev 0)
+++ cs/portal/trunk/seismo/SeismoWebPortal/templates/SeismoWebPortal/specfem3dgloberequest_form.html	2008-03-28 23:16:30 UTC (rev 11629)
@@ -0,0 +1,18 @@
+
+    <div class=checkbox>
+        {{ form.zero_half_duration }}
+        <label for="id_zero_half_duration" class=after>zero half duration</label>
+        {% if form.zero_half_duration.errors %}<span class=error>{{ form.zero_half_duration.errors|join:", " }}</span>{% endif %}
+    </div>
+
+    {% if help_visible %}
+    <dl class=help><dt>zero half duration</dt><dd>For point-source simulations, we recommend setting the source half-duration parameter <code>half duration</code> equal to zero, which corresponds to simulating a step source-time function, i.e., a moment-rate function that is a delta function. If <code>half duration</code> is not set to zero, the code will use a Gaussian (i.e., a signal with a shape similar to a 'smoothed triangle', as explained in Komatitsch and Tromp [2002a]) source-time function with half-width <code>half duration</code>. We prefer to run the solver with <code>half duration</code> set to zero and convolve the resulting synthetic seismograms in post-processing after the run, because this way it is easy to use a variety of source-time functions. Komatitsch and Tromp [2002a] determined that the noise generated in the simulation by using a step source time function may be safely filtered out afterward based upon a convolution with the desired source time function and/or low-pass filtering. Use the script <code>process_syn.pl</code> for this purpose by specifying the <code>-h</code> option (the <code>process_syn.pl</code> script can be found in the <a href="/specfem3dglobe/samples/UTILS.tar.gz">utilities package</a>). Alternatively, use signal-processing software packages such as <a href="http://www.llnl.gov/sac/">SAC</a>.<p>For finite fault simulations, it is usually not advisable to use a zero half duration and convolve afterwards, since the half duration is generally fixed by the finite fault model.</dd></dl>
+    {% endif %}
+
+
+    <div>
+        <label for="id_record_length" class=before>record length</label>
+        {{ form.record_length }} minutes
+        {% if form.record_length.errors %}<span class=error>{{ form.record_length.errors|join:", " }}</span>{% endif %}
+        {% if help_visible %}<span class=help>Choose the desired record length of the synthetic seismograms (in minutes). This controls the length of the numerical simulation, i.e., twice the record length requires twice as much CPU time. This must be 100 minutes or less for simulations run via the web.</span>{% endif %}
+    </div>

Modified: cs/portal/trunk/seismo/SeismoWebPortal/views.py
===================================================================
--- cs/portal/trunk/seismo/SeismoWebPortal/views.py	2008-03-28 22:02:26 UTC (rev 11628)
+++ cs/portal/trunk/seismo/SeismoWebPortal/views.py	2008-03-28 23:16:30 UTC (rev 11629)
@@ -13,7 +13,7 @@
 from models import Event, Source
 from models import Station, StationList, StationNetwork, DataSource, Region
 from models import Specfem3DGlobeModel, Specfem3DGlobeMesh, Specfem3DGlobeParameters
-from models import MineosModeCatalog, MineosParameters
+from models import MineosModeCatalog, MineosModel, MineosParameters
 from models import Run, Job, OutputFile
 from models import FSNode, Folder
 from cmt import CMTSolution
@@ -212,13 +212,18 @@
     if name == "events":
         return config_events(request, path, desktop)
     if name == "stations":
-        return config_stations(request, path, desktop)
+        return uploadOnly(request, path, desktop,
+                          UploadStationListManipulator(),
+                          "/specfem3dglobe/config/stations/upload/",
+                          "SeismoWebPortal/stationlist_upload.html")
+
     index = Index({
         "specfem3dglobe": Index({"models": Specfem3DGlobeModel,
                                  "meshes": [config_specfem3dglobe_meshes],
                                  "parameters": [config_specfem3dglobe_parameters] }),
         "mineos": Index({"modes": MineosModeCatalog,
-                         "parameters": MineosParameters}),
+                         "parameters": MineosParameters,
+                         "models": [config_mineos_models]}),
         })
     index = index[name]
     url = name
@@ -238,8 +243,17 @@
         return create(request, desktop, window, ModelClass)
 
     raise Http404
-        
 
+
+def uploadOnly(request, path, desktop, manipulator, url, templateName):
+    if not path: raise Http404
+    name = path.pop(0)
+    if name == "upload":
+        return uploadFile(request, path, desktop,
+                          manipulator,url, templateName)
+    raise Http404
+
+
 def configObject(name, request, path, desktop):
     objId = intOr404(name)
     url = "/specfem3dglobe/%d/" % objId
@@ -336,6 +350,7 @@
         gui.Menu("uploadMenu", "upload", "Upload",
                  [gui.MenuItem(config + "events/upload/", "Event"),
                   gui.MenuItem(config + "stations/upload/", "Station List"),
+                  gui.MenuItem(config + "mineos/models/upload/", "Mineos Model"),
                  ]
                  )
         ]
@@ -1079,7 +1094,7 @@
 
     index = Index({
         "new": lambda request, path, desktop: manipulate_event(request, path, desktop, action='new'),
-        "upload": upload_event,
+        "upload": uploadEvent,
         })
     view = index.get(name)
     if view:
@@ -1323,12 +1338,19 @@
     return desktop
 
 
-def upload_event(request, path, desktop):
+def uploadEvent(request, path, desktop):
     from forms import UploadEventManipulator
+    return uploadFile(request,
+                      path,
+                      desktop,
+                      UploadEventManipulator(),
+                      "/specfem3dglobe/config/events/upload/",
+                      "SeismoWebPortal/event_upload.html")
 
+
+def uploadFile(request, path, desktop, manipulator, url, templateName):
     if path: raise Http404
 
-    manipulator = UploadEventManipulator()
     help_visible = get_help_visible(request)
     
     if request.method == 'POST':
@@ -1345,15 +1367,15 @@
             errors = manipulator.get_validation_errors(new_data)
             if not errors:
                 manipulator.do_html2python(new_data)
-                new_event = manipulator.save(new_data, request.user)
-                return HttpResponseRedirect("/specfem3dglobe/%i/" % new_event.fsNode.id)
+                newObject = manipulator.save(new_data, request.user)
+                return HttpResponseRedirect("/specfem3dglobe/%i/" % newObject.fsNode.id)
     else:
         errors = new_data = {}
 
-    child = gui.ChildWindow("/specfem3dglobe/config/events/upload/", "Upload")
+    child = gui.ChildWindow(url, "Upload")
     child.buttons.append(helpButton(request))
     form = forms.FormWrapper(manipulator, new_data, errors)
-    html = loader.render_to_string('SeismoWebPortal/event_upload.html',
+    html = loader.render_to_string(templateName,
                                    {'form': form, 'help_visible': help_visible}
                                    )
     child.content = gui.StaticContent(html)
@@ -1455,17 +1477,6 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
-def config_stations(request, path, desktop):
-    if not path: raise Http404
-    name = path.pop(0)
-
-    if name == "upload":
-        if path: raise Http404
-        return upload_station_list(request, desktop)
-
-    raise Http404
-    
-
 def configStationList(stationList, url, request, path, desktop):
     from list_detail import object_detail
     from create_update import update_object
@@ -1523,41 +1534,6 @@
     return view(request, object_id = objId)
 
 
-def upload_station_list(request, desktop):
-    
-    manipulator = UploadStationListManipulator()
-    help_visible = get_help_visible(request)
-    
-    if request.method == 'POST':
-        new_data = request.POST.copy()
-        errors = {}
-        if new_data.has_key('show_help'):
-            help_visible = True
-            request.session['help_visible'] = help_visible
-        elif new_data.has_key('hide_help'):
-            help_visible = False
-            request.session['help_visible'] = help_visible
-        else:
-            new_data.update(request.FILES)
-            errors = manipulator.get_validation_errors(new_data)
-            if not errors:
-                manipulator.do_html2python(new_data)
-                stationList = manipulator.save(new_data, request.user)
-                return HttpResponseRedirect("/specfem3dglobe/%i/" % stationList.fsNode.id)
-    else:
-        errors = new_data = {}
-
-    child = gui.ChildWindow("/specfem3dglobe/config/stations/upload/", "Upload")
-    child.buttons.append(helpButton(request))
-    form = forms.FormWrapper(manipulator, new_data, errors)
-    html = loader.render_to_string('SeismoWebPortal/stationlist_upload.html',
-                                   {'form': form, 'help_visible': help_visible}
-                                   )
-    child.content = gui.StaticContent(html)
-    desktop.activeWindow.selectWindow(child)
-    return desktop
-
-
 def stationlist_detail_gearth(request, object_id):
     stationList = get_object_or_404(StationList, id=object_id)
     kwds = dict(queryset = stationList.station_set.all(),
@@ -1824,4 +1800,50 @@
     return response
 
 
+def config_mineos_models(request, path, desktop):
+    return uploadOnly(request, path, desktop,
+                      UploadMineosModelManipulator(),
+                      "/specfem3dglobe/config/mineos/models/upload/",
+                      "SeismoWebPortal/mineosmodel_upload.html")
+
+
+class UploadMineosModelManipulator(forms.Manipulator):
+    
+    def __init__(self):
+        super(UploadMineosModelManipulator, self).__init__()
+        self.fields = [
+            forms.FileUploadField(field_name='model', is_required=True),
+            ]
+
+    def get_validation_errors(self, new_data):
+        from StringIO import StringIO
+        
+        errors = super(UploadMineosModelManipulator, self).get_validation_errors(new_data)
+        
+        if not errors.get('model'):
+            try:
+                content = new_data['model']['content']
+                #stream = StringIO(content)
+                #parseMineosModel(None, stream)
+            except Exception:
+                errors['model'] = ['Please select a file in XXX format.']
+
+        return errors
+
+    def save(self, new_data, user):
+        from StringIO import StringIO
+
+        # Parse the uploaded MODEL file.
+        content = new_data['model']['content']
+        #stream = StringIO(content)
+        #parseMineosModel(None, stream)
+
+        # Create the new model.
+        model = MineosModel.objects.create(data = content)
+        model.fsNode.name = new_data['model']['filename']
+        model.fsNode.save()
+
+        return model
+
+
 # end of file



More information about the cig-commits mailing list