Ejemplo n.º 1
0
    def field_changed(changed):
        "Handle event where selected field changed"
        new = changed["new"]
        old = changed["old"]
        widgets.value_range.default = True
        cv = coverage.get(params.current_casedir)
        if cv is None:
            slider.disabled = True
            plot_field()
            return
        slider.disabled = False
        if new != old:

            min_ts, max_ts, step_ts, valid = get_timestepping(new)
            cbc_log(
                20,
                "In field-changed: Time-step range=%d-%d" % (min_ts, max_ts))
            widgets.slider.min = -1e16
            widgets.slider.max = 1e16
            widgets.slider.min = min_ts
            widgets.slider.max = max_ts
            widgets.slider.step = step_ts
            #value_range.value="-"
            #value_range.value = None
            if not valid:
                widgets.slider.value = widgets.slider.value
            plot_field()
Ejemplo n.º 2
0
    def update(self, t, timestep, cache, triggered_or_finalized):
        """Iterate through the triggered_or_finalized-list of fields, and save
        the fields with Field.params.save == True"""
        for field in triggered_or_finalized:
            #print name, cache[name]
            if field.params.save:
                cbc_log(20, "Saving field %s" % field.name)
                self._action_save(field, cache[field.name], timestep, t)

        if timestep % self.flush_frequency == 0:
            self._flush_data()
            self._timer.completed("PP: flush data")
Ejemplo n.º 3
0
    def setup_available_fields():
        num_all = np.count_nonzero(
            [c.value == "all" for c in widgets.batch_params.children])
        af = widgets.available_fields
        af.options = []
        current = af.value
        if num_all == 0:
            for k in fields:
                if k == "time":
                    continue
                af.options += fields[k]

            af.options = list(sorted(af.options))
        else:
            for k in fields:
                if "float" in k:
                    af.options += fields[k]

        if current not in af.options:
            if len(af.options) > 0:
                af.value = available_fields.options[0]
        cbc_log(20, "In setup_available_fields: af.options=" + str(af.options))
        cbc_log(20, "In setup_available_fields: af.value=" + str(af.value))
Ejemplo n.º 4
0
    def _action_save(self, field, data, timestep, t):
        "Apply the 'save' action to computed field data."
        field_name = field.name

        # Create save folder first time
        self._create_savedir(field_name)

        # Collect metadata shared between data types
        metadata = {
            'timestep': timestep,
            'time': t,
        }

        # Rename Functions to get the right name in file
        # (NB! This has the obvious side effect!)
        # TODO: We don't need to cache a distinct Function
        # object like we do for plotting, or?
        if isinstance(data, Function):
            data.rename(field_name, "Function produced by cbcpost.")

        # Get list of file formats
        save_as = _get_save_formats(field, data)
        # Notify user if self.rewrite_mesh has been set without mattering
        if field.params["rewrite_mesh"]:
            if not "xdmf" in save_as:
                cbc_log(
                    30, "rewrite_mesh flag has no effect for field {}".format(
                        field_name))

        # Write data to file for each filetype
        for saveformat in save_as:
            # Write data to file depending on type
            if saveformat == 'pvd':
                metadata[saveformat] = self._update_pvd_file(
                    field_name, saveformat, data, timestep, t)
            elif saveformat == 'xdmf':
                metadata[saveformat] = self._update_xdmf_file(
                    field_name, saveformat, data, timestep, t,
                    field.params["rewrite_mesh"])
            elif saveformat == 'xml':
                metadata[saveformat] = self._update_xml_file(
                    field_name, saveformat, data, timestep, t)
            elif saveformat == 'xml.gz':
                metadata[saveformat] = self._update_xml_gz_file(
                    field_name, saveformat, data, timestep, t)
            elif saveformat == 'txt':
                metadata[saveformat] = self._update_txt_file(
                    field_name, saveformat, data, timestep, t)
            elif saveformat == 'hdf5':
                metadata[saveformat] = self._update_hdf5_file(
                    field_name, saveformat, data, timestep, t)
            elif saveformat == 'shelve':
                metadata[saveformat] = self._update_shelve_file(
                    field_name, saveformat, data, timestep, t)
            else:
                error("Unknown save format %s." % (saveformat, ))
            self._timer.completed("PP: save %s %s" % (field_name, saveformat))

        # Write new data to metadata file
        self._update_metadata_file(field_name, data, t, timestep, save_as,
                                   metadata)
        self._timer.completed("PP: update metadata")
        self._fill_playlog(field, timestep, save_as)

        self._timer.completed("PP: update playlog")
