signature:
def get_content_commit_date ( extensions , acceptance_callback = None , root_dir = '.' ) :
    """Get the datetime for the most recent commit to a project that
 affected certain types of content .
 Parameters
 extensions : sequence of ' str '
 Extensions of files to consider in getting the most recent commit
 date . For example , ` ` ( ' rst ' , ' svg ' , ' png ' ) ` ` are content extensions
 for a Sphinx project . * * Extension comparision is case sensitive . * * add
 uppercase variants to match uppercase extensions .
 acceptance _ callback : callable
 Callable function whose sole argument is a file path , and returns
 ` True ` or ` False ` depending on whether the file ' s commit date should
 be considered or not . This callback is only run on files that are
 included by ` ` extensions ` ` . Thus this callback is a way to exclude
 specific files that would otherwise be included by their extension .
 root _ dir : ' str ` , optional
 Only content contained within this root directory is considered .
 This directory must be , or be contained by , a Git repository . This is
 the current working directory by default .
 Returns
 commit _ date : ` datetime . datetime `
 Datetime of the most recent content commit .
 Raises
 RuntimeError
 Raised if no content files are found ."""

implementation:
logger = logging . getLogger ( __name__ )
def _null_callback ( _ ) :
    return True
if acceptance_callback is None :
    acceptance_callback = _null_callback
# Cache the repo object for each query
root_dir = os . path . abspath ( root_dir )
repo = git . repo . base . Repo ( path = root_dir , search_parent_directories = True )
# Iterate over all files with all file extensions , looking for the
# newest commit datetime .
newest_datetime = None
iters = [ _iter_filepaths_with_extension ( ext , root_dir = root_dir ) for ext in extensions ]
for content_path in itertools . chain ( * iters ) :
    content_path = os . path . abspath ( os . path . join ( root_dir , content_path ) )
    if acceptance_callback ( content_path ) :
        logger . debug ( 'Found content path %r' , content_path )
        try :
            commit_datetime = read_git_commit_timestamp_for_file ( content_path , repo = repo )
            logger . debug ( 'Commit timestamp of %r is %s' , content_path , commit_datetime )
        except IOError :
            logger . warning ( 'Count not get commit for %r, skipping' , content_path )
            continue
        if not newest_datetime or commit_datetime > newest_datetime : # Seed initial newest _ datetime
        # or set a newer newest _ datetime
            newest_datetime = commit_datetime
            logger . debug ( 'Newest commit timestamp is %s' , newest_datetime )
    logger . debug ( 'Final commit timestamp is %s' , newest_datetime )
if newest_datetime is None :
    raise RuntimeError ( 'No content files found in {}' . format ( root_dir ) )
return newest_datetime


signature:
def _iter_filepaths_with_extension ( extname , root_dir = '.' ) :
    """Iterative over relative filepaths of files in a directory , and
 sub - directories , with the given extension .
 Parameters
 extname : ` str `
 Extension name ( such as ' txt ' or ' rst ' ) . Extension comparison is
 case sensitive .
 root _ dir : ' str ` , optional
 Root directory . Current working directory by default .
 Yields
 filepath : ` str `
 File path , relative to ` ` root _ dir ` ` , with the given extension ."""

implementation:
# needed for comparison with os . path . splitext
if not extname . startswith ( '.' ) :
    extname = '.' + extname
root_dir = os . path . abspath ( root_dir )
for dirname , sub_dirnames , filenames in os . walk ( root_dir ) :
    for filename in filenames :
        if os . path . splitext ( filename ) [ - 1 ] == extname :
            full_filename = os . path . join ( dirname , filename )
            rel_filepath = os . path . relpath ( full_filename , start = root_dir )
            yield rel_filepath


signature:
def get_variables_by_attributes ( self , ** kwargs ) :
    """Returns variables that match specific conditions .
 * Can pass in key = value parameters and variables are returned that
 contain all of the matches . For example ,
 > > > # Get variables with x - axis attribute .
 > > > vs = nc . get _ variables _ by _ attributes ( axis = ' X ' )
 > > > # Get variables with matching " standard _ name " attribute .
 > > > nc . get _ variables _ by _ attributes ( standard _ name = ' northward _ sea _ water _ velocity ' )
 * Can pass in key = callable parameter and variables are returned if the
 callable returns True . The callable should accept a single parameter ,
 the attribute value . None is given as the attribute value when the
 attribute does not exist on the variable . For example ,
 > > > # Get Axis variables .
 > > > vs = nc . get _ variables _ by _ attributes ( axis = lambda v : v in [ ' X ' , ' Y ' , ' Z ' , ' T ' ] )
 > > > # Get variables that don ' t have an " axis " attribute .
 > > > vs = nc . get _ variables _ by _ attributes ( axis = lambda v : v is None )
 > > > # Get variables that have a " grid _ mapping " attribute .
 > > > vs = nc . get _ variables _ by _ attributes ( grid _ mapping = lambda v : v is not None )"""

implementation:
vs = [ ]
has_value_flag = False
for vname in self . variables :
    var = self . variables [ vname ]
    for k , v in kwargs . items ( ) :
        if callable ( v ) :
            has_value_flag = v ( getattr ( var , k , None ) )
            if has_value_flag is False :
                break
        elif hasattr ( var , k ) and getattr ( var , k ) == v :
            has_value_flag = True
        else :
            has_value_flag = False
            break
    if has_value_flag is True :
        vs . append ( self . variables [ vname ] )
return vs


signature:
def json_attributes ( self , vfuncs = None ) :
    """vfuncs can be any callable that accepts a single argument , the
 Variable object , and returns a dictionary of new attributes to
 set . These will overwrite existing attributes"""

implementation:
vfuncs = vfuncs or [ ]
js = { 'global' : { } }
for k in self . ncattrs ( ) :
    js [ 'global' ] [ k ] = self . getncattr ( k )
for varname , var in self . variables . items ( ) :
    js [ varname ] = { }
    for k in var . ncattrs ( ) :
        z = var . getncattr ( k )
        try :
            assert not np . isnan ( z ) . all ( )
            js [ varname ] [ k ] = z
        except AssertionError :
            js [ varname ] [ k ] = None
        except TypeError :
            js [ varname ] [ k ] = z
    for vf in vfuncs :
        try :
            js [ varname ] . update ( vfuncs ( var ) )
        except BaseException :
            logger . exception ( "Could not apply custom variable attribue function" )
return json . loads ( json . dumps ( js , cls = BasicNumpyEncoder ) )


signature:
def ensure_pandoc ( func ) :
    """Decorate a function that uses pypandoc to ensure that pandoc is
 installed if necessary ."""

implementation:
logger = logging . getLogger ( __name__ )
@ functools . wraps ( func )
def _install_and_run ( * args , ** kwargs ) :
    try : # First try to run pypandoc function
        result = func ( * args , ** kwargs )
    except OSError : # Install pandoc and retry
        message = "pandoc needed but not found. Now installing it for you."
        logger . warning ( message )
        # This version of pandoc is known to be compatible with both
        # pypandoc . download _ pandoc and the functionality that
        # lsstprojectmeta needs . Travis CI tests are useful for ensuring
        # download _ pandoc works .
        pypandoc . download_pandoc ( version = '1.19.1' )
        logger . debug ( "pandoc download complete" )
        result = func ( * args , ** kwargs )
    return result
return _install_and_run


signature:
def convert_text ( content , from_fmt , to_fmt , deparagraph = False , mathjax = False , smart = True , extra_args = None ) :
    """Convert text from one markup format to another using pandoc .
 This function is a thin wrapper around ` pypandoc . convert _ text ` .
 Parameters
 content : ` str `
 Original content .
 from _ fmt : ` str `
 Format of the original ` ` content ` ` . Format identifier must be one of
 those known by Pandoc . See https : / / pandoc . org / MANUAL . html for details .
 to _ fmt : ` str `
 Output format for the content .
 deparagraph : ` bool ` , optional
 If ` True ` , then the
 ` lsstprojectmeta . pandoc . filters . deparagraph . deparagraph ` filter is
 used to remove paragraph ( ` ` < p > ` ` , for example ) tags around a single
 paragraph of content . That filter does not affect content that
 consists of multiple blocks ( several paragraphs , or lists , for
 example ) . Default is ` False ` .
 For example , * * without * * this filter Pandoc will convert
 the string ` ` " Title text " ` ` to ` ` " < p > Title text < / p > " ` ` in HTML . The
 paragraph tags aren ' t useful if you intend to wrap the converted
 content in different tags , like ` ` < h1 > ` ` , using your own templating
 system .
 * * With * * this filter , Pandoc will convert the string ` ` " Title text " ` `
 to ` ` " Title text " ` ` in HTML .
 mathjax : ` bool ` , optional
 If ` True ` then Pandoc will markup output content to work with MathJax .
 Default is False .
 smart : ` bool ` , optional
 If ` True ` ( default ) then ascii characters will be converted to unicode
 characters like smart quotes and em dashes .
 extra _ args : ` list ` , optional
 Sequence of Pandoc arguments command line arguments ( such as
 ` ` ' - - normalize ' ` ` ) . The ` ` deparagraph ` ` , ` ` mathjax ` ` , and ` ` smart ` `
 arguments are convenience arguments that are equivalent to items
 in ` ` extra _ args ` ` .
 Returns
 output : ` str `
 Content in the output ( ` ` to _ fmt ` ` ) format .
 Notes
 This function will automatically install Pandoc if it is not available .
 See ` ensure _ pandoc ` ."""

implementation:
logger = logging . getLogger ( __name__ )
if extra_args is not None :
    extra_args = list ( extra_args )
else :
    extra_args = [ ]
if mathjax :
    extra_args . append ( '--mathjax' )
if smart :
    extra_args . append ( '--smart' )
if deparagraph :
    extra_args . append ( '--filter=lsstprojectmeta-deparagraph' )
extra_args . append ( '--wrap=none' )
# de - dupe extra args
extra_args = set ( extra_args )
logger . debug ( 'Running pandoc from %s to %s with extra_args %s' , from_fmt , to_fmt , extra_args )
output = pypandoc . convert_text ( content , to_fmt , format = from_fmt , extra_args = extra_args )
return output


signature:
def convert_lsstdoc_tex ( content , to_fmt , deparagraph = False , mathjax = False , smart = True , extra_args = None ) :
    """Convert lsstdoc - class LaTeX to another markup format .
 This function is a thin wrapper around ` convert _ text ` that automatically
 includes common lsstdoc LaTeX macros .
 Parameters
 content : ` str `
 Original content .
 to _ fmt : ` str `
 Output format for the content ( see https : / / pandoc . org / MANUAL . html ) .
 For example , ' html5 ' .
 deparagraph : ` bool ` , optional
 If ` True ` , then the
 ` lsstprojectmeta . pandoc . filters . deparagraph . deparagraph ` filter is
 used to remove paragraph ( ` ` < p > ` ` , for example ) tags around a single
 paragraph of content . That filter does not affect content that
 consists of multiple blocks ( several paragraphs , or lists , for
 example ) . Default is ` False ` .
 For example , * * without * * this filter Pandoc will convert
 the string ` ` " Title text " ` ` to ` ` " < p > Title text < / p > " ` ` in HTML . The
 paragraph tags aren ' t useful if you intend to wrap the converted
 content in different tags , like ` ` < h1 > ` ` , using your own templating
 system .
 * * With * * this filter , Pandoc will convert the string ` ` " Title text " ` `
 to ` ` " Title text " ` ` in HTML .
 mathjax : ` bool ` , optional
 If ` True ` then Pandoc will markup output content to work with MathJax .
 Default is False .
 smart : ` bool ` , optional
 If ` True ` ( default ) then ascii characters will be converted to unicode
 characters like smart quotes and em dashes .
 extra _ args : ` list ` , optional
 Sequence of Pandoc arguments command line arguments ( such as
 ` ` ' - - normalize ' ` ` ) . The ` ` deparagraph ` ` , ` ` mathjax ` ` , and ` ` smart ` `
 arguments are convenience arguments that are equivalent to items
 in ` ` extra _ args ` ` .
 Returns
 output : ` str `
 Content in the output ( ` ` to _ fmt ` ` ) format .
 Notes
 This function will automatically install Pandoc if it is not available .
 See ` ensure _ pandoc ` ."""

implementation:
augmented_content = '\n' . join ( ( LSSTDOC_MACROS , content ) )
return convert_text ( augmented_content , 'latex' , to_fmt , deparagraph = deparagraph , mathjax = mathjax , smart = smart , extra_args = extra_args )


signature:
def decode_jsonld ( jsonld_text ) :
    """Decode a JSON - LD dataset , including decoding datetime
 strings into ` datetime . datetime ` objects .
 Parameters
 encoded _ dataset : ` str `
 The JSON - LD dataset encoded as a string .
 Returns
 jsonld _ dataset : ` dict `
 A JSON - LD dataset .
 Examples
 > > > doc = ' { " dt " : " 2018-01-01T12:00:00Z " } '
 > > > decode _ jsonld ( doc )
 { ' dt ' : datetime . datetime ( 2018 , 1 , 1 , 12 , 0 , tzinfo = datetime . timezone . utc ) }"""

