:py:mod:`gnome.scripting` ========================= .. py:module:: gnome.scripting .. autoapi-nested-parse:: Scripting package for GNOME with assorted utilities that make it easier to write scripts. The ultimate goal is to be able to run py_gnome for the "common" use cases with only functionality available in this module Classes and helper functions are imported from various py_gnome modules (spill, environment, movers etc). we recommend that this module be used like so:: import gnome.scripting as gs Then you will have easy access to most of the stuff you need to write py_gnome scripts with, e.g.:: model = gs.Model(start_time="2018-04-12T12:30", duration=gs.days(2), time_step=gs.minutes(15)) model.map = gs.MapFromBNA('coast.bna', refloat_halflife=0.0) model.spills += gs.surface_point_line_spill(num_elements=1000, start_position=(-163.75, 69.75, 0.0), release_time="2018-04-12T12:30") Submodules ---------- .. toctree:: :titlesonly: :maxdepth: 1 time_utils/index.rst utilities/index.rst Package Contents ---------------- Classes ~~~~~~~ .. autoapisummary:: gnome.scripting.Model gnome.scripting.PrintFinder gnome.scripting.MinusInfTime gnome.scripting.InfTime gnome.scripting.Spill gnome.scripting.PointLineRelease gnome.scripting.PolygonRelease gnome.scripting.NonWeatheringSubstance gnome.scripting.GnomeOil gnome.scripting.Wind gnome.scripting.Renderer gnome.scripting.NetCDFOutput gnome.scripting.KMZOutput gnome.scripting.OilBudgetOutput gnome.scripting.ShapeOutput gnome.scripting.WeatheringOutput gnome.scripting.MapFromBNA gnome.scripting.GnomeMap gnome.scripting.FileGridCurrent gnome.scripting.GridCurrent gnome.scripting.SteadyUniformCurrent gnome.scripting.GridWind gnome.scripting.IceAwareCurrent gnome.scripting.IceAwareWind gnome.scripting.Tide gnome.scripting.Water gnome.scripting.Waves gnome.scripting.IceVelocity gnome.scripting.IceConcentration gnome.scripting.RandomMover gnome.scripting.RandomMover3D gnome.scripting.PointWindMover gnome.scripting.CatsMover gnome.scripting.ComponentMover gnome.scripting.RiseVelocityMover gnome.scripting.WindMover gnome.scripting.CurrentMover gnome.scripting.IceAwareRandomMover gnome.scripting.SimpleMover Functions ~~~~~~~~~ .. autoapisummary:: gnome.scripting.make_images_dir gnome.scripting.remove_netcdf gnome.scripting.set_verbose gnome.scripting.asdatetime gnome.scripting.seconds gnome.scripting.minutes gnome.scripting.hours gnome.scripting.days gnome.scripting.weeks gnome.scripting.surface_point_line_spill gnome.scripting.point_line_spill gnome.scripting.subsurface_spill gnome.scripting.grid_spill gnome.scripting.spatial_release_spill gnome.scripting.polygon_release_spill gnome.scripting.constant_wind gnome.scripting.wind_from_values gnome.scripting.constant_point_wind_mover gnome.scripting.point_wind_mover_from_file gnome.scripting.get_datafile gnome.scripting.load_model Attributes ~~~~~~~~~~ .. autoapisummary:: gnome.scripting.oil_status_map gnome.scripting.now gnome.scripting.PointWind gnome.scripting.PyCurrentMover gnome.scripting.PyWindMover .. py:class:: Model(name='Model', time_step=timedelta(minutes=15), start_time=round_time(datetime.now(), 3600), duration=timedelta(days=1), weathering_substeps=1, map=None, uncertain=False, cache_enabled=False, mode=None, make_default_refs=True, location=[], environment=[], outputters=[], movers=[], weatherers=[], spills=[], uncertain_spills=[], weathering_activated=False, **kwargs) Bases: :py:obj:`gnome.gnomeobject.GnomeId` PyGnome Model Class Initializes a model. All arguments have a default. :param time_step=timedelta(minutes=15): model time step in seconds or as a timedelta object. NOTE: if you pass in a number, it WILL be interpreted as seconds :param start_time=datetime.now(): start time of model, datetime object. Rounded to the nearest hour. :param duration=timedelta(days=1): How long to run the model, a timedelta object. :param weathering_substeps=1: How many weathering substeps to run inside a single model time step. :param map=gnome.map.GnomeMap(): The land-water map. :param uncertain=False: Flag for setting uncertainty. :param cache_enabled=False: Flag for setting whether the model should cache results to disk. :param mode='Gnome': The runtime 'mode' that the model should use. This is a value that the Web Client uses to decide which UI views it should present. .. py:property:: uncertain Uncertainty attribute of the model. If flag is toggled, rewind model .. py:property:: uncertain_spills .. py:property:: cache_enabled If True, then generated data is cached .. py:property:: has_weathering_uncertainty .. py:property:: has_weathering .. py:property:: start_time Start time of the simulation .. py:property:: time_step time step over which the dynamics is computed .. py:property:: current_time_step Current timestep of the simulation .. py:property:: duration total duration of the model run .. py:property:: map land water map used for simulation .. py:property:: num_time_steps Read only attribute computed number of timesteps based on py:attribute:`duration` and py:attribute:`time_step` .. py:attribute:: _schema .. py:attribute:: _oc_list :value: ['movers', 'weatherers', 'environment', 'outputters'] .. py:attribute:: modes .. py:attribute:: next .. py:method:: load_savefile(filename) :classmethod: Load a model instance from a save file :param filename: the filename of the save file -- usually a zip file, but can also be a directry with the full contents of a zip file :return: a model instance all set up from the savefile. .. py:method:: _register_callbacks() Register callbacks with the OrderedCollections .. py:method:: add_weathering(which='standard') Add the weatherers :param which='standard': which weatheres to add. Default is 'standard', which will add all the standard weathering algorithms if you don't want them all, you can specify a list: ['evaporation', 'dispersion']. Options are: - 'evaporation' - 'dispersion' - 'emulsification' - 'dissolution': Dissolution, - 'half_life_weatherer' see: ``gnome.weatherers.__init__.py`` for the full list .. py:method:: reset(**kwargs) Resets model to defaults -- Caution -- clears all movers, spills, etc. Takes same keyword arguments as :meth:`__init__()` .. py:method:: rewind() Rewinds the model to the beginning (start_time) .. py:method:: update_from_dict(dict_, refs=None) functions in common_object. .. py:method:: _reset_num_time_steps() reset number of time steps if duration, or time_step change .. py:method:: contains_object(obj_id) .. py:method:: find_by_class(obj, collection, ret_all=False) Look for an object that isinstance() of obj in specified colleciton. By default, it will return the first object of this type. To get all obects of this type, set ret_all to True .. py:method:: find_by_attr(attr, value, collection, allitems=False) find first object in collection where the 'attr' attribute matches 'value'. This is primarily used to find 'wind', 'water', 'waves' objects in environment collection. Use the '_ref_as' attribute to search. # fixme: why don't we look for wind, water or waves directly? Ignore AttributeError since all objects in collection may not contain the attribute over which we are searching. :param attr: attribute whose value must match :type attr: str :param value: desired value of the attribute :type value: str :param OrderedCollection collection: the ordered collection in which to search .. py:method:: _order_weatherers() use weatherer_sort to sort the weatherers .. py:method:: _attach_default_refs(ref_dict) Model invokes the default reference attachment system. Please note the structure of this function as an example of how to extend the system to contained child objects. .. py:method:: setup_model_run() Runs the setup procedure preceding a model run. When complete, the model should be ready to run to completion without additional prep Currently this function consists of the following operations: 1. Set up special objects. Some weatherers currently require other weatherers to exist. This step satisfies those requirements 2. Remake collections in case ordering constraints apply (weatherers) 3. Compile array_types and run setup procedure on spills array_types defines what data arrays are required by the various components of the model 4. Attach default references 5. Call prepare_for_model_run on all relevant objects 6. Conduct miscellaneous prep items. See section in code for details. .. py:method:: post_model_run() A place where the model goes through all collections and calls post_model_run if the object has it. .. py:method:: setup_time_step() sets up everything for the current time_step: .. py:method:: move_elements() Moves elements: - loops through all the movers. and moves the elements - sets new_position array for each spill - calls the beaching code to beach the elements that need beaching. - sets the new position .. py:method:: _update_fate_status(sc) WeatheringData used to perform this operation in weather_elements; however, WeatheringData is one of the objects in weatherers collection so just let model do this for now. Eventually, we want to get rid of 'fate_status' array and only manipulate 'status_codes'. Until then, update fate_status in move_elements .. py:method:: weather_elements() Weathers elements: - loops through all the weatherers, passing in the spill_container and the time range - a weatherer modifies the data arrays in the spill container, so a particular time range should not be run multiple times. It is expected that we are processing a sequence of contiguous time ranges. - Note: If there are multiple sequential weathering processes, some inaccuracy could occur. A proposed solution is to 'super-sample' the model time step so that it will be replaced with many smaller time steps. We'll have to see if this pans out in practice. .. py:method:: _split_into_substeps() :return: sequence of (datetime, timestep) (Note: we divide evenly on second boundaries. Thus, there will likely be a remainder that needs to be included. We include this remainder, which results in 1 more sub-step than we requested.) .. py:method:: step_is_done() Loop through movers and weatherers and call model_step_is_done Remove elements that marked for removal Output data .. py:method:: write_output(valid, messages=None) .. py:method:: step() Steps the model forward in time. NOTE: in theory, it could also go backward with a negative time step, for hindcasting, but that has not been tested. .. py:method:: output_step(isvalid) .. py:method:: release_elements(start_time, end_time) release elements into the model :param start_time: -- beginning of the release :param end_time: -- end of the release. .. py:method:: compile_env() Produces a dictionary of objects that describe the model environmental conditions Currently, only works with the 'water' object because the other environmental phenomena are not compatible yet .. py:method:: __iter__() Rewinds the model and returns itself so it can be iterated over. .. py:method:: __next__() (This method satisfies Python's iterator and generator protocols) :return: the step number .. py:method:: full_run(rewind=True) Do a full run of the model. :param rewind=True: whether to rewind the model first -- if set to false, model will be run from the current step to the end :returns: list of outputter info dicts .. py:method:: _add_to_environ_collec(obj_added) if an environment object exists in obj_added, but not in the Model's environment collection, then add it automatically. todo: maybe we don't want to do this - revisit this requirement JAH 9/22/2021: We sort of need this now because a lot of script behavior expects it. A lamentable state of affairs indeed. CHB: maybe this could be more standardized though -- pity to have hard coded what all the possible environment types are. perhaps all objects could have a "need_env_objects" attribute? .. py:method:: _callback_add_mover(obj_added) Callback after mover has been added .. py:method:: _callback_add_outputter(obj_added) Callback after outputter has been added .. py:method:: _callback_add_weatherer_env(obj_added) Callback after weatherer/environment object has been added. 'waves' environment object contains 'wind' and 'water' so add those to environment collection and the 'water' attribute. todo: simplify this .. py:method:: _callback_add_spill(obj_added) .. py:method:: __eq__(other) .. function:: __eq__(other) Since this class is designed as a mixin with one objective being to save _state of the object, then recreate a new object with the same _state. Defines a base implementation of __eq__ so an object before persistence can be compared with a new object created after it is persisted. It can be overridden by the class with which it is mixed. It looks at attributes defined in self._state and checks that the values match It uses allclose() check for floats and numpy arrays, to avoid floating point tolerances: set to: RTOL=1e-05, ATOL=1e-08 :param other: another GnomeObject used for comparison in obj1 == other NOTE: super is not used. .. py:method:: __ne__(other) Return self!=value. .. py:method:: spills_update_from_dict(value) invoke SpillContainerPair().update_from_dict .. py:method:: save(saveloc='.', refs=None, overwrite=True) save the model state in saveloc. If self.zipsave is True, then a zip archive is created and model files are saved to the archive. :param saveloc=".": a directory or filename. If a directory, then either the model is saved into that dir, or a zip archive is created in that dir (with a .gnome extension). The file(s) are clobbered when save() is called. :type saveloc: A dir or file name (relative or full path) as a string. :param refs=None: dict of references mapping 'id' to a string used for the reference. The value could be a unique integer or it could be a filename. It is up to the creator of the reference list to decide how to reference a nested object. :param overwrite=True: :returns: references This overrides the base class save(). Model contains collections and model must invoke save for each object in the collection. It must also save the data in the SpillContainer's if it is a mid-run save. .. py:method:: _save_spill_data(saveloc, nc_filename) save the data arrays for current timestep to NetCDF If saveloc is zipfile, then move NetCDF to zipfile .. py:method:: load(saveloc='.', filename=None, refs=None) :classmethod: Load an instance of this class from an archive or folder :param saveloc: Can be an open zipfile.ZipFile archive, a folder, or a filename. If it is an open zipfile or folder, it must contain a ``.json`` file that describes an instance of this object type. If ``filename`` is not specified, it will load the first instance of this object discovered. If a filename, it must be a zip archive or a json file describing an object of this type. :param filename: If saveloc is an open zipfile or folder, this indicates the name of the file to be loaded. If saveloc is a filename, is parameter is ignored. :param refs: A dictionary of id -> object instances that will be used to complete references, if available. .. py:method:: _load_spill_data(saveloc, filename, nc_file) load NetCDF file and add spill data back in - designed for savefiles .. py:method:: merge(model) merge 'model' into self .. py:method:: check_inputs() check the user inputs before running the model raise an exception if user can't run the model todo: check if all spills start after model ends fixme: This should probably be broken out into its own module, class, something -- with each test independent. .. py:method:: validate() invoke validate for all gnome objects contained in model todo: should also check wind, water, waves are defined if weatherers are defined .. py:method:: _validate_env_coll(refs, raise_exc=False) validate refs + log warnings or raise error if required refs not found. If refs is None, model must query its weatherers/movers/environment collections to figure out what objects it needs to have in environment. .. py:method:: set_make_default_refs(value) make default refs for all items in ('weatherers', 'movers', 'environment') collections .. py:method:: list_spill_properties() Convenience method to list properties of a spill that can be retrieved using get_spill_property :return: list of spill simulation attributes .. py:method:: get_spill_property(prop_name, ucert=False) Convenience method to allow user to look up properties of a spill. :param prop_name: name of property: use `model.list_properties()` to see all the options. :type prop_name: str :param ucert: whether to get it from the uncertainty spill :type ucert: bool :returns: np.array .. py:method:: get_spill_data(target_properties, conditions, ucert=0) Convenience method to allow user to write an expression to filter raw spill data Example case:: get_spill_data('position && mass', 'position > 50 && spill_num == 1 || status_codes == 1' ) WARNING: EXPENSIVE! USE AT YOUR OWN RISK ON LARGE num_elements! Example spill element properties are below. This list may not contain all properties tracked by the model. 'positions', 'next_positions', 'last_water_positions', 'status_codes', 'spill_num', 'id', 'mass', 'age' .. py:method:: add_env(env, quash=False) .. py:data:: oil_status_map .. py:function:: make_images_dir(images_dir=None) Create output directory for rendered images. If it already exists, delete all old output files .. py:function:: remove_netcdf(netcdf_file) remove netcdf_file and associated uncertain netcdf file Give scripts control over deleting the netcdf file before instantiating a new NetCDFOutput object. .. py:function:: set_verbose(log_level='info') Set the logging system to dump to the console -- you can see much more what's going on with the model as it runs :param log_level='info': the level you want your log to show. options are, in order of importance: "debug", "info", "warning", "error", "critical". You will only get the logging messages at or above the level you set. Set to "debug" for everything. .. py:class:: PrintFinder Bases: :py:obj:`object` class to capture stdout so that you can find print statements This will print the file, line number, and line after a print statement To use, simply create an instance in your script PrintFinder() IF you want to be able to put it back, save it and call: pf = PrintFinder() pf.restore() initialize a PrintFinder object This captures stdout when it is initialized .. py:method:: write(content) The stream write method -- intercepts the write to stdout, writes to original stdout, then adds some traceback info. .. py:method:: restore() sets stdout back to the original .. py:method:: flush() forwards a flush call on to the original stdout .. py:function:: asdatetime(dt) makes sure the input is a datetime.datetime object if it already is, it will be passed through. If not it will attempt to parse a string to make a datetime object. None will also be passed through silently .. py:function:: seconds(seconds=1) returns a datetime.timedelta object representing the specified number of seconds" :param seconds=1: .. py:function:: minutes(minutes=1) returns a datetime.timedelta object representing the specified number of minutes :param minutes=1: .. py:function:: hours(hours=1) returns a datetime.timedelta object representing the specified number of hours :param hours=1: .. py:function:: days(days=1) returns a datetime.timedelta object representing the specified number of hours" :param hours=1: .. py:function:: weeks(weeks=1) returns a datetime.timedelta object representing the specified number of weeks" :param weeks=1: .. py:data:: now .. py:class:: MinusInfTime Bases: :py:obj:`object` class representing time from infinity in the past compares as less than any datetime (or any other object) .. py:method:: __str__() Return str(self). .. py:method:: __repr__() Return repr(self). .. py:method:: isoformat() .. py:method:: __lt__(other) an MinusInfTime object is always less than any other object except itself .. py:method:: __le__(other) an MinusInfTime object is always less than or equal to any other object. .. py:method:: __eq__(other) A MinusInfTime object is only equal to itself .. py:method:: __ne__(other) A MinusInfTime object is only equal to itself .. py:method:: __gt__(other) A MinusInfTime object is not greater than anything .. py:method:: __ge__(other) A Minus InfTime object is not greater than or equal to anything other than itself .. py:method:: __pos__() .. py:method:: __neg__() .. py:class:: InfTime Bases: :py:obj:`object` class representing time into infinity compares as greater than any datetime (or any other object..) .. py:method:: __str__() Return str(self). .. py:method:: __repr__() Return repr(self). .. py:method:: isoformat() .. py:method:: __lt__(other) an InfTime object is never less than any other object .. py:method:: __le__(other) an InfTime object is never less than or equal to any other object otehr than itself. .. py:method:: __eq__(other) an InfTime object is only equal to itself .. py:method:: __ne__(other) an InfTime object is only equal to itself .. py:method:: __gt__(other) an InfTime object is greater than eveything except another InfTime object .. py:method:: __ge__(other) an InfTime object is greater or equal to anything .. py:method:: __pos__() .. py:method:: __neg__() .. py:class:: Spill(on=True, num_elements=1000, amount=0, units='kg', substance=None, release=None, water=None, amount_uncertainty_scale=0.0, **kwargs) Bases: :py:obj:`BaseSpill` Models a spill by combining Release and Substance objects Spills used by the gnome model. It contains a release object, which releases elements. It also contains a Substance which contains the type of substance spilled and it initializes data arrays to non-default values (non-zero). :param release: an object defining how elements are to be released :type release: derived from :class:`~gnome.spills.release.Release` :param substance: an object defining the substance of this spill. Defaults to :class:`~gnome.spills.substance.NonWeatheringSubstance` :type substance: derived from :class:`~gnome.spills.substance.Substance` **Optional parameters (kwargs):** :param name: Human-usable Name of this spill :type name: str :param on=True: Toggles the spill on/off. :type on: bool :param amount=None: mass or volume of oil spilled. :type amount: double (volume or mass) :param units=None: must provide units for amount spilled. :type units: str :param amount_uncertainty_scale=0.0: scale value in range 0-1 that adds uncertainty to the spill amount. Maximum uncertainty scale is (2/3) * spill_amount. :type amount_uncertainty_scale: float .. note:: Define either volume or mass in 'amount' attribute and provide appropriate 'units'. .. py:property:: all_array_types Need to add array types from Release and Substance .. py:property:: substance .. py:property:: release_time .. py:property:: end_release_time .. py:property:: release_duration .. py:property:: num_elements .. py:property:: start_position .. py:property:: end_position .. py:property:: amount .. py:property:: units Default units in which amount of oil spilled was entered by user. The 'amount' property is returned in these 'units' .. py:attribute:: _schema .. py:attribute:: valid_vol_units .. py:attribute:: valid_mass_units .. py:method:: __repr__() Return repr(self). .. py:method:: _check_units(units) Checks the user provided units are in list of valid volume or mass units .. py:method:: get_mass() Return the total mass released during the spill. .. py:method:: uncertain_copy() Returns a deepcopy of this spill for the uncertainty runs The copy has everything the same, including the spill_num, but it is a new object with a new id. Not much to this method, but it could be overridden to do something fancier in the future or a subclass. There are a number of python objects that cannot be deepcopied. - Logger objects So we copy them temporarily to local variables before we deepcopy our Spill object. .. py:method:: set_amount_uncertainty(up_or_down=None) This function shifts the spill amount based on a scale value in the range [0.0 ... 1.0]. The maximum uncertainty scale value is (2/3) * spill_amount. We determine either an upper uncertainty or a lower uncertainty multiplier. Then we shift our spill amount value based on it. Since we are irreversibly changing the spill amount value, we should probably do this only once. .. py:method:: rewind() rewinds the release to original status (before anything has been released). .. py:method:: prepare_for_model_run(timestep) array_types comes from all the other objects above in the model such as movers, weatherers, etc. The ones from the substance still need to be added .. py:method:: release_elements(sc, start_time, end_time, environment=None) Releases and partially initializes new LEs Note: this will have to be updated if we allow backwards runs for continuous spills .. py:method:: num_elements_to_release(current_time, time_step) Determines the number of elements to be released during: current_time + time_step It invokes the num_elements_to_release method for the the underlying release object: self.release.num_elements_to_release() :param current_time: current time :type current_time: datetime.datetime :param int time_step: the time step, sometimes used to decide how many should get released. :returns: the number of elements that will be released. This is taken by SpillContainer to initialize all data_arrays. .. py:method:: _attach_default_refs(ref_dict) !!!IMPORTANT!!! If this object requires default references (self._req_refs exists), this function will use the name of the references as keys into a reference dictionary to get a list of satisfactory references (objects that have obj._ref_as == self._req_refs). It will then attach the first object in the reference list to that attribute on this object. This behavior can be overridden if the object needs more specific attachment behavior than simply 'first in line' In addition, this function SHOULD BE EXTENDED if this object should provide default references to any contained child objects. When doing so, please be careful to respect already existing references. The reference attachment system should only act if the requested reference 'is None' when the function is invoked. See Model._attach_default_refs() for an example. .. py:class:: PointLineRelease(release_time=None, start_position=None, num_elements=None, num_per_timestep=None, end_release_time=None, end_position=None, release_mass=0, **kwargs) Bases: :py:obj:`Release` The primary spill source class -- a release of floating non-weathering particles, can be instantaneous or continuous, and be released at a single point, or over a line. Required Arguments: :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param start_position: initial location the elements are released :type start_position: 3-tuple of floats (long, lat, z) Optional arguments: .. note:: Either num_elements or num_per_timestep must be given. If both are None, then it defaults to num_elements=1000. If both are given a TypeError is raised because user can only specify one or the other, not both. :param num_elements: total number of elements to be released :type num_elements: integer :param num_per_timestep: fixed number of LEs released at each timestep :type num_elements: integer :param end_release_time=None: optional -- for a time varying release, the end release time. If None, then release is instantaneous :type end_release_time: datetime.datetime :param end_position=None: optional. For moving source, the end position If None, then release from a point source :type end_position: 3-tuple of floats (long, lat, z) :param release_mass=0: optional. This is the mass released in kilograms. :type release_mass: integer .. py:property:: is_pointsource if end_position - start_position == 0, point source otherwise it is a line source :returns: True if point source, false otherwise .. py:property:: centroid .. py:property:: start_position .. py:property:: end_position .. py:attribute:: _schema .. py:method:: __repr__() Return repr(self). .. py:method:: generate_release_timeseries(num_ts, max_release, ts) Release timeseries describe release behavior as a function of time. _release_ts describes the number of LEs that should exist at time T _pos_ts describes the spill position at time T All use TimeseriesData objects. .. py:method:: rewind() .. py:method:: prepare_for_model_run(ts) :param ts: timestep as integer seconds .. py:method:: initialize_LEs(to_rel, sc, start_time, end_time) Initializes the mass and position for to_rel new LEs. :param data: spill container with data arrays :param to_rel: number of elements to initialize :param start_time: initial time of release :param end_time: final time of release .. py:method:: initialize_LEs_post_substance(to_rel, sc, start_time, end_time, environment) .. py:class:: PolygonRelease(filename=None, features=None, polygons=None, weights=None, thicknesses=None, **kwargs) Bases: :py:obj:`Release` A release of elements into a set of provided polygons. When X particles are determined to be released, they are into the polygons randomly. For each LE, pick a polygon, weighted by it's proportional area and place the LE randomly within it. By default the PolygonRelease uses simple area for polygon weighting. Other classes (NESDISRelease for example) may use other weighting functions. Required Arguments: :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param polygons: polygons to use in this release :type polygons: list of shapely.Polygon or shapely.MultiPolygon. Optional arguments: :param filename: (optional) shapefile :type filename: string name of a zip file. Polygons loaded are concatenated after polygons from kwarg :param weights: (optional) LE placement probability weighting for each polygon. Must be the same length as the polygons kwarg, and must sum to 1. If None, weights are generated at runtime based on area proportion. :param num_elements: total number of elements to be released :type num_elements: integer default 1000 :param num_per_timestep: fixed number of LEs released at each timestep :type num_elements: integer :param end_release_time=None: optional -- for a time varying release, the end release time. If None, then release is instantaneous :type end_release_time: datetime.datetime :param release_mass=0: optional. This is the mass released in kilograms. :type release_mass: integer .. py:property:: filename .. py:property:: centroid .. py:property:: __geo_interface__ .. py:property:: features .. py:property:: polygons .. py:property:: thicknesses .. py:property:: weights .. py:property:: areas .. py:attribute:: _schema .. py:method:: gen_fc_from_kwargs(kwargs) .. py:method:: rewind() .. py:method:: get_polys_as_tris(polys, weights=None) .. py:method:: compute_distribution() .. py:method:: prepare_for_model_run(ts) :param ts: timestep as integer seconds .. py:method:: initialize_LEs(to_rel, data, start_time, end_time) set positions for new elements added by the SpillContainer .. note:: this releases all the elements at their initial positions at the end_time .. py:method:: get_polygons() Returns an array of lengths, and a list of line arrays. The first array sequentially indexes the second array. When the second array is split up using the first array and the resulting lines are drawn, you should end up with a picture of the polygons. .. py:method:: get_metadata() .. py:method:: new_from_dict(dict_) :classmethod: creates a new object from dictionary This is base implementation and can be over-ridden by classes using this mixin .. py:function:: surface_point_line_spill(num_elements, start_position, release_time, end_position=None, end_release_time=None, substance=None, amount=0, units='kg', water=None, on=True, windage_range=None, windage_persist=None, name='Surface Point or Line Release') Helper function returns a Spill object :param num_elements: total number of elements to be released :type num_elements: integer :param start_position: initial location the elements are released :type start_position: 2-tuple of floats (long, lat) :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param end_position=None: Optional. For moving source, the end position If None, then release is from a point source :type end_position: 2-tuple of floats (long, lat) :param end_release_time=None: optional -- for a time varying release, the end release time. If None, then release is instantaneous :type end_release_time: datetime.datetime :param substance=None: Type of oil spilled. :type substance: Substance object :param amount=None: mass or volume of oil spilled :type amount: float :param units=None: units for amount spilled :type units: str :param tuple windage_range=(.01, .04): Percentage range for windage. Active only for surface particles when a mind mover is added :type windage_range: tuple :param windage_persist=900: Persistence for windage values in seconds. Use -1 for inifinite, otherwise it is randomly reset on this time scale :type windage_persist: int :param name='Surface Point/Line Spill': a name for the spill :type name: str .. py:function:: point_line_spill(num_elements, start_position, release_time, end_position=None, end_release_time=None, substance=None, amount=0, units='kg', water=None, on=True, windage_range=None, windage_persist=None, name='Point or Line Release') Helper function returns a Spill object :param num_elements: total number of elements to be released :type num_elements: integer :param start_position: initial location the elements are released :type start_position: 3-tuple of floats (long, lat, postive depth) or 2-tuple of floats (lon,lat) in which case depth will default to 0 :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param end_position=None: Optional. For moving source, the end position If None, then release is from a point source :type end_position: 2-tuple of floats (long, lat) :param end_release_time=None: optional -- for a time varying release, the end release time. If None, then release is instantaneous :type end_release_time: datetime.datetime :param substance=None: Type of oil spilled. :type substance: Substance object :param amount=None: mass or volume of oil spilled :type amount: float :param units=None: units for amount spilled :type units: str :param tuple windage_range=(.01, .04): Percentage range for windage. Active only for surface particles when a mind mover is added :type windage_range: tuple :param windage_persist=900: Persistence for windage values in seconds. Use -1 for inifinite, otherwise it is randomly reset on this time scale :type windage_persist: int :param name='Point/Line Spill': a name for the spill :type name: str .. py:function:: subsurface_spill(num_elements, start_position, release_time, distribution, distribution_type='droplet_size', end_release_time=None, substance=None, amount=0, units='kg', water=None, on=True, windage_range=None, windage_persist=None, name='Subsurface plume') Helper function returns a Spill object :param num_elements: total number of elements to be released :type num_elements: integer :param start_position: initial location the elements are released :type start_position: 3-tuple of floats (long, lat, z) :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param distribution=None: An object capable of generating a probability distribution. Right now, we have: * UniformDistribution * NormalDistribution * LogNormalDistribution * WeibullDistribution :type distribution: gnome.utilities.distribution :param str distribution_type=droplet_size: What is being sampled from the distribution. Options are: * droplet_size - Rise velocity is then calculated * rise_velocity - No droplet size is computed :param end_release_time=None: End release time for a time varying release. If None, then release is instantaneous :type end_release_time: datetime.datetime :param substance=None: Required unless density specified. Type of oil spilled. :type substance: GnomeOil :param float density=None: Required unless substance specified. Density of spilled material. :param str density_units='kg/m^3': :param float amount=None: mass or volume of oil spilled. :param str units=None: must provide units for amount spilled. :param tuple windage_range=(.01, .04): Percentage range for windage. Active only for surface particles when a mind mover is added :param windage_persist=900: Persistence for windage values in seconds. Use -1 for inifinite, otherwise it is randomly reset on this time scale. :param str name='Subsurface Release': a name for the spill. .. py:function:: grid_spill(bounds, resolution, release_time, substance=None, amount=1.0, units='kg', on=True, water=None, windage_range=None, windage_persist=None, name='Surface Grid Spill') Helper function returns a Grid Spill object :param bounds: bounding box of region you want the elements in: ((min_lon, min_lat), (max_lon, max_lat)) :type bounds: 2x2 numpy array or equivalent :param resolution: resolution of grid -- it will be a resoluiton X resolution grid :type resolution: integer :param substance=None: Type of oil spilled. :type substance: str or OilProps :param float amount=None: mass or volume of oil spilled :param str units=None: units for amount spilled :param release_time: time the LEs are released (datetime object) :type release_time: datetime.datetime :param tuple windage_range=(.01, .04): Percentage range for windage. Active only for surface particles when a mind mover is added :param int windage_persist=900: Persistence for windage values in seconds. Use -1 for inifinite, otherwise it is randomly reset on this time scale :param str name='Surface Point/Line Release': a name for the spill .. py:function:: spatial_release_spill(start_positions, release_time, substance=None, water=None, on=True, amount=0, units='kg', windage_range=None, windage_persist=None, name='spatial_release') Helper function returns a Spill object containing a spatial release A spatial release is a spill that releases elements at known locations. .. py:function:: polygon_release_spill(filename, release_time=None, substance=None, water=None, on=True, amount=0, units='kg', windage_range=None, windage_persist=None, name='spatial_release') Helper function returns a Spill object containing a polygon release A polygon release is a spill that releases elements randomly within polygons in a shapefile. .. py:class:: NonWeatheringSubstance(windage_range=None, windage_persist=None, standard_density=1000.0, *args, **kwargs) Bases: :py:obj:`Substance` A class for assigning a unique ID for an object :param windage_range: Range of windages for the substance (leeway). Default: (.01, .04) :type windage_range: tuple of values between 0 and 1 :param windage_persist=900: persistence of windage settings in seconds. -1 or Inf means infinite. :type windage_persist: integer seconds. :param standard_density=1000.0: The density of the substance, used to convert mass to/from volume :type standard_density: float in units of kg/m^3 .. py:property:: is_weatherable .. py:attribute:: _schema The simplest substance that can be used with the model It can not be weathered, but does have basic properties for transport: Windage, density, etc. .. py:method:: initialize_LEs(to_rel, arrs, environment=None) :param to_rel - number of new LEs to initialize :param arrs - dict-like of data arrays representing LEs .. py:class:: GnomeOil(oil_name=None, filename=None, water=None, **kwargs) Bases: :py:obj:`gnome.spills.substance.Substance` Class to create an oil for use in Gnome Initialize a GnomeOil: :param oil_name=None: Name of one of the sample oils provided by: ``gnome.spills.sample_oils`` :param filename=None: filename (Path) of JSON file in the Adios Oil Database format. :param water=None: Water object with environmental conditions -- Deprecated. Additional keyword arguments will be passed to Substance: e.g.: ``windage_range``, ``windage_persist=None``, A GnomeOil can be initialized in three ways: 1) From a sample oil name : ``GnomeOil(oil_name="sample_oil_name")`` the oils are available in gnome.spills.sample_oils 2) From a JSON file in the ADIOS Oil Database format: ``GnomeOil(filename="adios_oil.json")`` usually records from the ADIOS Oil Database (https://adios.orr.noaa.gov) 3) From the json : ``GnomeOil.new_from_dict(**json_)`` for loading save files, etc. (this is usually done under the hood) GnomeOil("sample_oil_name") ---works for test oils from sample_oils only GnomeOil(oil_name="sample_oil_name") GnomeOil(filename="oil.json") ---load from file using adios_db GnomeOil.new_from_dict(**json\_) ---webgnomeclient, savefiles, etc. GnomeOil("invalid_name") ---ValueError (not in sample oils) .. py:property:: standard_density Standard density is simply the density at 15C, which is the default temperature for density_at_temp() .. py:attribute:: _schema .. py:attribute:: _req_refs :value: ['water'] .. py:method:: from_adiosdb_file(filename, kwargs) .. py:method:: _set_up_array_types() .. py:method:: _init_from_json(*, api, pour_point, solubility, bullwinkle_fraction, original_bullwinkle_fraction=None, bullwinkle_time=None, original_bullwinkle_time=None, emulsion_water_fraction_max, densities, density_ref_temps, density_weathering, kvis, kvis_ref_temps, kvis_weathering, mass_fraction, boiling_point, molecular_weight, component_density, sara_type=None, adios_oil_id=None, k0y=None, num_components=None, **kwargs) .. py:method:: __hash__() needs to be hashable, so that it can be used in lru-cache Oils will only hash equal if they are the same object -- that's limiting, but OK. .. py:method:: __deepcopy__(memo) .. py:method:: get_GnomeOil(oil_info, max_cuts=None) :classmethod: #fixme: what is oil_info ??? Use this instead of get_oil_props .. py:method:: to_dict(json_=None) Returns a dictionary representation of this object. Uses the schema to determine which attributes are put into the dictionary. No extra processing is done to each attribute. They are presented as is. The ``json_`` parameter is ignored in this base class. 'save' is passed in when the schema is saving the object. This allows an override of this function to do any custom stuff necessary to prepare for saving. .. py:method:: initialize_LEs(to_rel, arrs, environment=None) :param to_rel - number of new LEs to initialize :param arrs - dict-like of data arrays representing LEs fixme: this shouldn't use water temp -- it should use standard density and STP temp -- and let weathering_data set it correctly .. note:: weathering data is currently broken for initial setting .. py:method:: _set_pc_values(prop, values) utility that sets a property to each pseudo component checks that it's the right size, and converts to an array .. py:method:: vapor_pressure(temp, atmos_pressure=101325.0) the vapor pressure on the PCs at a given temperature water_temp and boiling point units are Kelvin :param temp: temperature in K :returns: vapor_pressure array in SI units (Pascals) ## Fixme: shouldn't this be in the Evaporation code? .. py:method:: bounding_temperatures(obj_list, temperature) :classmethod: General Utility Function From a list of objects containing a ref_temp_k attribute, return the object(s) that are closest to the specified temperature(s) Specifically: - We want the ones that immediately bound our temperature. - If our temperature is high and out of bounds of the temperatures in our obj_list, then we return a range containing only the highest temperature. - If our temperature is low and out of bounds of the temperatures in our obj_list, then we return a range containing only the lowest temperature. We accept only a scalar temperature or a sequence of temperatures .. py:method:: get_densities() return a list of densities for the oil at a specified state of weathering. #fixme: this should not happen here! We include the API as a density if: - the specified weathering is 0 - the culled list of densities does not contain a measurement at 15C .. py:method:: density_at_temp(temperature=288.15) Get the oil density at a temperature or temperatures. .. note:: This is all kruft left over from the estimating code. At this point, a GnomeOil should already have what it needs. .. note:: There is a catch-22 which prevents us from getting the min_temp in some cases: - To estimate pour point, we need viscosities - If we need to convert dynamic viscosities to kinematic, we need density at 15C - To estimate density at temp, we need to estimate pour point - ...and then we recurse For this case we need to make an exception. .. note:: If we have a pour point that is higher than one or more of our reference temperatures, then the lowest reference temperature will become our minimum temperature. TODO: We are getting rid of the argument that specifies a weathering amount because it is currently implemented in an unusably precise manner. Robert would like us to implement a means of interpolating density using a combination of (temperature, weathering). But the algorithm for this is not defined at the moment. .. py:method:: _get_reference_densities(densities, temperature) Given a temperature, we return the best measured density, and its reference temperature, to be used in calculation. For our purposes, it is the density closest to the given temperature. .. py:method:: _vol_expansion_coeff(densities, temperature) .. py:method:: closest_to_temperature(obj_list, temperature, num=1) :classmethod: General Utility Function From a list of objects containing a ref_temp_k attribute, return the object(s) that are closest to the specified temperature(s) We accept only a scalar temperature or a sequence of temperatures .. py:method:: kvis_at_temp(temp_k=288.15, weathering=0.0) Compute the kinematic viscosity of the oil as a function of temperature :param temp_k: temperatures to compute at: can be scalar or array of values. should be in Kelvin :param weathering: fraction weathered -- currently not implemented viscosity as a function of temp is given by: v = A exp(k_v2 / T) with constants determined from measured data .. py:method:: determine_visc_constants() viscosity as a function of temp is given by: v = A exp(k_v2 / T) The constants, A and k_v2 are determined from the viscosity data: If only one data point, a default value for k_vs is used: 2100 K, based on analysis of data in the ADIOS database as of 2018 If two data points, the two constants are directly computed If three or more, the constants are computed by a least squares fit. .. py:method:: get(prop) get oil props .. py:data:: PointWind .. py:class:: Wind(timeseries=None, units=None, filename=None, coord_sys='r-theta', latitude=None, longitude=None, speed_uncertainty_scale=0.0, extrapolation_is_allowed=False, **kwargs) Bases: :py:obj:`gnome.utilities.timeseries.Timeseries`, :py:obj:`gnome.environment.environment.Environment` Provides a "point wind" -- uniform wind over all space Create a uniform Wind object, representing a time series of wind at a single location, applied over all space. :param timeseries=None: :param units=None: :param filename=None: :param coord_sys='r-theta': :param latitude=None: :param longitude=None: :param speed_uncertainty_scale=0.0: :param extrapolation_is_allowed=False: .. py:property:: time .. py:property:: timeseries returns entire timeseries in 'r-theta' coordinate system in the units in which the data was entered or as specified by units attribute .. py:property:: data_start The start time of the valid data for this wind timeseries .. py:property:: data_stop The stop time of the valid data for this wind timeseries .. py:property:: units define units in which wind data is input/output .. py:attribute:: _ref_as :value: 'wind' .. py:attribute:: _gnome_unit :value: 'm/s' .. py:attribute:: _schema .. py:attribute:: valid_vel_units .. py:method:: update_from_dict(dict_, refs=None) .. py:method:: _check_units(units) Checks the user provided units are in list Wind.valid_vel_units .. py:method:: __repr__() Return repr(self). .. py:method:: new_set_timeseries(value, coord_sys) .. py:method:: _convert_units(data, coord_sys, from_unit, to_unit) method to convert units for the 'value' stored in the date/time value pair .. py:method:: _write_timeseries_to_zip(saveloc, ts_name) use a StringIO type of file descriptor and write directly to zipfile .. py:method:: _write_timeseries_to_file(datafile) write timeseries data to file .. py:method:: _write_timeseries_to_fd(fd) Takes a general file descriptor as input and writes data to it. Writes the "OSSM format" with the full header .. py:method:: get_wind_data(datetime=None, units=None, coord_sys='r-theta') Returns the timeseries in the requested coordinate system. If datetime=None, then the original timeseries that was entered is returned. If datetime is a list containing datetime objects, then the value for each of those date times is determined by the underlying C++ object and the timeseries is returned. The output coordinate system is defined by the strings 'r-theta', 'uv' :param datetime: [optional] datetime object or list of datetime objects for which the value is desired :type datetime: datetime object :param units: [optional] outputs data in these units. Default is to output data without unit conversion :type units: string. Uses the nucos module. :param coord_sys: output coordinate system for the times series: either 'r-theta' or 'uv' :type coord_sys: either string or integer value defined by basic_types.ts_format.* (see cy_basic_types.pyx) :returns: numpy array containing dtype=basic_types.datetime_value_2d. Contains user specified datetime and the corresponding values in user specified ts_format .. note:: Invokes self._convert_units() to do the unit conversion. Override this method to define the derived object's unit conversion functionality todo: return data in appropriate significant digits .. py:method:: set_wind_data(wind_data, units, coord_sys='r-theta') Sets the timeseries of the Wind object to the new value given by a numpy array. The coordinate system for the input data defaults to basic_types.format.magnitude_direction but can be changed by the user. Units are also required with the data. :param datetime_value_2d: timeseries of wind data defined in a numpy array :type datetime_value_2d: numpy array of dtype basic_types.datetime_value_2d :param units: units associated with the data. Valid units defined in Wind.valid_vel_units list :param coord_sys: output coordinate system for the times series, as defined by basic_types.format. :type coord_sys: either string or integer value defined by basic_types.format.* (see cy_basic_types.pyx) .. py:method:: get_value(time) Return the value at specified time and location. Wind timeseries are independent of location; however, a gridded datafile may require location so this interface may get refactored if it needs to support different types of wind data. It returns the data in SI units (m/s) in 'r-theta' coordinate system (speed, direction) :param time: the time(s) you want the data for :type time: datetime object or sequence of datetime objects. .. note:: It invokes get_wind_data(..) function .. py:method:: at(points, time, coord_sys='uv', units=None, extrapolate=False, _auto_align=True) Returns the value of the wind at the specified points at the specified time. Valid coordinate systems include 'r-theta', 'r', 'theta', 'uv', 'u' or 'v'. This function is for API compatibility with the new environment objects. :param points: Nx2 or Nx3 array of positions (lon, lat, [z]). This may be None: this is a spatially independent wind - value is the same for all points. :param time: Datetime of the time to be queried :param coord_sys: String describing the coordinate system. .. py:method:: set_speed_uncertainty(up_or_down=None) This function shifts the wind speed values in our time series based on a single parameter Rayleigh distribution method, and scaled by a value in the range [0.0 ... 0.5]. This range represents a plus-or-minus percent of uncertainty that the distribution function should calculate For each wind value in our time series: * We assume it to be the average speed for that sample time * We calculate its respective Rayleigh distribution mode (sigma). * We determine either an upper percent uncertainty or a lower percent uncertainty based on a passed in parameter. * Using the Rayleigh Quantile method and our calculated percent, we determine the wind speed that is just at or above the fractional area under the Probability distribution. * We assign the wind speed to its new calculated value. Since we are irreversibly changing the wind speed values, we should probably do this only once. .. py:method:: __eq__(other) invoke super to check equality for all 'save' parameters. Also invoke __eq__ for Timeseries object to check equality of timeseries. Super is not used in any of the __eq__ methods .. py:method:: validate() only issues warning - object is always valid .. py:function:: constant_wind(speed, direction, units='m/s') utility to create a constant wind "timeseries" :param speed: speed of wind :param direction: direction -- direction wind is from (degrees True) :param unit='m/s': units for speed, as a string, i.e. "knots", "m/s", "cm/s", etc. .. note:: The time for a constant wind timeseries is irrelevant. This function simply sets it to datetime.now() accurate to hours. .. py:function:: wind_from_values(values, units='m/s') Creates a Wind object directly from data. :param values: list of (datetime, speed, direction) tuples :param units='m/s': speed units. Direction is the where the wind is coming from in degrees from North :returns: A Wind timeseries object that can be used for a wind mover, etc. .. py:function:: constant_point_wind_mover(speed, direction, units='m/s') utility function to create a point wind mover with a constant wind :param speed: wind speed :param direction: wind direction in degrees true (direction from, following the meteorological convention) :param units='m/s': the units that the input wind speed is in. options: 'm/s', 'knot', 'mph', others... :return: returns a gnome.movers.WindMover object all set up. .. note:: The time for a constant wind timeseries is irrelevant. This function simply sets it to datetime.now() accurate to hours. .. py:function:: point_wind_mover_from_file(filename, **kwargs) Creates a wind mover from a wind time-series file (OSM long wind format) :param filename: The full path to the data file :param kwargs: All keyword arguments are passed on to the WindMover constructor :returns mover: returns a wind mover, built from the file .. py:class:: Renderer(map_filename=None, output_dir='./', image_size=(800, 600), projection=None, viewport=None, map_BB=None, land_polygons=None, draw_back_to_fore=True, draw_map_bounds=False, draw_spillable_area=False, formats=['png', 'gif'], draw_ontop='forecast', cache=None, output_timestep=None, output_zero_step=True, output_last_step=True, output_single_step=False, output_start_time=None, on=True, timestamp_attrib={}, point_size=2, depth_colors=None, min_color_depth=0, max_color_depth=100, **kwargs) Bases: :py:obj:`gnome.outputters.Outputter`, :py:obj:`gnome.utilities.map_canvas.MapCanvas` Map Renderer class that writes map images for GNOME results. Writes the frames for the LE "movies", etc. Init the image renderer. :param map_filename=None: GnomeMap or name of file for basemap (BNA) :type map_filename: GnomeMap or PathLike (str or Path) :param str output_dir='./': directory to output the images :param 2-tuple image_size=(800, 600): size of images to output :param projection=None: projection instance to use: If None, set to projections.FlatEarthProjection() :type projection: a gnome.utilities.projection.Projection instance :param viewport: viewport of map -- what gets drawn and on what scale. Default is full globe: (((-180, -90), (180, 90))) If not specifies, it will be set to the map's bounds. :type viewport: pair of (lon, lat) tuples ( lower_left, upper right ) :param map_BB=None: bounding box of map if None, it will use the bounding box of the mapfile. :param draw_back_to_fore=True: draw the background (map) to the foregound image when outputting the images each time step. :type draw_back_to_fore: boolean :param formats=['gif']: list of formats to output. :type formats: string or list of strings. Options are: ['bmp', 'jpg', 'jpeg', 'gif', 'png'] :param draw_ontop: draw 'forecast' or 'uncertain' LEs on top. Default is to draw 'forecast' LEs, which are in black on top :type draw_ontop: str Following args are passed to base class Outputter's init: :param cache: sets the cache object from which to read prop. The model will automatically set this param :param output_timestep: default is None in which case everytime the write_output is called, output is written. If set, then output is written every output_timestep starting from model_start_time. :type output_timestep: timedelta object :param output_zero_step: default is True. If True then output for initial step (showing initial release conditions) is written regardless of output_timestep :type output_zero_step: boolean :param output_last_step: default is True. If True then output for final step is written regardless of output_timestep :type output_last_step: boolean :param point_size=2: size to draw elements, in pixels :param depth_colors=None: colorscheme to use to color elements according to their depth for 3D modeling. Any scheme that py_gd provides can be used:: `py_gd.colorschemes.keys()` Currently: 'cividis', 'inferno', 'magma', 'plasma', 'turbo', 'twilight', 'viridis' (borrowed from matplotlib) If None, elements will not be colored by depth :param min_color_depth=0: depth to map the first color in the scheme (m) :param max_color_depth=100: depth to map the last color in the scheme (m) Remaining kwargs are passed onto Outputter.__init__(...) .. py:property:: delay .. py:property:: repeat .. py:property:: map_filename .. py:property:: draw_ontop .. py:property:: formats .. py:attribute:: map_colors :value: [('background', (255, 255, 255)), ('lake', (255, 255, 255)), ('land', (255, 204, 153)), ('LE',... .. py:attribute:: background_map_name :value: 'background_map.' .. py:attribute:: foreground_filename_format :value: 'foreground_{0:05d}.' .. py:attribute:: foreground_filename_glob :value: 'foreground_?????.*' .. py:attribute:: _schema .. py:method:: output_dir_to_dict() .. py:method:: start_animation(filename) .. py:method:: prepare_for_model_run(*args, **kwargs) prepares the renderer for a model run. Parameters passed to base class (use super): model_start_time, cache Does not take any other input arguments; however, to keep the interface the same for all outputters, define ``**kwargs`` and pass into the base class In this case, it draws the background image and clears the previous images. If you want to save the previous images, a new output dir should be set. .. py:method:: set_timestamp_attrib(**kwargs) Function to set details of the timestamp's appearance when printed. These details are stored as a dict. Recognized attributes: :param on: Turn the draw function on or off :type on: Boolean :param dt_format: Format string for strftime to format the timestamp :type dt_format: String :param background: Color of the text background. Color must be present in foreground palette :type background: str :param color: Color of the font. Note that the color must be present in the foreground palette :type color: str :param size: Size of the font, one of {'tiny', 'small', 'medium', 'large', 'giant'} :type size: str :param position: x, y pixel coordinates of where to draw the timestamp. :type position: tuple :param align: The reference point of the text bounding box. One of: {'lt'(left top), 'ct', 'rt', 'l', 'r', 'lb', 'cb', 'rb'} :type align: str .. py:method:: draw_timestamp(time) Function that draws the timestamp to the foreground. Uses self.timestamp_attribs to determine it's appearance. :param time: the datetime object representing the timestamp :type time: datetime .. py:method:: clean_output_files() Cleans out the output dir This should be implemented by subclasses that dump files. Each outputter type dumps different types of files, and this should only clear out those. See the OutputterFilenameMixin for a simple example. .. py:method:: draw_background() Draws the background image -- land and optional graticule This should be called whenever the scale changes .. py:method:: add_grid(grid, on=True, color='grid_1', width=2) .. py:method:: draw_grids() .. py:method:: add_vec_prop(prop, on=True, color='LE', mask_color='uncert_LE', size=3, width=1, scale=1000) .. py:method:: draw_props(time) .. py:method:: draw_masked_nodes(grid, time) .. py:method:: draw_land() Draws the land map to the internal background image. .. py:method:: draw_elements(sc) Draws the individual elements to a foreground image :param sc: a SpillContainer object to draw .. py:method:: draw_raster_map() draws the raster map used for beaching to the image. draws a grid for the pixels this is pretty slow, but only used for diagnostics. (not bad for just the lines) .. py:method:: write_output(step_num, islast_step=False) Render the map image, according to current parameters. :param step_num: the model step number you want rendered. :type step_num: int :param islast_step: default is False. Flag that indicates that step_num is last step. If 'output_last_step' is True then this is written out :type islast_step: bool :returns: A dict of info about this step number if this step is to be output, None otherwise. 'step_num': step_num 'image_filename': filename 'time_stamp': time_stamp # as ISO string use super to call base class write_output method If this is last step, then prop is written; otherwise prepare_for_model_step determines whether to write the output for this step based on output_timestep .. py:method:: post_model_run() Override this method if a derived class needs to perform any actions after a model run is complete (StopIteration triggered) .. py:method:: _draw(step_num) create a small function so prop arrays are garbage collected from memory after this function exits - it returns current_time_stamp .. py:method:: projection_to_dict() store projection class as a string for now since that is all that is required for persisting todo: This may not be the case for all projection classes, but keep simple for now so we don't have to make the projection classes serializable .. py:method:: to_dict(json_=None) Returns a dictionary representation of this object. Uses the schema to determine which attributes are put into the dictionary. No extra processing is done to each attribute. They are presented as is. The ``json_`` parameter is ignored in this base class. 'save' is passed in when the schema is saving the object. This allows an override of this function to do any custom stuff necessary to prepare for saving. .. py:class:: NetCDFOutput(filename, zip_output=False, which_data='standard', compress=True, surface_conc='kde', _start_idx=0, **kwargs) Bases: :py:obj:`gnome.outputters.outputter.Outputter`, :py:obj:`gnome.outputters.outputter.OutputterFilenameMixin` A NetCDFOutput object is used to write the model's data to a NetCDF file. It inherits from Outputter class and implements the same interface. This class is meant to be used within the Model, to be added to list of outputters. >>> model = gnome.model.Model(...) >>> model.outputters += gnome.netcdf_outputter.NetCDFOutput( os.path.join(base_dir,'sample_model.nc'), which_data='most') `which_data` flag is used to set which data to add to the netcdf file: 'standard' : the basic stuff most people would want 'most': everything the model is tracking except the internal-use-only arrays 'all': everything tracked by the model (mostly used for diagnostics of save files) .. note:: cf_attributes is a class attribute: a dict that contains the global attributes per CF convention The attribute: `.arrays_to_output` is a set of the data arrays that will be added to the netcdf file. array names may be added to or removed from this set before a model run to customize what gets output: `the_netcdf_outputter.arrays_to_output.add['rise_vel']` Since some of the names of the netcdf variables are different from the names in the SpillContainer data_arrays, this list uses the netcdf names Constructor for Net_CDFOutput object. It reads data from cache and writes it to a NetCDF4 format file using the CF convention :param filename: Required parameter. The filename in which to store the NetCDF data. :type filename: str. or unicode :param zip_output=True: whether to zip up the output netcdf files :param which_data='standard': If 'standard', write only standard data. If 'most' means, write everything except the attributes we know are for internal model use. If 'all', write all data to NetCDF -- usually only for diagnostics. Default is 'standard'. These are defined in the standard_arrays and usually_skipped_arrays attributes :type which_data: string -- one of {'standard', 'most', 'all'} NOTE: if you want a custom set of output arrays, you can cahnge the `.self.arrays_to_output` set after initialization. Optional arguments passed on to base class (kwargs): :param cache: sets the cache object from which to read data. The model will automatically set this param :param output_timestep: default is None in which case every time the write_output is called, output is written. If set, then output is written every output_timestep starting from model_start_time. :type output_timestep: timedelta object :param output_zero_step: default is True. If True then output for initial step (showing initial release conditions) is written regardless of output_timestep :type output_zero_step: boolean :param output_last_step: default is True. If True then output for final step is written regardless of output_timestep :type output_last_step: boolean use super to pass optional kwargs to base class __init__ method .. py:property:: uncertain_filename if uncertain SpillContainer is present, write its data out to this file .. py:property:: which_data .. py:property:: chunksize .. py:property:: compress .. py:property:: netcdf_format .. py:attribute:: which_data_lu .. py:attribute:: compress_lu .. py:attribute:: cf_attributes .. py:attribute:: standard_arrays :value: ['latitude', 'longitude', 'depth', 'status_codes', 'spill_num', 'id', 'mass', 'age', 'density',... .. py:attribute:: special_arrays .. py:attribute:: usually_skipped_arrays :value: ['next_positions', 'last_water_positions', 'windages', 'mass_components', 'half_lives',... .. py:attribute:: _schema .. py:method:: _update_var_attributes(spills) update instance specific self._var_attributes .. py:method:: _initialize_rootgrp(rootgrp, sc) create dimensions for root group and set cf_attributes .. py:method:: _update_arrays_to_output(sc) create list of variables that we want to put in the file .. py:method:: prepare_for_model_run(model_start_time, spills, uncertain=False, **kwargs) .. function:: prepare_for_model_run(model_start_time, spills, **kwargs) Write global attributes and define dimensions and variables for NetCDF file. This must be done in prepare_for_model_run because if model _state changes, it is rewound and re-run from the beginning. If there are existing output files, they are deleted here. This takes more than standard 'cache' argument. Some of these are required arguments - they contain None for defaults because non-default argument cannot follow default argument. Since cache is already 2nd positional argument for Renderer object, the required non-default arguments must be defined following 'cache'. If uncertainty is on, then SpillContainerPair object contains identical _data_arrays in both certain and uncertain SpillContainers, the data itself is different, but they contain the same type of data arrays. If uncertain, then datay arrays for uncertain spill container are written to filename + '_uncertain.nc' :param spills: If 'which_data' flag is set to 'all' or 'most', then model must provide the model.spills object (SpillContainerPair object) so NetCDF variables can be defined for the remaining data arrays. If spills is None, but which_data flag is 'all' or 'most', a ValueError will be raised. It does not make sense to write 'all' or 'most' but not provide 'model.spills'. :type spills: gnome.spill_container.SpillContainerPair object. .. note:: Does not take any other input arguments; however, to keep the interface the same for all outputters, define ``**kwargs`` in case future outputters require different arguments. use super to pass model_start_time, cache=None and remaining kwargs to base class method .. py:method:: _create_nc_var(grp, var_name, dtype, shape, chunksz) .. py:method:: write_output(step_num, islast_step=False) Write NetCDF output at the end of the step :param int step_num: the model step number you want rendered. :param bool islast_step: Default is False. Flag that indicates that step_num is last step. If 'output_last_step' is True then this is written out Use super to call base class write_output method .. py:method:: post_model_run() This is where to clean up -- close files, etc. .. py:method:: _zip_output_files() .. py:method:: clean_output_files() deletes output files that may be around called by prepare_for_model_run here in case it needs to be called from elsewhere .. py:method:: rewind() reset a few parameter and call base class rewind to reset internal variables. .. py:method:: read_data(netcdf_file, time=None, index=None, which_data='standard') :classmethod: Read and create standard data arrays for a netcdf file that was created with NetCDFOutput class. Make it a class method since it is independent of an instance of the Outputter. The method is put with this class because the NetCDF functionality for PyGnome data with CF standard is captured here. :param netcdf_file: Name of the NetCDF file from which to read the data :param time: timestamp at which the data is desired. Looks in the netcdf data's 'time' array and finds the closest time to this and outputs this data. If both 'time' and 'index' are None, return data if file only contains one 'time' else raise an error :param int index: Index of the 'time' variable (or time_step). This is only used if 'time' is None. If both 'time' and 'index' are None,return data if file only contains one 'time' else raise an error :param which_data='standard': Which data arrays are desired. Options are: ('standard', 'most', 'all', [list_of_array_names]) :type which_data: string or sequence of strings. :return: A dict containing standard data closest to the indicated 'time'. Standard data is defined as follows: Standard data arrays are numpy arrays of size N, where N is number of particles released at time step of interest. They are defined by the class attribute "standard_arrays", currently:: 'current_time_stamp': datetime object associated with this data 'positions' : NX3 array. NetCDF variables: 'longitude', 'latitude', 'depth' 'status_codes' : NX1 array. NetCDF variable :'status_codes' 'spill_num' : NX1 array. NetCDF variable: 'spill_num' 'id' : NX1 array of particle id. NetCDF variable 'id' 'mass' : NX1 array showing 'mass' of each particle standard_arrays = ['latitude', 'longitude', # pulled from the 'positions' array 'depth', 'status_codes', 'spill_num', 'id', 'mass', 'age', ] .. py:method:: to_dict(json_=None) Returns a dictionary representation of this object. Uses the schema to determine which attributes are put into the dictionary. No extra processing is done to each attribute. They are presented as is. The ``json_`` parameter is ignored in this base class. 'save' is passed in when the schema is saving the object. This allows an override of this function to do any custom stuff necessary to prepare for saving. .. py:class:: KMZOutput(filename, **kwargs) Bases: :py:obj:`gnome.outputters.outputter.OutputterFilenameMixin`, :py:obj:`gnome.outputters.outputter.Outputter` class that outputs GNOME results in a kmz format. Suitable for Google Earth, and semi-suitable for MarPlot :param str output_dir=None: output directory for kmz files. uses super to pass optional ``**kwargs`` to base class ``__init__`` method .. py:attribute:: _schema .. py:attribute:: time_formatter :value: '%m/%d/%Y %H:%M' .. py:method:: prepare_for_model_run(model_start_time, spills, **kwargs) .. function:: prepare_for_model_run(model_start_time, cache=None, uncertain=False, spills=None, **kwargs) Write the headers, png files, etc for the KMZ file This must be done in prepare_for_model_run because if model _state changes, it is rewound and re-run from the beginning. If there are existing output files, they are deleted here. This takes more than standard 'cache' argument. Some of these are required arguments - they contain None for defaults because non-default argument cannot follow default argument. Since cache is already 2nd positional argument for Renderer object, the required non-default arguments must be defined following 'cache'. If uncertainty is on, then SpillContainerPair object contains identical _data_arrays in both certain and uncertain SpillContainer's, the data itself is different, but they contain the same type of data arrays. If uncertain, then data arrays for uncertain spill container are written to the KMZ file. .. note:: Does not take any other input arguments; however, to keep the interface the same for all outputters, define kwargs in case future outputters require different arguments. .. py:method:: write_output(step_num, islast_step=False) dump a timestep's data into the kmz file .. py:method:: rewind() reset a few parameter and call base class rewind to reset internal variables. .. py:class:: OilBudgetOutput(filename='gnome_oil_budget.csv', file_format='csv', cache=None, on=True, output_timestep=None, *args, **kwargs) Bases: :py:obj:`gnome.outputters.weathering.BaseMassBalanceOutputter`, :py:obj:`gnome.outputters.outputter.OutputterFilenameMixin` Outputter for the oil budget table Sets attributes for outputters, like output_timestep, cache, etc. :param cache: sets the cache object from which to read data. The model will automatically set this parameter. :param output_timestep=None: If ``None`` output will be written every model time step. If set, then output is written every output_timestep starting from the model start time. If the output_timestep is less than the model timestep, an Warning will be raised at runtime. :type output_timestep: timedelta object :param output_zero_step=True: If True then output for initial step (showing initial release conditions) is written regardless of ``output_timestep`` or ``output_single_step`` :type output_zero_step: bool :param output_last_step=True: If True then output for final step is written regardless of ``output_timestep`` or ``output_single_step``. This is potentially an extra output, if not aligned with ``output_timestep``. :type output_last_step: bool :param output_single_step=False: If ``True`` then output is written for only one step, the output_start_time, regardless of ``output_timestep``. ``output_zero_step`` and ``output_last_step`` are still respected, set these to False if you want only one time step. :type output_single_step: boolean :param output_start_time=None: Time to start outputting restults. If None it is set to the model start time :type output_start_time: datetime object :param output_dir=None: Directory to dump output in, if it needs to do this. :type output_dir: PathLike :param surface_conc=None: Compute surface concentration Any non-empty string will compute (and output) the surface concentration. The contents of the string determine the algorithm used. "kde" is currently the only available option. :type surface_conc: str or None .. py:attribute:: _valid_file_formats .. py:attribute:: budget_categories :value: ['amount_released', 'evaporated', 'natural_dispersion', 'sedimentation', 'beached', 'floating',... .. py:attribute:: header_row :value: ['Model Time', 'Hours Since Model Start', 'Amount Released (kg)', 'Evaporated (kg)', 'Dispersed... .. py:attribute:: _schema .. py:method:: prepare_for_model_run(model_start_time, spills, **kwargs) start the csv file .. py:method:: write_output(step_num, islast_step=False) Oil budget is only output for forecast spill container, not the uncertain spill container. This is because Weathering has its own uncertainty and mixing the two was giving weird results. The cloned models that are modeling weathering uncertainty do not include the uncertain spill container. .. py:method:: post_model_run() Called after a model run is complete remove the csv file - hopefully resulting in the file being closed. .. py:class:: ShapeOutput(filename, zip_output=True, include_certain_boundary=False, certain_boundary_separate_by_spill=True, certain_boundary_hull_ratio=0.5, certain_boundary_hull_allow_holes=False, include_uncertain_boundary=True, uncertain_boundary_separate_by_spill=True, uncertain_boundary_hull_ratio=0.5, uncertain_boundary_hull_allow_holes=False, surface_conc='kde', **kwargs) Bases: :py:obj:`gnome.outputters.outputter.Outputter` class that outputs GNOME results (particles) in a shapefile format. :param filename: Full path and basename of the shape file. :param zip_output=True: Whether to zip up the output shape files. :param surface_conc="kde": Method to use to compute surface concentration current options are: 'kde' and None .. py:attribute:: _schema .. py:attribute:: time_formatter :value: '%m/%d/%Y %H:%M' .. py:method:: __del__() .. py:method:: prepare_for_model_run(model_start_time, spills, uncertain=False, **kwargs) If uncertainty is on, then SpillContainerPair object contains identical _data_arrays in both certain and uncertain SpillContainer's, the data itself is different, but they contain the same type of data arrays. If uncertain, then data arrays for uncertain spill container are written. .. py:method:: write_output(step_num, islast_step=False) Dump a timestep's data into the shapefile .. py:method:: post_model_run() The final step to wrap everything up .. py:method:: create_bundle(uncertain) Create a shapefile bundle including both certain and uncertain shapefiles .. py:method:: rewind() reset a few parameter and call base class rewind to reset internal variables. .. py:method:: clean_output_files() deletes ouput files that may be around called by prepare_for_model_run here in case it needs to be called from elsewhere .. py:class:: WeatheringOutput(output_dir=None, **kwargs) Bases: :py:obj:`BaseMassBalanceOutputter` class that outputs GNOME weathering results on a time step by time step basis The output is the aggregation of properties for all LEs (aka Mass Balance) for a particular time step. There are a number of different things we would like to graph: - Evaporation - Dissolution - Dissipation - Biodegradation - ??? :param str output_dir=None: output directory for the json files. If not directory is provided, files will not be written. other arguments as defined in the Outputter class .. py:attribute:: _schema .. py:method:: write_output(step_num, islast_step=False) Weathering data is only output for forecast spill container, not the uncertain spill container. This is because Weathering has its own uncertainty and mixing the two was giving weird results. The cloned models that are modeling weathering uncertainty do not include the uncertain spill container. .. py:method:: output_to_file(json_content, step_num) .. py:method:: clean_output_files() Cleans out the output dir This should be implemented by subclasses that dump files. Each outputter type dumps different types of files, and this should only clear out those. See the OutputterFilenameMixin for a simple example. .. py:method:: __getstate__() This is to support pickle.dumps() inside the uncertainty model subprocesses. We need to be able to pickle our weathering outputters so that our uncertainty subprocesses can send them back to the parent process through a message queue. And the cache attribute (specifically, the ElementCache.lock attribute) can not be pickled, and instead produces a RuntimeError. (Note: The __setstate__() probably doesn't need to recreate the ElementCache since it will be created inside the Model.setup_model_run() function.) .. py:class:: MapFromBNA(filename, raster_size=4096 * 4096, map_bounds=None, spillable_area=None, shift_lons=0, **kwargs) Bases: :py:obj:`RasterMap` A raster land-water map, created from file with polygons in it. Currently only support BNA, but could be shapefile, or ??? Creates a RasterMap from a data file. It is expected that you will get the spillable area and map bounds from the data file -- if they exist Required arguments: :param filename: full path to the data file :param raster_size: the total number of pixels (bytes) to make the raster -- the actual size will match the aspect ratio of the bounding box of the land :type raster_size: integer :param shiftLons: shift longitudes to be in -180 to 180 coords or 0 to 360. 180, or 360 are valid inputs :type shiftLons: integer Optional arguments (kwargs): :param refloat_halflife: the half-life (in hours) for the re-floating. :param map_bounds: The polygon bounding the map -- could be larger or smaller than the land raster :param spillable_area: The polygon bounding the spillable_area :param id: unique ID of the object. Using UUID as a string. This is only used when loading object from save file. :type id: string .. py:property:: raster_size Maximum physical size of the raster in bytes .. py:attribute:: _schema .. py:method:: build_raster(land_polys=None, BB=None) Build the underlying raster used for the map This should be called if the resolution or land polygons change .. py:method:: to_geojson() Output the vector version of the shoreline polygons. This is what gets drawn in the WebGNOME client, for example This version directly writes the polygons already stored in the map object -- keeping the door open to that data coming from something other than a bna file. FIXME: Technically, geojson recommends ccw polygons -- but putting that check in was pretty slow, so it's commented out. FIXME: This really should export the map_bounds and spillable_area as well. .. py:class:: GnomeMap(map_bounds=None, spillable_area=None, land_polys=None, **kwargs) Bases: :py:obj:`gnome.gnomeobject.GnomeId` The very simplest map for GNOME -- all water with only a bounding box for the map bounds. This also serves as a description of the interface and base class for more complex maps The __init__ will be different for other implementations :param map_bounds: The polygon bounding the map if any elements are outside the map bounds, they are removed from the simulation. :param spillable_area: The PolygonSet bounding the spillable_area. :type spillable_area: Either a PolygonSet object or a list of lists from which a polygon set can be created. Each element in the list is a list of points defining a polygon. :param land_polys: The PolygonSet holding the land polygons :type land_polys: Either a PolygonSet object or a list of lists from which a polygon set can be created. Each element in the list is a list of points defining a polygon. Note on 'map_bounds': ``[(lon, lat), (lon, lat), (lon, lat), ..`` An NX2 array of points that describe a polygon if no map bounds is provided -- the whole world is valid .. py:property:: map_bounds Bounds of the map -- an NX2 array of float describing a polygon. [(lon, lat), (lon, lat), ...] .. py:property:: spillable_area List of polygons defining the region in which it is legal to set spills .. py:property:: land_polys Sequence of polygons surrounding land -- mostly used for rendering. .. py:attribute:: _schema .. py:attribute:: refloat_halflife .. py:attribute:: _ref_as :value: 'map' .. py:method:: __add__(other) .. py:method:: get_polygons() .. py:method:: _attr_from_list_to_array(l_) dict returned as list of tuples to be converted to numpy array Again used to update_from_dict map_bounds and spillable_area .. py:method:: get_map_bounding_box() return a bounding box of the map needed because map_bounds can be a polygon bounding box is a 2x2 tuple: ((left, bottom), (right, top)) .. py:method:: on_map(coords) Determine whether points are on the map or not :param coords: location for test. :type coords: NX3 numpy array of floats: (long, lat, depth) or something that can be turned into one. :return: bool array: True if the location is on the map, False otherwise Note: coords are 3-d, but the concept of "on the map" is 2-d in this context, so depth is ignored. .. py:method:: on_land(coord) :param coord: location for test. :type coord: 3-tuple of floats: (long, lat, depth) :return: - Always returns False-- no land in this implementation .. py:method:: in_water(coords) Determines if the points are in water (rather than on land) :param coords: location for test. :type coords: 3-tuple of floats: (long, lat, depth) or an Nx3 array :returns: - True if the point is in the water, - False if the point is on land (or off map?) This implementation has no land, so always True in on the map. .. py:method:: allowable_spill_position(coord) :param coord: location for test. :type coord: 3-tuple of floats: (long, lat, depth) :return: - True if the point is an allowable spill position - False if the point is not an allowable spill position .. note:: it could be either off the map, or in a location that spills aren't allowed .. py:method:: _set_off_map_status(sc) Determines which elements moved off the map Called by beach_elements after checking for land-hits :param sc: current SpillContainer :type sc: :class:`gnome.spill_container.SpillContainer` .. py:method:: beach_elements(sc, model_time=None) Determines which LEs were or weren't beached or moved off_map. status_code is changed to oil_status.off_maps if off the map. Called by the model in the main time loop, after all movers have acted. :param sc: current SpillContainer :type sc: :class:`gnome.spill_container.SpillContainer` This map class has no land, so only the map check and resurface_airborn elements is done: noting else changes. subclasses that override this probably want to make sure that: self.resurface_airborne_elements(sc) self._set_off_map_status(sc) are called. .. py:method:: refloat_elements(spill_container, time_step, model_time=None) This method performs the re-float logic -- changing the element status flag, and moving the element to the last known water position :param spill_container: current SpillContainer :type spill_container: :class:`gnome.spill_container.SpillContainer` .. note:: This map class has no land, and so is a no-op. .. py:method:: resurface_airborne_elements(spill_container) Takes any elements that are left above the water surface (z < 0.0) and puts them on the surface (z == 0.0) :param spill_container: current SpillContainer :type spill_container: :class:`gnome.spill_container.SpillContainer` .. note:: While this shouldn't occur according to the physics we're modeling, some movers may push elements up too high, or multiple movers may add vertical movement that adds up to over the surface. e.g rise velocity. .. py:method:: to_geojson() .. py:class:: FileGridCurrent(filename=None, extrapolation_is_allowed=False, *args, **kwargs) Bases: :py:obj:`GridCurrent` class that presents an interface for GridCurrent loaded from files of various formats Done as a class to provide a Schema for the persistence system And to provide a simple interface to making a current from a file. :param angle: scalar field of cell rotation angles (for rotated/distorted grids) .. py:attribute:: _schema .. py:method:: init_from_gridcur(filename, extrapolation_is_allowed, **kwargs) Wrapper for external initalize function .. py:method:: new_from_dict(serial_dict) :classmethod: creates a new object from dictionary This is base implementation and can be over-ridden by classes using this mixin .. py:class:: GridCurrent(angle=None, **kwargs) Bases: :py:obj:`VelocityGrid`, :py:obj:`gnome.environment.environment.Environment` GridCurrent is VelocityGrid that adds specific stuff for currents: - Information about how to find currents in netCDF file - Ability to apply an angle adjustment of grid-aligned currents - overloading the memorization to memoize the angle-adjusted current. - add a get_data_vectors() provides magnitude, direction -- used to draw the currents in a GUI loading code for netcdf files for gridded currents, and an interpolation (`.at`), function that provides caching :param angle: scalar field of cell rotation angles (for rotated/distorted grids) .. py:attribute:: _ref_as :value: 'current' .. py:attribute:: _gnome_unit :value: 'm/s' .. py:attribute:: default_names .. py:attribute:: cf_names .. py:method:: at(points, time, *args, **kwargs) Find the value of the property at positions P at time T :param points: Coordinates to be queried (P) :type points: Nx2 or Nx3 array of double :param time: The time at which to query these points (T) :type time: datetime.datetime object :param units: units the values will be returned in (or converted to) :type units: string such as ('m/s', 'knots', etc) :param extrapolate: if True, extrapolation will be supported :type extrapolate: boolean (True or False) :return: returns a Nx2 array of interpolated values :rtype: double .. py:class:: SteadyUniformCurrent(speed, direction, units='m/s', name='Steady Uniform Current') Bases: :py:obj:`gnome.environment.environment.Environment` Simple current: the same at all time and places Create a steady, uniform current (same at all time and places) :param speed: speed of the current :param direction: direction of the current (direction to, not from), in degrees from north :param units="m/s": units of speed: defaults to "m/s" :param name="Steady Uniform Current": optional name for the current .. py:property:: speed .. py:property:: direction .. py:property:: u .. py:property:: v .. py:attribute:: _ref_as :value: 'current' .. py:attribute:: _schema .. py:attribute:: data_start .. py:attribute:: data_stop .. py:method:: __repr__() Return repr(self). .. py:method:: _set_uv() .. py:method:: at(points, time, units=None) Find the value of the property at positions of points at time T :param points: will be ignored :param time: will be ignored :param units='m/s': units the values will be returned in (or converted to) if None, the default units for the environment type will be used. :type units: string such as ('m/s', 'knots', etc) :return: returns an Nx2 arrary is points is Nx2, Nx3 is points is Nx3 .. py:class:: GridWind(wet_dry_mask=None, *args, **kwargs) Bases: :py:obj:`VelocityGrid`, :py:obj:`gnome.environment.environment.Environment` Gridded winds -- usually from netcdf files from meteorological models. This will most often be initialized from netcdf files as: wind = GridWind.from_netCDF(filename="a/path/to/a/netcdf_file.nc") filename can be: * An already open netCDF4 Dataset * A single path to a netcdf file * A list of paths to a set of netcdf files with timeseries :param angle: scalar field of cell rotation angles (for rotated/distorted grids) .. py:attribute:: _ref_as :value: 'wind' .. py:attribute:: _gnome_unit :value: 'm/s' .. py:attribute:: default_names .. py:attribute:: cf_names .. py:method:: at(points, time, coord_sys='uv', _auto_align=True, **kwargs) Find the value of the property at positions P at time T :param points: Coordinates to be queried (P) :type points: Nx2 array of double :param time: The time at which to query these points (T) :type time: datetime.datetime object :param depth: Specifies the depth level of the variable :type depth: integer :param units: units the values will be returned in (or converted to) :type units: string such as ('m/s', 'knots', etc) :param extrapolate: if True, extrapolation will be supported :type extrapolate: boolean (True or False) :param coord_sys: String describing the coordinate system to be used. :type coord_sys: string, one of ('uv','u','v','r-theta','r','theta') :return: returns a Nx2 array of interpolated values :rtype: double .. py:method:: transform_result(value, coord_sys) .. py:method:: get_start_time() .. py:method:: get_end_time() .. py:class:: IceAwareCurrent(ice_velocity=None, ice_concentration=None, *args, **kwargs) Bases: :py:obj:`GridCurrent` IceAwareCurrent is a GridCurrent that modulates the usual water velocity field using ice velocity and concentration information. While under 20% ice coverage, queries will return water velocity. Between 20% and 80% coverage, queries will interpolate linearly between water and ice velocity Above 80% coverage, queries will return the ice velocity. :param ice_velocity: VectorVariable representing surface ice velocity :type ice_velocity: VectorVariable or compatible object :param ice_concentration: Variable representing surface ice concentration :type ice_concentration: Variable or compatible object .. py:attribute:: _ref_as :value: ['current', 'ice_aware'] .. py:attribute:: _req_refs .. py:attribute:: _schema .. py:method:: from_netCDF(*args, **kwargs) :classmethod: create a new VectorVariable object from a netcdf file See init_from_netcdf for signature .. py:method:: init_from_netCDF(ice_file=None, ice_concentration=None, ice_velocity=None, *args, **kwargs) Allows one-function initialization of a VectorVariable from a file. :param filename: Default data source. Parameters below take precedence :param varnames: Names of the variables in the data source file :param grid_topology: Description of the relationship between grid attributes and variable names. :param name: Name of property :param units: Units :param time: Time axis of the data :param data: Underlying data source :param grid: Grid that the data corresponds with :param dataset: Instance of open Dataset :param data_file: Name of data source file :param grid_file: Name of grid source file :type filename: string :type varnames: [] of string :type grid_topology: {string : string, ...} :type name: string :type units: string :type time: [] of datetime.datetime, netCDF4 Variable, or Time object :type data: netCDF4.Variable or numpy.array :type grid: pysgrid or pyugrid :type dataset: netCDF4.Dataset :type data_file: string :type grid_file: string .. py:method:: at(points, time, *args, **kwargs) Find the value of the property at positions P at time T :param points: Coordinates to be queried (P) :type points: Nx2 or Nx3 array of double :param time: The time at which to query these points (T) :type time: datetime.datetime object :param units: units the values will be returned in (or converted to) :type units: string such as ('m/s', 'knots', etc) :param extrapolate: if True, extrapolation will be supported :type extrapolate: boolean (True or False) :return: returns a Nx2 array of interpolated values :rtype: double .. py:class:: IceAwareWind(ice_concentration=None, *args, **kwargs) Bases: :py:obj:`GridWind` Gridded winds -- usually from netcdf files from meteorological models. This will most often be initialized from netcdf files as: wind = GridWind.from_netCDF(filename="a/path/to/a/netcdf_file.nc") filename can be: * An already open netCDF4 Dataset * A single path to a netcdf file * A list of paths to a set of netcdf files with timeseries :param angle: scalar field of cell rotation angles (for rotated/distorted grids) .. py:attribute:: _ref_as :value: ['wind', 'ice_aware'] .. py:attribute:: _req_refs .. py:attribute:: _schema .. py:method:: from_netCDF(ice_concentration=None, ice_velocity=None, **kwargs) :classmethod: create a new VectorVariable object from a netcdf file See init_from_netcdf for signature .. py:method:: at(points, time, min_val=0, *args, **kwargs) Find the value of the property at positions P at time T :param points: Coordinates to be queried (P) :type points: Nx2 array of double :param time: The time at which to query these points (T) :type time: datetime.datetime object :param depth: Specifies the depth level of the variable :type depth: integer :param units: units the values will be returned in (or converted to) :type units: string such as ('m/s', 'knots', etc) :param extrapolate: if True, extrapolation will be supported :type extrapolate: boolean (True or False) :param coord_sys: String describing the coordinate system to be used. :type coord_sys: string, one of ('uv','u','v','r-theta','r','theta') :return: returns a Nx2 array of interpolated values :rtype: double .. py:class:: Tide(filename, yeardata=os.path.join(os.path.dirname(gnome.__file__), 'data', 'yeardata'), scale_factor=None, **kwargs) Bases: :py:obj:`gnome.environment.environment.Environment` todo: baseclass called ScaleTimeseries (or something like that) ScaleCurrent Define the tide for a spill Currently, this internally defines and uses the CyShioTime object, which is a cython wrapper around the C++ Shio object Tide information can be obtained from a filename or set as a timeseries (timeseries is NOT TESTED YET) It requires one of the following to initialize: 1. 'timeseries' assumed to be in 'uv' format (NOT TESTED/IMPLEMENTED OR USED YET) 2. a 'filename' containing a header that defines units amongst other meta data :param timeseries: numpy array containing tide data :type timeseries: numpy.ndarray with dtype=datetime_value_1d :param units: units associated with the timeseries data. If 'filename' is given, then units are read in from the filename. unit conversion - NOT IMPLEMENTED YET :type units=None: (Optional) string, for example: 'knot', 'meter per second', 'mile per hour' etc :param filename: path to a long wind filename from which to read wind data :param yeardata='gnome/data/yeardata/': path to yeardata used for Shio data. .. py:property:: extrapolation_is_allowed .. py:property:: data_start .. py:property:: data_stop .. py:property:: yeardata .. py:attribute:: _ref_as :value: 'tide' .. py:attribute:: _schema .. py:attribute:: scale_factor .. py:method:: _obj_to_create(filename) open file, read a few lines to determine if it is an ossm file or a shio file .. py:class:: Water(temperature=300.0, salinity=35.0, sediment=0.005, wave_height=None, fetch=None, units=None, name='Water', **kwargs) Bases: :py:obj:`gnome.environment.environment.Environment` Define the environmental conditions for a spill, like water_temperature, Single values for all all time and space Defined in a Serializable class since user will need to set/get some of these properties through the client Includes attributes with a Environment interface: Temperature Salinity Sediment WaveHeight Example: water.Temperature.at(points, time, unit) Assume units are SI for all properties. 'units' attribute assumes SI by default. This can be changed, but initialization takes SI. Units is dict, with some subset of these keys:: { 'temperature': 'K', 'salinity': 'psu', 'sediment': 'kg/m^3', 'wave_height': 'm', 'fetch': 'm', } So to set units of temperature to F: ``units = {'temperature': 'F'}`` .. py:property:: data_start The Water object doesn't directly manage a time series of data, so it will not have a data range. We will just return an infinite range for Water. .. py:property:: data_stop .. py:property:: density return the density based on water salinity and temperature. The salinity is in 'psu'; it is not being converted to absolute salinity units - for our purposes, this is sufficient. Using gsw.rho() internally which expects salinity in absolute units. .. py:property:: units .. py:attribute:: _ref_as :value: 'water' .. py:attribute:: _field_descr .. py:attribute:: _schema .. py:attribute:: _units_type .. py:attribute:: _gnome_units .. py:attribute:: __str__ .. py:method:: __repr__() Return repr(self). .. py:method:: get(attr, unit=None) return value in desired unit. If None, then return the value in SI units. The user_unit are given in 'units' attribute and each attribute carries the value in as given in these user_units. .. py:method:: set(attr, value, unit) provide a corresponding set method that requires value and units The attributes can be directly set. This function just sets the desired property and also updates the units dict .. py:method:: _get_density(salinity, temp, temp_units) :staticmethod: use lru cache so we don't recompute if temp is not changing .. py:method:: _convert_sediment_units(from_, to) used internally to convert to/from sediment units. .. py:class:: Waves(wind=None, water=None, **kwargs) Bases: :py:obj:`gnome.environment.environment.Environment` class to compute the wave height for a time series At the moment, it only does a single point, non spatially variable, but may be extended in the future wind and water must be set before running the model; however, these can be set after object construction :param wind: A wind object to get the wind speed. This should be a moving average wind object. :type wind: A Wind type, or equivelent :param water: water properties, specifically fetch and wave height :type water: environment.Water object. .. note:: must take ``**kwargs`` since base class supports more inputs like 'name'. The new_from_dict() alternate constructor will invoke __init__ will arguments that supported by baseclass .. py:property:: data_start The Waves object doesn't directly manage a time series of data, so it will not have a data range itself. But it depends upon a Wind and a Water object. The Water won't have a data range either, but the Wind will. So its data range will be that of the Wind it is associated with. .. py:property:: data_stop .. py:attribute:: _ref_as :value: 'waves' .. py:attribute:: _req_refs :value: ['wind', 'water'] .. py:attribute:: _schema .. py:method:: validate() All pygnome objects should be able to validate themselves. Many py_gnome objects reference other objects like wind, water, waves. These may not be defined when object is created so they can be None at construction time; however, they should reference valid objects when running in the model. If make_default_refs is True, then object is valid because the model will set these up at runtime. To raise an exception for missing references at runtime, directly call validate_refs(level='error') 'wind', 'water', 'waves' attributes also have special meaning. An object containing this attribute references the corresponding object. Logs warnings: :returns: a tuple of length two containing: (a list of messages that were logged, isvalid bool) If any references are missing and make_default_refs is False, object is not valid .. note: validate() only logs warnings since it designed to be used to validate before running model. To log these as errors during model run, invoke validate_refs() directly. .. py:method:: get_value(points, time) return the rms wave height, peak period and percent wave breaking at a given time. Does not currently support location-variable waves. :param time: the time you want the wave data for :type time: datetime.datetime object :returns: wave_height, peak_period, whitecap_fraction, dissipation_energy Units: wave_height: meters (RMS height) peak_period: seconds whitecap_fraction: unit-less fraction dissipation_energy: not sure!! # fixme! .. py:method:: get_wind_speed(points, model_time, coord_sys='r', fill_value=1.0) Wrapper for the weatherers so they can extrapolate .. py:method:: get_emulsification_wind(points, time) Return the right wind for the wave climate If a wave height was specified, then you need the greater of the real or pseudo wind. If not, then you need the actual wind. The idea here is that if there is a low wind, but the user specified waves, we really want emulsification that makes sense for the waves. But if the actual wind is stronger than that for the wave height give, we should use the actual wind. fixme: I'm not sure this is right -- if we stick with the wave energy given by the user for dispersion, why not for emulsification? .. py:method:: compute_H(U) .. py:method:: pseudo_wind(H) .. py:method:: whitecap_fraction(U) .. py:method:: mean_wave_period(U) .. py:method:: peak_wave_period(points, time) :param time: the time you want the wave data for :type time: datetime.datetime object :returns: peak wave period (s) .. py:method:: dissipative_wave_energy(H) .. py:method:: energy_dissipation_rate(H, U) c_ub = 100 = dimensionless empirical coefficient to correct for non-Law-of-the-Wall results (Umlauf and Burchard, 2003) u_c = water friction velocity (m/s) sqrt(rho_air / rho_w) * u_a ~ .03 * u_a u_a = air friction velocity (m/s) z_0 = surface roughness (m) (Taylor and Yelland) c_p = peak wave speed for Pierson-Moskowitz spectrum w_p = peak angular frequency for Pierson-Moskowitz spectrum (1/s) TODO: This implementation should be in a utility function. It should not be part of the Waves management object itself. .. py:class:: IceVelocity(angle=None, **kwargs) Bases: :py:obj:`VelocityGrid`, :py:obj:`gnome.environment.environment.Environment` A class for assigning a unique ID for an object :param angle: scalar field of cell rotation angles (for rotated/distorted grids) .. py:attribute:: _ref_as :value: ['ice_velocity', 'ice_aware'] .. py:attribute:: _gnome_unit :value: 'm/s' .. py:attribute:: default_names .. py:attribute:: cf_names .. py:class:: IceConcentration(*args, **kwargs) Bases: :py:obj:`gnome.environment.gridded_objects_base.Variable`, :py:obj:`gnome.environment.environment.Environment` Variable object: represents a field of values associated with the grid. Abstractly, it is usually a scalar physical property such a temperature, salinity that varies over a the domain of the model. This more or less maps to a variable in a netcdf file, but does not have to come form a netcdf file, and this provides and abstraction where the user can access the value in world coordinates, interpolated from the grid. It holds a reference to its own grid object, and its data. This class represents a value defined on a grid :param name: Name :type name: string :param units: Units :type units: string :param time: Time axis of the data :type time: list of `datetime.datetime`, netCDF4 Variable, or Time object :param data: Underlying data source :type data: array-like object such as netCDF4.Variable or numpy.ndarray :param grid: Grid that the data corresponds with :type grid: Grid object (pysgrid or pyugrid or ) :param data_file: Name of data source file :type data_file: string :param grid_file: Name of grid source file :type grid_file: string :param varname: Name of the variable in the data source file :type varname: string :param fill_value: the fill value used for undefined data :param location: location on the grid -- possible values depend on the grid type :type location: str :param attributes: attributes associated with the Variable (analogous to netcdf variable attributes) :type attributes: dict .. py:attribute:: _ref_as :value: ['ice_concentration', 'ice_aware'] .. py:attribute:: default_names .. py:attribute:: cf_names .. py:attribute:: _gnome_unit :value: 'fraction' .. py:class:: RandomMover(diffusion_coef=100000.0, uncertain_factor=2.0, **kwargs) Bases: :py:obj:`gnome.movers.CyMover` "Random Walk" diffusion mover Moves the elements each time step in a random direction, according to the specified diffusion coefficient. :param diffusion_coef: Diffusion coefficient for random diffusion. Default is 100,000 cm2/sec :type diffusion_coef: float or integer in units of cm^2/s :param uncertain_factor: Uncertainty factor. Default is 2.0 Remaining kwargs are passed onto :class:`gnome.movers.Mover` __init__ See Mover documentation for remaining valid kwargs. .. py:property:: data_start .. py:property:: data_stop .. py:property:: diffusion_coef .. py:property:: uncertain_factor .. py:attribute:: _schema .. py:method:: __repr__() Return repr(self). .. py:class:: RandomMover3D(vertical_diffusion_coef_above_ml=5, vertical_diffusion_coef_below_ml=0.11, horizontal_diffusion_coef_above_ml=100000, horizontal_diffusion_coef_below_ml=126, mixed_layer_depth=10.0, surface_is_allowed=False, **kwargs) Bases: :py:obj:`gnome.movers.CyMover` This mover class inherits from CyMover and contains CyRandomMover3D The real work is done by CyRandomMover3D. CyMover sets everything up that is common to all movers. :param vertical_diffusion_coef_above_ml: Vertical diffusion coefficient for random diffusion above the mixed layer. Default is 5 cm2/s :param vertical_diffusion_coef_below_ml: Vertical diffusion coefficient for random diffusion below the mixed layer. Default is .11 cm2/s :param mixed_layer_depth: Mixed layer depth. Default is 10 meters :param horizontal_diffusion_coef_above_ml: Horizontal diffusion coefficient for random diffusion above the mixed layer. Default is 100000 cm2/s :param horizontal_diffusion_coef_below_ml: Horizontal diffusion coefficient for random diffusion below the mixed layer. Default is 126 cm2/s :param surface_is_allowed: Vertical diffusion will ignore surface particles if this is True. Default is False. Remaining kwargs are passed onto Mover's __init__ using super. See Mover documentation for remaining valid kwargs. .. py:property:: horizontal_diffusion_coef_above_ml .. py:property:: horizontal_diffusion_coef_below_ml .. py:property:: vertical_diffusion_coef_above_ml .. py:property:: vertical_diffusion_coef_below_ml .. py:property:: mixed_layer_depth .. py:property:: surface_is_allowed .. py:attribute:: _schema .. py:method:: __repr__() Return repr(self). .. py:class:: PointWindMover(wind=None, **kwargs) Bases: :py:obj:`WindMoversBase` Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. .. py:property:: wind .. py:property:: data_start .. py:property:: data_stop .. py:attribute:: _schema .. py:attribute:: _ref_as :value: 'wind_mover' .. py:attribute:: _req_refs .. py:method:: __repr__() Return repr(self). .. py:method:: __str__() Return str(self). .. py:method:: prepare_for_model_run() if wind attribute is not set, raise ReferencedObjectNotSet excpetion .. py:class:: CatsMover(filename=None, tide=None, uncertain_duration=48, **kwargs) Bases: :py:obj:`CurrentMoversBase` Base class from which all Python movers/weatherers can inherit It defines the base functionality for mover/weatherer. NOTE: Since base class is not Serializable, it does not need a class level _schema attribute. Uses super to invoke base class __init__ method. :param filename: file containing currents patterns for Cats Optional parameters (kwargs). Defaults are defined by CyCatsMover object. :param tide: a gnome.environment.Tide object to be attached to CatsMover :param scale: a boolean to indicate whether to scale value at reference point or not :param scale_value: value used for scaling at reference point :param scale_refpoint: reference location (long, lat, z). The scaling applied to all data is determined by scaling the raw value at this location. :param uncertain_duration: how often does a given uncertain element gets reset :param uncertain_time_delay: when does the uncertainly kick in. :param up_cur_uncertain: Scale for uncertainty along the flow :param down_cur_uncertain: Scale for uncertainty along the flow :param right_cur_uncertain: Scale for uncertainty across the flow :param left_cur_uncertain: Scale for uncertainty across the flow :param uncertain_eddy_diffusion: Diffusion coefficient for eddy diffusion. Default is 0. :param uncertain_eddy_v0: Default is .1 (Check that this is still used) Remaining kwargs are passed onto Mover's __init__ using super. See Mover documentation for remaining valid kwargs. .. py:property:: ref_scale .. py:property:: scale_refpoint .. py:property:: tide .. py:property:: data_start .. py:property:: data_stop .. py:attribute:: _schema .. py:attribute:: filename .. py:attribute:: scale .. py:attribute:: scale_value .. py:attribute:: up_cur_uncertain .. py:attribute:: down_cur_uncertain .. py:attribute:: right_cur_uncertain .. py:attribute:: left_cur_uncertain .. py:attribute:: uncertain_eddy_diffusion .. py:attribute:: uncertain_eddy_v0 .. py:method:: __repr__() Return repr(self). .. py:method:: get_grid_data() Invokes the GetToplogyHdl method of TriGridVel_c object .. py:method:: get_center_points() .. py:method:: get_scaled_velocities(model_time) Get file values scaled to ref pt value, with tide applied (if any) .. py:class:: ComponentMover(filename1=None, filename2=None, wind=None, scale_refpoint=None, pat1_angle=0, pat1_speed=10, pat1_speed_units=2, pat1_scale_to_value=0.1, pat2_angle=90, pat2_scale_to_value=0.1, pat2_speed=10, pat2_speed_units=2, scale_by=0, **kwargs) Bases: :py:obj:`CurrentMoversBase` Base class from which all Python movers/weatherers can inherit It defines the base functionality for mover/weatherer. NOTE: Since base class is not Serializable, it does not need a class level _schema attribute. Uses super to invoke base class __init__ method. :param filename: file containing currents for first Cats pattern Optional parameters (kwargs). Defaults are defined by CyCatsMover object. :param filename: file containing currents for second Cats pattern :param wind: A gnome.environment.Wind object to be used to drive the CatsMovers. Will want a warning that mover will not be active without a wind :param scale: A boolean to indicate whether to scale value at reference point or not :param scale_value: Value used for scaling at reference point :param scale_refpoint: Reference location (long, lat, z). The scaling applied to all data is determined by scaling the raw value at this location. Remaining kwargs are passed onto Mover's __init__ using super. See Mover documentation for remaining valid kwargs. .. py:property:: data_start .. py:property:: data_stop .. py:property:: scale_refpoint .. py:property:: wind .. py:attribute:: _schema .. py:attribute:: _ref_as :value: 'component_mover' .. py:attribute:: _req_refs .. py:attribute:: pat1_angle .. py:attribute:: pat1_speed .. py:attribute:: pat1_speed_units .. py:attribute:: pat1_scale_to_value .. py:attribute:: pat2_angle .. py:attribute:: pat2_speed .. py:attribute:: pat2_speed_units .. py:attribute:: pat2_scale_to_value .. py:attribute:: scale_by .. py:attribute:: extrapolate .. py:attribute:: use_averaged_winds .. py:attribute:: wind_power_factor .. py:attribute:: past_hours_to_average .. py:attribute:: scale_factor_averaged_winds .. py:attribute:: use_original_scale_factor .. py:method:: __repr__() unambiguous representation of object .. py:method:: get_grid_data() Invokes the GetToplogyHdl method of TriGridVel_c object .. py:method:: get_center_points() .. py:method:: get_optimize_values(model_time) .. py:method:: get_scaled_velocities(model_time) Get file values scaled to optimized check if pat2 exists .. py:class:: RiseVelocityMover(**kwargs) Bases: :py:obj:`gnome.movers.CyMover` This mover class inherits from CyMover and contains CyRiseVelocityMover The real work is done by CyRiseVelocityMover. CyMover sets everything up that is common to all movers. Uses super to invoke base class __init__ method. Optional parameters (kwargs) used to initialize CyRiseVelocityMover :param water_density: Default is 1020 kg/m3 :param water_viscosity: Default is 1.e-6 Remaining kwargs are passed onto Mover's __init__ using super. See Mover documentation for remaining valid kwargs. .. py:attribute:: _schema .. py:method:: __repr__() .. todo:: We probably want to include more information. .. py:method:: get_move(sc, time_step, model_time_datetime) Override base class functionality because mover has a different get_move signature :param sc: an instance of the gnome.SpillContainer class :param time_step: time step in seconds :param model_time_datetime: current time of the model as a date time object .. py:class:: WindMover(wind=None, time_offset=0, uncertain_duration=3.0 * 3600, uncertain_time_delay=0, uncertain_speed_scale=2.0, uncertain_angle_scale=0.4, scale_value=1, default_num_method='RK2', filename=None, **kwargs) Bases: :py:obj:`gnome.movers.movers.PyMover` WindMover implemented in Python. Uses the .wind attribute to move particles. The .at() interface is expected on the .wind attribute Initialize a WindMover :param wind: Environment object representing wind to be used. :type wind: Any Wind or Wind-like that implements the .at() function :param active_range: Range of datetimes for when the mover should be active :type active_range: 2-tuple of datetimes :param scale_value: Value to scale wind data :param uncertain_duration: how often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_speed_scale: Scale for uncertainty of wind speed :param uncertain_angle_scale: Scale for uncertainty of wind angle :param time_offset: Time zone shift if data is in GMT :param num_method: Numerical method for calculating movement delta. Choices:('Euler', 'RK2', 'RK4') Default: RK2 .. py:property:: data_start .. py:property:: data_stop .. py:attribute:: _schema .. py:attribute:: _ref_as :value: 'py_wind_movers' .. py:attribute:: _req_refs .. py:method:: from_netCDF(filename=None, time_offset=0, scale_value=1, uncertain_duration=3 * 3600, uncertain_time_delay=0, uncertain_speed_scale=2.0, uncertain_angle_scale=0.4, default_num_method='RK2', **kwargs) :classmethod: .. py:method:: prepare_for_model_run() reset uncertainty .. py:method:: prepare_for_model_step(sc, time_step, model_time_datetime) Call base class method using super Also updates windage for this timestep :param sc: an instance of gnome.spill_container.SpillContainer class :param time_step: time step in seconds :param model_time_datetime: current time of model as a date time object .. py:method:: model_step_is_done(sc) remove any off map les .. py:method:: get_bounds() Return a bounding box surrounding the grid data. This function exists because it is part of the top level Mover API .. py:method:: update_uncertainty(num_les, elapsed_time) update uncertainty :param num_les: the number released so far :param elapsed_time: time in seconds since model run started .. py:method:: update_uncertainty_values(elapsed_time) update uncertainty values :param elapsed_time: time in seconds since model run started .. py:method:: allocate_uncertainty(num_les) add uncertainty :param num_les: the number of les released so far .. py:method:: add_uncertainty(deltas, time_step) add uncertainty :param deltas: the movement for the current time step .. py:method:: get_move(sc, time_step, model_time_datetime, num_method=None) Compute the move in (long,lat,z) space. It returns the delta move for each element of the spill as a numpy array of size (number_elements X 3) and dtype = gnome.basic_types.world_point_type Base class returns an array of numpy.nan for delta to indicate the get_move is not implemented yet. Each class derived from Mover object must implement it's own get_move :param sc: an instance of gnome.spill_container.SpillContainer class :param time_step: time step in seconds :param model_time_datetime: current model time as datetime object All movers must implement get_move() since that's what the model calls .. py:class:: CurrentMover(current=None, time_offset=0, scale_value=1, uncertain_duration=24 * 3600, uncertain_time_delay=0, uncertain_along=0.5, uncertain_cross=0.25, default_num_method='RK2', filename=None, **kwargs) Bases: :py:obj:`gnome.movers.movers.PyMover` CurrentMover implemented in Python. Uses the .current attribute to move particles. The .at() interface is expected on the .current attribute Initialize a CurrentMover :param current: Environment object representing ocean currents to be used. :type current: Any Current or Current-like that implements the .at() function :param active_range: Range of datetimes for when the mover should be active :type active_range: 2-tuple of datetimes :param scale_value: Value to scale current data :param uncertain_duration: how often does a given uncertain element get reset in seconds :param uncertain_time_delay: when does the uncertainly kick in in seconds :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param time_offset: Time zone shift: not functional :param default_num_method: Numerical method for calculating movement delta. Choices:('Euler', 'RK2', 'RK4') Default: RK2 .. py:property:: filename .. py:property:: data_start .. py:property:: data_stop .. py:attribute:: _schema .. py:attribute:: _ref_as :value: 'py_current_movers' .. py:attribute:: _req_refs .. py:method:: from_netCDF(filename=None, name=None, time_offset=0, scale_value=1, uncertain_duration=24 * 3600, uncertain_time_delay=0, uncertain_along=0.5, uncertain_cross=0.25, **kwargs) :classmethod: Function for specifically creating a CurrentMover from a file .. py:method:: get_bounds() Return a bounding box surrounding the grid data. This function exists because it is part of the top level Mover API .. py:method:: get_move(sc, time_step, model_time_datetime, num_method=None) Compute the move in (long,lat,z) space. It returns the delta move for each element of the spill as a numpy array of size (number_elements X 3) and dtype = gnome.basic_types.world_point_type Base class returns an array of numpy.nan for delta to indicate the get_move is not implemented yet. Each class derived from Mover object must implement it's own get_move :param sc: an instance of gnome.spill_container.SpillContainer class :param time_step: time step in seconds :param model_time_datetime: current model time as datetime object All movers must implement get_move() since that's what the model calls .. py:method:: _update_uncertainty(num_les, elapsed_time) update uncertainty :param num_les: the number released so far :param elapsed_time: time in seconds since model run started .. py:method:: _update_uncertainty_values(elapsed_time) update uncertainty values :param elapsed_time: time in seconds since model run started .. py:method:: _allocate_uncertainty(num_les) add uncertainty :param num_les: the number of les released so far .. py:method:: _add_uncertainty(deltas) add uncertainty :param deltas: the movement for the current time step .. py:method:: prepare_for_model_run() reset uncertainty .. py:method:: prepare_for_model_step(sc, time_step, model_time_datetime) add uncertainty .. py:method:: model_step_is_done(sc) remove any off map les .. py:class:: IceAwareRandomMover(ice_concentration=None, **kwargs) Bases: :py:obj:`RandomMover` "Random Walk" diffusion mover Moves the elements each time step in a random direction, according to the specified diffusion coefficient. :param diffusion_coef: Diffusion coefficient for random diffusion. Default is 100,000 cm2/sec :type diffusion_coef: float or integer in units of cm^2/s :param uncertain_factor: Uncertainty factor. Default is 2.0 Remaining kwargs are passed onto :class:`gnome.movers.Mover` __init__ See Mover documentation for remaining valid kwargs. .. py:attribute:: _schema .. py:attribute:: _req_refs .. py:method:: from_netCDF(filename=None, dataset=None, grid_topology=None, units=None, time=None, ice_concentration=None, grid=None, grid_file=None, data_file=None, **kwargs) :classmethod: .. py:method:: get_move(sc, time_step, model_time_datetime) Base implementation of Cython wrapped C++ movers Override for things like the PointWindMover since it has a different implementation :param sc: spill_container.SpillContainer object :param time_step: time step in seconds :param model_time_datetime: current model time as datetime object .. py:class:: SimpleMover(velocity=0, uncertainty_scale=0.5, **kwargs) Bases: :py:obj:`gnome.movers.Mover` simple_mover a really simple mover -- moves all LEs a constant speed and direction (not all that different than a constant wind mover, now that I think about it) simple_mover (velocity) create a simple_mover instance :param velocity: a (u, v, w) triple -- in meters per second :param uncertainty_scale=0.5: the scale of the uncertainty of the velocity Remaining kwargs are passed onto Mover's __init__ using super. See Mover documentation for remaining valid kwargs. .. py:attribute:: _schema .. py:method:: __repr__() Return repr(self). .. py:method:: get_move(spill, time_step, model_time) moves the particles defined in the spill object :param spill: spill is an instance of the gnome.spills.Spill class :param time_step: time_step in seconds :param model_time: current model time as a datetime object In this case, it uses the positions and status_code data arrays. :returns delta: Nx3 numpy array of movement -- in (long, lat, meters) units .. py:data:: PyCurrentMover .. py:data:: PyWindMover .. py:function:: get_datafile(filename) Looks to see if filename exists in local directory. If it exists, then it simply returns the 'filename' back as a string. If 'filename' does not exist in the local filesystem, then it tries to download it from the gnome server (http://gnome.orr.noaa.gov/py_gnome_testdata). If it successfully downloads the file, it puts it in the user specified path given in filename and returns the 'filename' string. If file is not found or server is down, it re-throws the HTTPError raised by urllib :param filename: path to the file including filename :type filename: string :exception: raises HTTPError if server is down or file not found on server :returns: returns the string 'filename' once it has been downloaded to user specified location .. py:function:: load_model(filename) load a model from an existing savefile :param filename: filename (path) of the save file to load. :returns: A configured Model object. :note: This is simply a handy wrapper around the Model.load_savefile classmethod