Ejemplo n.º 5
0
 def value_range_changed(change):
     "Handle value range changed"
     vr = widgets.value_range
     cbc_log(20, "In value range changed: change=" + str(change))
     cbc_log(20, "In value range changed: default=" + str(vr.default))
     cbc_log(20, "In value range changed: visible=" + str(vr.visible))
     cbc_log(20, "In value range changed: value=" + str(vr.value))
     r = vr.max - vr.min
     cbc_log(20, "In value range changed: range=" + str(r))
     min, max = vr.value
     if r < 1e-12 or (abs(min - vr.min) / r < 1e-4
                      and abs(max - vr.max) / r < 1e-4):
         vr.default = True
     else:
         if r < 1e-12:
             vr.default = True
         else:
             vr.default = False
     cbc_log(20,
             "In value range changed (after): default=" + str(vr.default))
     plot_field()
Ejemplo n.º 6
0
    def plot_field():
        "Plot field. This method is called on every scene change in the gui"
        compute_current_value()
        type = current_value.type
        if type == "function":
            cbc_log(20, "Plotting function field")
            widgets.value_range.visible = True
            widgets.edge_cb.visible = True
            widgets.slider.visible = True
            widgets.play_pause_button.visible = True
            #widgets.plot_type.visible = False
            #widgets.log_scale.visible = False

            # Bug if these are added on first render, without function plot,
            # they are still shown. Therefore, adding them here
            c = list(containers[2][1].children)
            if widgets.value_range not in c:
                c.append(widgets.value_range)
            if widgets.edge_cb not in c:
                c.append(widgets.edge_cb)
            containers[2][1].children = tuple(c)
            #widgets.time.visible = True
            if current_value.key not in fields.timedependent_function:
                widgets.slider.disabled = True
                widgets.play_pause_button.disabled = True
            else:
                widgets.slider.disabled = False
                widgets.play_pause_button.disabled = False
            plot_function_field()
        elif type == "matplotlib":
            cbc_log(20, "Plotting matplotlib field")
            widgets.value_range.visible = False
            widgets.slider.visible = False
            widgets.play_pause_button.visible = False
            widgets.edge_cb.visible = False
            """
            c = list(containers[2][1].children)
            if not widgets.plot_type in c:
                c.append(widgets.plot_type)
            if not widgets.log_scale in c:
                c.append(widgets.log_scale)
            containers[2][1].children = tuple(c)
            
            if widgets.plot_type.value == "plot":
                widgets.log_scale.visible = False
            else:
                widgets.log_scale.visible = True
            widgets.plot_type.visible = True
            """
            #if current_value.xlabel == "Time":
            #    widgets.time.visible = False
            plot_matplotlib_field()
        elif type == "float":
            cbc_log(20, "Plotting float field")
            widgets.value_range.visible = False
            widgets.edge_cb.visible = False
            widgets.slider.visible = False
            widgets.play_pause_button.visible = False
            #widgets.plot_type.visible = False
            #widgets.log_scale.visible = False
            #widgets.time.visible = True
            plot_float_field()
        elif type == "pandas":
            cbc_log(20, "Plotting pandas field")
            widgets.value_range.visible = False
            widgets.edge_cb.visible = False
            widgets.slider.visible = False
            widgets.play_pause_button.visible = False
            #widgets.plot_type.visible = False
            #widgets.log_scale.visible = False
            #widgets.time.visible = True
            plot_pandas_field()
        else:
            raise RuntimeError("Unable to recognize field type %s" % type)