implementation:
decoder = json . JSONDecoder ( object_pairs_hook = _decode_object_pairs )
return decoder . decode ( jsonld_text )


signature:
def default ( self , obj ) :
    """Encode values as JSON strings .
 This method overrides the default implementation from
 ` json . JSONEncoder ` ."""

implementation:
if isinstance ( obj , datetime . datetime ) :
    return self . _encode_datetime ( obj )
# Fallback to the default encoding
return json . JSONEncoder . default ( self , obj )


signature:
def _encode_datetime ( self , dt ) :
    """Encode a datetime in the format ' % Y - % m - % dT % H : % M : % SZ ' .
 The datetime can be naieve ( doesn ' t have timezone info ) or aware
 ( it does have a tzinfo attribute set ) . Regardless , the datetime
 is transformed into UTC ."""

implementation:
if dt . tzinfo is None : # Force it to be a UTC datetime
    dt = dt . replace ( tzinfo = datetime . timezone . utc )
# Convert to UTC ( no matter what )
dt = dt . astimezone ( datetime . timezone . utc )
return dt . strftime ( '%Y-%m-%dT%H:%M:%SZ' )


signature:
def find_repos ( self , depth = 10 ) :
    '''Get all git repositories within this environment'''

implementation:
repos = [ ]
for root , subdirs , files in walk_dn ( self . root , depth = depth ) :
    if 'modules' in root :
        continue
    if '.git' in subdirs :
        repos . append ( root )
return repos


signature:
def clone ( self , repo_path , destination , branch = None ) :
    '''Clone a repository to a destination relative to envrionment root'''

implementation:
logger . debug ( 'Installing ' + repo_path )
if not destination . startswith ( self . env_path ) :
    destination = unipath ( self . env_path , destination )
if branch :
    return shell . run ( 'git' , 'clone' , repo_path , '--branch' , branch , '--single-branch' , '--recursive' , destination )
return shell . run ( 'git' , 'clone' , '--recursive' , repo_path , destination )


signature:
def pull ( self , repo_path , * args ) :
    '''Clone a repository to a destination relative to envrionment root'''

implementation:
logger . debug ( 'Pulling ' + repo_path )
if not repo_path . startswith ( self . env_path ) :
    repo_path = unipath ( self . env_path , repo_path )
return shell . run ( 'git' , 'pull' , * args , ** { 'cwd' : repo_path } )


signature:
def install ( self , package ) :
    '''Install a python package using pip'''

implementation:
logger . debug ( 'Installing ' + package )
shell . run ( self . pip_path , 'install' , package )


signature:
def upgrade ( self , package ) :
    '''Update a python package using pip'''

implementation:
logger . debug ( 'Upgrading ' + package )
shell . run ( self . pip_path , 'install' , '--upgrade' , '--no-deps' , package )
shell . run ( self . pip_path , 'install' , package )


signature:
def df_quantile ( df , nb = 100 ) :
    """Returns the nb quantiles for datas in a dataframe"""

implementation:
quantiles = np . linspace ( 0 , 1. , nb )
res = pd . DataFrame ( )
for q in quantiles :
    res = res . append ( df . quantile ( q ) , ignore_index = True )
return res


signature:
def mean ( a , rep = 0.75 , ** kwargs ) :
    """Compute the average along a 1D array like ma . mean ,
 but with a representativity coefficient : if ma . count ( a ) / ma . size ( a ) > = rep ,
 then the result is a masked value"""

implementation: return rfunc ( a , ma . mean , rep , ** kwargs )


signature:
def max ( a , rep = 0.75 , ** kwargs ) :
    """Compute the max along a 1D array like ma . mean ,
 but with a representativity coefficient : if ma . count ( a ) / ma . size ( a ) > = rep ,
 then the result is a masked value"""

implementation: return rfunc ( a , ma . max , rep , ** kwargs )


signature:
def min ( a , rep = 0.75 , ** kwargs ) :
    """Compute the min along a 1D array like ma . mean ,
 but with a representativity coefficient : if ma . count ( a ) / ma . size ( a ) > = rep ,
 then the result is a masked value"""

implementation: return rfunc ( a , ma . min , rep , ** kwargs )


signature:
def rfunc ( a , rfunc = None , rep = 0.75 , ** kwargs ) :
    """Applies func on a if a comes with a representativity coefficient rep ,
 i . e . ma . count ( a ) / ma . size ( a ) > = rep . If not , returns a masked array"""

implementation:
if float ( ma . count ( a ) ) / ma . size ( a ) < rep :
    return ma . masked
else :
    if rfunc is None :
        return a
    return rfunc ( a , ** kwargs )


signature:
def rmse ( a , b ) :
    """Returns the root mean square error betwwen a and b"""

implementation: return np . sqrt ( np . square ( a - b ) . mean ( ) )


signature:
def nmse ( a , b ) :
    """Returns the normalized mean square error of a and b"""

implementation: return np . square ( a - b ) . mean ( ) / ( a . mean ( ) * b . mean ( ) )


signature:
def mfbe ( a , b ) :
    """Returns the mean fractionalized bias error"""

implementation: return 2 * bias ( a , b ) / ( a . mean ( ) + b . mean ( ) )


signature:
def fa ( a , b , alpha = 2 ) :
    """Returns the factor of ' alpha ' ( 2 or 5 normally )"""

implementation: return np . sum ( ( a > b / alpha ) & ( a < b * alpha ) , dtype = float ) / len ( a ) * 100


signature:
def foex ( a , b ) :
    """Returns the factor of exceedance"""

implementation: return ( np . sum ( a > b , dtype = float ) / len ( a ) - 0.5 ) * 100


signature:
def correlation ( a , b ) :
    """Computes the correlation between a and b , says the Pearson ' s correlation
 coefficient R"""

implementation:
diff1 = a - a . mean ( )
diff2 = b - b . mean ( )
return ( diff1 * diff2 ) . mean ( ) / ( np . sqrt ( np . square ( diff1 ) . mean ( ) * np . square ( diff2 ) . mean ( ) ) )


signature:
def gmb ( a , b ) :
    """Geometric mean bias"""

implementation: return np . exp ( np . log ( a ) . mean ( ) - np . log ( b ) . mean ( ) )


signature:
def gmv ( a , b ) :
    """Geometric mean variance"""

implementation: return np . exp ( np . square ( np . log ( a ) - np . log ( b ) ) . mean ( ) )


signature:
def fmt ( a , b ) :
    """Figure of merit in time"""

implementation: return 100 * np . min ( [ a , b ] , axis = 0 ) . sum ( ) / np . max ( [ a , b ] , axis = 0 ) . sum ( )


signature:
def fullStats ( a , b ) :
    """Performs several stats on a against b , typically a is the predictions
 array , and b the observations array
 Returns :
 A dataFrame of stat name , stat description , result"""

implementation:
stats = [ [ 'bias' , 'Bias' , bias ( a , b ) ] , [ 'stderr' , 'Standard Deviation Error' , stderr ( a , b ) ] , [ 'mae' , 'Mean Absolute Error' , mae ( a , b ) ] , [ 'rmse' , 'Root Mean Square Error' , rmse ( a , b ) ] , [ 'nmse' , 'Normalized Mean Square Error' , nmse ( a , b ) ] , [ 'mfbe' , 'Mean Fractionalized bias Error' , mfbe ( a , b ) ] , [ 'fa2' , 'Factor of Two' , fa ( a , b , 2 ) ] , [ 'foex' , 'Factor of Exceedance' , foex ( a , b ) ] , [ 'correlation' , 'Correlation R' , correlation ( a , b ) ] , [ 'determination' , 'Coefficient of Determination r2' , determination ( a , b ) ] , [ 'gmb' , 'Geometric Mean Bias' , gmb ( a , b ) ] , [ 'gmv' , 'Geometric Mean Variance' , gmv ( a , b ) ] , [ 'fmt' , 'Figure of Merit in Time' , fmt ( a , b ) ] ]
rec = np . rec . fromrecords ( stats , names = ( 'stat' , 'description' , 'result' ) )
df = pd . DataFrame . from_records ( rec , index = 'stat' )
return df


signature:
def site_path ( self ) :
    '''Path to environments site - packages'''

implementation:
if platform == 'win' :
    return unipath ( self . path , 'Lib' , 'site-packages' )
py_ver = 'python{0}' . format ( sys . version [ : 3 ] )
return unipath ( self . path , 'lib' , py_ver , 'site-packages' )


signature:
def _pre_activate ( self ) :
    '''Prior to activating , store everything necessary to deactivate this
 environment .'''

implementation:
if 'CPENV_CLEAN_ENV' not in os . environ :
    if platform == 'win' :
        os . environ [ 'PROMPT' ] = '$P$G'
    else :
        os . environ [ 'PS1' ] = '\\u@\\h:\\w\\$'
    clean_env_path = utils . get_store_env_tmp ( )
    os . environ [ 'CPENV_CLEAN_ENV' ] = clean_env_path
    utils . store_env ( path = clean_env_path )
else :
    utils . restore_env_from_file ( os . environ [ 'CPENV_CLEAN_ENV' ] )


signature:
def _activate ( self ) :
    '''Do some serious mangling to the current python environment . . .
 This is necessary to activate an environment via python .'''

implementation:
old_syspath = set ( sys . path )
site . addsitedir ( self . site_path )
site . addsitedir ( self . bin_path )
new_syspaths = set ( sys . path ) - old_syspath
for path in new_syspaths :
    sys . path . remove ( path )
    sys . path . insert ( 1 , path )
if not hasattr ( sys , 'real_prefix' ) :
    sys . real_prefix = sys . prefix
sys . prefix = self . path


signature:
def remove ( self ) :
    '''Remove this environment'''

implementation:
self . run_hook ( 'preremove' )
utils . rmtree ( self . path )
self . run_hook ( 'postremove' )


signature:
def command ( self ) :
    '''Command used to launch this application module'''

implementation:
cmd = self . config . get ( 'command' , None )
if cmd is None :
    return
cmd = cmd [ platform ]
return cmd [ 'path' ] , cmd [ 'args' ]


signature:
def create ( name_or_path = None , config = None ) :
    '''Create a virtual environment . You can pass either the name of a new
 environment to create in your CPENV _ HOME directory OR specify a full path
 to create an environment outisde your CPENV _ HOME .
 Create an environment in CPENV _ HOME : :
 > > > cpenv . create ( ' myenv ' )
 Create an environment elsewhere : :
 > > > cpenv . create ( ' ~ / custom _ location / myenv ' )
 : param name _ or _ path : Name or full path of environment
 : param config : Environment configuration including dependencies etc . . .'''

implementation:
# Get the real path of the environment
if utils . is_system_path ( name_or_path ) :
    path = unipath ( name_or_path )
else :
    path = unipath ( get_home_path ( ) , name_or_path )
if os . path . exists ( path ) :
    raise OSError ( '{} already exists' . format ( path ) )
env = VirtualEnvironment ( path )
utils . ensure_path_exists ( env . path )
if config :
    if utils . is_git_repo ( config ) :
        Git ( '' ) . clone ( config , env . path )
    else :
        shutil . copy2 ( config , env . config_path )
else :
    with open ( env . config_path , 'w' ) as f :
        f . write ( defaults . environment_config )
utils . ensure_path_exists ( env . hook_path )
utils . ensure_path_exists ( env . modules_path )
env . run_hook ( 'precreate' )
virtualenv . create_environment ( env . path )
if not utils . is_home_environment ( env . path ) :
    EnvironmentCache . add ( env )
    EnvironmentCache . save ( )
try :
    env . update ( )
except :
    utils . rmtree ( path )
    logger . debug ( 'Failed to update, rolling back...' )
    raise
else :
    env . run_hook ( 'postcreate' )
return env


signature:
def remove ( name_or_path ) :
    '''Remove an environment or module
 : param name _ or _ path : name or path to environment or module'''

implementation:
r = resolve ( name_or_path )
r . resolved [ 0 ] . remove ( )
EnvironmentCache . discard ( r . resolved [ 0 ] )
EnvironmentCache . save ( )


signature:
def launch ( module_name , * args , ** kwargs ) :
    '''Activates and launches a module
 : param module _ name : name of module to launch'''

implementation:
r = resolve ( module_name )
r . activate ( )
mod = r . resolved [ 0 ]
mod . launch ( * args , ** kwargs )


signature:
def deactivate ( ) :
    '''Deactivates an environment by restoring all env vars to a clean state
 stored prior to activating environments'''

implementation:
if 'CPENV_ACTIVE' not in os . environ or 'CPENV_CLEAN_ENV' not in os . environ :
    raise EnvironmentError ( 'Can not deactivate environment...' )
utils . restore_env_from_file ( os . environ [ 'CPENV_CLEAN_ENV' ] )


