.. currentmodule:: sciris
All major updates to Sciris are documented here.
By import convention, components of the Sciris library are listed beginning with sc.
, e.g. sc.odict()
.
- Added a new profiler, :class:`sc.cprofile() <sc_profiling.cprofile>`, as an interface to Python's built-in cProfile.
- Updated :func:`sc.iterobj() <sc_nested.iterobj>` to include several new arguments:
skip
will skip objects to avoid iterating over;depthfirst
switches between depth-first (default) and breadth-first (new) iteration options;flatten
returns object traces as strings rather than tuples; andto_df
converts the output to a dataframe. - Pretty-repr functions and classes (e.g. :func:`sc.pr() <sc_printing.pr>`, :class:`sc.prettyobj() <sc_printing.prettyobj>`) now include protections against infinite recursion.
sc.prettyobj()
was linked back tosc.sc_utils
to prevent unpickling errors (partially reversing the change in version 3.1.4). - :class:`sc.dictobj.copy() <sc_odict.dictobj>` now returns another
dictobj
(previously it returned adict
). - :func:`sc.require() <sc_versioning.require>` has been reimplemented to be faster and avoid
pkg_resources
deprecations.
- Added a new :class:`sc.quickobj() <sc_printing.quickobj>` class, which is like :class:`sc.prettyobj() <sc_printing.prettyobj>` except it only prints attribute names, not values. This is useful for large objects that can be slow to print.
- :func:`sc.pr() <sc_printing.pr>` has a new
vals=False
argument that skips printing attribute values. The default column width was also increased (from 18 to 22 chars). - A new function :func:`sc.ifelse() <sc_utils.ifelse>` was added, which is a shortcut to finding the first non-
None
(or non-False
) value in a list. - Updated :func:`sc.iterobj() <sc_nested.iterobj>` to prevent recursion, and to handle atomic classes (i.e. objects that are not descended into) more flexibly.
- Fixed failures of pretty-repr (e.g. :func:`sc.pr() <sc_printing.pr>` and :class:`sc.prettyobj() <sc_printing.prettyobj>`) for objects with invalid properties (e.g., properties that rely on missing/invalid attributes).
sc.prettyobj()
was also moved fromsc_utils
tosc_printing
. - Added additional flexibility for loading zip files (:func:`sc.loadzip() <sc_fileio.loadzip>`); saving zip files (:func:`sc.savezip() <sc_fileio.savezip>`) now saves text as plain text even with
tobytes=True
. - :func:`sc.dcp(die=False) <sc_utils.dcp>` now passes
die=False
to :func:`sc.cp() <sc_utils.cp>`, and will return the original object if it cannot be copied. - :func:`sc.urlopen() <sc_utils.urlopen>` now has additional response options, including
'json'
and'full'
.
- :func:`sc.equal() <sc_nested.equal>` now parses the structure of all objects (not just the first), with missing keys/attributes listed in the output table. It also now allows for a
detailed=2
argument, which prints the value of each key/attribute in each object. (Thanks to Kelvin Burke for this and other features.) - Fixed incorrect keyword arguments (
iterkwargs
) in :func:`sc.parallelize() <sc_parallel.parallelize>` when usingthread
or another non-copying parallelizer, when theiterkwargs
are not consistent between iterations. - Fixed incorrect printout on the final iteration of :func:`sc.asd() <sc_asd.asd>` in verbose mode.
- Fixed incorrect plotting of non-cumulative data in :func:`sc.stackedbar() <sc_plotting.stackedbar>`.
- :func:`sc.download(..., save=False) <sc_utils.download>` now returns an :class:`sc.objdict <sc_odict.objdict>` (instead of an :class:`sc.odict <sc_odict.odict>`).
- :func:`sc.checktype(obj, 'arraylike') <sc_utils.checktype>` is now more robust to handling non-array-like objects (e.g., a ragged list of lists now returns
False
instead of raising an exception). - :func:`sc.require() <sc_versioning.require>` now takes an optional
message
argument, allowing for a custom message if the requirement(s) aren't met. - Removed
object
from the list of classes shown by :func:`sc.prepr() <sc_printing.prepr>` (since all objects derive fromobject
).
- Updated logic for :func:`sc.iterobj() <sc_nested.iterobj>` and added a new :class:`sc.IterObj() <sc_nested.IterObj>` class, allowing greater customization of how objects are iterated over.
- Fixed a bug in which 3D plotting functions (e.g. :func:`sc.bar3d() <sc_plotting.bar3d>`) would create a new figure even if an existing axes instance was passed.
- :class:`sc.odict <sc_odict.odict>` now supports steps in slice-based indexing, e.g.:
myodict['foo':'bar':5]
will select every 5th item from'foo'
to'bar'
inclusive. - :meth:`sc.odict.copy() <sc_odict.odict.copy>` now behaves the same as
dict.copy()
; the previous behavior (which copied an item) is deprecated. Instead ofmydict.copy(oldkey, newkey)
, usemydict[newkey] = sc.dcp(mydict[oldkey])
instead. - :func:`sc.download() <sc_utils.download>` now defaults to expecting
filename:URL
pairs rather thanURL:filename
pairs (e.g.sc.download({'wikipedia.html':'http://wikipedia.org/index.html'})
, though it can accept either as long ashttp
appears in one. - :func:`sc.parallelize() <sc_parallel.parallelize>` has more robust error handling (previously, certain types of exceptions, such as HTTP errors, were not caught even if
die=False
). - :func:`sc.load() <sc_fileio.load>` has improved support for loading old pickles, including a new
NoneObj
class that is used when the user explicitly remaps an old class/function toNone
. - :func:`sc.sanitizefilename() <sc_fileio.sanitizefilename>` now excludes newlines and tabs even when
strict=False
. - :func:`sc.runcommand() <sc_utils.runcommand>` now prints out terminal output in real time if
wait=False
. - Added support for Python 3.12. Note:
line_profiler
is not compatible with Python 3.12 at the time of writing, so :func:`sc.profile() <sc_profiling.profile>` is not available on Python 3.12.
- :func:`sc.equal() <sc_nested.equal>` compares two (or more) arbitrarily complex objects. It can handle arrays, dataframes, custom objects with no
__eq__
method defined, etc. It can also print a detailed comparison of the objects. - :func:`sc.nanequal() <sc_math.nanequal>` is an extension of :func:`np.array_equal() <numpy.array_equal>` to handle a broader range of types (e.g., mixed-type
object
arrays that cannot be cast to float). OtherNaN
-related methods have also been updated to be more robust. - :func:`sc.manualcolorbar() <sc_colors.manualcolorbar>` allows highly customized colorbars to be added to plots, including to plots with no "mappable" data (e.g., scatterplots).
- Added :meth:`sc.options.reset() <sc_settings.ScirisOptions.reset>` as an alias to
sc.options.set('defaults')
.
- Sciris is now compatible with a broader range of dependencies (e.g., Python, NumPy, pandas, and Matplotlib); in most cases, the latest version of Sciris is now backwards-compatible with all dependency versions since January 2021.
- Updated :func:`sc.pr() <sc_printing.pr>` to include class attributes (as well as instance attributes), and added a new function :func:`sc.classatt() <sc_printing.classatt>` to list them.
- :func:`sc.readdate() <sc_datetime.readdate>` now returns
datetime
objects unchanged, rather than raising an exception. - Fixed
repr
for empty :class:`sc.objdict() <sc_odict.objdict>`. - Fixed transposed ordering for :func:`sc.bar3d() <sc_plotting.bar3d>`.
- :func:`sc.load() <sc_fileio.load>` has been significantly refactored to be simpler and more robust. Pandas' :func:`pd.read_pickle() <pandas.read_pickle>` is now included as one of the default unpickling options. Unsuccessful unpickling now always produces a :class:`Failed <sc_fileio.Failed>` object, with as much data retained as possible.
- :func:`sc.jsonpickle() <sc_fileio.jsonpickle>` and :func:`sc.jsonunpickle() <sc_fileio.jsonunpickle>` can now save to/read from files directly.
- Updated :func:`sc.toarray() <sc_utils.toarray>` to use
dtype=object
instead ofdtype=str
by default; otherwise, all elements in mixed-type arrays (e.g.[1,'a']
) are cast to string. - :class:`sc.dataframe <sc_dataframe.dataframe>` has a new
equal
class method (e.g.sc.dataframe.equal(df1, df2)
), and revisedequals()
and==
behavior to match pandas. - Improved robustness of :func:`sc.parallelize() <sc_parallel.parallelize>`, especially when using custom parallelizers, including more options for customizing the global dictionary.
- :class:`sc.timer() <sc_datetime.timer>` objects can now be added, which will concatenate all the times.
- Added an option to run :func:`sc.benchmark() <sc_profiling.benchmark>` in parallel (to test the full capacity of the machine rather than a single core).
- :func:`sc.iterobj() <sc_nested.iterobj>` now provides more options for controlling how the object is iterated, and no longer (by default) descends into NumPy arrays, pandas DataFrames, etc. :func:`sc.search() <sc_nested.search>` also has additional options.
- Updated 3D plotting functions (:func:`sc.plot3d() <sc_plotting.plot3d>`, :func:`sc.surf3d() <sc_plotting.surf3d>`, etc.) to have more flexibility of data input, consistency, and robustness.
This version's major changes include:
- New Parallel class: A new :class:`sc.Parallel() <sc_parallel.Parallel>` class allows finer-grained managing of parallel processes, including automatic progress bars, better exception handling, and asynchronous running.
- Better versioning: New functions :func:`sc.metadata() <sc_versioning.metadata>`, :func:`sc.savearchive() <sc_versioning.savearchive>`, and :func:`sc.loadarchive() <sc_versioning.loadarchive>` make it easier to store and save metadata along with objects.
- Faster data structures: :class:`sc.odict() <sc_odict.odict>` and :class:`sc.dataframe() <sc_dataframe.dataframe>` have both been reimplemented for better performance and with additional methods.
- Easier imports: :func:`sc.importbypath() <sc_utils.importbypath>` lets you load a module into Python by providing the folder or filename (useful for loading one-off scripts, or two versions of the same library).
- Better documentation: A comprehensive set of tutorials has been added to the documentation, and the documentation has been rewritten in a new style.
- There is a new :class:`sc.Parallel() <sc_parallel.Parallel>` class, which is used to implement the (more or less unchanged) :func:`sc.parallelize() <sc_parallel.parallelize>` function.
- :func:`sc.parallelize() <sc_parallel.parallelize>` now has a
progress
argument that will show a progress bar; thereturnpool
argument has been removed (use :class:`sc.Parallel() <sc_parallel.Parallel>` instead).
- Better implementation of underlying logic, leading to significant performance increases in some cases (e.g., iteratively appending rows).
- Numerous methods have been renamed, modified, or added, specifically:
append
,col_index
,col_name
,findind
,findinds
,merge
,popcols
,poprow
,poprows
, andsort
. - Keyword arguments are now interpreted as columns, e.g.
df = sc.dataframe(a=[1,2], b=[3,4])
. - Better handling of (and preservation) of
dtypes
for dataframe columns, including a new :meth:`df.set_dtypes() <sc_dataframe.dataframe.set_dtypes>` method. - Dataframes now support equality checks.
- Support for
pandas
andNumpy
datetime objects. - New :class:`sc.timer <sc_datetime.timer>` attributes and methods: :obj:`sc.rawtimings <sc_datetime.timer.rawtimings>`, :meth:`sc.sum() <sc_datetime.timer.sum>`, :meth:`sc.min() <sc_datetime.timer.min>`, :meth:`sc.max() <sc_datetime.timer.max>`, :meth:`sc.mean() <sc_datetime.timer.mean>`, :meth:`sc.std() <sc_datetime.timer.std>`.
- :class:`sc.timer <sc_datetime.timer>` now displays time in human-appropriate units (e.g., 3.4 μs instead of 0.0000034 s) by default, or accepts a
unit
argument. - New :func:`sc.time() <sc_datetime.time>` alias for :func:`time.time()`.
- :func:`sc.datedelta() <sc_datetime.datedelta>` can now operate on a list of dates.
- :func:`sc.randsleep() <sc_datetime.randsleep>` now accepts a
seed
argument. - More accurate computation of self-time in :func:`sc.timedsleep() <sc_datetime.timedsleep>`.
- A new function :func:`sc.unzip() <sc_fileio.unzip>` extracts zip files to disk, while :func:`sc.loadzip() <sc_fileio.loadzip>` now defaults to loading the zip file contents to memory. :func:`sc.savezip() <sc_fileio.savezip>` can now save both data and files, and its
filelist
argument has been renamedfiles
. - If a saved file can't be unpickled, :func:`sc.load() <sc_fileio.load>` now defaults to using
dill
, and has more robust error handling (see also "versioning" updates below). - :func:`sc.makefilepath() <sc_fileio.makefilepath>` now defaults to
makedirs=False
. - File save functions now make new subfolders by default
- :func:`sc.save() <sc_fileio.save>` now has an
allow_empty
argument (instead ofdie='never'
). - :func:`sc.glob() <sc_fileio.glob>` is a new alias for :func:`sc.getfilelist() <sc_fileio.getfilelist>`.
- :func:`sc.thisdir() <sc_fileio.thisdir>` now gives a correct answer when running in a Jupyter notebook.
- :func:`sc.progressbar() <sc_printing.progressbar>` can now be used to wrap an iterable, in which case it acts as an alias to
tqdm.tqdm()
. - The new :func:`sc.progressbars() <sc_printing.progressbars>` class will create and manage multiple progress bars, which can be useful for monitoring multiple parallel long-running jobs.
- New functions :func:`sc.arraymean() <sc_printing.arraymean>` and :func:`sc.arraymedian() <sc_printing.arraymedian>` can be used to quickly summarize an array. To print rather than return a string, use :func:`sc.printmean() <sc_printing.printmean>` and :func:`sc.printmedian() <sc_printing.printmedian>`.
- The new function :func:`sc.humanize_bytes() <sc_printing.humanize_bytes>` will convert a number of bytes into a human-readable number (e.g.
32975281
to32.975 MB
). - The new function :func:`sc.readjson() <sc_fileio.readjson>` will read a JSON from a string (alias to :func:`sc.loadjson(string=...) <sc_fileio.loadjson>`); likewise :func:`sc.readyaml() <sc_fileio.readyaml>`. :func:`sc.printjson() <sc_fileio.printjson>` and print an object as if it was a JSON.
- :func:`sc.printarr() <sc_printing.printarr>` now has configurable decimal places (
decimals
argument) and can return a string instead of printing (doprint=False
). - :func:`sc.pp() <sc_utils.pp>` no longer casts objects to JSON first (see :func:`sc.printjson() <sc_fileio.printjson>` for that).
- :func:`sc.sigfigs() <sc_printing.sigfigs>` is a new alias of :func:`sc.sigfig() <sc_printing.sigfig>`.
- The new :func:`sc.benchmark() <sc_profiling.benchmark>` function runs tests on both regular Python and Numpy operations and reports the performance of the current machine.
- :func:`sc.checkmem() <sc_profiling.checkmem>` now returns a dataframe, can descend multiple levels through an object, reports subtotals, and has an
order
argument instead ofalphabetical
.
- A new versioning module has been added.
- A new function :func:`sc.metadata() <sc_versioning.metadata>` gathers all relevant metadata and returns a dict that can be used for versioning.
- A pair of new functions :func:`sc.savearchive() <sc_versioning.savearchive>` and :func:`sc.loadarchive() <sc_versioning.loadarchive>`, provide a way to automatically save metadata along with an object for better versioning.
- Known regressions from older library versions are now automatically handled by :func:`sc.load() <sc_fileio.load>` (e.g.,
pandas
v2.0 dataframes cannot be loaded in v1.5, and vice versa). - :func:`sc.require() <sc_versioning.require>` now has the option to raise a warning instead of an error if a module is not found.
- :func:`sc.findnans() <sc_math.findnans>` is a new alias for
sc.findinds(np.isnan(data))
. :func:`sc.rmnans() <sc_math.rmnans>` is a new alias for :func:`sc.sanitize() <sc_math.sanitize>`. - :func:`sc.randround() <sc_math.randround>` now works with multidimensional arrays. (Thanks to Jamie Cohen for the suggestion.)
- :func:`sc.smoothinterp() <sc_math.smoothinterp>` now defaults to
ensurefinite=True
. - :func:`sc.asd() <sc_asd.asd>` now uses its own random number stream.
- :func:`sc.cat() <sc_math.cat>` now works on 2D arrays.
- :class:`sc.odict() <sc_odict.odict>` now inherits from :class:`dict` rather than :class:`OrderedDict <collections.OrderedDict>`. This makes initialization and some other operations nearly four times faster.
- :class:`sc.odict() <sc_odict.odict>` can now be initialized with integer keys.
- There is a new :meth:`sc.dictobj.to_json() <sc_odict.dictobj.to_json>` method. :meth:`sc.dictobj.fromkeys() <sc_odict.dictobj.fromkeys>` is now a static method.
- Nested "dictionary" operations can now act on other types of object, including lists and regular objects.
- :func:`sc.iterobj() <sc_nested.iterobj>` applies a function iteratively to an object.
- :func:`sc.search() <sc_nested.search>` now works on values as well as keys/attributes.
- The new function :func:`sc.importbypath() <sc_utils.importbypath>` will import a module by path, as an alternative to standard
import
. :func:`sc.importbyname() <sc_utils.importbyname>` also now accepts apath
argument. - The new function :func:`sc.getuser() <sc_utils.getuser>` will return the current username (as an alias to
getpass.getuser()
). - The new function :func:`sc.isjupyter() <sc_utils.isjupyter>` determines whether or not the code is running in a Jupyter notebook. Default Jupyter plotting has been updated from
widget
toretina
.
- The two Sciris plotting styles,
sciris.simple
andsciris.fancy
, are now available through standard Matplotlib (e.g.pl.style.use('sciris.simple')
. - 3D plots (e.g. :func:`sc.plot3d() <sc_plotting.plot3d>`) will now render into existing figures and axes where possible, rather than always creating a new figure.
- The
freeze
argument of :func:`sc.savefig() <sc_plotting.savefig>` has been renamedpipfreeze
, andframe
has been replaced withrelframe
.
- A new environment variable,
SCIRIS_NUM_THREADS
, will set the number of threads Numpy uses (if Sciris is imported first). In some cases, more threads results in slower processing (and of course uses way more CPU time). - The new function :func:`sc.sanitizestr() <sc_printing.sanitizestr>` will sanitize an input string to e.g. ASCII-only or a valid variable name.
- :func:`sc.download() <sc_utils.download>` now handles exceptions gracefully with
die=False
. - :func:`sc.isiterable() <sc_utils.isiterable>` now has optional
exclude
andminlen
arguments. - :func:`sc.flexstr() <sc_utils.flexstr>` now has more options for converting arbitrary or multiple objects to a string.
- :func:`sc.transposelist() <sc_utils.transposelist>` has a new
fix_uneven
argument (previously, elements longer than the shortest sublist were silently removed). - :func:`sc.tryexcept() <sc_utils.tryexcept>` now has
to_df()
anddisp()
methods.
- Fixed
<=
comparison in :func:`sc.compareversions() <sc_versioning.compareversions>` not handling equality. - Fixed the implementation of the
midpoint
argument in :func:`sc.vectocolor() <sc_colors.vectocolor>`. - Fixed corner cases where some :class:`sc.dataframe <sc_dataframe.dataframe>` methods returned
pd.DataFrame
objects instead. - Fixed corner cases where some :class:`sc.objdict <sc_odict.objdict>` methods returned :class:`sc.odict <sc_odict.odict>` objects instead.
- :func:`sc.findinds() <sc_math.findinds>` now returns a tuple for multidimensional arrays, allowing it to be used directly for indexing.
- :func:`sc.rmnans() <sc_math.rmnans>` now returns a zero-length array if all input is NaNs.
- :meth:`sc.options.with_style(style) <sc_settings.ScirisOptions.with_style>` now correctly applies the style.
- Fixed :func:`sc.daydiff() <sc_datetime.daydiff>` with one argument computing the number of days from Jan. 1st of the current year (instead of Jan. 1st of the provided year).
keepends
andskipnans
arguments were removed from :func:`sc.smoothinterp() <sc_math.smoothinterp>`.
tqdm
is now a required dependency.- Calls to :func:`sc.makepath() <sc_fileio.makepath>` and :func:`sc.makefilepath() <sc_fileio.makefilepath>` now need to specify
makedirs=True
. - :class:`sc.odict() <sc_odict.odict>` is no longer an instance of :class:`OrderedDict <collections.OrderedDict>`.
- The
returnpool
argument of :func:`sc.parallelize() <sc_parallel.parallelize>` has been removed. - For :func:`sc.savefig() <sc_plotting.savefig>`,
freeze
should be renamedpipfreeze
, andframe
should be replaced withrelframe
with an offset of 2 (e.g.frame=2 → relframe=0
). - :func:`sc.checkmem(..., alphabetical=True) <sc_profiling.checkmem>` has been replaced with :func:`sc.checkmem(..., order='alphabetical') <sc_profiling.checkmem>`
- The
Options
class has been renamed class :class:`sc.ScirisOptions() <sc_settings.ScirisOptions>`. sc.parallel_progress()
has been moved tosc.sc_legacy
. Please use :func:`sc.parallelize(..., progress=True) <sc_parallel.parallelize>` instead.sc.parallelcmd()
has been moved tosc.sc_legacy
. Please do not use this function :)
sc.save()
/sc.load()
now allow files to be saved/loaded in zstandard (instead ofgzip
) format, since the former is usually faster for the same level of compression.sc.save()
still usesgzip
by default; the equivalentsc.zsave()
useszstandard
by default.sc.save()
also now has the option of not using any compression viasc.save(..., compression='none')
. (Thanks to Fabio Mazza for the suggestion.)- Functions that returned paths as strings by default --
sc.thisdir()
,sc.getfilelist()
,sc.makefilepath()
,sc.sanitizefilename()
-- now all have aliases that returnPath
objects by default:sc.thispath()
,sc.getfilepaths()
,sc.makepath()
, andsc.sanitizepath()
. sc.thisfile()
gets the path of the current file.sc.sanitizecolor()
will convert any form of color specification (e.g.'g'
,'crimson'
) into an RGB tuple.sc.tryexcept()
silences all (or some) exceptions in awith
block.
- Fixed bug where
sc.save(filename=None)
would incorrectly result in creation of a file on disk in addition to returning aio.BytesIO
stream. - Fixed bug where
sc.checkmem()
would sometimes raise an exception when saving aNone
object to check its size. - Fixed bug where
sc.loadbalancer()
would sometimes fail ifinterval
was 0 (it is now required to be at least 1 ms).
sc.vectocolor()
now has anancolor
argument to handle NaN values; NaNs are also now handled correctly.sc.timer()
now has a more compact default string representation; usetimer.disp()
to display the full object. In addition,timer.total
is now a property instead of a function.sc.thisdir()
now takes aframe
argument, in case the folder of a file other than the calling script is desired.sc.getfilelist()
now has afnmatch
argument, which allows for Unix-style file matching via the fnmatch module.sc.importbyname()
now has averbose
argument.sc.promotetolist()
andsc.promotetoarray()
are now aliases ofsc.tolist()
andsc.toarray()
, rather than vice versa.
sc.stackedbar()
will automatically plot a 2D array as a stacked bar chart.sc.parallelize()
now usesmultiprocess
again by default (due to issues withconcurrent.futures
).- Added a
die
argument tosc.save()
. - Added a
prefix
argument tosc.urlopen()
, allowing e.g.http://
to be omitted from the URL.
- Added
sc.linregress()
as a simple way to perform linear regression (fit a line of best fit). - Improved
sc.printarr()
formatting. - Reverted incompatibility with older Matplotlib versions introduced in version 2.0.2.
- The default parallelizer has been changed from
multiprocess
toconcurrent.futures
. The latter is faster, but less robust (e.g., it can't parallelize lambda functions). If an error is encountered, it will automatically fall back to the former. - For debugging, instead of
sc.parallelize(..., serial=True)
, you can also now usesc.parallelize(..., parallelizer='serial')
. - Arguments to
sc.parallelize()
are now no longer usually deepcopied, since usually they are automatically during the pickling/unpickling process. However, deepcopying has been retained forserial
andthread
parallelizers; to not deepcopy, use e.g.parallelizer='thread-nocopy'
.
sc.autolist()
now correctly handles input arguments, and can be added on to other objects. (Previously, if an object was added to ansc.autolist
, it would itself become ansc.autolist
.)sc.cat()
now has the same default behavior asnp.concatenate()
for 2D arrays (i.e., concatenating rows). Usesc.cat(.., axis=None)
for the previous behavior.sc.dataframe.from_dict()
andsc.dataframe.from_records()
now return ansc.dataframe
object (previously they returned apd.DataFrame
object).
sc.dataframe.cat()
will concatenate multiple objects (dataframes, arrays, etc.) into a single dataframe.sc.dataframe().concat()
now by default does not modify in-place.- Colormaps are now also available with a
sciris-
prefix, e.g.sciris-alpine
, as well as their original names (to avoid possible name collisions). - Added
packaging
as a dependency and removed the (deprecated)minimal
install option.
sc.asciify()
converts a Unicode input string to the closest ASCII equivalent.sc.dataframe().disp()
flexibly prints a dataframe (by default, all rows/columns).
sc.findinds()
now allows a wider variety of numeric-but-non-array inputs.sc.sanitizefilename()
now handles more characters, including Unicode, and has many new options.sc.odict()
now allows you to delete by index instead of key.sc.download()
now creates folders if they do not already exist.sc.checktype(obj, 'arraylike')
now returnsTrue
for pandasSeries
objects.sc.promotetoarray()
now converts pandasSeries
orDataFrame
objects into arrays.sc.savetext()
can now save arrays (likenp.savetxt()
).
- Fixed a bug with addition (concatenation) for
sc.autolist()
. - Fixed a bug with the
_copy
argument forsc.mergedicts()
being ignored. sc.checkmem()
no longer uses compression, giving more accurate estimates.- Fixed a bug with
sc.options()
setting the plot style automatically; a'default'
style was also added that restores Matplotlib defaults (which is now the Sciris default as well; use'sciris'
or'simple'
for the Sciris style). - Fixed a bug with
packaging.version
not being found on some systems. - Fixed an issue with colormaps attempting to be re-registered, which caused warnings.
This version contains a number of major improvements, including:
- New functions: new functions for downloading (
sc.download()
), paths (sc.rmpath()
), and data handling (sc.loadyaml()
) have been added. - Better parallelization:
sc.parallel()
now allows more flexibility in choosing the pool, includingconcurrent.futures
. There's a newsc.resourcemonitor()
for monitoring or limiting resources during big runs. - Improved dataframe:
sc.dataframe()
is now implemented as an extension of a pandas DataFrame.
sc.resourcemonitor()
provides memory or CPU limits, as well as monitors running processes.sc.download()
downloads multiple files in parallel.sc.rmpath()
removes both files and folders, with an optional interactive mode.sc.ispath()
is an alias forisinstance(obj, pathlib.Path)
.sc.loadyaml()
andsc.saveyaml()
load and save YAML files, respectively.sc.loadzip()
extracts (or reads data from) zip files.sc.count()
counts the number of matching elements in an array (similar tonp.count_nonzero()
, but more flexible with e.g. float vs. int mismatches).sc.rmnans()
andsc.fillnans()
have been added as aliases ofsc.sanitize()
with default options.sc.strsplit()
will automatically split common types of delimited strings (e.g.sc.strsplit('a b c')
).sc.parse_env()
parses environment variables into common types (e.g., will interpret'False'
asFalse
).sc.LazyModule()
handles lazily loaded modules (seesc.importbyname()
for usage).sc.randsleep()
sleeps for a nondeterministic period of time.
sc.mergedicts()
now handles keyword arguments (previously they were silently ignored). Non-dict inputs also now raise an error by default rather than being silently ignored (except forNone
).sc.savespreadsheet()
now allows NaNs to be saved.sc.loadspreadsheet()
has been updated to match currentpd.read_excel()
syntax.Spreadsheet
objects no longer pickle the binary spreadsheet (in some cases reducing size by 50%).- File-saving functions now have a
sanitizepath
argument (previously, some used file path sanitization and others didn't). They also now return the full path of the saved file.
- If a copy/deepcopy is not possible,
sc.cp()
/sc.dcp()
now raise an exception by default (previously, they silenced it). sc.dataframe()
has been completely revamped, and is now a backwards-compatible extension ofpd.DataFrame()
.sc.parallelize()
now supports additional parallelization options, e.g.concurrent.futures
, and newmaxcpu
/maxmem
arguments.
sc.timer()
now hasplot()
andtotal()
methods, as well asindivtimings
andcumtimings
properties. It also has new methodstocout()
andttout()
, which return output by default (rather than print a string).sc.daterange()
now acceptsdatedelta
arguments, e.g.sc.daterange('2022-02-22', weeks=2)
.sc.date()
can now readnp.datetime64
objects.
sc.animation()
now defaults toffmpeg
for saving.sc.commaticks()
can now set bothx
andy
axes in a single call.sc.savefig()
by default now creates folders if they don't exist.sc.loadmetadata()
can now read metadata from JPG files.
sc.findinds()
can now handle multiple inputs, e.g.sc.findinds(data>0.1, data<0.5)
.sc.checktype()
now includes boolean arrays as beingarraylike
, and has a new'bool'
option.sc.sanitize()
can now handle multidimensional arrays.
sc.urlopen()
can now save to files.sc.savezip()
can now save data to zip files (instead of just compressing files).sc.path()
is more flexible, including handlingNone
inputs.sc.Spreadsheet()
now has anew()
method that creates a blank workbook.
- Added
dict_keys()
,dict_values()
, anddict_items()
methods forsc.odict()
. sc.checkmem()
now returns a dictionary of sizes rather than prints to screen.sc.importbyname()
can now load multiple modules, and load them lazily.sc.prettyobj()
andsc.dictobj()
now both take either positional or keyword arguments, e.g.sc.prettyobj(a=3)
orsc.dictobj({'a':3})
.
pyyaml
has been added as a dependency.- Profiling and load balancing functions have beem moved from
sc.sc_utils
andsc.sc_parallel
to a new submodule,sc.sc_profiling
. - Most instances of
DeprecationWarning
have been changed toFutureWarning
. - Python 2 compatibility functions (e.g.
sc.loadobj2or3()
) have been moved to a separate module,sc.sc_legacy
, which is no longer imported by default. - Added style and contributing guides.
- Added official support for Python 3.7-3.10.
sc.wget()
was renamedsc.urlopen()
.- Sciris now has a "lazy loading" option, which does not import submodules, meaning loading is effectively instant. To use, set the environment variable
SCIRIS_LAZY=1
, then load submodules via e.g.from sciris import sc_odict as sco
.
- The default for
sc.cp()
andsc.dcp()
changed fromdie=False
todie=True
, which may cause previously caught exceptions to be uncaught. For previous behavior, usesc.dcp(..., die=False)
. - The argument
maxload
(insc.loadbalancer()
,sc.parallelize()
, etc.) has been renamedmaxcpu
(for consistency with the newmaxmem
argument). - Previously
sc.loadbalancer(maxload=None)
was interpreted as a default load limit (0.8);None
is now interpreted as no limit. - Legacy load functions have been moved to a separate module and must be used from there, e.g.
sc.sc_legacy.loadobj2or3()
.
- Added
sc.savefig()
, which is likepl.savefig()
but stores additional metadata in the figure -- the file that created the figure, git hash, even the entire contents ofpip freeze
if desired. Useful for making figures more reproducible. - Likewise,
sc.loadmetadata()
will load the metadata from a PNG/SVG file saved withsc.savefig()
. - Added
sc.animation()
as a more flexible alternative tosc.savemovie()
. Whilesc.savemovie()
works directly with Matplotlib artists,sc.animation()
works with entire figure objects so if you can plot it, you can animate it. - Split
sc.dateformatter()
into two:sc.dateformatter()
reformats axes that already use dates (e.g.pl.plot(sc.daterange('2022-01-01', '2022-01-31'), pl.rand(31))
), whilesc.datenumformatter()
reformats axes that use numbers (e.g.pl.plot(np.arange(31), pl.rand(31))
). - Added flexibility for
sc.boxoff()
to turn off any sides of the box.
- Added
sc.capture()
, which will redirectstdout
to a string, e.g.with sc.capture() as txt: print('This will be stored in "txt"')
. This is very useful for writing tests against text that is supposed to be printed out. - Added quick aliases for
sc.colorize()
, e.g.sc.printgreen('This is like print(), but green')
. Colors available are red, green, blue, cyan, yellow, magenta. - Keyword arguments are now allowed for
sc.mergedicts()
, e.g.sc.mergedicts({'a':1}, b=2)
. Existing keywords have been renamed to start with an underscore, e.g._strict
. - Added an
every
argument tosc.progressbar()
, to not update on every step. - Fixed labeling bugs in several corner cases for
sc.timer()
. - Added an explicit
start
argument tosc.timedsleep()
. - Added additional flexibility to
sc.getcaller()
, including storing the code of the calling line.
- Additional flexibility in
sc.timer()
: it now stores a list of times (timer.timings
), allows auto-generated labels (sc.timer(auto=True)
, and has a new methodtimer.tt()
(short fortoctic
) that will restart the timer (i.e. time diff rather than cumulative time). - Fixed a bug preventing the label from being passed in
timer.toc()
. - Fixed a bug blocking
style=None
insc.dateformatter()
, and added an argument to allow using they
axis.
- Major improvements to
sc.odict()
performance: key lookup (e.g.my_odict['key']
) is ~30% faster, nearly identical to nativedict()
; integer lookup (my_odict[3]
) is now 10-100x faster. This was achieved by caching the keys rather than looking them up each time. - Allow dicts with integer keys to be converted to odicts via the
makefrom()
method, e.g.sc.odict.makefrom({0:'foo', 1:'bar'})
. If an odict has integer keys, then these take precedence. - Added
force
option toobjdict.setattribute()
to allow attributes to be set even if they already exist. Addedobjdict.delattribute()
to delete attributes. - Removed the
to_OD()
method (since dicts preserve order,dict(my_odict)
is now much more common). - Made
sc.dictobj()
a subclass ofdict
, soisinstance(my_dictobj, dict)
is nowTrue
. - Added
sc.ddict()
as an alias tocollections.defaultdict()
.
- Updated
sc.commaticks()
to use a more thoughtful number of significant figures.
- Fixed a bug in
sc.heading()
that printed an extraneousNone
. Also allows more flexibility in spaces before/after the heading. - Fixed a bug in
sc.fonts()
that prevented using aPath
object. Also added arebuild
argument that rebuilds the Matplotlib font cache (useful when added fonts don't show up). - Updated
sc.colorize()
to wrap theansicolors
module, allowing more flexible inputs such assc.colorize('cat', fg='orange')
. - Added
output
argument tosc.pp()
which acts as an alias topprint.pformat()
.
- Removed the
pkg_resources
import, which roughly halves Sciris import time (from 0.3 s to 0.15 s, assumingmatplotlib.pyplot
is already imported). - Added option to search the source code in
sc.help()
. - Improved the implementations of
sc.smooth()
,sc.gauss1d()
, andsc.gauss2d()
to handle different object types and edge cases. - Fixed requirements for
minimal
install option. - Removed the
openpyexcel
dependency (falling back to the nearly identicalopenpyxl
).
This version contains a number of major improvements, including:
- Better date plotting:
sc.dateformatter()
has been revamped to provide compact and intuitive date plotting. - Better smoothing: The new functions
sc.convolve()
/sc.gauss1d()
/sc.gauss2d()
, and the updatedsc.smooth()
, provide new options for smoothing data. - Simpler fonts:
sc.fonts()
can both list fonts and add new ones. - Simpler options: Need a bigger font? Just do
sc.options(fontsize=18)
.
- Added a settings module to quickly set both Sciris and Matplotlib options; e.g.
sc.options(dpi=150)
is a shortcut forpl.rc('figure', dpi=150)
, while e.g.sc.options(aspath=True)
will globally set Sciris functions to returnPath
objects instead of strings. - Added
sc.timer()
as a simpler and more flexible way of accessingsc.tic()
/sc.toc()
andsc.Timer()
. - Added
sc.convolve()
, a simple fix tonp.convolve()
that avoids edge effects (see update tosc.smooth()
below). - Added
sc.gauss1d()
andsc.gauss2d()
as additional (high-performance) smoothing functions. - Added
sc.fonts()
, to easily list or add fonts for use in plotting. - Added
sc.dictobj()
, the inverse ofsc.objdict()
-- an object that acts like a dictionary (instead of a dictionary that acts like an object). Compared tosc.objdict()
,sc.dictobj()
is lighter-weight and slightly faster but less powerful. - Added
sc.swapdict()
, a shortcut for swapping the keys and values of a dictionary. - Added
sc.loadobj2or3()
, for legacy support for loading Python 2 pickles. (Support had been removed in version 1.1.1.) - Added
sc.help()
, to quickly allow searching of Sciris' docstrings.
- Fixed edge effects when using
sc.smooth()
by usingsc.convolve()
instead ofnp.convolve()
. - Fixed a bug with checking types when saving files via
sc.save()
. (Thanks to Rowan Martin-Hughes.) - Fixed a bug with
output=True
not being passed correctly forsc.heading()
.
sc.dateformatter()
is now an interface to a new formatter for plotting dates (ScirisDateFormatter
). This formatter is optimized for aesthetics, combining the best aspects of Matplotlib's and Plotly's date formatters. (Thanks to Daniel Klein.)sc.daterange()
now accepts aninterval
argument.sc.datedelta()
can now return the actual delta rather than just the date.sc.toc()
has more flexible printing options.sc.Spreadsheet()
now keeps a copy of the opened workbook, so there is no need to reopen it for every operation.sc.commaticks()
can now use non-comma separators.- Many other functions had small usability improvements, e.g. input arguments are more consistent and more flexible.
xlrd
has been removed as a dependency;openpyexcel
is used instead, with simple spreadsheet loading now done bypandas
.- Source files were refactored and split into smaller pieces (e.g.
sc_utils.py
was split intosc_utils.py
,sc_printing.py
,sc_datetime.py
,sc_nested.py
).
- To restore previous spreadsheet loading behavior, use
sc.loadspreadsheet(..., method='xlrd')
. - To use previous smoothing (with edge effects), use
sc.smooth(..., legacy=True)
- Fixed a bug with
sc.asd()
failing forverbose > 1
. (Thanks to Nick Scott and Romesh Abeysuriya.) - Added
sc.rolling()
as a shortcut to pandas' rolling average function. - Added a
die
argument tosc.findfirst()
andsc.findlast()
, to allow returning no indices without error.
- A new class,
sc.autolist()
, is available to simplify appending to lists, e.g.ls = sc.autolist(); ls += 'not a list'
. - Added
sc.freeze()
as a programmatic equivalent ofpip freeze
. - Added
sc.require()
as a flexible way of checking (or asserting) environment requirements, e.g.sc.require('numpy')
. - Added
sc.path()
as an alias topathlib.Path()
.
- Added an even more robust unpickler, that should be able to recover data even if exceptions are raised when unpickling.
- Updated
sc.loadobj()
to allow loading standard (not gzipped) pickles and fromdill
. - Updated
sc.saveobj()
to automatically swap arguments if the object is supplied first, then the filename. - Updated
sc.asd()
to allow more flexible argument passing to the optimized function; also updatedverbose
to allow skipping iterations. - Added a
path
argument tosc.thisdir()
to more easily allow subfolders/files. - Instead of being separate function definitions,
sc.load()
,sc.save()
, andsc.jsonify()
are now identical to their aliases (e.g.sc.loadobj()
). sc.dateformatter()
now allows arotation
argument, since date labels often collide.sc.readdate()
andsc.date()
can now read additional numeric dates, e.g.sc.readdate(16166, dateformat='ordinal')
.
sc.promotetolist()
now converts (rather than wraps) ranges and dict_keys objects to lists. To restore the previous behavior, use the argumentcoerce='none'
.- The
start_day
argument has been renamedstart_date
forsc.day()
andsc.dateformatter()
. - The
dateformat
argument forsc.date()
has been renamedoutformat
, to differentiate fromreadformat
.
- Added
openpyxl
as a Sciris dependency, since it was removed from pandas. - Added
sc.datedelta()
, a function that wrapsdatetime.timedelta
to easily do date operations on strings, e.g.sc.datedelta('2021-07-07', days=-3)
returns'2021-07-04'
. - Added additional supported date formats to
sc.readdate()
, along with new'dmy'
and'mdy'
options todateformat
, to read common day-month-year and month-day-year formats. - Added the ability for
sc.compareversions()
to handle'<'
,'>='
, etc. - Errors loading pickles from
sc.load()
are now more informative.
- Added
sc.figlayout()
as an alias to bothfig.set_tight_layout(True)
andfig.subplots_adjust()
. - Added
sc.midpointnorm()
as an alias to Matplotlib'sTwoSlopeNorm
; it can also be used in e.g.sc.vectocolor()
. - Added
sc.dateformatter()
, which will (semi-)automatically format the x-axis using dates. - Added
sc.getplatform()
,sc.iswindows()
,sc.islinux()
, andsc.ismac()
. These are all shortcuts for checkingsys.platform
output directly. - Added
sc.cpu_count()
as a simple alias formultiprocessing.cpu_count()
.
- Fixed
sc.checkmem()
from failing when an attribute wasNone
. - Fixed a file handle that was being left open by
sc.gitinfo()
.
- Defined
+
forsc.odict
and derived classes; adding two dictionaries is the same as callingsc.mergedicts()
on them. - Updated nested dictionary functions, and added them as methods to
sc.odict()
and derived classes (likesc.objdict()
); for example, you can now donestedobj = sc.objdict(); nestedobj.setnested(['a','b','c'], 4)
. - Added
sc.odict.enumvalues()
as an alias tosc.odict.enumvals()
.
- Updated
sc.commaticks()
to use better formatting. - Removed the
fig
argument fromsc.commaticks()
andsc.SIticks()
; now, the first argument can be anAxes
object, aFigure
object, or a list of axes. - Updated
sc.get_rows_cols()
to optionally create subplots, rather than just return the number of rows/columns. - Removed
sc.SItickformatter
; usesc.SIticks()
instead.
- Updated
sc.heading()
to handle arguments the same way asprint()
, e.g.sc.heading([1,2,3], 'is a list')
. - Allowed more flexibility with the
ncpus
argument ofsc.parallelize()
: it can now be a fraction, representing a fraction of available CPUs. Also, it will now never exceed the number of tasks to be run. - Updated
sc.suggest()
to modify the threshold to be based on the length of the input word.
- The implementations of
sc.odict()
andsc.objdict()
have been updated, to allow for more flexible use of thedefaultdict
argument, including better nesting and subclassing. - A new
serial
argument has been added tosc.parallelize()
to allow for quick debugging. - Legacy support for Python 2 has been removed from
sc.loadobj()
andsc.saveobj()
. - A fallback method for
sc.gitinfo()
(based ongitpython
) has been added, in case reading from the filesystem fails.
sc.mergelists()
is similar tosc.mergedicts()
: it will take a sequence of inputs and attempt to merge them into a list.sc.transposelist()
will perform a transposition on a list of lists: for example, a list of 10 lists (or tuples) each of length 3 will be transformed into a list of 3 lists each of length 10.sc.strjoin()
andsc.newlinejoin()
are shortcuts to', '.join(items)
and'\n'.join(items)
, respectively. The latter is especially useful inside f-strings since you cannot use the\n
character.
sc.day()
now returns a numeric array when an array of datetime objects is passed to it; a bug which was introduced in version 1.0.2 which meant it returned an object array instead.- Slices with numeric start and stop indices have been fixed for
sc.odict()
. sc.objatt()
now correctly handles objects with slots instead of a dict.
sc.loadobj()
now accepts aremapping
argument, which lets the user load old pickle files even if the modules no longer exist.- Most file functions (e.g.
sc.makefilepath
,sc.getfilelist()
now accept anaspath
argument, which, ifTrue
, will return apathlib.Path
object instead of a string. - Most array-returning functions, such as
sc.promotetoarray()
andsc.cat()
, now accept acopy
argument and other keywords; these keywords are passed tonp.array()
, allowing e.g. thedtype
to be set. - A fallback option for
sc.findinds()
has been implemented, allowing it to work even if the input array isn't numeric. sc.odict()
now has adefaultdict
argument, which lets you use it like a defaultdict as well as an ordered dict.sc.odict()
has atranspose
argument for methods likeitems()
andenumvalues()
, which will return a tuple of lists instead of a list of tuples.sc.objdict()
now prints out differently, to distinguish it from ansc.odict
.sc.promotetolist()
has a newcoerce
argument, which will convert that data type into a list (instead of wrapping it).
- The functions
sc.tolist()
andsc.toarray()
have been added as aliases ofsc.promotetolist()
andsc.promotetoarray()
, respectively. You may use whichever you prefer. - The
skipnone
keyword has been removed fromsc.promotetoarray()
and replaced withkeepnone
(which does something slightly different).
- Exceptions have been made more specific (e.g.
TypeError
instead ofException
). - Test code coverage has been increased significantly (from 63% to 84%).
- Fixed bug (introduced in version 1.0.1) with
sc.readdate()
returning only the first element of a list of a dates. - Fixed bug (introduced in version 1.0.1) with
sc.date()
treating an integer as a timestamp rather than an integer number of days when a start day is supplied. - Updated
sc.readdate()
,sc.date()
, andsc.day()
to always return consistent output types (e.g. if an array is supplied as an input, an array is supplied as an output).
- Fixed bug with Matplotlib 3.4.0 also defining colormap
'turbo'
, which caused Sciris to fail to load. - Added a new function,
sc.orderlegend()
, that lets you specify the order you want the legend items to appear. - Fixed bug with paths returned by
sc.getfilelist(nopath=True)
. - Fixed bug with
sc.loadjson()
only reading from a string iffromfile=False
. - Fixed recursion issue with printing
sc.Failed
objects. - Changed
sc.approx()
to be an alias tonp.isclose()
; this function may be removed in future versions. - Changed
sc.findinds()
to callnp.isclose()
, allowing for greater flexibility. - Changed the
repr
forsc.objdict()
to differ fromsc.odict()
. - Improved
sc.maximize()
to work on more platforms (but still not inline or on Macs). - Improved the flexiblity of
sc.htmlify()
to handle tabs and other kinds of newlines. - Added additional checks to
sc.prepr()
to avoid failing on recursive objects. - Updated
sc.mergedicts()
to return the same type as the first dict supplied. - Updated
sc.readdate()
andsc.date()
to support timestamps as well as strings. - Updated
sc.gitinfo()
to try each piece independently, so if it fails on one (e.g., extracting the date) it will still return the other pieces (e.g., the hash). - Pinned
xlrd
to 1.2.0 since later versions fail to read xlsx files.
This major update (and official release!) includes many new utilities adopted from the Covasim and Atomica libraries, as well as important improvements and bugfixes for parallel processing, object representation, and file I/O.
sc.findfirst()
andsc.findlast()
return the first and last indices, respectively, of whatsc.findinds()
would return. These keywords (first
andlast
) can also be passed directly tosc.findinds()
.sc.randround()
probabilistically rounds numbers to the nearest integer; e.g. 1.2 will round down 80% of the time.sc.cat()
is a generalization ofnp.append()
/np.concatenate()
that handles arbitrary types and numbers of inputs.sc.isarray()
checks if the object is a Numpy array.
- A new diverging colormap,
'orangeblue'
, has been added (courtesy Prashanth Selvaraj). It is rather pretty; you should try it out. sc.get_rows_cols()
solves the small but annoying issue of trying to figure out how many rows and columns you need to plot N axes. It is similar tonp.unravel_index()
, but allows the desired aspect ratio to be varied.sc.maximize()
maximizes the current figure window.
sc.date()
will convert practically anything to a date.sc.day()
will convert practically anything to an integer number of days from a starting point; for example,sc.day(sc.now())
returns the number of days since Jan. 1st.sc.daydiff()
computes the number of days between two or more start and end dates.sc.daterange()
returns a list of date strings or date objects between the start and end dates.sc.datetoyear()
converts a date to a decimal year (from Romesh Abeysuriya via Atomica).
- The "flagship" functions
sc.loadobj()
/sc.saveobj()
now have shorter aliases:sc.load()
/sc.save()
. These functions can be used interchangeably. - A convenience function,
sc.toctic()
, has been added that doessc.toc(); sc.tic()
, i.e. for sequentially timing multiple blocks of code. sc.checkram()
reports the current process' RAM usage at the current moment in time; useful for debugging memory leaks.sc.getcaller()
returns the name and line number of the calling function; useful for logging and version control purposes.sc.nestedloop()
iterates over lists in the specified order (from Romesh Abeysuriya via Atomica).sc.parallel_progress()
runs a function in parallel whilst displaying a single progress bar across all processes (from Romesh Abeysuriya via Atomica).- An experimental function,
sc.asobj()
, has been added that lets any dictionary-like object be used with attributes instead (i.e.foo.bar
instead offoo['bar']
).
sc.parallelize()
now uses themultiprocess
library instead ofmultiprocessing
. This update fixes bugs with trying to run parallel processing in certain environments (e.g., in Jupyter notebooks). This function also returns a more helpful error message when running in the wrong context on Windows.sc.prepr()
has been updated to use a simpler method of parsing objects for display; this should be faster and more robust. A default 3 second time limit has also been added.sc.savejson()
now uses an indent of 2 by default, leading to much more human-readable JSON files.sc.gitinfo()
has been updated to use the code from Atomica'sfast_gitinfo()
instead (courtesy Romesh Abeysuriya).sc.thisdir()
now no longer requires the__file__
argument to be supplied to get the current folder.sc.readdate()
can now handle a list of dates.sc.getfilelist()
now has more options, such as to return the absolute path or no path, as well as handling file matching patterns more flexibly.sc.Failed
andsc.Empty
, which may be encountered when loading a corrupted pickle file, are now exposed to the user (before they could only be accessed viasc.sc_fileio.Failed
).sc.perturb()
can now use either uniform or normal perturbations via thenormal
argument.
- The function
sc.quantile()
has been removed. Please usenp.quantile()
instead (though admittedly, it is extremely unlikely you were using it to begin with). - The function
sc.scaleratio()
has been renamedsc.normsum()
, since it normalizes an array by the sum.
- Module imports were moved to inside functions, improving Sciris loading time by roughly 30%.
- All tests were refactored to be in consistent format, increasing test coverage by roughly 50%.
- Continuous integration testing was updated to use GitHub Actions instead of Travis/Tox.
sc.profile()
andsc.mprofile()
now return the line profiler instance for later use (e.g., to extract additional statistics).sc.prepr()
(also used insc.prettyobj()
) can now support objects with slots instead of dicts.
sc.parallelize()
now explicitly deep-copies objects, since on some platforms this copying does not take place as part of the parallelization process.
sc.search()
is a new function to find nested attributes/keys within objects or dictionaries.
sc.Blobject
has been modified to allow more flexibility with saving (e.g.,Path
objects).
sc.mprofile()
has been added, which does memory profiling just likesc.profile()
.sc.progressbar()
has been added, which prints a progress bar.sc.jsonpickle()
andsc.jsonunpickle()
have been added, wrapping the module of the same name, to convert arbitrary objects to JSON.sc.jsonify()
checks objects for ato_json()
method, handling e.g Pandas dataframes, and falls back tosc.jsonpickle()
instead of raising an exception for unknown object types.sc.suggest()
now usesjellyfish
instead ofpython-levenshtein
for fuzzy string matching.sc.saveobj()
now uses protocol 4 instead of the latest by default, to avoid backwards incompatibility issues caused by using protocol 5 (only compatible with Python 3.8).sc.odict()
and related classes now raisesc.KeyNotFoundError
exceptions. These are derived fromKeyError
, but fix a bug in the string representation to allow multi-line error messages.- Rewrote all tests to be pytest-compatible.
sc.makefilepath()
now has acheckexists
flag, which will optionally raise an exception if the file does (or doesn't) exist.sc.sanitizejson()
now handlesdatetime.date
anddatetime.time
.sc.uuid()
andsc.fast_uuid()
now work with non-integer inputs, e.g.,sc.uuid(n=10e3)
.sc.thisdir()
now accepts additional arguments, so can be used to form a full path, e.g.sc.thisdir(__file__, 'myfile.txt')
.sc.checkmem()
has better parsing of objects.sc.prepr()
now lists properties of objects, and has some aesthetic improvements.