def check_save_version(expected=None, filename=None, die=False, verbose=True, **kwargs): ''' A convenience function that bundles check_version with git_info and saves automatically to disk from the calling file. The idea is to put this at the top of an analysis script, and commit the resulting file, to keep track of which version of Covasim was used. Args: expected (str): expected version information filename (str): file to save to; if None, guess based on current file name kwargs (dict): passed to git_info(), and thence to sc.savejson() **Examples**:: cv.check_save_version() cv.check_save_version('1.3.2', filename='script.gitinfo', comments='This is the main analysis script') cv.check_save_version('1.7.2', folder='gitinfo', comments={'SynthPops':sc.gitinfo(sp.__file__)}) ''' # First, check the version if supplied if expected: check_version(expected, die=die, verbose=verbose) # Now, check and save the git info if filename is None: filename = sc.getcaller(tostring=False)['filename'] git_info(filename=filename, frame=3, **kwargs) return
def git_info(filename=None, check=False, comments=None, old_info=None, die=False, indent=2, verbose=True, frame=2, **kwargs): ''' Get current git information and optionally write it to disk. Simplest usage is cv.git_info(__file__) Args: filename (str): name of the file to write to or read from check (bool): whether or not to compare two git versions comments (dict): additional comments to include in the file old_info (dict): dictionary of information to check against die (bool): whether or not to raise an exception if the check fails indent (int): how many indents to use when writing the file to disk verbose (bool): detail to print frame (int): how many frames back to look for caller info kwargs (dict): passed to sc.loadjson() (if check=True) or sc.savejson() (if check=False) **Examples**:: cv.git_info() # Return information cv.git_info(__file__) # Writes to disk cv.git_info('covasim_version.gitinfo') # Writes to disk cv.git_info('covasim_version.gitinfo', check=True) # Checks that current version matches saved file ''' # Handle the case where __file__ is supplied as the argument if isinstance(filename, str) and filename.endswith('.py'): filename = filename.replace('.py', '.gitinfo') # Get git info calling_file = sc.makefilepath(sc.getcaller(frame=frame, tostring=False)['filename']) cv_info = {'version':cvv.__version__} cv_info.update(sc.gitinfo(__file__, verbose=False)) caller_info = sc.gitinfo(calling_file, verbose=False) caller_info['filename'] = calling_file info = {'covasim':cv_info, 'called_by':caller_info} if comments: info['comments'] = comments # Just get information and optionally write to disk if not check: if filename is not None: output = sc.savejson(filename, info, indent=indent, **kwargs) else: output = info return output # Check if versions match, and optionally raise an error else: if filename is not None: old_info = sc.loadjson(filename, **kwargs) string = '' old_cv_info = old_info['covasim'] if 'covasim' in old_info else old_info if cv_info != old_cv_info: # pragma: no cover string = f'Git information differs: {cv_info} vs. {old_cv_info}' if die: raise ValueError(string) elif verbose: print(string) return
def savefig(filename=None, comments=None, **kwargs): ''' Wrapper for Matplotlib's savefig() function which automatically stores Covasim metadata in the figure. By default, saves (git) information from both the Covasim version and the calling function. Additional comments can be added to the saved file as well. These can be retrieved via cv.get_png_metadata(). Metadata can also be stored for SVG and PDF formats, but cannot be automatically retrieved. Args: filename (str): name of the file to save to (default, timestamp) comments (str): additional metadata to save to the figure kwargs (dict): passed to savefig() **Example**:: cv.Sim().run(do_plot=True) filename = cv.savefig() ''' # Handle inputs dpi = kwargs.pop('dpi', 150) metadata = kwargs.pop('metadata', {}) if filename is None: # pragma: no cover now = sc.getdate(dateformat='%Y-%b-%d_%H.%M.%S') filename = f'covasim_{now}.png' metadata = {} metadata['Covasim version'] = cvv.__version__ gitinfo = git_info() for key, value in gitinfo['covasim'].items(): metadata[f'Covasim {key}'] = value for key, value in gitinfo['called_by'].items(): metadata[f'Covasim caller {key}'] = value metadata['Covasim current time'] = sc.getdate() metadata['Covasim calling file'] = sc.getcaller() if comments: metadata['Covasim comments'] = comments # Handle different formats lcfn = filename.lower() # Lowercase filename if lcfn.endswith('pdf') or lcfn.endswith('svg'): metadata = { 'Keywords': str(metadata) } # PDF and SVG doesn't support storing a dict # Save the figure pl.savefig(filename, dpi=dpi, metadata=metadata, **kwargs) return filename
def savefig(filename=None, comments=None, fig=None, **kwargs): ''' Wrapper for Matplotlib's ``pl.savefig()`` function which automatically stores Covasim metadata in the figure. By default, saves (git) information from both the Covasim version and the calling function. Additional comments can be added to the saved file as well. These can be retrieved via ``cv.get_png_metadata()`` (or ``sc.loadmetadata``). Metadata can also be stored for PDF, but cannot be automatically retrieved. Args: filename (str/list): name of the file to save to (default, timestamp); can also be a list of names comments (str/dict): additional metadata to save to the figure fig (fig/list): figure to save (by default, current one); can also be a list of figures kwargs (dict): passed to ``fig.savefig()`` **Example**:: cv.Sim().run().plot() cv.savefig() ''' # Handle inputs dpi = kwargs.pop('dpi', 150) metadata = kwargs.pop('metadata', {}) if fig is None: fig = pl.gcf() figlist = sc.tolist(fig) if filename is None: # pragma: no cover now = sc.getdate(dateformat='%Y-%b-%d_%H.%M.%S') filename = f'covasim_{now}.png' filenamelist = sc.tolist(filename) if len(figlist) != len(filenamelist): errormsg = f'You have supplied {len(figlist)} figures and {len(filenamelist)} filenames: these must be the same length' raise ValueError(errormsg) metadata = {} metadata['Covasim version'] = cvv.__version__ gitinfo = git_info() for key,value in gitinfo['covasim'].items(): metadata[f'Covasim {key}'] = value for key,value in gitinfo['called_by'].items(): metadata[f'Covasim caller {key}'] = value metadata['Covasim current time'] = sc.getdate() metadata['Covasim calling file'] = sc.getcaller() if comments: metadata['Covasim comments'] = comments # Loop over the figures (usually just one) for thisfig, thisfilename in zip(figlist, filenamelist): # Handle different formats lcfn = thisfilename.lower() # Lowercase filename if lcfn.endswith('pdf') or lcfn.endswith('svg'): metadata = {'Keywords':str(metadata)} # PDF and SVG doesn't support storing a dict # Save the figure thisfig.savefig(thisfilename, dpi=dpi, metadata=metadata, **kwargs) return filename