def __new__( cls, input_array, units=None, registry=None, info=None, bypass_validation=False, input_units=None, ): if input_units is not None: issue_deprecation_warning( "'input_units' is deprecated. Please use 'units'.", since="4.0.0", removal="4.2.0", ) units = input_units obj = super().__new__(cls, input_array, units, registry, bypass_validation=bypass_validation) if info is None: info = {} obj.info = info return obj
def get_vertex_centered_data(self, fields): _old_api = isinstance(fields, (str, tuple)) if _old_api: message = ( "get_vertex_centered_data() requires list of fields, rather than " "a single field as an argument.") issue_deprecation_warning(message, since="4.0.0", removal="4.1.0") fields = [fields] # Make sure the field list has only unique entries fields = list(set(fields)) new_fields = {} cg = self.retrieve_ghost_zones(1, fields) for field in fields: new_fields[field] = cg[field][1:, 1:, 1:].copy() np.add(new_fields[field], cg[field][:-1, 1:, 1:], new_fields[field]) np.add(new_fields[field], cg[field][1:, :-1, 1:], new_fields[field]) np.add(new_fields[field], cg[field][1:, 1:, :-1], new_fields[field]) np.add(new_fields[field], cg[field][:-1, 1:, :-1], new_fields[field]) np.add(new_fields[field], cg[field][1:, :-1, :-1], new_fields[field]) np.add(new_fields[field], cg[field][:-1, :-1, 1:], new_fields[field]) np.add(new_fields[field], cg[field][:-1, :-1, :-1], new_fields[field]) np.multiply(new_fields[field], 0.125, new_fields[field]) if _old_api: return new_fields[fields[0]] return new_fields
def requires_sim(sim_fn, sim_type, big_data=False, file_check=False): issue_deprecation_warning( "This function is no longer used in the " "yt project testing framework and is " "targeted for deprecation.", since="4.0.0", removal="4.1.0", ) from functools import wraps from nose import SkipTest def ffalse(func): @wraps(func) def fskip(*args, **kwargs): raise SkipTest return fskip def ftrue(func): return func if not run_big_data and big_data: return ffalse elif not can_run_sim(sim_fn, sim_type, file_check): return ffalse else: return ftrue
def add_volume_weighted_smoothed_field( ptype, coord_name, mass_name, smoothing_length_name, density_name, smoothed_field, registry, nneighbors=64, kernel_name="cubic", ): from yt._maintenance.deprecation import issue_deprecation_warning issue_deprecation_warning( "This function is deprecated. " "Since yt-4.0, it's no longer necessary to add a field specifically for " "smoothing, because the global octree is removed. The old behavior of " "interpolating onto a grid structure can be recovered through data objects " "like ds.arbitrary_grid, ds.covering_grid, and most closely ds.octree. The " "visualization machinery now treats SPH fields properly by smoothing onto " "pixel locations. See this page to learn more: " "https://yt-project.org/doc/yt4differences.html", since="4.0.0", removal="4.1.0", )
def get_brewer_cmap(cmap): """Returns a colorbrewer colormap from palettable""" try: import brewer2mpl except ImportError: brewer2mpl = None try: import palettable except ImportError: palettable = None if palettable is not None: bmap = palettable.colorbrewer.get_map(*cmap) elif brewer2mpl is not None: issue_deprecation_warning( "Using brewer2mpl colormaps is deprecated. " "Please install the successor to brewer2mpl, " "palettable, with `pip install palettable`. " "Colormap tuple names remain unchanged.", since="3.3", removal="4.2", ) bmap = brewer2mpl.get_map(*cmap) else: raise RuntimeError("Please install palettable to use colorbrewer colormaps") return bmap.get_mpl_colormap(N=cmap[2])
def can_run_sim(sim_fn, sim_type, file_check=False): issue_deprecation_warning( "This function is no longer used in the " "yt project testing framework and is " "targeted for deprecation.", since="4.0.0", removal="4.1.0", ) result_storage = AnswerTestingTest.result_storage if isinstance(sim_fn, SimulationTimeSeries): return result_storage is not None path = ytcfg.get("yt", "test_data_dir") if not os.path.isdir(path): return False if file_check: return os.path.isfile(os.path.join(path, sim_fn)) and result_storage is not None try: load_simulation(sim_fn, sim_type) except FileNotFoundError: if ytcfg.get("yt", "internals", "strict_requires"): if result_storage is not None: result_storage["tainted"] = True raise return False return result_storage is not None
def from_filenames(cls, filenames, parallel=True, setup_function=None, **kwargs): r"""Create a time series from either a filename pattern or a list of filenames. This method provides an easy way to create a :class:`~yt.data_objects.time_series.DatasetSeries`, given a set of filenames or a pattern that matches them. Additionally, it can set the parallelism strategy. Parameters ---------- filenames : list or pattern This can either be a list of filenames (such as ["DD0001/DD0001", "DD0002/DD0002"]) or a pattern to match, such as "DD*/DD*.index"). If it's the former, they will be loaded in order. The latter will be identified with the glob module and then sorted. parallel : True, False or int This parameter governs the behavior when .piter() is called on the resultant DatasetSeries object. If this is set to False, the time series will not iterate in parallel when .piter() is called. If this is set to either True or an integer, it will be iterated with 1 or that integer number of processors assigned to each parameter file provided to the loop. setup_function : callable, accepts a ds This function will be called whenever a dataset is loaded. Examples -------- >>> def print_time(ds): ... print(ds.current_time) ... >>> ts = DatasetSeries.from_filenames( ... "GasSloshingLowRes/sloshing_low_res_hdf5_plt_cnt_0[0-6][0-9]0", ... setup_function=print_time, ... ) ... >>> for ds in ts: ... SlicePlot(ds, "x", ("gas", "density")).save() """ issue_deprecation_warning( "DatasetSeries.from_filenames() is deprecated and will be removed " "in a future version of yt. Use DatasetSeries() directly.", since="4.0.0", removal="4.1.0", ) obj = cls(filenames, parallel=parallel, setup_function=setup_function, **kwargs) return obj
def _check_deprecated_parameters(): from yt._maintenance.deprecation import issue_deprecation_warning from yt.config import ytcfg if ytcfg.get("yt", "load_field_plugins"): issue_deprecation_warning( "Found deprecated parameter 'load_field_plugins' in yt's configuration file.", removal="4.1.0", )
def convert_ramses_ages(ds, conformal_ages): issue_deprecation_warning( msg= ("The `convert_ramses_ages' function is deprecated. It should be replaced " "by the `convert_ramses_conformal_time_to_physical_age' function."), since="4.0.2", removal="4.0.4", ) return convert_ramses_conformal_time_to_physical_age(ds, conformal_ages)
def __call__(self, fields, weight): issue_deprecation_warning( "'weighted_variance' incorrectly returns the " "standard deviation and has been deprecated. " "Use 'weighted_standard_deviation' instead.", since="4.0.0", removal="4.1.0", ) return super().__call__(fields, weight)
def _dep_field(field, data): if not isinstance(data, FieldDetector): issue_deprecation_warning( ('The "%s_%s" field is deprecated. ' + 'Please use "%s_%s" instead.') % (alias_species, suffix, species, suffix), since="4.0.0", removal="4.1.0", ) return data[ftype, f"{species}_{suffix}"]
def simulation(fn, simulation_type, find_outputs=False): issue_deprecation_warning( "yt.simulation is a deprecated alias for yt.load_simulation" "and will be removed in a future version of yt.", since="4.0.0", removal="4.1.0", ) return load_simulation( fn=fn, simulation_type=simulation_type, find_outputs=find_outputs )
def add_cmap(name, cdict): """Deprecated alias, kept for backwards compatibility.""" from yt._maintenance.deprecation import issue_deprecation_warning issue_deprecation_warning( "`add_cmap` is a deprecated alias for `add_colormap`", since="4.0.0", removal="4.1.0", ) add_colormap(name, cdict)
def locate_brick(self, position): """Given a position, find the node that contains it.""" from yt._maintenance.deprecation import issue_deprecation_warning issue_deprecation_warning( "`AMRKDTree.locate_brick` is a deprecated alias " "for `AMRKDTree.locate_node`.", removal="4.1.0", ) return self.locate_node(position)
def __init__(self, filename, args=None, kwargs=None): super(YTUnidentifiedDataType, self).__init__(filename, args, kwargs) # this cannot be imported at the module level (creates circular imports) from yt._maintenance.deprecation import issue_deprecation_warning issue_deprecation_warning( "YTOutputNotIdentified is a deprecated alias for YTUnidentifiedDataType", since="4.0.0", removal="4.1.0", )
def get_vertex_centered_data( self, fields: List[Tuple[str, str]], smoothed: bool = True, no_ghost: bool = False, ): _old_api = isinstance(fields, (str, tuple)) if _old_api: issue_deprecation_warning( "get_vertex_centered_data() requires list of fields, rather than " "a single field as an argument.", since="3.3", removal="4.2", ) fields = [fields] # type: ignore # Make sure the field list has only unique entries fields = list(set(fields)) new_fields = {} for field in fields: finfo = self.ds._get_field_info(field) new_fields[field] = self.ds.arr( np.zeros(self.ActiveDimensions + 1), finfo.output_units) if no_ghost: for field in fields: # Ensure we have the native endianness in this array. Avoid making # a copy if possible. old_field = np.asarray(self[field], dtype="=f8") # We'll use the ghost zone routine, which will naturally # extrapolate here. input_left = np.array([0.5, 0.5, 0.5], dtype="float64") output_left = np.array([0.0, 0.0, 0.0], dtype="float64") # rf = 1 here ghost_zone_interpolate(1, old_field, input_left, new_fields[field], output_left) else: cg = self.retrieve_ghost_zones(1, fields, smoothed=smoothed) for field in fields: src = cg[field].in_units(new_fields[field].units).d dest = new_fields[field].d np.add(dest, src[1:, 1:, 1:], dest) np.add(dest, src[:-1, 1:, 1:], dest) np.add(dest, src[1:, :-1, 1:], dest) np.add(dest, src[1:, 1:, :-1], dest) np.add(dest, src[:-1, 1:, :-1], dest) np.add(dest, src[1:, :-1, :-1], dest) np.add(dest, src[:-1, :-1, 1:], dest) np.add(dest, src[:-1, :-1, :-1], dest) np.multiply(dest, 0.125, dest) if _old_api: return new_fields[fields[0]] return new_fields
def apply_callback(f): issue_deprecation_warning( "The apply_callback decorator is not used in yt any more and " "will be removed in a future version. " "Please do not use it.", since="4.1", ) @wraps(f) def newfunc(*args, **kwargs): args[0]._callbacks.append((f.__name__, (args, kwargs))) return args[0] return newfunc
def _sanitize_sampling_type(sampling_type, particle_type=None): """Detect conflicts between deprecated and new parameters to specify the sampling type in a new field. This is a helper function to add_field methods. Parameters ---------- sampling_type: str One of "cell", "particle" or "local" (case insensitive) particle_type: str This is a deprecated argument of the add_field method, which was replaced by sampling_type. Raises ------ ValueError For unsupported values in sampling_type RuntimeError If conflicting parameters are passed. """ try: sampling_type = sampling_type.lower() except AttributeError as e: raise TypeError("sampling_type should be a string.") from e acceptable_samplings = ("cell", "particle", "local") if sampling_type not in acceptable_samplings: raise ValueError( "Invalid sampling type %s. Valid sampling types are %s", sampling_type, ", ".join(acceptable_samplings), ) if particle_type: issue_deprecation_warning( "'particle_type' keyword argument is deprecated in favour " "of the positional argument 'sampling_type'.", since="4.0.0", removal="4.1.0", ) if sampling_type != "particle": raise RuntimeError( "Conflicting values for parameters " "'sampling_type' and 'particle_type'." ) return sampling_type
def _sanitize_cmap(cmap): # this function should be removed entierly after yt 4.0.0 is released if not isinstance(cmap, str): return cmap if cmocean is not None: try: cmo_cmap = f"cmo.{cmap}" get_cmap(cmo_cmap) issue_deprecation_warning(CMOCEAN_DEPR_MSG, since="4.0.0", removal="4.1.0") return cmo_cmap except ValueError: pass get_cmap(cmap) return cmap
def apply_filter(f): issue_deprecation_warning( "The apply_filter decorator is not used in yt any more and " "will be removed in a future version. " "Please do not use it.", since="4.1", ) @wraps(f) def newfunc(self, *args, **kwargs): self._filters.append((f.__name__, (args, kwargs))) # Invalidate the data of the frb to force its regeneration self._data_valid = False return self return newfunc
def strip_colormap_data( fn="color_map_data.py", cmaps=( "jet", "cmyt.algae", "hot", "gist_stern", "RdBu", "cmyt.pastel", "cmyt.kelp", "cmyt.arbre", "cmyt.octarine", "cmyt.dusk", ), ): import pprint from yt._maintenance.deprecation import issue_deprecation_warning from . import color_maps as rcm issue_deprecation_warning( "yt.visualization.image_writer.strip_colormap_data is deprecated.", since="4.1.0", removal="4.2.0", ) f = open(fn, "w") f.write( "### Auto-generated colormap tables, taken from Matplotlib ###\n\n") f.write("from numpy import array\n") f.write("color_map_luts = {}\n\n\n") if cmaps is None: cmaps = rcm.ColorMaps if isinstance(cmaps, str): cmaps = [cmaps] for cmap_name in sorted(cmaps): vals = get_colormap_lut(cmap_name) f.write(f"### {cmap_name} ###\n\n") f.write(f"color_map_luts['{cmap_name}'] = \\\n") f.write(" (\n") for v in vals: f.write(pprint.pformat(v, indent=3)) f.write(",\n") f.write(" )\n\n") f.close()
def set_cbar_minorticks(self, field, state): """ turn colorbar minor ticks "on" or "off" in the current plot, following *state* Parameters ---------- field : string the field to remove colorbar minorticks state : string the state indicating 'on' or 'off' """ issue_deprecation_warning( "`ImagePlotContainer.set_cbar_minorticks` is a deprecated alias " "for `ImagePlotContainer.set_colorbar_minorticks`.", removal="4.1.0", ) boolstate = {"on": True, "off": False}[state.lower()] return self.set_colorbar_minorticks(field, boolstate)
def set_minorticks(self, field, state): """Turn minor ticks on or off in the current plot. Displaying minor ticks reduces performance; turn them off using set_minorticks('all', False) if drawing speed is a problem. Parameters ---------- field : string the field to remove minorticks if field == 'all', applies to all plots. state : bool the state indicating 'on' (True) or 'off' (False) """ if isinstance(state, str): issue_deprecation_warning("Deprecated api, use bools for *state*.", removal="4.1.0") state = {"on": True, "off": False}[state.lower()] self._minorticks[field] = state return self
# Add support for IPython rich display # see https://ipython.readthedocs.io/en/stable/config/integrating.html def _repr_json_(self): return self.config_root._repr_json_() _global_config_file = YTConfig.get_global_config_file() _local_config_file = YTConfig.get_local_config_file() if os.path.exists(old_config_file()): if os.path.exists(_global_config_file): issue_deprecation_warning( f"The configuration file {old_config_file()} is deprecated in " f"favor of {_global_config_file}. Currently, both are present. " "Please manually remove the deprecated one to silence " "this warning.", since="4.0.0", removal="4.1.0", ) else: issue_deprecation_warning( f"The configuration file {_OLD_CONFIG_FILE} is deprecated. " f"Please migrate your config to {_global_config_file} by running: " "'yt config migrate'", since="4.0.0", removal="4.1.0", ) if not os.path.exists(_global_config_file): cfg = {"yt": {}} try:
def write_projection( data, filename, colorbar=True, colorbar_label=None, title=None, vmin=None, vmax=None, limits=None, take_log=True, figsize=(8, 6), dpi=100, cmap_name=None, extent=None, xlabel=None, ylabel=None, ): r"""Write a projection or volume rendering to disk with a variety of pretty parameters such as limits, title, colorbar, etc. write_projection uses the standard matplotlib interface to create the figure. N.B. This code only works *after* you have created the projection using the standard framework (i.e. the Camera interface or off_axis_projection). Accepts an NxM sized array representing the projection itself as well as the filename to which you will save this figure. Note that the final resolution of your image will be a product of dpi/100 * figsize. Parameters ---------- data : array_like image array as output by off_axis_projection or camera.snapshot() filename : string the filename where the data will be saved colorbar : boolean do you want a colorbar generated to the right of the image? colorbar_label : string the label associated with your colorbar title : string the label at the top of the figure vmin : float or None the lower limit of the zaxis (part of matplotlib api) vmax : float or None the lower limit of the zaxis (part of matplotlib api) take_log : boolean plot the log of the data array (and take the log of the limits if set)? figsize : array_like width, height in inches of final image dpi : int final image resolution in pixels / inch cmap_name : string The name of the colormap. Examples -------- >>> image = off_axis_projection(ds, c, L, W, N, "Density", no_ghost=False) >>> write_projection(image, 'test.png', colorbar_label="Column Density (cm$^{-2}$)", title="Offaxis Projection", vmin=1e-5, vmax=1e-3, take_log=True) """ if cmap_name is None: cmap_name = ytcfg.get("yt", "default_colormap") import matplotlib.colors import matplotlib.figure from ._mpl_imports import FigureCanvasAgg, FigureCanvasPdf, FigureCanvasPS if limits is not None: if vmin is not None or vmax is not None: raise ValueError( "The `limits` keyword argument is deprecated and can not " "be used simultaneously with `vmin` or `vmax`.") issue_deprecation_warning( "The `limits` keyword argument is deprecated and will " "be removed in a future version of yt. Use `vmin` and `vmax` instead.", since="4.0.0", removal="4.1.0", ) vmin, vmax = limits # If this is rendered as log, then apply now. if take_log: norm_cls = matplotlib.colors.LogNorm else: norm_cls = matplotlib.colors.Normalize norm = norm_cls(vmin=vmin, vmax=vmax) # Create the figure and paint the data on fig = matplotlib.figure.Figure(figsize=figsize) ax = fig.add_subplot(111) cax = ax.imshow( data.to_ndarray(), norm=norm, extent=extent, cmap=cmap_name, ) if title: ax.set_title(title) if xlabel: ax.set_xlabel(xlabel) if ylabel: ax.set_ylabel(ylabel) # Suppress the x and y pixel counts if extent is None: ax.set_xticks(()) ax.set_yticks(()) # Add a color bar and label if requested if colorbar: cbar = fig.colorbar(cax) if colorbar_label: cbar.ax.set_ylabel(colorbar_label) suffix = get_image_suffix(filename) if suffix == "": suffix = ".png" filename = f"{filename}{suffix}" mylog.info("Saving plot %s", filename) if suffix == ".pdf": canvas = FigureCanvasPdf(fig) elif suffix in (".eps", ".ps"): canvas = FigureCanvasPS(fig) else: canvas = FigureCanvasAgg(fig) fig.tight_layout() canvas.print_figure(filename, dpi=dpi) return filename
def __init__( self, name: Tuple[str, str], sampling_type, function, units: Optional[Union[str, bytes, Unit]] = None, take_log=True, validators=None, vector_field=False, display_field=True, not_in_all=False, display_name=None, output_units=None, dimensions=None, ds=None, nodal_flag=None, *, particle_type=None, ): validate_field_key(name) self.name = name self.take_log = take_log self.display_name = display_name self.not_in_all = not_in_all self.display_field = display_field if particle_type is not None: issue_deprecation_warning( "The 'particle_type' keyword argument is deprecated. " "Please use sampling_type='particle' instead.", since="3.2", removal="4.2", ) sampling_type = "particle" self.sampling_type = sampling_type self.vector_field = vector_field self.ds = ds if self.ds is not None: self._ionization_label_format = self.ds._ionization_label_format else: self._ionization_label_format = "roman_numeral" if nodal_flag is None: self.nodal_flag = [0, 0, 0] else: self.nodal_flag = nodal_flag self._function = function self.validators = list(always_iterable(validators)) # handle units self.units: Optional[Union[str, bytes, Unit]] if units is None: self.units = "" elif isinstance(units, str): if units.lower() == "auto": if dimensions is None: raise RuntimeError( "To set units='auto', please specify the dimensions " "of the field with dimensions=<dimensions of field>!") self.units = None else: self.units = units elif isinstance(units, Unit): self.units = str(units) elif isinstance(units, bytes): self.units = units.decode("utf-8") else: raise FieldUnitsError("Cannot handle units '%s' (type %s). " "Please provide a string or Unit " "object." % (units, type(units))) if output_units is None: output_units = self.units self.output_units = output_units if isinstance(dimensions, str): dimensions = getattr(ytdims, dimensions) self.dimensions = dimensions
import numpy as np # This next item will handle most of the actual startup procedures, but it will # also attempt to parse the command line and set up the global state of various # operations. The variable unparsed_args is not used internally but is # provided as a convenience for users who wish to parse arguments in scripts. # https://mail.python.org/archives/list/[email protected]/thread/L6AQPJ3OIMJC5SNKVM7CJG32YVQZRJWA/ import yt.startup_tasks as __startup_tasks from yt import * from yt._maintenance.deprecation import issue_deprecation_warning from yt.config import ytcfg, ytcfg_defaults from yt.utilities.logger import ytLogger issue_deprecation_warning("The yt.mods module is deprecated.", since="4.1.0", removal="4.2.0") unparsed_args = __startup_tasks.unparsed_args if ytLogger.getEffectiveLevel() >= int( ytcfg_defaults["yt"]["log_level"]): # type: ignore # This won't get displayed. mylog.debug("Turning off NumPy error reporting") np.seterr(all="ignore") # We load plugins. Keep in mind, this can be fairly dangerous - # the primary purpose is to allow people to have a set of functions # that get used every time that they don't have to *define* every time. # This way, other command-line tools can be used very simply. # Unfortunately, for now, I think the easiest and simplest way of doing
def load_amr_grids( grid_data, domain_dimensions, bbox=None, sim_time=0.0, length_unit=None, mass_unit=None, time_unit=None, velocity_unit=None, magnetic_unit=None, periodicity=(True, True, True), geometry="cartesian", refine_by=2, unit_system="cgs", ): r"""Load a set of grids of data into yt as a :class:`~yt.frontends.stream.data_structures.StreamHandler`. This should allow a sequence of grids of varying resolution of data to be loaded directly into yt and analyzed as would any others. This comes with several caveats: * Units will be incorrect unless the unit system is explicitly specified. * Some functions may behave oddly, and parallelism will be disappointing or non-existent in most cases. * Particles may be difficult to integrate. * No consistency checks are performed on the index Parameters ---------- grid_data : list of dicts This is a list of dicts. Each dict must have entries "left_edge", "right_edge", "dimensions", "level", and then any remaining entries are assumed to be fields. Field entries must map to an NDArray. The grid_data may also include a particle count. If no particle count is supplied, the dataset is understood to contain no particles. The grid_data will be modified in place and can't be assumed to be static. domain_dimensions : array_like This is the domain dimensions of the grid length_unit : string or float Unit to use for lengths. Defaults to unitless. If set to be a string, the bbox dimensions are assumed to be in the corresponding units. If set to a float, the value is a assumed to be the conversion from bbox dimensions to centimeters. mass_unit : string or float Unit to use for masses. Defaults to unitless. time_unit : string or float Unit to use for times. Defaults to unitless. velocity_unit : string or float Unit to use for velocities. Defaults to unitless. magnetic_unit : string or float Unit to use for magnetic fields. Defaults to unitless. bbox : array_like (xdim:zdim, LE:RE), optional Size of computational domain in units specified by length_unit. Defaults to a cubic unit-length domain. sim_time : float, optional The simulation time in seconds periodicity : tuple of booleans Determines whether the data will be treated as periodic along each axis geometry : string or tuple "cartesian", "cylindrical", "polar", "spherical", "geographic" or "spectral_cube". Optionally, a tuple can be provided to specify the axis ordering -- for instance, to specify that the axis ordering should be z, x, y, this would be: ("cartesian", ("z", "x", "y")). The same can be done for other coordinates, for instance: ("spherical", ("theta", "phi", "r")). refine_by : integer or list/array of integers. Specifies the refinement ratio between levels. Defaults to 2. This can be an array, in which case it specifies for each dimension. For instance, this can be used to say that some datasets have refinement of 1 in one dimension, indicating that they span the full range in that dimension. Examples -------- >>> grid_data = [ ... dict(left_edge = [0.0, 0.0, 0.0], ... right_edge = [1.0, 1.0, 1.], ... level = 0, ... dimensions = [32, 32, 32], ... number_of_particles = 0), ... dict(left_edge = [0.25, 0.25, 0.25], ... right_edge = [0.75, 0.75, 0.75], ... level = 1, ... dimensions = [32, 32, 32], ... number_of_particles = 0) ... ] ... >>> for g in grid_data: ... g["density"] = (np.random.random(g["dimensions"])*2**g["level"], "g/cm**3") ... >>> ds = load_amr_grids(grid_data, [32, 32, 32], length_unit=1.0) """ from yt.frontends.stream.data_structures import ( StreamDataset, StreamDictFieldHandler, StreamHandler, ) from yt.frontends.stream.definitions import process_data, set_particle_types domain_dimensions = np.array(domain_dimensions) ngrids = len(grid_data) if bbox is None: bbox = np.array([[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]], "float64") domain_left_edge = np.array(bbox[:, 0], "float64") domain_right_edge = np.array(bbox[:, 1], "float64") grid_levels = np.zeros((ngrids, 1), dtype="int32") grid_left_edges = np.zeros((ngrids, 3), dtype="float64") grid_right_edges = np.zeros((ngrids, 3), dtype="float64") grid_dimensions = np.zeros((ngrids, 3), dtype="int32") number_of_particles = np.zeros((ngrids, 1), dtype="int64") parent_ids = np.zeros(ngrids, dtype="int64") - 1 sfh = StreamDictFieldHandler() for i, g in enumerate(grid_data): grid_left_edges[i, :] = g.pop("left_edge") grid_right_edges[i, :] = g.pop("right_edge") grid_dimensions[i, :] = g.pop("dimensions") grid_levels[i, :] = g.pop("level") # If someone included this throw it away--old API if "number_of_particles" in g: issue_deprecation_warning( "It is no longer necessary to include " "the number of particles in the data " "dict. The number of particles is " "determined from the sizes of the " "particle fields.", since="4.0.0", removal="4.1.0", ) g.pop("number_of_particles") field_units, data, n_particles = process_data( g, grid_dims=tuple(grid_dimensions[i, :]) ) number_of_particles[i, :] = n_particles sfh[i] = data # We now reconstruct our parent ids, so that our particle assignment can # proceed. mask = np.empty(ngrids, dtype="int32") for gi in range(ngrids): get_box_grids_level( grid_left_edges[gi, :], grid_right_edges[gi, :], grid_levels[gi] + 1, grid_left_edges, grid_right_edges, grid_levels, mask, ) ids = np.where(mask.astype("bool")) for ci in ids: parent_ids[ci] = gi # Check if the grid structure is properly aligned (bug #1295) for lvl in range(grid_levels.min() + 1, grid_levels.max() + 1): idx = grid_levels.flatten() == lvl dims = domain_dimensions * refine_by ** (lvl - 1) for iax, ax in enumerate("xyz"): cell_edges = np.linspace( domain_left_edge[iax], domain_right_edge[iax], dims[iax], endpoint=False ) if set(grid_left_edges[idx, iax]) - set(cell_edges): raise YTIllDefinedAMR(lvl, ax) if length_unit is None: length_unit = "code_length" if mass_unit is None: mass_unit = "code_mass" if time_unit is None: time_unit = "code_time" if velocity_unit is None: velocity_unit = "code_velocity" if magnetic_unit is None: magnetic_unit = "code_magnetic" particle_types = {} for grid in sfh.values(): particle_types.update(set_particle_types(grid)) handler = StreamHandler( grid_left_edges, grid_right_edges, grid_dimensions, grid_levels, parent_ids, number_of_particles, np.zeros(ngrids).reshape((ngrids, 1)), sfh, field_units, (length_unit, mass_unit, time_unit, velocity_unit, magnetic_unit), particle_types=particle_types, periodicity=periodicity, ) handler.name = "AMRGridData" handler.domain_left_edge = domain_left_edge handler.domain_right_edge = domain_right_edge handler.refine_by = refine_by if np.all(domain_dimensions[1:] == 1): dimensionality = 1 elif domain_dimensions[2] == 1: dimensionality = 2 else: dimensionality = 3 handler.dimensionality = dimensionality handler.domain_dimensions = domain_dimensions handler.simulation_time = sim_time handler.cosmology_simulation = 0 sds = StreamDataset(handler, geometry=geometry, unit_system=unit_system) return sds
def load_uniform_grid( data, domain_dimensions, length_unit=None, bbox=None, nprocs=1, sim_time=0.0, mass_unit=None, time_unit=None, velocity_unit=None, magnetic_unit=None, periodicity=(True, True, True), geometry="cartesian", unit_system="cgs", ): r"""Load a uniform grid of data into yt as a :class:`~yt.frontends.stream.data_structures.StreamHandler`. This should allow a uniform grid of data to be loaded directly into yt and analyzed as would any others. This comes with several caveats: * Units will be incorrect unless the unit system is explicitly specified. * Some functions may behave oddly, and parallelism will be disappointing or non-existent in most cases. * Particles may be difficult to integrate. Particle fields are detected as one-dimensional fields. Parameters ---------- data : dict This is a dict of numpy arrays or (numpy array, unit spec) tuples. The keys are the field names. domain_dimensions : array_like This is the domain dimensions of the grid length_unit : string Unit to use for lengths. Defaults to unitless. bbox : array_like (xdim:zdim, LE:RE), optional Size of computational domain in units specified by length_unit. Defaults to a cubic unit-length domain. nprocs: integer, optional If greater than 1, will create this number of subarrays out of data sim_time : float, optional The simulation time in seconds mass_unit : string Unit to use for masses. Defaults to unitless. time_unit : string Unit to use for times. Defaults to unitless. velocity_unit : string Unit to use for velocities. Defaults to unitless. magnetic_unit : string Unit to use for magnetic fields. Defaults to unitless. periodicity : tuple of booleans Determines whether the data will be treated as periodic along each axis geometry : string or tuple "cartesian", "cylindrical", "polar", "spherical", "geographic" or "spectral_cube". Optionally, a tuple can be provided to specify the axis ordering -- for instance, to specify that the axis ordering should be z, x, y, this would be: ("cartesian", ("z", "x", "y")). The same can be done for other coordinates, for instance: ("spherical", ("theta", "phi", "r")). Examples -------- >>> np.random.seed(int(0x4D3D3D3)) >>> bbox = np.array([[0., 1.0], [-1.5, 1.5], [1.0, 2.5]]) >>> arr = np.random.random((128, 128, 128)) >>> data = dict(density=arr) >>> ds = load_uniform_grid(data, arr.shape, length_unit='cm', ... bbox=bbox, nprocs=12) >>> dd = ds.all_data() >>> dd['density'] unyt_array([0.76017901, 0.96855994, 0.49205428, ..., 0.78798258, 0.97569432, 0.99453904], 'g/cm**3') """ from yt.frontends.stream.data_structures import ( StreamDataset, StreamDictFieldHandler, StreamHandler, ) from yt.frontends.stream.definitions import ( assign_particle_data, process_data, set_particle_types, ) domain_dimensions = np.array(domain_dimensions) if bbox is None: bbox = np.array([[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]], "float64") domain_left_edge = np.array(bbox[:, 0], "float64") domain_right_edge = np.array(bbox[:, 1], "float64") grid_levels = np.zeros(nprocs, dtype="int32").reshape((nprocs, 1)) # If someone included this throw it away--old API if "number_of_particles" in data: issue_deprecation_warning( "It is no longer necessary to include " "the number of particles in the data " "dict. The number of particles is " "determined from the sizes of the " "particle fields.", since="4.0.0", removal="4.1.0", ) data.pop("number_of_particles") # First we fix our field names, apply units to data # and check for consistency of field shapes field_units, data, number_of_particles = process_data( data, grid_dims=tuple(domain_dimensions) ) sfh = StreamDictFieldHandler() if number_of_particles > 0: particle_types = set_particle_types(data) # Used much further below. pdata = {"number_of_particles": number_of_particles} for key in list(data.keys()): if len(data[key].shape) == 1 or key[0] == "io": if not isinstance(key, tuple): field = ("io", key) mylog.debug("Reassigning '%s' to '%s'", key, field) else: field = key sfh._additional_fields += (field,) pdata[field] = data.pop(key) else: particle_types = {} if nprocs > 1: temp = {} new_data = {} for key in data.keys(): psize = get_psize(np.array(data[key].shape), nprocs) grid_left_edges, grid_right_edges, shapes, slices = decompose_array( data[key].shape, psize, bbox ) grid_dimensions = np.array([shape for shape in shapes], dtype="int32") temp[key] = [data[key][slice] for slice in slices] for gid in range(nprocs): new_data[gid] = {} for key in temp.keys(): new_data[gid].update({key: temp[key][gid]}) sfh.update(new_data) del new_data, temp else: sfh.update({0: data}) grid_left_edges = domain_left_edge grid_right_edges = domain_right_edge grid_dimensions = domain_dimensions.reshape(nprocs, 3).astype("int32") if length_unit is None: length_unit = "code_length" if mass_unit is None: mass_unit = "code_mass" if time_unit is None: time_unit = "code_time" if velocity_unit is None: velocity_unit = "code_velocity" if magnetic_unit is None: magnetic_unit = "code_magnetic" handler = StreamHandler( grid_left_edges, grid_right_edges, grid_dimensions, grid_levels, -np.ones(nprocs, dtype="int64"), np.zeros(nprocs, dtype="int64").reshape(nprocs, 1), # particle count np.zeros(nprocs).reshape((nprocs, 1)), sfh, field_units, (length_unit, mass_unit, time_unit, velocity_unit, magnetic_unit), particle_types=particle_types, periodicity=periodicity, ) handler.name = "UniformGridData" handler.domain_left_edge = domain_left_edge handler.domain_right_edge = domain_right_edge handler.refine_by = 2 if np.all(domain_dimensions[1:] == 1): dimensionality = 1 elif domain_dimensions[2] == 1: dimensionality = 2 else: dimensionality = 3 handler.dimensionality = dimensionality handler.domain_dimensions = domain_dimensions handler.simulation_time = sim_time handler.cosmology_simulation = 0 sds = StreamDataset(handler, geometry=geometry, unit_system=unit_system) # Now figure out where the particles go if number_of_particles > 0: # This will update the stream handler too assign_particle_data(sds, pdata, bbox) return sds
def write_png( self, filename, sigma_clip=None, background="black", rescale=True, clip_ratio=None, ): r"""Writes ImageArray to png file. Parameters ---------- filename : string Filename to save to. If None, PNG contents will be returned as a string. sigma_clip : float, optional Image will be clipped before saving to the standard deviation of the image multiplied by this value. Useful for enhancing images. Default: None background: This can be used to set a background color for the image, and can take several types of values: * ``white``: white background, opaque * ``black``: black background, opaque * ``None``: transparent background * 4-element array [r,g,b,a]: arbitrary rgba setting. Default: 'black' rescale : boolean, optional If True, will write out a rescaled image (without modifying the original image). Default: True Examples -------- >>> im = np.zeros([64, 128, 4]) >>> for i in range(im.shape[0]): ... for k in range(im.shape[2]): ... im[i, :, k] = np.linspace(0.0, 10.0 * k, im.shape[1]) >>> im_arr = ImageArray(im) >>> im_arr.write_png("standard.png") >>> im_arr.write_png("non-scaled.png", rescale=False) >>> im_arr.write_png("black_bg.png", background="black") >>> im_arr.write_png("white_bg.png", background="white") >>> im_arr.write_png("green_bg.png", background=[0, 1, 0, 1]) >>> im_arr.write_png("transparent_bg.png", background=None) """ if rescale: scaled = self.rescale(inline=False) else: scaled = self if self.shape[-1] == 4: out = scaled.add_background_color(background, inline=False) else: out = scaled if filename is not None and filename[-4:] != ".png": filename += ".png" if clip_ratio is not None: issue_deprecation_warning( "The 'clip_ratio' keyword argument is a deprecated alias for 'sigma_clip'. " "Please use 'sigma_clip' directly.", since="3.3", removal="4.2", ) sigma_clip = clip_ratio if sigma_clip is not None: clip_value = self._clipping_value(sigma_clip, im=out) return write_bitmap(out.swapaxes(0, 1), filename, clip_value) else: return write_bitmap(out.swapaxes(0, 1), filename)