signature:
def get_home_path ( ) :
    ''': returns : your home path . . . CPENV _ HOME env var OR ~ / . cpenv'''

implementation:
home = unipath ( os . environ . get ( 'CPENV_HOME' , '~/.cpenv' ) )
home_modules = unipath ( home , 'modules' )
if not os . path . exists ( home ) :
    os . makedirs ( home )
if not os . path . exists ( home_modules ) :
    os . makedirs ( home_modules )
return home


signature:
def get_module_paths ( ) :
    ''': returns : paths in CPENV _ MODULES env var and CPENV _ HOME / modules'''

implementation:
module_paths = [ ]
cpenv_modules_path = os . environ . get ( 'CPENV_MODULES' , None )
if cpenv_modules_path :
    module_paths . extend ( cpenv_modules_path . split ( os . pathsep ) )
module_paths . append ( unipath ( get_home_path ( ) , 'modules' ) )
return module_paths


signature:
def get_environments ( ) :
    '''Returns a list of all known virtual environments as
 : class : ` VirtualEnvironment ` instances . This includes those in CPENV _ HOME
 and any others that are cached ( created by the current user or activated
 once by full path . )'''

implementation:
environments = set ( )
cwd = os . getcwd ( )
for d in os . listdir ( cwd ) :
    if d == 'environment.yml' :
        environments . add ( VirtualEnvironment ( cwd ) )
        continue
    path = unipath ( cwd , d )
    if utils . is_environment ( path ) :
        environments . add ( VirtualEnvironment ( path ) )
home = get_home_path ( )
for d in os . listdir ( home ) :
    path = unipath ( home , d )
    if utils . is_environment ( path ) :
        environments . add ( VirtualEnvironment ( path ) )
for env in EnvironmentCache :
    environments . add ( env )
return sorted ( list ( environments ) , key = lambda x : x . name )


signature:
def get_modules ( ) :
    '''Returns a list of available modules .'''

implementation:
modules = set ( )
cwd = os . getcwd ( )
for d in os . listdir ( cwd ) :
    if d == 'module.yml' :
        modules . add ( Module ( cwd ) )
    path = unipath ( cwd , d )
    if utils . is_module ( path ) :
        modules . add ( Module ( cwd ) )
module_paths = get_module_paths ( )
for module_path in module_paths :
    for d in os . listdir ( module_path ) :
        path = unipath ( module_path , d )
        if utils . is_module ( path ) :
            modules . add ( Module ( path ) )
return sorted ( list ( modules ) , key = lambda x : x . name )


signature:
def get_active_modules ( ) :
    ''': returns : a list of active : class : ` Module ` s or [ ]'''

implementation:
modules = os . environ . get ( 'CPENV_ACTIVE_MODULES' , None )
if modules :
    modules = modules . split ( os . pathsep )
    return [ Module ( module ) for module in modules ]
return [ ]


signature:
def add_active_module ( module ) :
    '''Add a module to CPENV _ ACTIVE _ MODULES environment variable'''

implementation:
modules = set ( get_active_modules ( ) )
modules . add ( module )
new_modules_path = os . pathsep . join ( [ m . path for m in modules ] )
os . environ [ 'CPENV_ACTIVE_MODULES' ] = str ( new_modules_path )


signature:
def rem_active_module ( module ) :
    '''Remove a module from CPENV _ ACTIVE _ MODULES environment variable'''

implementation:
modules = set ( get_active_modules ( ) )
modules . discard ( module )
new_modules_path = os . pathsep . join ( [ m . path for m in modules ] )
os . environ [ 'CPENV_ACTIVE_MODULES' ] = str ( new_modules_path )


signature:
def format_objects ( objects , children = False , columns = None , header = True ) :
    '''Format a list of environments and modules for terminal output'''

implementation:
columns = columns or ( 'NAME' , 'TYPE' , 'PATH' )
objects = sorted ( objects , key = _type_and_name )
data = [ ]
for obj in objects :
    if isinstance ( obj , cpenv . VirtualEnvironment ) :
        data . append ( get_info ( obj ) )
        modules = obj . get_modules ( )
        if children and modules :
            for mod in modules :
                data . append ( get_info ( mod , indent = 2 , root = obj . path ) )
    else :
        data . append ( get_info ( obj ) )
maxes = [ len ( max ( col , key = len ) ) for col in zip ( * data ) ]
tmpl = '{:%d}  {:%d}  {:%d}' % tuple ( maxes )
lines = [ ]
if header :
    lines . append ( '\n' + bold_blue ( tmpl . format ( * columns ) ) )
for obj_data in data :
    lines . append ( tmpl . format ( * obj_data ) )
return '\n' . join ( lines )


signature:
def info ( ) :
    '''Show context info'''

implementation:
env = cpenv . get_active_env ( )
modules = [ ]
if env :
    modules = env . get_modules ( )
active_modules = cpenv . get_active_modules ( )
if not env and not modules and not active_modules :
    click . echo ( '\nNo active modules...' )
    return
click . echo ( bold ( '\nActive modules' ) )
if env :
    click . echo ( format_objects ( [ env ] + active_modules ) )
    available_modules = set ( modules ) - set ( active_modules )
    if available_modules :
        click . echo ( bold ( '\nInactive modules in {}\n' ) . format ( cyan ( env . name ) ) )
        click . echo ( format_objects ( available_modules , header = False ) )
else :
    click . echo ( format_objects ( active_modules ) )
available_shared_modules = set ( cpenv . get_modules ( ) ) - set ( active_modules )
if not available_shared_modules :
    return
click . echo ( bold ( '\nInactive shared modules \n' ) )
click . echo ( format_objects ( available_shared_modules , header = False ) )


signature:
def list_ ( ) :
    '''List available environments and modules'''

implementation:
environments = cpenv . get_environments ( )
modules = cpenv . get_modules ( )
click . echo ( format_objects ( environments + modules , children = True ) )


signature:
def activate ( paths , skip_local , skip_shared ) :
    '''Activate an environment'''

implementation:
if not paths :
    ctx = click . get_current_context ( )
    if cpenv . get_active_env ( ) :
        ctx . invoke ( info )
        return
    click . echo ( ctx . get_help ( ) )
    examples = ( '\nExamples: \n' '    cpenv activate my_env\n' '    cpenv activate ./relative/path/to/my_env\n' '    cpenv activate my_env my_module\n' )
    click . echo ( examples )
    return
if skip_local :
    cpenv . module_resolvers . remove ( cpenv . resolver . module_resolver )
    cpenv . module_resolvers . remove ( cpenv . resolver . active_env_module_resolver )
if skip_shared :
    cpenv . module_resolvers . remove ( cpenv . resolver . modules_path_resolver )
try :
    r = cpenv . resolve ( * paths )
except cpenv . ResolveError as e :
    click . echo ( '\n' + str ( e ) )
    return
resolved = set ( r . resolved )
active_modules = set ( )
env = cpenv . get_active_env ( )
if env :
    active_modules . add ( env )
active_modules . update ( cpenv . get_active_modules ( ) )
new_modules = resolved - active_modules
old_modules = active_modules & resolved
if old_modules and not new_modules :
    click . echo ( '\nModules already active: ' + bold ( ' ' . join ( [ obj . name for obj in old_modules ] ) ) )
    return
if env and contains_env ( new_modules ) :
    click . echo ( '\nUse bold(exit) to leave your active environment first.' )
    return
click . echo ( '\nResolved the following modules...' )
click . echo ( format_objects ( r . resolved ) )
r . activate ( )
click . echo ( blue ( '\nLaunching subshell...' ) )
modules = sorted ( resolved | active_modules , key = _type_and_name )
prompt = ':' . join ( [ obj . name for obj in modules ] )
shell . launch ( prompt )


signature:
def create ( name_or_path , config ) :
    '''Create a new environment .'''

implementation:
if not name_or_path :
    ctx = click . get_current_context ( )
    click . echo ( ctx . get_help ( ) )
    examples = ( '\nExamples:\n' '    cpenv create my_env\n' '    cpenv create ./relative/path/to/my_env\n' '    cpenv create my_env --config ./relative/path/to/config\n' '    cpenv create my_env --config git@github.com:user/config.git\n' )
    click . echo ( examples )
    return
click . echo ( blue ( 'Creating a new virtual environment ' + name_or_path ) )
try :
    env = cpenv . create ( name_or_path , config )
except Exception as e :
    click . echo ( bold_red ( 'FAILED TO CREATE ENVIRONMENT!' ) )
    click . echo ( e )
else :
    click . echo ( bold_green ( 'Successfully created environment!' ) )
click . echo ( blue ( 'Launching subshell' ) )
cpenv . activate ( env )
shell . launch ( env . name )


signature:
def remove ( name_or_path ) :
    '''Remove an environment'''

implementation:
click . echo ( )
try :
    r = cpenv . resolve ( name_or_path )
except cpenv . ResolveError as e :
    click . echo ( e )
    return
obj = r . resolved [ 0 ]
if not isinstance ( obj , cpenv . VirtualEnvironment ) :
    click . echo ( '{} is a module. Use `cpenv module remove` instead.' )
    return
click . echo ( format_objects ( [ obj ] ) )
click . echo ( )
user_confirmed = click . confirm ( red ( 'Are you sure you want to remove this environment?' ) )
if user_confirmed :
    click . echo ( 'Attempting to remove...' , nl = False )
    try :
        obj . remove ( )
    except Exception as e :
        click . echo ( bold_red ( 'FAIL' ) )
        click . echo ( e )
    else :
        click . echo ( bold_green ( 'OK!' ) )


implementation:
click . echo ( 'Cached Environments' )
environments = list ( EnvironmentCache )
click . echo ( format_objects ( environments , children = False ) )


signature:
def add ( path ) :
    '''Add an environment to the cache . Allows you to activate the environment
 by name instead of by full path'''

implementation:
click . echo ( '\nAdding {} to cache......' . format ( path ) , nl = False )
try :
    r = cpenv . resolve ( path )
except Exception as e :
    click . echo ( bold_red ( 'FAILED' ) )
    click . echo ( e )
    return
if isinstance ( r . resolved [ 0 ] , cpenv . VirtualEnvironment ) :
    EnvironmentCache . add ( r . resolved [ 0 ] )
    EnvironmentCache . save ( )
    click . echo ( bold_green ( 'OK!' ) )


signature:
def remove ( path ) :
    '''Remove a cached environment . Removed paths will no longer be able to
 be activated by name'''

implementation:
r = cpenv . resolve ( path )
if isinstance ( r . resolved [ 0 ] , cpenv . VirtualEnvironment ) :
    EnvironmentCache . discard ( r . resolved [ 0 ] )
    EnvironmentCache . save ( )


signature:
def create ( name_or_path , config ) :
    '''Create a new template module .
 You can also specify a filesystem path like " . / modules / new _ module "'''

implementation:
click . echo ( 'Creating module {}...' . format ( name_or_path ) , nl = False )
try :
    module = cpenv . create_module ( name_or_path , config )
except Exception as e :
    click . echo ( bold_red ( 'FAILED' ) )
    raise
else :
    click . echo ( bold_green ( 'OK!' ) )
    click . echo ( 'Browse to your new module and make some changes.' )
    click . echo ( "When you're ready add the module to an environment:" )
    click . echo ( '    cpenv module add my_module ./path/to/my_module' )
    click . echo ( 'Or track your module on git and add it directly from the repo:' )
    click . echo ( '    cpenv module add my_module git@github.com:user/my_module.git' )


signature:
def add ( name , path , branch , type ) :
    '''Add a module to an environment . PATH can be a git repository path or
 a filesystem path .'''

implementation:
if not name and not path :
    ctx = click . get_current_context ( )
    click . echo ( ctx . get_help ( ) )
    examples = ( '\nExamples:\n' '    cpenv module add my_module ./path/to/my_module\n' '    cpenv module add my_module git@github.com:user/my_module.git' '    cpenv module add my_module git@github.com:user/my_module.git --branch=master --type=shared' )
    click . echo ( examples )
    return
if not name :
    click . echo ( 'Missing required argument: name' )
    return
if not path :
    click . echo ( 'Missing required argument: path' )
env = cpenv . get_active_env ( )
if type == 'local' :
    if not env :
        click . echo ( '\nActivate an environment to add a local module.\n' )
        return
    if click . confirm ( '\nAdd {} to active env {}?' . format ( name , env . name ) ) :
        click . echo ( 'Adding module...' , nl = False )
        try :
            env . add_module ( name , path , branch )
        except :
            click . echo ( bold_red ( 'FAILED' ) )
            raise
        else :
            click . echo ( bold_green ( 'OK!' ) )
    return
module_paths = cpenv . get_module_paths ( )
click . echo ( '\nAvailable module paths:\n' )
for i , mod_path in enumerate ( module_paths ) :
    click . echo ( '    {}. {}' . format ( i , mod_path ) )
