gnome.spill_container ===================== .. py:module:: gnome.spill_container .. autoapi-nested-parse:: spill_container.py Implements a container for spills -- keeps all the data from each spill in one set of arrays. The spills themselves provide some of the arrays themselves (adding more each time LEs are released). Classes ------- .. autoapisummary:: gnome.spill_container.FateDataView gnome.spill_container.SpillContainerData gnome.spill_container.SpillContainer gnome.spill_container.SpillContainerPairData gnome.spill_container.SpillContainerPair Module Contents --------------- .. py:class:: FateDataView Bases: :py:obj:`gnome.AddLogger` need a docstring -- what is this for? .. py:method:: reset() .. py:method:: get_data(sc, array_types, fate_status='surface_weather') Get data that matches the given fate_status. Since this is weathering data, only include elements with 'mass' > 0 Options are: 'all', 'surface_weather', 'subsurf_weather', 'skim', 'non_weather', 'burn' .. py:method:: update_sc(sc, fate_status='surface_weather') update SC arrays with FateDataView arrays for specified fate - update all arrays just to make sure everything is in sync After update, remove LEs with mass = 0. Since weatherers call this at the end of a weathering step, this ensures zero mass LEs are removed from the arrays. .. note:: the 'id' of each LE corresponds with the index into SC array when it was added. if LEs are removed, then this will not be the case. Do not rely on this indexing. Instead, get the mask again - the assumption is that the fate_mask should be the same between getting the data and resync'ing the original arrays in the SC .. py:class:: SpillContainerData(data_arrays=None, uncertain=False) Bases: :py:obj:`object` A really simple SpillContainer -- holds the data arrays, but doesn't manage spills, etc. Think of it as a read-only SpillContainer. Designed primarily to hold data retrieved from cache Initialize a SimpleSpillContainer. :param uncertain=False: flag indicating whether this holds uncertainty elements or not :param data_arrays=None: A dict of all the data arrays you want to hold :: NOTE: no error checking! they should be correctly aligned, etc. The common use-case for this is for loading from cache for re-rendering, etc. Note: initialize current_time_stamp attribute to None. It is responsibility of caller to set current_time_stamp (for eg: Model) .. py:attribute:: uncertain :value: False .. py:attribute:: on :value: True .. py:attribute:: current_time_stamp :value: None .. py:attribute:: mass_balance .. py:attribute:: substance :value: None .. py:property:: num_released The number of elements currently in the SpillContainer If SpillContainer is initialized, all data_arrays exist as ndarrays even if no elements are released. So this will always return a valid int >= 0. .. py:property:: data_arrays Returns a dict of the all the data arrays .. py:method:: keys() a keys() function so it looks a bit more like a dict .. py:class:: SpillContainer(uncertain=False) Bases: :py:obj:`gnome.AddLogger`, :py:obj:`SpillContainerData` Container class for all spills -- it takes care of capturing the released LEs from all the spills, putting them all in a single set of arrays. Many of the "fields" associated with a collection of elements are optional, or used only by some movers, so only the ones required will be requested by each mover. The data for the elements is stored in the _data_arrays dict. They can be accessed by indexing. For example: positions = spill_container['positions'] : returns a (num_LEs, 3) array of world_point_types Initialize a SimpleSpillContainer. :param uncertain=False: flag indicating whether this holds uncertainty elements or not :param data_arrays=None: A dict of all the data arrays you want to hold :: NOTE: no error checking! they should be correctly aligned, etc. The common use-case for this is for loading from cache for re-rendering, etc. Note: initialize current_time_stamp attribute to None. It is responsibility of caller to set current_time_stamp (for eg: Model) .. py:attribute:: spills .. py:method:: reset_fate_dataview() reset data arrays for each fate_dataviewer. Each substance that is not None has a fate_dataviewer object. .. py:method:: substancefatedata(substance, array_types, fate='surface_weather') Only one substance now! todo: fix this so it works for type of fate requested return the data for specified substance data must contain array names specified in 'array_types' .. py:method:: iterspillsbysubstance() iterate through the substances spills datastructure and return the spills associated with each substance. This is used by release_elements DataStructure contains all spills. If some spills contain None for substance, these will be returned .. py:method:: itersubstancedata(array_types, fate_status='surface_weather') There is only one substance allowed per SpillContainer, so this is returns the data cooresponding to the fate_status. This is only here to preserve compatiblity returns (substance, substance_data) This is used by weatherers - if a substance is None, StopIteration is raised :param array_types: iterable containing array that should be in the data. This could be a set of strings corresponding with array names or ArrayType objects which have a name attribute :param select='select': a string stating the type of data to be returned. Default if 'surface', so all elements with status_codes==oil_status.in_water and z == 0 in positions array :returns: (substance, substance_data) for each iteration substance: substance object substance_data: dict of numpy arrays associated with substance with elements in_water and on surface if select == 'surface' or subsurface if select == 'subsurface' .. py:method:: update_from_fatedataview(fate_status='surface_weather') let's only update the arrays that were changed only update if a copy of 'data' exists. .. py:method:: get_substances(complete=True) only one substance... .. py:property:: total_mass return total mass spilled in 'kg' .. py:property:: substances Returns list of substances for weathering - not including None since that is non-weathering. Currently, only one weathering substance is supported .. py:property:: array_types user can modify ArrayType initial_value in middle of run. Changing the shape should throw an error. Change the dtype at your own risk. This returns a new dict so user cannot add/delete an ArrayType in middle of run. Use prepare_for_model_run() to do add an ArrayType. .. py:method:: rewind() In the rewind operation, we: - rewind all the spills - restore _array_types to contain only defaults - movers/weatherers could have been deleted and we don't want to carry associated data_arrays - prepare_for_model_run() will be called before the next run and new arrays can be given - purge the data arrays - we gather data arrays for each contained spill - the stored arrays are cleared, then replaced with appropriate empty arrays .. py:method:: get_spill_mask(spill) .. py:method:: uncertain_copy() Returns a copy of the spill_container suitable for uncertainty It has all the same spills, with the same ids, and the uncertain flag set to True .. py:method:: prepare_for_model_run(array_types=None, time_step=300) called when setting up the model prior to 1st time step This is considered 0th timestep by model Make current_time optional since SpillContainer doesn't require it especially for 0th step; however, the model needs to set it because it will write_output() after each step. The data_arrays along with the current_time_stamp must be set in order to write_output() :param model_start_time: model_start_time to initialize current_time_stamp. This is the time_stamp associated with 0-th step so initial conditions for data arrays :param array_types: a set of additional names and/or array_types to append to standard array_types attribute. Set can contain only strings or a tuple with (string, ArrayType). See Note below. .. note:: set can contains strings or tuples. If set contains only strings, say: {'mass', 'windages'}, then SpillContainer looks for corresponding ArrayType object defined in gnome.array_types for 'mass' and 'windages'. If set contains a tuple, say: {('mass', gnome.array_types.mass)}, then SpillContainer uses the ArrayType defined in the tuple. .. note:: The SpillContainer iterates through each of the item in array_types and checks to see if there is an associated initializer in any Spill. If corresponding initializer is found, it gets the array_types from initializer and appends them to its own list. This was added for the case where 'droplet_diameter' array is defined/used by initializer (InitRiseVelFromDropletSizeFromDist) and we would like to see it in output, but no Mover/Weatherer needs it. .. py:method:: initialize_data_arrays() initialize_data_arrays() is called without input data during rewind and prepare_for_model_run to define all data arrays. At this time the arrays are empty. .. py:method:: release_elements(start_time, end_time, environment=None) :param start_time: -- beginning of the release :param end_time: -- end of the release. This calls release_elements on all of the contained spills, and adds the elements to the data arrays :returns: total number of particles released .. py:method:: split_element(ix, num, l_frac=None) split an element into specified number. For data, like mass, that gets divided, l_frac can be optionally provided. l_frac is a list containing fraction of component's value given to each new element. len(l_frac) must be equal to num and sum(l_frac) == 1.0 :param ix: id of element to be split - before splitting each element has a unique 'id' defined in 'id' data array :type ix: int :param num: split ix into 'num' number of elements :type num: int :param l_frac: list containing fractions that sum to 1.0 with len(l_frac) == num :type l_frac: list or tuple or numpy array .. py:method:: model_step_is_done() Called at the end of a time step Need to remove particles marked as to_be_removed... .. py:class:: SpillContainerPairData(sc, u_sc=None) Bases: :py:obj:`object` A really simple SpillContainerPair - holds SpillContainerPairData objects, but doen't manage spills, etc. Think of it as a read-only SpillContainerPair. Designed primarily to hold data retrieved from cache Initialize object with the spill_containers passed in .. py:property:: uncertain .. py:method:: items() returns a tuple of the enclosed spill containers if uncertainty is off, just one is in the tuple if uncertainly is on -- then it is a two-tuple: :: (certain_container, uncertain_container) To act on both: :: for sc in spill_container_pair.items(): do_something_with(sc) NOTE: cache code counts on the uncertain SpillContainer being last .. py:property:: LE_data .. py:method:: LE(prop_name, uncertain=False) .. py:class:: SpillContainerPair(uncertain=False) Bases: :py:obj:`SpillContainerPairData` Container holds two SpillContainers, one contains the certain spills while the other contains uncertainty spills if model uncertainty is on. initialize object: init spill_container, _uncertain and u_spill_container if uncertain Note: all operations like add, remove, replace and __iter__ are exposed to user for the spill_container.spills OrderedCollection .. py:method:: rewind() rewind spills in spill_container .. py:property:: uncertain .. py:method:: add(spills) Add spill to spill_container and make copy in u_spill_container if uncertainty is on Note: Method can take either a list, tuple, or list of tuples with following assumptions: 1. spills = Spill() # A spill object, if uncertainty is on, make a copy for uncertain_spill_container. 2. spills = [s0, s1, ..,] # List of forecast spills. if uncertain, make a copy of each and add to uncertain_spill_container 3. spills = (s0, uncertain_s0) # tuple of length two. Assume first one is forecast spill and second one is the uncertain copy. Used when restoring from save file 4. spills = [(s0, uncertain_s0), ..] # list of tuples of length two. Added for completeness. .. py:method:: append(spill) .. py:method:: remove(ident) remove object from spill_container.spills and the corresponding uncertainty spill as well .. py:method:: to_dict() takes the instance of SpillContainerPair class and outputs a dict with: 'spills': call to_dict() on spills ordered collection stored in certain spill container if uncertain, then also return: 'uncertain_spills': call to_dict() on spills ordered collection stored in uncertain spill container The input param ``json_`` is not used. It is there to keep the same interface for all to_dict() functions .. py:method:: update_from_dict(dict_) takes a dict {'spills': [list of spill objects]}, checks them against the forecast spills contained in _spill_container.spills and updates if they are different It also creates a copy of the different spill and replaces the corresponding spill in _u_spill_container This is primarily intended for the webapp so the ``dict_`` will only contain a list of forecast spills .. py:method:: spill_by_index(index, uncertain=False) return either the forecast spill or the uncertain spill at specified index .. py:method:: index(spill) Look for spill in forecast SpillContainer or uncertain SpillContainer and return the index of ordered collection where spill is found .. py:property:: num_released elements released by (forecast, uncertain) spills .. py:method:: clear() clear all spills from container pairs