Ejemplo n.º 7
0
    def get(self, name, relative_timestep=0, compute=True, finalize=False):
        """Get the value of a named field at a particular relative_timestep.

        The relative_timestep is relative to now.
        Values are computed at first request and cached.
        """
        cbc_log(
            20, "Getting: %s, %d (compute=%s, finalize=%s)" %
            (name, relative_timestep, compute, finalize))

        # Check cache
        c = self._cache[relative_timestep]
        data = c.get(name, "N/A")

        # Check if field has been finalized, and if so,
        # return finalized value
        if name in self._finalized and data == "N/A":
            if compute:
                cbc_warning(
                    "Field %s has already been finalized. Will not call compute on field."
                    % name)
            return self._finalized[name]

        # Are we attempting to get value from before update was started?
        # Use constant extrapolation if allowed.
        if abs(relative_timestep) > self._update_all_count and data == "N/A":
            if self._extrapolate:
                cbc_log(
                    20, "Extrapolating %s from %d to %d" %
                    (name, relative_timestep, -self._update_all_count))
                data = self.get(name, -self._update_all_count, compute,
                                finalize)
                c[name] = data
            else:
                raise RuntimeError(
                    "Unable to get data from before update was started. \
                                   (%s, relative_timestep: %d, update_all_count: %d)"
                    % (name, relative_timestep, self._update_all_count))
        # Cache miss?
        if data == "N/A":
            field = self._fields[name]
            if relative_timestep == 0:
                # Ensure before_first_compute is always called once initially
                if self._compute_counts[field.name] == 0:
                    init_data = field.before_first_compute(self.get)
                    self._timer.completed("PP: before first compute %s" % name)
                    if init_data is not None:
                        cbc_warning("Did not expect a return value from \
                                    %s.before_first_compute." %
                                    field.__class__)

                # Compute value
                if name in self._solution:
                    data = self._solution[name]()
                    self._timer.completed("PP: call solution %s" % name)
                else:
                    if compute:
                        data = field.compute(self.get)
                        self._timer.completed("PP: compute %s" % name)
                    """
                    if finalize:
                        finalized_data = field.after_last_compute(self.get)
                        if finalized_data not in [None, "N/A"]:
                            data = finalized_data
                        self._finalized[name] = data
                        self._timer.completed("PP: finalize %s" %name)
                    """
                self._compute_counts[field.name] += 1

                # Copy functions to avoid storing references to the same function objects at each relative_timestep
                # NB! In other cases we assume that the fields return a new object for every compute!
                # Check first if we actually will cache this object by looking at 'time to keep' in the plan
                if self._plan[0][name] > 0:
                    if isinstance(data, Function):
                        # TODO: Use function pooling to avoid costly allocations?
                        data = data.copy(deepcopy=True)

                # Cache it!
                #c[name] = data
            else:
                # Cannot compute missing value from previous relative_timestep,
                # dependency handling must have failed
                raise DependencyException(name,
                                          relative_timestep=relative_timestep)

        if finalize:
            field = self._fields[name]
            finalized_data = field.after_last_compute(self.get)
            if finalized_data not in [None, "N/A"]:
                data = finalized_data
            self._finalized[name] = data
            self._timer.completed("PP: finalize %s" % name)

        c[name] = data
        return data
Ejemplo n.º 8
0
    def add_field(self, field, exists_reaction="error"):
        "Add field to postprocessor."
        assert isinstance(field, Field)

        # Note: If field already exists, replace anyway to overwrite params, this
        # typically happens when a fields has been created implicitly by dependencies.
        # This is a bit unsafe though, the user might add a field twice with different parameters...
        # Check that at least the same name is not used for different field classes:
        # UPDATE: Keep it safe, and raise error if field exists.
        if field.name in self._fields:
            s = "Field with name %s already been added to postprocessor." % field.name
            if exists_reaction == "replace":
                cbc_log(30, s + " Replacing.")
            elif exists_reaction == "ignore":
                cbc_log(30, s + " Ignoring.")
                return
            else:
                raise AssertionError(s)

        #assert field.name not in self._fields, "Field with name %s already been added to postprocessor." %field.name
        #assert type(field) == type(self._fields.get(field.name,field))
        #if field.name in self._fields:
        #    cbc_warning("Field with name %s already been added to postprocessor. Ignoring." %field.name)
        #    return

        # Add fields explicitly specified by field
        self.add_fields(field.add_fields(), "ignore")

        # Analyze dependencies of field through source inspection
        deps = field.explicit_dependencies()
        if deps is None:
            deps = find_dependencies(field)

        for dep in deps:
            if dep[0] not in self._fields and dep[0] not in builtin_fields:
                raise DependencyException(fieldname=field.name,
                                          dependency=dep[0])

        # Build full dependency list
        full_deps = []
        existing_full_deps = set()
        for dep in deps:
            depname, ts = dep
            for fdep in self._full_dependencies[depname]:
                # Sort out correct (relative) timestep of dependency
                fdepname, fts = fdep
                fts += ts
                fdep = (fdepname, fts)
                if fdep not in existing_full_deps:
                    existing_full_deps.add(fdep)
                    full_deps.append(fdep)
            existing_full_deps.add(dep)
            full_deps.append(dep)

        # Add field to internal data structures
        self._fields[field.name] = field
        self._dependencies[field.name] = deps
        self._full_dependencies[field.name] = full_deps
        self._insert_in_sorted_list(field.name)

        cbc_log(20, "Added field: %s" % field.name)

        # Returning the field object is useful for testing
        return field