choice = click . prompt ( 'Where do you want to add your module?' , type = int , default = 0 )
module_root = module_paths [ choice ]
module_path = utils . unipath ( module_root , name )
click . echo ( 'Creating module {}...' . format ( module_path ) , nl = False )
try :
    cpenv . create_module ( module_path , path , branch )
except :
    click . echo ( bold_red ( 'FAILED' ) )
    raise
else :
    click . echo ( bold_green ( 'OK!' ) )


signature:
def remove ( name , local ) :
    '''Remove a module named NAME . Will remove the first resolved module named NAME . You can also specify a full path to a module . Use the - - local option
 to ensure removal of modules local to the currently active environment .'''

implementation:
click . echo ( )
if not local : # Use resolver to find module
    try :
        r = cpenv . resolve ( name )
    except cpenv . ResolveError as e :
        click . echo ( e )
        return
    obj = r . resolved [ 0 ]
else : # Try to find module in active environment
    env = cpenv . get_active_env ( )
    if not env :
        click . echo ( 'You must activate an env to remove local modules' )
        return
    mod = env . get_module ( name )
    if not mod :
        click . echo ( 'Failed to resolve module: ' + name )
        return
    obj = mod
if isinstance ( obj , cpenv . VirtualEnvironment ) :
    click . echo ( '{} is an environment. Use `cpenv remove` instead.' )
    return
click . echo ( format_objects ( [ obj ] ) )
click . echo ( )
user_confirmed = click . confirm ( red ( 'Are you sure you want to remove this module?' ) )
if user_confirmed :
    click . echo ( 'Attempting to remove...' , nl = False )
    try :
        obj . remove ( )
    except Exception as e :
        click . echo ( bold_red ( 'FAILED' ) )
        click . echo ( e )
    else :
        click . echo ( bold_green ( 'OK!' ) )


signature:
def localize ( name ) :
    '''Copy a global module to the active environment .'''

implementation:
env = cpenv . get_active_env ( )
if not env :
    click . echo ( 'You need to activate an environment first.' )
    return
try :
    r = cpenv . resolve ( name )
except cpenv . ResolveError as e :
    click . echo ( '\n' + str ( e ) )
module = r . resolved [ 0 ]
if isinstance ( module , cpenv . VirtualEnvironment ) :
    click . echo ( '\nCan only localize a module not an environment' )
    return
active_modules = cpenv . get_active_modules ( )
if module in active_modules :
    click . echo ( '\nCan not localize an active module.' )
    return
if module in env . get_modules ( ) :
    click . echo ( '\n{} is already local to {}' . format ( module . name , env . name ) )
    return
if click . confirm ( '\nAdd {} to env {}?' . format ( module . name , env . name ) ) :
    click . echo ( 'Adding module...' , nl = False )
    try :
        module = env . add_module ( module . name , module . path )
    except :
        click . echo ( bold_red ( 'FAILED' ) )
        raise
    else :
        click . echo ( bold_green ( 'OK!' ) )
click . echo ( '\nActivate the localize module:' )
click . echo ( '    cpenv activate {} {}' . format ( env . name , module . name ) )


signature:
def path_resolver ( resolver , path ) :
    '''Resolves VirtualEnvironments with a relative or absolute path'''

implementation:
path = unipath ( path )
if is_environment ( path ) :
    return VirtualEnvironment ( path )
raise ResolveError


signature:
def home_resolver ( resolver , path ) :
    '''Resolves VirtualEnvironments in CPENV _ HOME'''

implementation:
from . api import get_home_path
path = unipath ( get_home_path ( ) , path )
if is_environment ( path ) :
    return VirtualEnvironment ( path )
raise ResolveError


signature:
def cache_resolver ( resolver , path ) :
    '''Resolves VirtualEnvironments in EnvironmentCache'''

implementation:
env = resolver . cache . find ( path )
if env :
    return env
raise ResolveError


signature:
def module_resolver ( resolver , path ) :
    '''Resolves module in previously resolved environment .'''

implementation:
if resolver . resolved :
    if isinstance ( resolver . resolved [ 0 ] , VirtualEnvironment ) :
        env = resolver . resolved [ 0 ]
        mod = env . get_module ( path )
        if mod :
            return mod
raise ResolveError


signature:
def modules_path_resolver ( resolver , path ) :
    '''Resolves modules in CPENV _ MODULES path and CPENV _ HOME / modules'''

implementation:
from . api import get_module_paths
for module_dir in get_module_paths ( ) :
    mod_path = unipath ( module_dir , path )
    if is_module ( mod_path ) :
        return Module ( mod_path )
raise ResolveError


signature:
def active_env_module_resolver ( resolver , path ) :
    '''Resolves modules in currently active environment .'''

implementation:
from . api import get_active_env
env = get_active_env ( )
if not env :
    raise ResolveError
mod = env . get_module ( path )
if not mod :
    raise ResolveError
return mod


signature:
def redirect_resolver ( resolver , path ) :
    '''Resolves environment from . cpenv file . . . recursively walks up the tree
 in attempt to find a . cpenv file'''

implementation:
if not os . path . exists ( path ) :
    raise ResolveError
if os . path . isfile ( path ) :
    path = os . path . dirname ( path )
for root , _ , _ in walk_up ( path ) :
    if is_redirecting ( root ) :
        env_paths = redirect_to_env_paths ( unipath ( root , '.cpenv' ) )
        r = Resolver ( * env_paths )
        return r . resolve ( )
raise ResolveError


signature:
def _engine_affinity ( obj ) :
    """Which engine or engines are preferred for processing this object
 Returns : ( location , weight )
 location ( integer or tuple ) : engine id ( or in the case of a distributed
 array a tuple ( engine _ id _ list , distaxis ) ) .
 weight ( integer ) : Proportional to the cost of moving the object to a
 different engine . Currently just taken to be the size of data ."""

implementation:
from distob import engine
this_engine = engine . eid
if isinstance ( obj , numbers . Number ) or obj is None :
    return ( this_engine , 0 )
elif hasattr ( obj , '__engine_affinity__' ) : # This case includes Remote subclasses and DistArray
    return obj . __engine_affinity__
else :
    return ( this_engine , _rough_size ( obj ) )


signature:
def _ufunc_move_input ( obj , location , bshape ) :
    """Copy ufunc input ` obj ` to new engine location ( s ) unless obj is scalar .
 If the input is requested to be distributed to multiple engines , this
 function will also take care of broadcasting along the distributed axis .
 If the input obj is a scalar , it will be passed through unchanged .
 Args :
 obj ( array _ like or scalar ) : one of the inputs to a ufunc
 location ( integer or tuple ) : If an integer , this specifies a single
 engine id to which an array input should be moved . If it is a tuple ,
 location [ 0 ] is a list of engine ids for distributing the array input
 and location [ 1 ] an integer indicating which axis should be distributed .
 bshape ( tuple ) : The shape to which the input will ultimately be broadcast
 Returns :
 array _ like or RemoteArray or DistArray or scalar"""

implementation:
if ( not hasattr ( type ( obj ) , '__array_interface__' ) and not isinstance ( obj , Remote ) and ( isinstance ( obj , string_types ) or not isinstance ( obj , Sequence ) ) ) : # then treat it as a scalar
    return obj
from distob import engine
this_engine = engine . eid
if location == this_engine : # move obj to the local host , if not already here
    if isinstance ( obj , Remote ) or isinstance ( obj , DistArray ) :
        return gather ( obj )
    else :
        return obj
elif isinstance ( location , numbers . Integral ) : # move obj to a single remote engine
    if isinstance ( obj , Remote ) and obj . _ref . id . engine == location : # print ( ' no data movement needed ! ' )
        return obj
    obj = gather ( obj )
    return _directed_scatter ( obj , axis = None , destination = location )
else : # location is a tuple ( list of engine ids , distaxis ) indicating that
# obj should be distributed .
    engine_ids , distaxis = location
    if not isinstance ( obj , DistArray ) :
        gather ( obj )
        if isinstance ( obj , Sequence ) :
            obj = np . array ( obj )
    if obj . ndim < len ( bshape ) :
        ix = ( np . newaxis , ) * ( len ( bshape ) - obj . ndim ) + ( slice ( None ) , ) * obj . ndim
        obj = obj [ ix ]
    if ( isinstance ( obj , DistArray ) and distaxis == obj . _distaxis and engine_ids == [ ra . _ref . id . engine for ra in obj . _subarrays ] ) : # print ( ' no data movement needed ! ' )
        return obj
    obj = gather ( obj )
    if obj . shape [ distaxis ] == 1 : # broadcast this axis across engines
        subarrays = [ _directed_scatter ( obj , None , m ) for m in engine_ids ]
        return DistArray ( subarrays , distaxis )
    else :
        return _directed_scatter ( obj , distaxis , destination = engine_ids )


signature:
def transpose ( a , axes = None ) :
    """Returns a view of the array with axes transposed .
 For a 1 - D array , this has no effect .
 For a 2 - D array , this is the usual matrix transpose .
 For an n - D array , if axes are given , their order indicates how the
 axes are permuted
 Args :
 a ( array _ like ) : Input array .
 axes ( list of int , optional ) : By default , reverse the dimensions ,
 otherwise permute the axes according to the values given ."""

implementation:
if isinstance ( a , np . ndarray ) :
    return np . transpose ( a , axes )
elif isinstance ( a , RemoteArray ) :
    return a . transpose ( * axes )
elif isinstance ( a , Remote ) :
    return _remote_to_array ( a ) . transpose ( * axes )
elif isinstance ( a , DistArray ) :
    if axes is None :
        axes = range ( a . ndim - 1 , - 1 , - 1 )
    axes = list ( axes )
    if len ( set ( axes ) ) < len ( axes ) :
        raise ValueError ( "repeated axis in transpose" )
    if sorted ( axes ) != list ( range ( a . ndim ) ) :
        raise ValueError ( "axes don't match array" )
    distaxis = a . _distaxis
    new_distaxis = axes . index ( distaxis )
    new_subarrays = [ ra . transpose ( * axes ) for ra in a . _subarrays ]
    return DistArray ( new_subarrays , new_distaxis )
else :
    return np . transpose ( a , axes )


signature:
def rollaxis ( a , axis , start = 0 ) :
    """Roll the specified axis backwards , until it lies in a given position .
 Args :
 a ( array _ like ) : Input array .
 axis ( int ) : The axis to roll backwards . The positions of the other axes
 do not change relative to one another .
 start ( int , optional ) : The axis is rolled until it lies before this
 position . The default , 0 , results in a " complete " roll .
 Returns :
 res ( ndarray )"""

implementation:
if isinstance ( a , np . ndarray ) :
    return np . rollaxis ( a , axis , start )
if axis not in range ( a . ndim ) :
    raise ValueError ( 'rollaxis: axis (%d) must be >=0 and < %d' % ( axis , a . ndim ) )
if start not in range ( a . ndim + 1 ) :
    raise ValueError ( 'rollaxis: start (%d) must be >=0 and < %d' % ( axis , a . ndim + 1 ) )
axes = list ( range ( a . ndim ) )
axes . remove ( axis )
axes . insert ( start , axis )
return transpose ( a , axes )


signature:
def expand_dims ( a , axis ) :
    """Insert a new axis , corresponding to a given position in the array shape
 Args :
 a ( array _ like ) : Input array .
 axis ( int ) : Position ( amongst axes ) where new axis is to be inserted ."""

implementation:
if hasattr ( a , 'expand_dims' ) and hasattr ( type ( a ) , '__array_interface__' ) :
    return a . expand_dims ( axis )
else :
    return np . expand_dims ( a , axis )


signature:
def concatenate ( tup , axis = 0 ) :
    """Join a sequence of arrays together .
 Will aim to join ` ndarray ` , ` RemoteArray ` , and ` DistArray ` without moving
 their data , if they happen to be on different engines .
 Args :
 tup ( sequence of array _ like ) : Arrays to be concatenated . They must have
 the same shape , except in the dimension corresponding to ` axis ` .
 axis ( int , optional ) : The axis along which the arrays will be joined .
 Returns :
 res : ` ndarray ` , if inputs were all local
 ` RemoteArray ` , if inputs were all on the same remote engine
 ` DistArray ` , if inputs were already scattered on different engines"""

implementation:
from distob import engine
if len ( tup ) is 0 :
    raise ValueError ( 'need at least one array to concatenate' )
first = tup [ 0 ]
others = tup [ 1 : ]
# allow subclasses to provide their own implementations of concatenate :
if ( hasattr ( first , 'concatenate' ) and hasattr ( type ( first ) , '__array_interface__' ) ) :
    return first . concatenate ( others , axis )
# convert all arguments to arrays / RemoteArrays if they are not already :
arrays = [ ]
for ar in tup :
    if isinstance ( ar , DistArray ) :
        if axis == ar . _distaxis :
            arrays . extend ( ar . _subarrays )
        else : # Since not yet implemented arrays distributed on more than
        # one axis , will fetch and re - scatter on the new axis :
            arrays . append ( gather ( ar ) )
    elif isinstance ( ar , RemoteArray ) :
        arrays . append ( ar )
    elif isinstance ( ar , Remote ) :
        arrays . append ( _remote_to_array ( ar ) )
    elif hasattr ( type ( ar ) , '__array_interface__' ) : # then treat as a local ndarray
        arrays . append ( ar )
    else :
        arrays . append ( np . array ( ar ) )
if all ( isinstance ( ar , np . ndarray ) for ar in arrays ) :
    return np . concatenate ( arrays , axis )
total_length = 0
# validate dimensions are same , except for axis of concatenation :
commonshape = list ( arrays [ 0 ] . shape )
commonshape [ axis ] = None
# ignore this axis for shape comparison
for ar in arrays :
    total_length += ar . shape [ axis ]
    shp = list ( ar . shape )
    shp [ axis ] = None
    if shp != commonshape :
        raise ValueError ( 'incompatible shapes for concatenation' )
# set sensible target block size if splitting subarrays further :
blocksize = ( ( total_length - 1 ) // engine . nengines ) + 1
rarrays = [ ]
for ar in arrays :
    if isinstance ( ar , DistArray ) :
        rarrays . extend ( ar . _subarrays )
    elif isinstance ( ar , RemoteArray ) :
        rarrays . append ( ar )
    else :
        da = _scatter_ndarray ( ar , axis , blocksize )
        for ra in da . _subarrays :
            rarrays . append ( ra )
        del da
del arrays
# At this point rarrays is a list of RemoteArray to be concatenated
eid = rarrays [ 0 ] . _id . engine
if all ( ra . _id . engine == eid for ra in rarrays ) : # Arrays to be joined are all on the same engine
    if eid == engine . eid : # Arrays are all local
        return concatenate ( [ gather ( r ) for r in rarrays ] , axis )
    else :
        return call ( concatenate , rarrays , axis )
else : # Arrays to be joined are on different engines .
# TODO : consolidate any consecutive arrays already on same engine
    return DistArray ( rarrays , axis )


signature:
def vstack ( tup ) :
    """Stack arrays in sequence vertically ( row wise ) ,
 handling ` ` RemoteArray ` ` and ` ` DistArray ` ` without moving data .
 Args :
 tup ( sequence of array _ like )
 Returns :
 res : ` ndarray ` , if inputs were all local
 ` RemoteArray ` , if inputs were all on the same remote engine
 ` DistArray ` , if inputs were already scattered on different engines"""

implementation:
# Follow numpy . vstack behavior for 1D arrays :
arrays = list ( tup )
for i in range ( len ( arrays ) ) :
    if arrays [ i ] . ndim is 1 :
        arrays [ i ] = arrays [ i ] [ np . newaxis , : ]
return concatenate ( tup , axis = 0 )


signature:
def hstack ( tup ) :
    """Stack arrays in sequence horizontally ( column wise ) ,
 handling ` ` RemoteArray ` ` and ` ` DistArray ` ` without moving data .
 Args :
 tup ( sequence of array _ like )
 Returns :
 res : ` ndarray ` , if inputs were all local
 ` RemoteArray ` , if inputs were all on the same remote engine
 ` DistArray ` , if inputs were already scattered on different engines"""

implementation:
# Follow numpy . hstack behavior for 1D arrays :
if all ( ar . ndim is 1 for ar in tup ) :
    return concatenate ( tup , axis = 0 )
else :
    return concatenate ( tup , axis = 1 )


signature:
def dstack ( tup ) :
    """Stack arrays in sequence depth wise ( along third dimension ) ,
 handling ` ` RemoteArray ` ` and ` ` DistArray ` ` without moving data .
 Args :
 tup ( sequence of array _ like )
 Returns :
 res : ` ndarray ` , if inputs were all local
 ` RemoteArray ` , if inputs were all on the same remote engine
 ` DistArray ` , if inputs were already scattered on different engines"""

implementation:
# Follow numpy . dstack behavior for 1D and 2D arrays :
arrays = list ( tup )
for i in range ( len ( arrays ) ) :
    if arrays [ i ] . ndim is 1 :
        arrays [ i ] = arrays [ i ] [ np . newaxis , : ]
    if arrays [ i ] . ndim is 2 :
        arrays [ i ] = arrays [ i ] [ : , : , np . newaxis ]
return concatenate ( arrays , axis = 2 )


signature:
def _broadcast_shape ( * args ) :
    """Return the shape that would result from broadcasting the inputs"""

implementation:
# TODO : currently incorrect result if a Sequence is provided as an input
shapes = [ a . shape if hasattr ( type ( a ) , '__array_interface__' ) else ( ) for a in args ]
ndim = max ( len ( sh ) for sh in shapes )
# new common ndim after broadcasting
for i , sh in enumerate ( shapes ) :
    if len ( sh ) < ndim :
        shapes [ i ] = ( 1 , ) * ( ndim - len ( sh ) ) + sh
return tuple ( max ( sh [ ax ] for sh in shapes ) for ax in range ( ndim ) )


signature:
def mean ( a , axis = None , dtype = None , out = None , keepdims = False ) :
    """Compute the arithmetic mean along the specified axis .
 Returns the average of the array elements . The average is taken over
 the flattened array by default , otherwise over the specified axis .
 ` float64 ` intermediate and return values are used for integer inputs .
 Parameters
 a : array _ like
 Array containing numbers whose mean is desired . If ` a ` is not an
 array , a conversion is attempted .
 axis : None or int or tuple of ints , optional
 Axis or axes along which the means are computed . The default is to
 compute the mean of the flattened array .
 If this is a tuple of ints , a mean is performed over multiple axes ,
 instead of a single axis or all the axes as before .
 dtype : data - type , optional
 Type to use in computing the mean . For integer inputs , the default
 is ` float64 ` ; for floating point inputs , it is the same as the
 input dtype .
 out : ndarray , optional
 Alternate output array in which to place the result . The default
 is ` ` None ` ` ; if provided , it must have the same shape as the
 expected output , but the type will be cast if necessary .
 See ` doc . ufuncs ` for details .
 keepdims : bool , optional
 If this is set to True , the axes which are reduced are left
 in the result as dimensions with size one . With this option ,
 the result will broadcast correctly against the original ` arr ` .
 Returns
 m : ndarray , see dtype parameter above
 Notes
 np . mean fails to pass the keepdims parameter to ndarray subclasses .
 That is the main reason we implement this function ."""

implementation:
if ( isinstance ( a , np . ndarray ) or isinstance ( a , RemoteArray ) or isinstance ( a , DistArray ) ) :
    return a . mean ( axis = axis , dtype = dtype , out = out , keepdims = keepdims )
else :
    return np . mean ( a , axis = axis , dtype = dtype , out = out , keepdims = keepdims )


signature:
def _fetch ( self ) :
    """forces update of a local cached copy of the real object
 ( regardless of the preference setting self . cache )"""

implementation:
if not self . _obcache_current :
    from distob import engine
    ax = self . _distaxis
    self . _obcache = concatenate ( [ ra . _ob for ra in self . _subarrays ] , ax )
    # let subarray obcaches and main obcache be views on same memory :
    for i in range ( self . _n ) :
        ix = [ slice ( None ) ] * self . ndim
        ix [ ax ] = slice ( self . _si [ i ] , self . _si [ i + 1 ] )
        self . _subarrays [ i ] . _obcache = self . _obcache [ tuple ( ix ) ]
    self . _obcache_current = True
    # now prefer local processing :
    self . __engine_affinity__ = ( engine . eid , self . __engine_affinity__ [ 1 ] )


signature:
def _tosubslices ( self , sl ) :
    """Maps a slice object for whole array to slice objects for subarrays .
 Returns pair ( ss , ms ) where ss is a list of subarrays and ms is a list
 giving the slice object that should be applied to each subarray ."""

implementation:
N = self . shape [ self . _distaxis ]
start , stop , step = sl . start , sl . stop , sl . step
if step is None :
    step = 1
ss = [ ]
ms = [ ]
if step > 0 :
    if start is None :
        start = 0
    if stop is None :
        stop = N
    subs = range ( 0 , self . _n )
    for s in subs :
        low = self . _si [ s ]
        high = self . _si [ s + 1 ]
        first = low + ( ( low - start ) % step )
        last = high + ( ( high - start ) % step )
        if start < high and stop > low and first < high :
            ss . append ( s )
            substart = max ( first , start ) - low
            substop = min ( last , stop ) - low
            ms . append ( slice ( substart , substop , step ) )
elif step < 0 :
    if start is None :
        start = N - 1
    if stop is None :
        stop = - 1
    subs = range ( self . _n - 1 , - 1 , - 1 )
    for s in subs :
        low = self . _si [ s ]
        high = self . _si [ s + 1 ]
        first = high + step + ( ( high - start ) % step )
        last = low + step + ( ( low - start ) % step )
        if start >= low and stop < high and first >= low :
            ss . append ( s )
            substart = min ( first , start ) - low
            substop = max ( last + step , stop ) - low
            if substop < 0 :
                substop = None
            ms . append ( slice ( substart , substop , step ) )
else :
    raise ValueError ( 'slice step cannot be zero' )
return ss , ms


signature:
def _valid_distaxis ( shapes , ax ) :
    """` ax ` is a valid candidate for a distributed axis if the given
 subarray shapes are all the same when ignoring axis ` ax `"""

implementation:
compare_shapes = np . vstack ( shapes )
if ax < compare_shapes . shape [ 1 ] :
    compare_shapes [ : , ax ] = - 1
return np . count_nonzero ( compare_shapes - compare_shapes [ 0 ] ) == 0


signature:
def expand_dims ( self , axis ) :
    """Insert a new axis , at a given position in the array shape
 Args :
 axis ( int ) : Position ( amongst axes ) where new axis is to be inserted ."""

implementation:
if axis == - 1 :
    axis = self . ndim
if axis <= self . _distaxis :
    subaxis = axis
    new_distaxis = self . _distaxis + 1
else :
    subaxis = axis - 1
    new_distaxis = self . _distaxis
new_subarrays = [ expand_dims ( ra , subaxis ) for ra in self . _subarrays ]
return DistArray ( new_subarrays , new_distaxis )


signature:
def mean ( self , axis = None , dtype = None , out = None , keepdims = False ) :
    """Compute the arithmetic mean along the specified axis .
 See np . mean ( ) for details ."""

implementation:
if axis == - 1 :
    axis = self . ndim
if axis is None :
    results = vectorize ( mean ) ( self , axis , dtype , keepdims = False )
    weights = self . _sublengths
    res = np . average ( results , axis = None , weights = weights )
    if keepdims :
        for i in range ( self . ndim ) :
            res = expand_dims ( res , res . ndim )
elif axis == self . _distaxis :
    results = vectorize ( mean ) ( self , axis , dtype , keepdims = True )
    results = gather ( results )
    # Average manually ( np . average doesn ' t preserve ndarray subclasses )
    weights = ( np . array ( self . _sublengths , dtype = np . float64 ) / sum ( self . _sublengths ) )
    ix = [ slice ( None ) ] * self . ndim
    ix [ axis ] = 0
    res = results [ ix ] * weights [ 0 ]
    for i in range ( 1 , self . _n ) :
        ix [ axis ] = i
        res = res + results [ ix ] * weights [ i ]
    if keepdims :
        res = expand_dims ( res , axis )
else :
    res = vectorize ( mean ) ( self , axis , dtype , keepdims = False )
    if keepdims :
        res = expand_dims ( res , axis )
if out is not None :
    out [ : ] = res
return res


signature:
def run ( * args , ** kwargs ) :
    '''Returns True if successful , False if failure'''

implementation:
kwargs . setdefault ( 'env' , os . environ )
kwargs . setdefault ( 'shell' , True )
try :
    subprocess . check_call ( ' ' . join ( args ) , ** kwargs )
    return True
except subprocess . CalledProcessError :
    logger . debug ( 'Error running: {}' . format ( args ) )
    return False


signature:
def cmd ( ) :
    '''Return a command to launch a subshell'''

implementation:
if platform == 'win' :
    return [ 'cmd.exe' , '/K' ]
elif platform == 'linux' :
    ppid = os . getppid ( )
    ppid_cmdline_file = '/proc/{0}/cmdline' . format ( ppid )
    try :
        with open ( ppid_cmdline_file ) as f :
            cmd = f . read ( )
        if cmd . endswith ( '\x00' ) :
            cmd = cmd [ : - 1 ]
        cmd = cmd . split ( '\x00' )
        return cmd + [ binpath ( 'subshell.sh' ) ]
    except :
        cmd = 'bash'
else :
    cmd = 'bash'
return [ cmd , binpath ( 'subshell.sh' ) ]


signature:
def prompt ( prefix = None , colored = True ) :
    '''Generate a prompt with a given prefix
 linux / osx : [ prefix ] user @ host cwd $
 win : [ prefix ] cwd :'''


signature:
def launch ( prompt_prefix = None ) :
    '''Launch a subshell'''

implementation:
if prompt_prefix :
    os . environ [ 'PROMPT' ] = prompt ( prompt_prefix )
subprocess . call ( cmd ( ) , env = os . environ . data )


signature:
def add_file ( self , file , ** kwargs ) :
    """Append a file to file repository .
 For file monitoring , monitor instance needs file .
 Please put the name of file to ` file ` argument .
 : param file : the name of file you want monitor ."""

implementation:
if os . access ( file , os . F_OK ) :
    if file in self . f_repository :
        raise DuplicationError ( "file already added." )
    self . f_repository . append ( file )
else :
    raise IOError ( "file not found." )


signature:
def add_files ( self , filelist , ** kwargs ) :
    """Append files to file repository .
 ModificationMonitor can append files to repository using this .
 Please put the list of file names to ` filelist ` argument .
 : param filelist : the list of file nmaes"""

implementation:
# check filelist is list type
if not isinstance ( filelist , list ) :
    raise TypeError ( "request the list type." )
for file in filelist :
    self . add_file ( file )


signature:
def monitor ( self , sleep = 5 ) :
    """Run file modification monitor .
 The monitor can catch file modification using timestamp and file body .
 Monitor has timestamp data and file body data . And insert timestamp
 data and file body data before into while roop . In while roop , monitor
 get new timestamp and file body , and then monitor compare new timestamp
 to originaltimestamp . If new timestamp and file body differ original ,
 monitor regard thease changes as ` modification ` . Then monitor create
 instance of FileModificationObjectManager and FileModificationObject ,
 and monitor insert FileModificationObject to FileModificationObject -
 Manager . Then , yield this object .
 : param sleep : How times do you sleep in while roop ."""

implementation:
manager = FileModificationObjectManager ( )
timestamps = { }
filebodies = { }
# register original timestamp and filebody to dict
for file in self . f_repository :
    timestamps [ file ] = self . _get_mtime ( file )
    filebodies [ file ] = open ( file ) . read ( )
while True :
    for file in self . f_repository :
        mtime = timestamps [ file ]
        fbody = filebodies [ file ]
        modified = self . _check_modify ( file , mtime , fbody )
        # file not modify - > continue
        if not modified :
            continue
        # file modifies - > create the modification object
        new_mtime = self . _get_mtime ( file )
        new_fbody = open ( file ) . read ( )
        obj = FileModificationObject ( file , ( mtime , new_mtime ) , ( fbody , new_fbody ) )
        # overwrite new timestamp and filebody
        timestamps [ file ] = new_mtime
        filebodies [ file ] = new_fbody
        # append file modification object to manager
        manager . add_object ( obj )
        # return new modification object
        yield obj
    time . sleep ( sleep )


signature:
def init_app ( self , app ) :
    """Initialize a : class : ` ~ flask . Flask ` application for use with
 this extension ."""

implementation:
self . _jobs = [ ]
if not hasattr ( app , 'extensions' ) :
    app . extensions = { }
app . extensions [ 'restpoints' ] = self
app . restpoints_instance = self
app . add_url_rule ( '/ping' , 'ping' , ping )
app . add_url_rule ( '/time' , 'time' , time )
app . add_url_rule ( '/status' , 'status' , status ( self . _jobs ) )


signature:
def add_status_job ( self , job_func , name = None , timeout = 3 ) :
    """Adds a job to be included during calls to the ` / status ` endpoint .
 : param job _ func : the status function .
 : param name : the name used in the JSON response for the given status
 function . The name of the function is the default .
 : param timeout : the time limit before the job status is set to
 " timeout exceeded " ."""

implementation:
job_name = job_func . __name__ if name is None else name
job = ( job_name , timeout , job_func )
self . _jobs . append ( job )


signature:
def status_job ( self , fn = None , name = None , timeout = 3 ) :
    """Decorator that invokes ` add _ status _ job ` .
 @ app . status _ job
 def postgresql ( ) :
 # query / ping postgres
 @ app . status _ job ( name = " Active Directory " )
 def active _ directory ( ) :
 # query active directory
 @ app . status _ job ( timeout = 5)
 def paypal ( ) :
 # query paypal , timeout after 5 seconds"""

implementation:
if fn is None :
    def decorator ( fn ) :
        self . add_status_job ( fn , name , timeout )
    return decorator
else :
    self . add_status_job ( fn , name , timeout )


signature:
def _pipepager ( text , cmd , color ) :
    """Page through text by feeding it to another program . Invoking a
 pager through this might support colors ."""

implementation:
import subprocess
env = dict ( os . environ )
# If we ' re piping to less we might support colors under the
# condition that
cmd_detail = cmd . rsplit ( '/' , 1 ) [ - 1 ] . split ( )
if color is None and cmd_detail [ 0 ] == 'less' :
    less_flags = os . environ . get ( 'LESS' , '' ) + ' ' . join ( cmd_detail [ 1 : ] )
    if not less_flags :
        env [ 'LESS' ] = '-R'
        color = True
    elif 'r' in less_flags or 'R' in less_flags :
        color = True
if not color :
    text = strip_ansi ( text )
c = subprocess . Popen ( cmd , shell = True , stdin = subprocess . PIPE , env = env )
encoding = get_best_encoding ( c . stdin )
try :
    c . stdin . write ( text . encode ( encoding , 'replace' ) )
    c . stdin . close ( )
except ( IOError , KeyboardInterrupt ) :
    pass
# Less doesn ' t respect ^ C , but catches it for its own UI purposes ( aborting
# search or other commands inside less ) .
# That means when the user hits ^ C , the parent process ( click ) terminates ,
# but less is still alive , paging the output and messing up the terminal .
# If the user wants to make the pager exit on ^ C , they should set
# ` LESS = ' - K ' ` . It ' s not our decision to make .
while True :
    try :
        c . wait ( )
    except KeyboardInterrupt :
        pass
    else :
        break


signature:
def _get_funky ( func ) :
    """Renvoie une fonction numpy correspondant au nom passé en paramètre ,
 sinon renvoie la fonction elle - même"""

implementation:
if isinstance ( func , str ) :
    try :
        func = getattr ( np , func )
    except :
        raise NameError ( "Nom de fonction non comprise" )
return func


signature:
def profil_journalier ( df , func = 'mean' ) :
    """Calcul du profil journalier
 Paramètres :
 df : DataFrame de données dont l ' index est une série temporelle
 ( cf module xair par exemple )
 func : function permettant le calcul . Soit un nom de fonction numpy ( ' mean ' , ' max ' , . . . )
 soit la fonction elle - même ( np . mean , np . max , . . . )
 Retourne :
 Un DataFrame de moyennes par heure sur une journée"""

implementation:
func = _get_funky ( func )
res = df . groupby ( lambda x : x . hour ) . aggregate ( func )
return res


signature:
def profil_hebdo ( df , func = 'mean' ) :
    """Calcul du profil journalier
 Paramètres :
 df : DataFrame de données dont l ' index est une série temporelle
 ( cf module xair par exemple )
 func : function permettant le calcul . Soit un nom de fonction numpy ( ' mean ' , ' max ' , . . . )
 soit la fonction elle - même ( np . mean , np . max , . . . )
 Retourne :
 Un DataFrame de moyennes par journée sur la semaine"""

implementation:
func = _get_funky ( func )
res = df . groupby ( lambda x : x . weekday ) . aggregate ( func )
# On met des noms de jour à la place des numéros dans l ' index
res . index = [ cal . day_name [ i ] for i in range ( 0 , 7 ) ]
return res


signature:
def profil_annuel ( df , func = 'mean' ) :
    """Calcul du profil annuel
 Paramètres :
 df : DataFrame de données dont l ' index est une série temporelle
 ( cf module xair par exemple )
 func : function permettant le calcul . Soit un nom de fonction numpy ( ' mean ' , ' max ' , . . . )
 soit la fonction elle - même ( np . mean , np . max , . . . )
 Retourne :
 Un DataFrame de moyennes par mois"""

implementation:
func = _get_funky ( func )
res = df . groupby ( lambda x : x . month ) . aggregate ( func )
# On met des noms de mois à la place des numéros dans l ' index
res . index = [ cal . month_name [ i ] for i in range ( 1 , 13 ) ]
return res


signature:
def to_date ( date , dayfirst = False , format = None ) :
    """Transforme un champ date vers un objet python datetime
 Paramètres :
 date :
 - si None , renvoie la date du jour
 - si de type str , renvoie un objet python datetime
 - si de type datetime , le retourne sans modification
 dayfirst : Si True , aide l ' analyse du champ date de type str en informant
 le décrypteur que le jour se situe en début de chaîne ( ex : 11/09/2012
 pourrait être interpreté comme le 09 novembre si dayfirst = False )
 format : chaîne de caractère décrivant précisement le champ date de type
 str . Voir la documentation officielle de python . datetime pour description"""

implementation:
# # TODO : voir si pd . tseries . api ne peut pas remplacer tout ca
if not date :
    return dt . datetime . fromordinal ( dt . date . today ( ) . toordinal ( ) )
    # mieux que dt . datetime . now ( ) car ca met les heures , minutes et secondes à zéro
elif isinstance ( date , dt . datetime ) :
    return date
elif isinstance ( date , str ) :
    return pd . to_datetime ( date , dayfirst = dayfirst , format = format )
elif isinstance ( date , dt . date ) :
    return dt . datetime . fromordinal ( date . toordinal ( ) )
else :
    raise ValueError ( "Les dates doivent être de type None, str, datetime.date ou datetime.datetime" )


signature:
def _format ( noms ) :
    """Formate une donnée d ' entrée pour être exploitable dans les fonctions liste _ *
 et get _ * .
 Paramètres :
 noms : chaîne de caractère , liste ou tuples de chaînes de caractères ou
 pandas . Series de chaînes de caractères .
 Retourne :
 Une chaînes de caractères dont chaque élément est séparé du suivant par les
 caractères ' , ' ( simples quotes comprises )"""

implementation:
if isinstance ( noms , ( list , tuple , pd . Series ) ) :
    noms = ',' . join ( noms )
noms = noms . replace ( "," , "','" )
return noms


signature:
def date_range ( debut , fin , freq ) :
    """Génère une liste de date en tenant compte des heures de début et fin d ' une journée .
 La date de début sera toujours calée à 0h , et celle de fin à 23h
 Paramètres :
 debut : datetime représentant la date de début
 fin : datetime représentant la date de fin
 freq : freq de temps . Valeurs possibles : T ( minute ) , H ( heure ) , D ( jour ) ,
 M ( mois ) , Y ( année ) . Peux prendre des cycles , comme 15T pour 15 minutes"""

implementation:
debut_dt = debut . replace ( hour = 0 , minute = 0 , second = 0 , microsecond = 0 )
fin_dt = fin . replace ( hour = 23 , minute = 59 , second = 0 , microsecond = 0 )
if freq in ( 'M' , 'A' ) : # Calle la fréquence sur le début de mois / année
    freq += 'S'
    debut_dt = debut_dt . replace ( day = 1 , minute = 0 , second = 0 , microsecond = 0 )
    fin_dt = fin_dt . replace ( day = 1 , minute = 0 , second = 0 , microsecond = 0 )
dates_completes = pd . date_range ( start = debut_dt , end = fin_dt , freq = freq )
return dates_completes


signature:
def _connect ( self ) :
    """Connexion à la base XAIR"""

implementation:
try : # On passe par Oracle Instant Client avec le TNS ORA _ FULL
    self . conn = cx_Oracle . connect ( self . _ORA_FULL )
    self . cursor = self . conn . cursor ( )
    print ( 'XAIR: Connexion établie' )
except cx_Oracle . Error as e :
    print ( "Erreur: %s" % ( e ) )
    raise cx_Oracle . Error ( 'Echec de connexion' )


signature:
def liste_parametres ( self , parametre = None ) :
    """Liste des paramètres
 Paramètres :
 parametre : si fourni , retourne l ' entrée pour ce parametre uniquement"""

implementation:
condition = ""
if parametre :
    condition = "WHERE CCHIM='%s'" % parametre
_sql = """SELECT CCHIM AS PARAMETRE,
        NCON AS LIBELLE,
        NOPOL AS CODE
        FROM NOM_MESURE %s ORDER BY CCHIM""" % condition
return psql . read_sql ( _sql , self . conn )


signature:
def liste_mesures ( self , reseau = None , station = None , parametre = None , mesure = None ) :
    """Décrit les mesures :
 - d ' un ou des reseaux ,
 - d ' une ou des stations ,
 - d ' un ou des parametres
 ou décrit une ( des ) mesures suivant son ( leur ) identifiant ( s )
 Chaque attribut peut être étendu en rajoutant des noms séparés par des
 virgules ou en les mettant dans une liste / tuple / pandas . Series .
 Ainsi pour avoir la liste des mesures en vitesse et direction de vent :
 parametre = " VV , DV " ou = [ " VV " , " DV " ]
 Les arguments sont combinés ensemble pour la sélection des mesures .
 Paramètres :
 reseau : nom du reseau dans lequel lister les mesures
 station : nom de la station où lister les mesures
 parametre : Code chimique du parametre à lister
 mesure : nom de la mesure à décrire"""

implementation:
tbreseau = ""
conditions = [ ]
if reseau :
    reseau = _format ( reseau )
    tbreseau = """INNER JOIN RESEAUMES R USING (NOM_COURT_MES) """
    conditions . append ( """R.NOM_COURT_RES IN ('%s') """ % reseau )
if parametre :
    parametre = _format ( parametre )
    conditions . append ( """N.CCHIM IN ('%s')""" % parametre )
if station :
    station = _format ( station )
    conditions . append ( """S.IDENTIFIANT IN ('%s')""" % station )
if mesure :
    mesure = _format ( mesure )
    conditions . append ( """M.IDENTIFIANT IN ('%s')""" % mesure )
condition = "WHERE %s" % " and " . join ( conditions ) if conditions else ""
_sql = """SELECT
        M.IDENTIFIANT AS MESURE,
        M.NOM_MES AS LIBELLE,
        M.UNITE AS UNITE,
        S.IDENTIFIANT AS STATION,
        N.CCHIM AS CODE_PARAM,
        N.NCON AS PARAMETRE
        FROM MESURE M
        INNER JOIN NOM_MESURE N USING (NOPOL)
        INNER JOIN STATION S USING (NOM_COURT_SIT)
        %s
        %s
        ORDER BY M.IDENTIFIANT""" % ( tbreseau , condition )
return psql . read_sql ( _sql , self . conn )


signature:
def liste_stations ( self , station = None , detail = False ) :
    """Liste des stations
 Paramètres :
 station : un nom de station valide ( si vide , liste toutes les stations )
 detail : si True , affiche plus de détail sur la ( les ) station ( s ) ."""

implementation:
condition = ""
if station :
    station = _format ( station )
    condition = "WHERE IDENTIFIANT IN ('%s')" % station
select = ""
if detail :
    select = """,
            ISIT AS DESCRIPTION,
            NO_TELEPHONE AS TELEPHONE,
            ADRESSE_IP,
            LONGI AS LONGITUDE,
            LATI AS LATITUDE,
            ALTI AS ALTITUDE,
            AXE AS ADR,
            CODE_POSTAL AS CP,
            FLAG_VALID AS VALID"""
_sql = """SELECT
        NSIT AS NUMERO,
        IDENTIFIANT AS STATION %s
        FROM STATION
        %s
        ORDER BY NSIT""" % ( select , condition )
return psql . read_sql ( _sql , self . conn )


signature:
def liste_campagnes ( self , campagne = None ) :
    """Liste des campagnes de mesure et des stations associées
 Paramètres :
 campagne : Si définie , liste des stations que pour cette campagne"""

implementation:
condition = ""
if campagne :
    condition = "WHERE NOM_COURT_CM='%s' " "" % campagne
_sql = """SELECT
        NOM_COURT_CM AS CAMPAGNE,
        IDENTIFIANT AS STATION,
        LIBELLE AS LIBELLE_CM,
        DATEDEB AS DEBUT,
        DATEFIN AS FIN
        FROM CAMPMES
        INNER JOIN CAMPMES_STATION USING (NOM_COURT_CM)
        INNER JOIN STATION USING (NOM_COURT_SIT)
        %s ORDER BY DATEDEB DESC""" % condition
return psql . read_sql ( _sql , self . conn )


signature:
def get_manuelles ( self , site , code_parametre , debut , fin , court = False ) :
    """Recupération des mesures manuelles ( labo ) pour un site
 site : numéro du site ( voir fonction liste _ sites _ prelevement )
 code _ parametre : code ISO du paramètre à rechercher ( C6H6 = V4)
 debut : date de début du premier prélèvement
 fin : date de fin du dernier prélèvement
 court : Renvoie un tableau au format court ou long ( colonnes )"""

implementation:
condition = "WHERE MESLA.NOPOL='%s' " % code_parametre
condition += "AND SITMETH.NSIT=%s " % site
condition += "AND PRELEV.DATE_DEB>=TO_DATE('%s', 'YYYY-MM-DD') " % debut
condition += "AND PRELEV.DATE_FIN<=TO_DATE('%s', 'YYYY-MM-DD') " % fin
if court == False :
    select = """SELECT
                        MESLA.LIBELLE AS MESURE,
                        METH.LIBELLE AS METHODE,
                        ANA.VALEUR AS VALEUR,
                        MESLA.UNITE AS UNITE,
                        ANA.CODE_QUALITE AS CODE_QUALITE,
                        ANA.DATE_ANA AS DATE_ANALYSE,
                        ANA.ID_LABO AS LABO,
                        PRELEV.DATE_DEB AS DEBUT,
                        PRELEV.DATE_FIN AS FIN,
                        ANA.COMMENTAIRE AS COMMENTAIRE,
                        SITE.LIBELLE AS SITE,
                        SITE.AXE AS ADRESSE,
                        COM.NOM_COMMUNE AS COMMUNE"""
else :
    select = """SELECT
                        MESLA.LIBELLE AS MESURE,
                        ANA.VALEUR AS VALEUR,
                        MESLA.UNITE AS UNITE,
                        ANA.CODE_QUALITE AS CODE_QUALITE,
                        PRELEV.DATE_DEB AS DEBUT,
                        PRELEV.DATE_FIN AS FIN,
                        SITE.AXE AS ADRESSE,
                        COM.NOM_COMMUNE AS COMMUNE"""
_sql = """%s
        FROM ANALYSE ANA
        INNER JOIN PRELEVEMENT PRELEV ON (ANA.CODE_PRELEV=PRELEV.CODE_PRELEV AND ANA.CODE_SMP=PRELEV.CODE_SMP)
        INNER JOIN MESURE_LABO MESLA ON (ANA.CODE_MES_LABO=MESLA.CODE_MES_LABO AND ANA.CODE_SMP=MESLA.CODE_SMP)
        INNER JOIN SITE_METH_PRELEV SITMETH ON (ANA.CODE_SMP=SITMETH.CODE_SMP)
        INNER JOIN METH_PRELEVEMENT METH ON (SITMETH.CODE_METH_P=METH.CODE_METH_P)
        INNER JOIN SITE_PRELEVEMENT SITE ON (SITE.NSIT=SITMETH.NSIT)
        INNER JOIN COMMUNE COM ON (COM.NINSEE=SITE.NINSEE)
        %s
        ORDER BY MESLA.NOPOL,MESLA.LIBELLE,PRELEV.DATE_DEB""" % ( select , condition )
return psql . read_sql ( _sql , self . conn )


signature:
def get_indices ( self , res , debut , fin ) :
    """Récupération des indices ATMO pour un réseau donné .
 Paramètres :
 res : Nom du ou des réseaux à chercher ( str , list , pandas . Series )
 debut : date de début , format YYYY - MM - JJ ( str )
 fin : Date de fin , format YYYY - MM - JJ ( str )"""

implementation:
res = _format ( res )
_sql = """SELECT
        J_DATE AS "date",
        NOM_AGGLO AS "reseau",
        C_IND_CALCULE AS "indice"
        FROM RESULTAT_INDICE
        INNER JOIN GROUPE_ATMO USING (NOM_COURT_GRP)
        WHERE NOM_AGGLO IN ('%s')
        AND J_DATE BETWEEN TO_DATE('%s', 'YYYY-MM-DD') AND TO_DATE('%s', 'YYYY-MM-DD') """ % ( res , debut , fin )
rep = psql . read_sql ( _sql , self . conn )
df = rep . set_index ( [ 'reseau' , 'date' ] )
df = df [ 'indice' ]
df = df . unstack ( 'reseau' )
dates_completes = date_range ( to_date ( debut ) , to_date ( fin ) , freq = 'D' )
df = df . reindex ( dates_completes )
return df


signature:
def get_indices_et_ssi ( self , reseau , debut , fin , complet = True ) :
    """Renvoie l ' indice et les sous _ indices
 complet : renvoyer les complets ou les prévus
 reseau : nom du réseau à renvoyer
 debut : date de début à renvoyer
 fin : date de fin à renvoyer
 Renvoi : reseau , date , Indice , sous _ ind NO2 , PM10 , O3 , SO2"""

implementation:
if complet :
    i_str = "c_ind_diffuse"
    ssi_str = "c_ss_indice"
else :
    i_str = "p_ind_diffuse"
    ssi_str = "p_ss_indice"
_sql = """SELECT
                g.nom_agglo as "reseau",
                i.j_date as "date",
                max(case when i.{0}>0 then i.{0} else 0 end) indice,
                max(case when n.cchim='NO2' then ssi.{1} else 0 end) no2,
                max(case when n.cchim='PM10' then ssi.{1} else 0 end) pm10,
                max(case when n.cchim='O3' then ssi.{1} else 0 end) o3,
                max(case when n.cchim='SO2' then ssi.{1} else 0 end) so2
        FROM resultat_indice i
        INNER JOIN resultat_ss_indice ssi ON (i.nom_court_grp=ssi.nom_court_grp AND i.j_date=ssi.j_date)
        INNER JOIN groupe_atmo g ON (i.nom_court_grp=g.nom_court_grp)
        INNER JOIN nom_mesure n ON (ssi.nopol=n.nopol)
        WHERE g.nom_agglo='{2}'
        AND i.j_date BETWEEN
        TO_DATE('{3}', 'YYYY-MM-DD') AND
        TO_DATE('{4}', 'YYYY-MM-DD')
        GROUP BY
        g.nom_agglo,
        i.j_date
        ORDER BY i.j_date""" . format ( i_str , ssi_str , reseau , debut , fin )
df = psql . read_sql ( _sql , self . conn )
df = df . set_index ( [ 'reseau' , 'date' ] )
return df


signature:
def get_sqltext ( self , format_ = 1 ) :
    """retourne les requêtes actuellement lancées sur le serveur"""

implementation:
if format_ == 1 :
    _sql = """SELECT u.sid, substr(u.username,1,12) user_name, s.sql_text
            FROM v$sql s,v$session u
            WHERE s.hash_value = u.sql_hash_value
            AND sql_text NOT LIKE '%from v$sql s, v$session u%'
            AND u.username NOT LIKE 'None'
            ORDER BY u.sid"""
if format_ == 2 :
    _sql = """SELECT u.username, s.first_load_time, s.executions, s.sql_text
            FROM dba_users u,v$sqlarea s
            WHERE u.user_id=s.parsing_user_id
            AND u.username LIKE 'LIONEL'
            AND sql_text NOT LIKE '%FROM dba_users u,v$sqlarea s%'
            ORDER BY s.first_load_time"""
return psql . read_sql ( _sql , self . conn )


signature:
def run_global_hook ( hook_name , * args ) :
    '''Attempt to run a global hook by name with args'''

implementation:
hook_finder = HookFinder ( get_global_hook_path ( ) )
hook = hook_finder ( hook_name )
if hook :
    hook . run ( * args )


signature:
def status ( jobs ) :
    """Handler that calls each status job in a worker pool , attempting to timeout .
 The resulting durations / errors are written to the response
 as JSON .
 eg .
 " endpoints " : [
 { " endpoint " : " Jenny ' s Database " , " duration " : 1.002556324005127 } ,
 { " endpoint " : " Hotmail " , " duration " : - 1 , " error " : " Host is down " } ,"""

implementation:
def status_handler ( ) :
    endpoints = [ ]
    stats = { "endpoints" : None }
    executor = concurrent . futures . ThreadPoolExecutor ( max_workers = 5 )
    # This is basically calling the below within the executor :
    # > > > timeit ( job [ 2 ] , number = 1)
    # job is a tuple of ( name , timeout , func ) so the above is really :
    # > > > timeit ( func , number = 1)
    # gen = ( ( job , executor . submit ( timeit , job [ 2 ] , number = 1 ) ) for job in jobs )
    # for job , future in gen :
    for job , future in [ ( job , executor . submit ( timeit , job [ 2 ] , number = 1 ) ) for job in jobs ] :
        name , timeout , _ = job
        endpoint = { "endpoint" : name }
        try :
            data = future . result ( timeout = timeout )
            endpoint [ "duration" ] = data
        except concurrent . futures . TimeoutError :
            endpoint [ "error" ] = "timeout exceeded"
        except Exception as ex :
            endpoint [ "error" ] = str ( ex )
        endpoints . append ( endpoint )
    if len ( endpoints ) > 0 :
        stats [ "endpoints" ] = endpoints
    executor . shutdown ( wait = False )
    return jsonify ( ** stats )
    # TODO : Look into potentially cleaning up jobs that have timed - out .
    # This could be done by changing jobs from a func to an object
    # that implements ` def interrupt ( self ) : ` which would be used
    # to interrupt / stop / close / cleanup any resources .
return status_handler


signature:
def moyennes_glissantes ( df , sur = 8 , rep = 0.75 ) :
    """Calcule de moyennes glissantes
 Paramètres :
 df : DataFrame de mesures sur lequel appliqué le calcul
 sur : ( int , par défaut 8 ) Nombre d ' observations sur lequel s ' appuiera le
 calcul
 rep : ( float , défaut 0.75 ) Taux de réprésentativité en dessous duquel le
 calcul renverra NaN
 Retourne :
 Un DataFrame des moyennes glissantes calculées"""

implementation: return pd . rolling_mean ( df , window = sur , min_periods = rep * sur )


signature:
def consecutive ( df , valeur , sur = 3 ) :
    """Calcule si une valeur est dépassée durant une période donnée . Détecte
 un dépassement de valeur sur X heures / jours / . . . consécutifs
 Paramètres :
 df : DataFrame de mesures sur lequel appliqué le calcul
 valeur : ( float ) valeur à chercher le dépassement ( strictement supérieur à )
 sur : ( int ) Nombre d ' observations consécutives où la valeur doit être dépassée
 Retourne :
 Un DataFrame de valeurs , de même taille ( shape ) que le df d ' entrée , dont toutes
 les valeurs sont supprimées , sauf celles supérieures à la valeur de référence
 et positionnées sur les heures de début de dépassements"""

implementation:
dep = pd . rolling_max ( df . where ( df > valeur ) , window = sur , min_periods = sur )
return dep


signature:
def nombre_depassement ( df , valeur , freq = None ) :
    """Calcule le nombre de dépassement d ' une valeur sur l ' intégralité du temps ,
 ou suivant un regroupement temporel .
 Paramètres :
 df : DataFrame de mesures sur lequel appliqué le calcul
 valeur : ( float ) valeur à chercher le dépassement ( strictement supérieur à )
 freq : ( str ou None ) : Fréquence de temps sur lequel effectué un regroupement .
 freq peut prendre les valeurs ' H ' pour heure , ' D ' pour jour , ' W ' pour semaine ,
 ' M ' pour mois et ' A ' pour année , ou None pour ne pas faire de regroupement .
 Le nombre de dépassement sera alors regroupé suivant cette fréquence de temps .
 Retourne :
 Une Series du nombre de dépassement , total suivant la fréquence intrinsèque
 du DataFrame d ' entrée , ou aggloméré suivant la fréquence de temps choisie ."""

implementation:
dep = depassement ( df , valeur )
if freq is not None :
    dep = dep . resample ( freq , how = 'sum' )
return dep . count ( )


signature:
def aot40_vegetation ( df , nb_an ) :
    """Calcul de l ' AOT40 du 1er mai au 31 juillet
 * AOT40 : AOT 40 ( exprimé en micro g / m3 par heure ) signifie la somme des
 différences entre les concentrations horaires supérieures à 40 parties par
 milliard ( 40 ppb soit 80 micro g / m3 ) , durant une période donnée en
 utilisant uniquement les valeurs sur 1 heure mesurées quotidiennement
 entre 8 heures ( début de la mesure ) et 20 heures ( pile , fin de la mesure ) CET ,
 ce qui correspond à de 8h à 19h TU ( donnant bien 12h de mesures , 8h donnant
 la moyenne horaire de 7h01 à 8h00)
 Paramètres :
 df : DataFrame de mesures sur lequel appliqué le calcul
 nb _ an : ( int ) Nombre d ' années contenu dans le df , et servant à diviser le
 résultat retourné
 Retourne :
 Un DataFrame de résultat de calcul"""

implementation: return _aot ( df . tshift ( 1 ) , nb_an = nb_an , limite = 80 , mois_debut = 5 , mois_fin = 7 , heure_debut = 8 , heure_fin = 19 )


signature:
def _aot ( df , nb_an = 1 , limite = 80 , mois_debut = 5 , mois_fin = 7 , heure_debut = 7 , heure_fin = 19 ) :
    """Calcul de l ' AOT de manière paramètrable . Voir AOT40 _ vegetation ou
 AOT40 _ foret pour des paramètres préalablement fixés .
 Paramètres :
 df : DataFrame de mesures sur lequel appliqué le calcul
 nb _ an : ( int ) Nombre d ' années contenu dans le df , et servant à diviser le
 résultat retourné
 limite : ( float ) valeur limite au delà de laquelle les différences seront
 additionnées pour calculer l ' AOT
 mois _ debut : ( int ) mois de début de calcul
 mois _ fin : ( int ) mois de fin de calcul
 heure _ debut : ( int ) première heure de chaque jour après laquelle les valeurs
 sont retenues
 heure _ fin : ( int ) dernière heure de chaque jour avant laquelle les valeurs
 sont retenues
 Retourne :
 Un DataFrame de résultat de calcul"""

implementation:
res = df [ ( df . index . month >= mois_debut ) & ( df . index . month <= mois_fin ) & ( df . index . hour >= heure_debut ) & ( df . index . hour <= heure_fin ) ]
nb_valid = res . count ( )
nb_total = res . shape [ 0 ]
pcent = nb_valid . astype ( pd . np . float ) / nb_total * 100
brut = ( res [ res > limite ] - limite ) / nb_an
brut = brut . sum ( )
net = brut / nb_valid * nb_total
print ( """{total} mesures au totales
    du {m_d} au {m_f}
    entre {h_d} et {h_f}""" . format ( total = nb_total , m_d = mois_debut , m_f = mois_fin , h_d = heure_debut , h_f = heure_fin ) )
aot = pd . DataFrame ( [ brut . round ( ) , nb_valid . round ( ) , pcent . round ( ) , net . round ( ) ] , index = [ 'brutes' , 'mesures valides' , '% de rep.' , 'nettes' ] )
return aot


signature:
def no2 ( df ) :
    """Calculs réglementaires pour le dioxyde d ' azote
 Paramètres :
 df : DataFrame contenant les mesures , avec un index temporel
 ( voir xair . get _ mesure )
 Retourne :
 Une série de résultats dans un DataFrame :
 unité ( u ) : μg / m3 ( microgramme par mètre cube )
 Seuil de RI en moyenne H : 200u
 Seuil d ' Alerte sur 3H consécutives : 400u
 Seuil d ' Alerte sur 3J consécutifs : 200u
 Valeur limite pour la santé humaine 18H / A : 200u
 Valeur limite pour la santé humaine en moyenne A : 40u
 Objectif de qualité en moyenne A : 40u
 Protection de la végétation en moyenne A : 30u
 Les résultats sont donnés en terme d ' heure de dépassement"""

implementation:
polluant = "NO2"
# Le DataFrame doit être en heure
if not isinstance ( df . index . freq , pdoffset . Hour ) :
    raise FreqException ( "df doit être en heure." )
res = { "Seuil de RI en moyenne H: 200u" : depassement ( df , valeur = 200 ) , "Seuil d'Alerte sur 3H consécutives: 400u" : consecutive ( df , valeur = 400 , sur = 3 ) , "Seuil d'Alerte sur 3J consécutifs: 200u" : consecutive ( df . resample ( 'D' , how = 'max' ) , valeur = 200 , sur = 3 ) , "Valeur limite pour la santé humaine 18H/A: 200u" : depassement ( df , valeur = 200 ) , "Valeur limite pour la santé humaine en moyenne A: 40u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 40 ) , "Objectif de qualité en moyenne A: 40u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 40 ) , "Protection de la végétation en moyenne A: 30u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 30 ) , }
return polluant , res


signature:
def pm10 ( df ) :
    """Calculs réglementaires pour les particules PM10
 Paramètres :
 df : DataFrame contenant les mesures , avec un index temporel
 ( voir xair . get _ mesure )
 Retourne :
 Une série de résultats dans un DataFrame :
 unité ( u ) : μg / m3 ( microgramme par mètre cube )
 Seuil de RI en moyenne J : 50u
 Seuil d ' Alerte en moyenne J : 80u
 Valeur limite pour la santé humaine 35J / A : 50u
 Valeur limite pour la santé humaine en moyenne A : 40u
 Objectif de qualité en moyenne A : 30u
 Les résultats sont donnés en terme d ' heure de dépassement"""

implementation:
polluant = 'PM10'
# Le DataFrame doit être en jour
if not isinstance ( df . index . freq , pdoffset . Day ) :
    raise FreqException ( "df doit être en jour." )
res = { "Seuil de RI en moyenne J: 50u" : depassement ( df , valeur = 50 ) , "Seuil d'Alerte en moyenne J: 80u" : depassement ( df , valeur = 80 ) , "Valeur limite pour la santé humaine 35J/A: 50u" : depassement ( df , valeur = 50 ) , "Valeur limite pour la santé humaine en moyenne A: 40u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 40 ) , "Objectif de qualité en moyenne A: 30u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 30 ) , }
return polluant , res


signature:
def so2 ( df ) :
    """Calculs réglementaires pour le dioxyde de soufre
 Paramètres :
 df : DataFrame contenant les mesures , avec un index temporel
 ( voir xair . get _ mesure )
 Retourne :
 Une série de résultats dans un DataFrame :
 unité ( u ) : μg / m3 ( microgramme par mètre cube )
 Seuil de RI en moyenne H : 300u
 Seuil d ' Alerte sur 3H consécutives : 500u
 Valeur limite pour la santé humaine 24H / A : 350u
 Valeur limite pour la santé humaine 3J / A : 125u
 Objectif de qualité en moyenne A : 50u
 Protection de la végétation en moyenne A : 20u
 Protection de la végétation du 01/10 au 31/03 : 20u
 Les résultats sont donnés en terme d ' heure de dépassement"""

implementation:
polluant = 'SO2'
# Le DataFrame doit être en heure
if not isinstance ( df . index . freq , pdoffset . Hour ) :
    raise FreqException ( "df doit être en heure." )
res = { "Seuil de RI en moyenne H: 300u" : depassement ( df , valeur = 300 ) , "Seuil d'Alerte sur 3H consécutives: 500u" : depassement ( df , valeur = 500 ) , "Valeur limite pour la santé humaine 24H/A: 350u" : depassement ( df , valeur = 350 ) , "Valeur limite pour la santé humaine 3J/A: 125u" : depassement ( df . resample ( 'D' , how = 'mean' ) , valeur = 125 ) , "Objectif de qualité en moyenne A: 50u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 50 ) , "Protection de la végétation en moyenne A: 20u" : depassement ( df . resample ( 'A' , how = 'mean' ) , valeur = 20 ) , "Protection de la végétation du 01/10 au 31/03: 20u" : depassement ( df [ ( df . index . month <= 3 ) | ( df . index . month >= 10 ) ] , valeur = 20 ) , }
return polluant , res


signature:
def co ( df ) :
    """Calculs réglementaires pour le monoxyde de carbone
 Paramètres :
 df : DataFrame contenant les mesures , avec un index temporel
 ( voir xair . get _ mesure )
 Retourne :
 Une série de résultats dans un DataFrame :
 unité ( u ) : μg / m3 ( microgramme par mètre cube )
 Valeur limite pour la santé humaine max J 8H glissantes : 10000u
 Les résultats sont donnés en terme d ' heure de dépassement"""

implementation:
polluant = 'CO'
# Le DataFrame doit être en heure
if not isinstance ( df . index . freq , pdoffset . Hour ) :
    raise FreqException ( "df doit être en heure." )
res = { "Valeur limite pour la santé humaine sur 8H glissantes: 10000u" : depassement ( moyennes_glissantes ( df , sur = 8 ) , valeur = 10 ) , }
return polluant , res


signature:
def o3 ( df ) :
    """Calculs réglementaires pour l ' ozone
 Paramètres :
 df : DataFrame contenant les mesures , avec un index temporel
 ( voir xair . get _ mesure )
 Retourne :
 Une série de résultats dans un DataFrame :
 unité ( u ) : μg / m3 ( microgramme par mètre cube )
 Seuil de RI sur 1H : 180u
 Seuil d ' Alerte sur 1H : 240u
 Seuil d ' Alerte sur 3H consécutives : 240u
 Seuil d ' Alerte sur 3H consécutives : 300u
 Seuil d ' Alerte sur 1H : 360u
 Objectif de qualité pour la santé humaine sur 8H glissantes : 120u
 Les résultats sont donnés en terme d ' heure de dépassement"""

implementation:
polluant = 'O3'
# Le DataFrame doit être en heure
if not isinstance ( df . index . freq , pdoffset . Hour ) :
    raise FreqException ( "df doit être en heure." )
res = { "Seuil de RI sur 1H: 180u" : depassement ( df , valeur = 180 ) , "Seuil d'Alerte sur 1H: 240u" : depassement ( df , valeur = 240 ) , "Seuil d'Alerte sur 1H: 360u" : depassement ( df , valeur = 360 ) , "Seuil d'Alerte sur 3H consécutives: 240u" : consecutive ( df , valeur = 240 , sur = 3 ) , "Seuil d'Alerte sur 3H consécutives: 300u" : consecutive ( df , valeur = 300 , sur = 3 ) , "Objectif de qualité pour la santé humaine sur 8H glissantes: 120u" : depassement ( moyennes_glissantes ( df , sur = 8 ) , valeur = 120 ) , }
return polluant , res