signature:
def _sim_trajectories ( self , time_size , start_pos , rs , total_emission = False , save_pos = False , radial = False , wrap_func = wrap_periodic ) :
    """Simulate ( in - memory ) ` time _ size ` steps of trajectories .
 Simulate Brownian motion diffusion and emission of all the particles .
 Uses the attributes : num _ particles , sigma _ 1d , box , psf .
 Arguments :
 time _ size ( int ) : number of time steps to be simulated .
 start _ pos ( array ) : shape ( num _ particles , 3 ) , particles start
 positions . This array is modified to store the end position
 after this method is called .
 rs ( RandomState ) : a ` numpy . random . RandomState ` object used
 to generate the random numbers .
 total _ emission ( bool ) : if True , store only the total emission array
 containing the sum of emission of all the particles .
 save _ pos ( bool ) : if True , save the particles 3D trajectories
 wrap _ func ( function ) : the function used to apply the boundary
 condition ( use : func : ` wrap _ periodic ` or : func : ` wrap _ mirror ` ) .
 Returns :
 POS ( list ) : list of 3D trajectories arrays ( 3 x time _ size )
 em ( array ) : array of emission ( total or per - particle )"""

implementation:
time_size = int ( time_size )
num_particles = self . num_particles
if total_emission :
    em = np . zeros ( time_size , dtype = np . float32 )
else :
    em = np . zeros ( ( num_particles , time_size ) , dtype = np . float32 )
POS = [ ]
# pos _ w = np . zeros ( ( 3 , c _ size ) )
for i , sigma_1d in enumerate ( self . sigma_1d ) :
    delta_pos = rs . normal ( loc = 0 , scale = sigma_1d , size = 3 * time_size )
    delta_pos = delta_pos . reshape ( 3 , time_size )
    pos = np . cumsum ( delta_pos , axis = - 1 , out = delta_pos )
    pos += start_pos [ i ]
    # Coordinates wrapping using the specified boundary conditions
    for coord in ( 0 , 1 , 2 ) :
        pos [ coord ] = wrap_func ( pos [ coord ] , * self . box . b [ coord ] )
    # Sample the PSF along i - th trajectory then square to account
    # for emission and detection PSF .
    Ro = sqrt ( pos [ 0 ] ** 2 + pos [ 1 ] ** 2 )
    # radial pos . on x - y plane
    Z = pos [ 2 ]
    current_em = self . psf . eval_xz ( Ro , Z ) ** 2
    if total_emission : # Add the current particle emission to the total emission
        em += current_em . astype ( np . float32 )
    else : # Store the individual emission of current particle
        em [ i ] = current_em . astype ( np . float32 )
    if save_pos :
        pos_save = np . vstack ( ( Ro , Z ) ) if radial else pos
        POS . append ( pos_save [ np . newaxis , : , : ] )
    # Update start _ pos in - place for current particle
    start_pos [ i ] = pos [ : , - 1 : ]
return POS , em


signature:
def simulate_diffusion ( self , save_pos = False , total_emission = True , radial = False , rs = None , seed = 1 , path = './' , wrap_func = wrap_periodic , chunksize = 2 ** 19 , chunkslice = 'times' , verbose = True ) :
    """Simulate Brownian motion trajectories and emission rates .
 This method performs the Brownian motion simulation using the current
 set of parameters . Before running this method you can check the
 disk - space requirements using : method : ` print _ sizes ` .
 Results are stored to disk in HDF5 format and are accessible in
 in ` self . emission ` , ` self . emission _ tot ` and ` self . position ` as
 pytables arrays .
 Arguments :
 save _ pos ( bool ) : if True , save the particles 3D trajectories
 total _ emission ( bool ) : if True , store only the total emission array
 containing the sum of emission of all the particles .
 rs ( RandomState object ) : random state object used as random number
 generator . If None , use a random state initialized from seed .
 seed ( uint ) : when ` rs ` is None , ` seed ` is used to initialize the
 random state , otherwise is ignored .
 wrap _ func ( function ) : the function used to apply the boundary
 condition ( use : func : ` wrap _ periodic ` or : func : ` wrap _ mirror ` ) .
 path ( string ) : a folder where simulation data is saved .
 verbose ( bool ) : if False , prints no output ."""

implementation:
if rs is None :
    rs = np . random . RandomState ( seed = seed )
self . open_store_traj ( chunksize = chunksize , chunkslice = chunkslice , radial = radial , path = path )
# Save current random state for reproducibility
self . traj_group . _v_attrs [ 'init_random_state' ] = rs . get_state ( )
em_store = self . emission_tot if total_emission else self . emission
print ( '- Start trajectories simulation - %s' % ctime ( ) , flush = True )
if verbose :
    print ( '[PID %d] Diffusion time:' % os . getpid ( ) , end = '' )
i_chunk = 0
t_chunk_size = self . emission . chunkshape [ 1 ]
chunk_duration = t_chunk_size * self . t_step
par_start_pos = self . particles . positions
prev_time = 0
for time_size in iter_chunksize ( self . n_samples , t_chunk_size ) :
    if verbose :
        curr_time = int ( chunk_duration * ( i_chunk + 1 ) )
        if curr_time > prev_time :
            print ( ' %ds' % curr_time , end = '' , flush = True )
            prev_time = curr_time
    POS , em = self . _sim_trajectories ( time_size , par_start_pos , rs , total_emission = total_emission , save_pos = save_pos , radial = radial , wrap_func = wrap_func )
    # # Append em to the permanent storage
    # if total _ emission , data is just a linear array
    # otherwise is a 2 - D array ( self . num _ particles , c _ size )
    em_store . append ( em )
    if save_pos :
        self . position . append ( np . vstack ( POS ) . astype ( 'float32' ) )
    i_chunk += 1
    self . store . h5file . flush ( )
# Save current random state
self . traj_group . _v_attrs [ 'last_random_state' ] = rs . get_state ( )
self . store . h5file . flush ( )
print ( '\n- End trajectories simulation - %s' % ctime ( ) , flush = True )


signature:
def get_timestamps_part ( self , name ) :
    """Return matching ( timestamps , particles ) pytables arrays ."""

implementation:
par_name = name + '_par'
timestamps = self . ts_store . h5file . get_node ( '/timestamps' , name )
particles = self . ts_store . h5file . get_node ( '/timestamps' , par_name )
return timestamps , particles


signature:
def _sim_timestamps ( self , max_rate , bg_rate , emission , i_start , rs , ip_start = 0 , scale = 10 , sort = True ) :
    """Simulate timestamps from emission trajectories .
 Uses attributes : ` . t _ step ` .
 Returns :
 A tuple of two arrays : timestamps and particles ."""

implementation:
counts_chunk = sim_timetrace_bg ( emission , max_rate , bg_rate , self . t_step , rs = rs )
nrows = emission . shape [ 0 ]
if bg_rate is not None :
    nrows += 1
assert counts_chunk . shape == ( nrows , emission . shape [ 1 ] )
max_counts = counts_chunk . max ( )
if max_counts == 0 :
    return np . array ( [ ] , dtype = np . int64 ) , np . array ( [ ] , dtype = np . int64 )
time_start = i_start * scale
time_stop = time_start + counts_chunk . shape [ 1 ] * scale
ts_range = np . arange ( time_start , time_stop , scale , dtype = 'int64' )
# Loop for each particle to compute timestamps
times_chunk_p = [ ]
par_index_chunk_p = [ ]
for ip , counts_chunk_ip in enumerate ( counts_chunk ) : # Compute timestamps for particle ip for all bins with counts
    times_c_ip = [ ]
    for v in range ( 1 , max_counts + 1 ) :
        times_c_ip . append ( ts_range [ counts_chunk_ip >= v ] )
    # Stack the timestamps from different " counts "
    t = np . hstack ( times_c_ip )
    # Append current particle
    times_chunk_p . append ( t )
    par_index_chunk_p . append ( np . full ( t . size , ip + ip_start , dtype = 'u1' ) )
# Merge the arrays of different particles
times_chunk = np . hstack ( times_chunk_p )
par_index_chunk = np . hstack ( par_index_chunk_p )
if sort : # Sort timestamps inside the merged chunk
    index_sort = times_chunk . argsort ( kind = 'mergesort' )
    times_chunk = times_chunk [ index_sort ]
    par_index_chunk = par_index_chunk [ index_sort ]
return times_chunk , par_index_chunk


signature:
def simulate_timestamps_mix ( self , max_rates , populations , bg_rate , rs = None , seed = 1 , chunksize = 2 ** 16 , comp_filter = None , overwrite = False , skip_existing = False , scale = 10 , path = None , t_chunksize = None , timeslice = None ) :
    """Compute one timestamps array for a mixture of N populations .
 Timestamp data are saved to disk and accessible as pytables arrays in
 ` . _ timestamps ` and ` . _ tparticles ` .
 The background generated timestamps are assigned a
 conventional particle number ( last particle index + 1 ) .
 Arguments :
 max _ rates ( list ) : list of the peak max emission rate for each
 population .
 populations ( list of slices ) : slices to ` self . particles `
 defining each population .
 bg _ rate ( float , cps ) : rate for a Poisson background process
 rs ( RandomState object ) : random state object used as random number
 generator . If None , use a random state initialized from seed .
 seed ( uint ) : when ` rs ` is None , ` seed ` is used to initialize the
 random state , otherwise is ignored .
 chunksize ( int ) : chunk size used for the on - disk timestamp array
 comp _ filter ( tables . Filter or None ) : compression filter to use
 for the on - disk ` timestamps ` and ` tparticles ` arrays .
 If None use default compression .
 overwrite ( bool ) : if True , overwrite any pre - existing timestamps
 array . If False , never overwrite . The outcome of simulating an
 existing array is controlled by ` skip _ existing ` flag .
 skip _ existing ( bool ) : if True , skip simulation if the same
 timestamps array is already present .
 scale ( int ) : ` self . t _ step ` is multiplied by ` scale ` to obtain the
 timestamps units in seconds .
 path ( string ) : folder where to save the data .
 timeslice ( float or None ) : timestamps are simulated until
 ` timeslice ` seconds . If None , simulate until ` self . t _ max ` ."""

implementation:
self . open_store_timestamp ( chunksize = chunksize , path = path )
rs = self . _get_group_randomstate ( rs , seed , self . ts_group )
if t_chunksize is None :
    t_chunksize = self . emission . chunkshape [ 1 ]
timeslice_size = self . n_samples
if timeslice is not None :
    timeslice_size = timeslice // self . t_step
name = self . _get_ts_name_mix ( max_rates , populations , bg_rate , rs = rs )
kw = dict ( name = name , clk_p = self . t_step / scale , max_rates = max_rates , bg_rate = bg_rate , populations = populations , num_particles = self . num_particles , bg_particle = self . num_particles , overwrite = overwrite , chunksize = chunksize )
if comp_filter is not None :
    kw . update ( comp_filter = comp_filter )
try :
    self . _timestamps , self . _tparticles = ( self . ts_store . add_timestamps ( ** kw ) )
except ExistingArrayError as e :
    if skip_existing :
        print ( ' - Skipping already present timestamps array.' )
        return
    else :
        raise e
self . ts_group . _v_attrs [ 'init_random_state' ] = rs . get_state ( )
self . _timestamps . attrs [ 'init_random_state' ] = rs . get_state ( )
self . _timestamps . attrs [ 'PyBroMo' ] = __version__
ts_list , part_list = [ ] , [ ]
# Load emission in chunks , and save only the final timestamps
bg_rates = [ None ] * ( len ( max_rates ) - 1 ) + [ bg_rate ]
prev_time = 0
for i_start , i_end in iter_chunk_index ( timeslice_size , t_chunksize ) :
    curr_time = np . around ( i_start * self . t_step , decimals = 0 )
    if curr_time > prev_time :
        print ( ' %.1fs' % curr_time , end = '' , flush = True )
        prev_time = curr_time
    em_chunk = self . emission [ : , i_start : i_end ]
    times_chunk_s , par_index_chunk_s = self . _sim_timestamps_populations ( em_chunk , max_rates , populations , bg_rates , i_start , rs , scale )
    # Save sorted timestamps ( suffix ' _ s ' ) and corresponding particles
    ts_list . append ( times_chunk_s )
    part_list . append ( par_index_chunk_s )
for ts , part in zip ( ts_list , part_list ) :
    self . _timestamps . append ( ts )
    self . _tparticles . append ( part )
# Save current random state so it can be resumed in the next session
self . ts_group . _v_attrs [ 'last_random_state' ] = rs . get_state ( )
self . _timestamps . attrs [ 'last_random_state' ] = rs . get_state ( )
self . ts_store . h5file . flush ( )


signature:
def simulate_timestamps_mix_da ( self , max_rates_d , max_rates_a , populations , bg_rate_d , bg_rate_a , rs = None , seed = 1 , chunksize = 2 ** 16 , comp_filter = None , overwrite = False , skip_existing = False , scale = 10 , path = None , t_chunksize = 2 ** 19 , timeslice = None ) :
    """Compute D and A timestamps arrays for a mixture of N populations .
 This method reads the emission from disk once , and generates a pair
 of timestamps arrays ( e . g . donor and acceptor ) from each chunk .
 Timestamp data are saved to disk and accessible as pytables arrays in
 ` . _ timestamps _ d / a ` and ` . _ tparticles _ d / a ` .
 The background generated timestamps are assigned a
 conventional particle number ( last particle index + 1 ) .
 Arguments :
 max _ rates _ d ( list ) : list of the peak max emission rate in the
 donor channel for each population .
 max _ rates _ a ( list ) : list of the peak max emission rate in the
 acceptor channel for each population .
 populations ( list of slices ) : slices to ` self . particles `
 defining each population .
 bg _ rate _ d ( float , cps ) : rate for a Poisson background process
 in the donor channel .
 bg _ rate _ a ( float , cps ) : rate for a Poisson background process
 in the acceptor channel .
 rs ( RandomState object ) : random state object used as random number
 generator . If None , use a random state initialized from seed .
 seed ( uint ) : when ` rs ` is None , ` seed ` is used to initialize the
 random state , otherwise is ignored .
 chunksize ( int ) : chunk size used for the on - disk timestamp array
 comp _ filter ( tables . Filter or None ) : compression filter to use
 for the on - disk ` timestamps ` and ` tparticles ` arrays .
 If None use default compression .
 overwrite ( bool ) : if True , overwrite any pre - existing timestamps
 array . If False , never overwrite . The outcome of simulating an
 existing array is controlled by ` skip _ existing ` flag .
 skip _ existing ( bool ) : if True , skip simulation if the same
 timestamps array is already present .
 scale ( int ) : ` self . t _ step ` is multiplied by ` scale ` to obtain the
 timestamps units in seconds .
 path ( string ) : folder where to save the data .
 timeslice ( float or None ) : timestamps are simulated until
 ` timeslice ` seconds . If None , simulate until ` self . t _ max ` ."""

implementation:
self . open_store_timestamp ( chunksize = chunksize , path = path )
rs = self . _get_group_randomstate ( rs , seed , self . ts_group )
if t_chunksize is None :
    t_chunksize = self . emission . chunkshape [ 1 ]
timeslice_size = self . n_samples
if timeslice is not None :
    timeslice_size = timeslice // self . t_step
name_d = self . _get_ts_name_mix ( max_rates_d , populations , bg_rate_d , rs )
name_a = self . _get_ts_name_mix ( max_rates_a , populations , bg_rate_a , rs )
kw = dict ( clk_p = self . t_step / scale , populations = populations , num_particles = self . num_particles , bg_particle = self . num_particles , overwrite = overwrite , chunksize = chunksize )
if comp_filter is not None :
    kw . update ( comp_filter = comp_filter )
kw . update ( name = name_d , max_rates = max_rates_d , bg_rate = bg_rate_d )
try :
    self . _timestamps_d , self . _tparticles_d = ( self . ts_store . add_timestamps ( ** kw ) )
except ExistingArrayError as e :
    if skip_existing :
        print ( ' - Skipping already present timestamps array.' )
        return
    else :
        raise e
kw . update ( name = name_a , max_rates = max_rates_a , bg_rate = bg_rate_a )
try :
    self . _timestamps_a , self . _tparticles_a = ( self . ts_store . add_timestamps ( ** kw ) )
except ExistingArrayError as e :
    if skip_existing :
        print ( ' - Skipping already present timestamps array.' )
        return
    else :
        raise e
self . ts_group . _v_attrs [ 'init_random_state' ] = rs . get_state ( )
self . _timestamps_d . attrs [ 'init_random_state' ] = rs . get_state ( )
self . _timestamps_d . attrs [ 'PyBroMo' ] = __version__
self . _timestamps_a . attrs [ 'init_random_state' ] = rs . get_state ( )
self . _timestamps_a . attrs [ 'PyBroMo' ] = __version__
# Load emission in chunks , and save only the final timestamps
bg_rates_d = [ None ] * ( len ( max_rates_d ) - 1 ) + [ bg_rate_d ]
bg_rates_a = [ None ] * ( len ( max_rates_a ) - 1 ) + [ bg_rate_a ]
prev_time = 0
for i_start , i_end in iter_chunk_index ( timeslice_size , t_chunksize ) :
    curr_time = np . around ( i_start * self . t_step , decimals = 1 )
    if curr_time > prev_time :
        print ( ' %.1fs' % curr_time , end = '' , flush = True )
        prev_time = curr_time
    em_chunk = self . emission [ : , i_start : i_end ]
    times_chunk_s_d , par_index_chunk_s_d = self . _sim_timestamps_populations ( em_chunk , max_rates_d , populations , bg_rates_d , i_start , rs , scale )
    times_chunk_s_a , par_index_chunk_s_a = self . _sim_timestamps_populations ( em_chunk , max_rates_a , populations , bg_rates_a , i_start , rs , scale )
    # Save sorted timestamps ( suffix ' _ s ' ) and corresponding particles
    self . _timestamps_d . append ( times_chunk_s_d )
    self . _tparticles_d . append ( par_index_chunk_s_d )
    self . _timestamps_a . append ( times_chunk_s_a )
    self . _tparticles_a . append ( par_index_chunk_s_a )
# Save current random state so it can be resumed in the next session
self . ts_group . _v_attrs [ 'last_random_state' ] = rs . get_state ( )
self . _timestamps_d . _v_attrs [ 'last_random_state' ] = rs . get_state ( )
self . ts_store . h5file . flush ( )


signature:
def merge_da ( ts_d , ts_par_d , ts_a , ts_par_a ) :
    """Merge donor and acceptor timestamps and particle arrays .
 Parameters :
 ts _ d ( array ) : donor timestamp array
 ts _ par _ d ( array ) : donor particles array
 ts _ a ( array ) : acceptor timestamp array
 ts _ par _ a ( array ) : acceptor particles array
 Returns :
 Arrays : timestamps , acceptor bool mask , timestamp particle"""

implementation:
ts = np . hstack ( [ ts_d , ts_a ] )
ts_par = np . hstack ( [ ts_par_d , ts_par_a ] )
a_ch = np . hstack ( [ np . zeros ( ts_d . shape [ 0 ] , dtype = bool ) , np . ones ( ts_a . shape [ 0 ] , dtype = bool ) ] )
index_sort = ts . argsort ( )
return ts [ index_sort ] , a_ch [ index_sort ] , ts_par [ index_sort ]


signature:
def em_rates_from_E_DA ( em_rate_tot , E_values ) :
    """Donor and Acceptor emission rates from total emission rate and E ( FRET ) ."""

implementation:
E_values = np . asarray ( E_values )
em_rates_a = E_values * em_rate_tot
em_rates_d = em_rate_tot - em_rates_a
return em_rates_d , em_rates_a


signature:
def em_rates_from_E_unique ( em_rate_tot , E_values ) :
    """Array of unique emission rates for given total emission and E ( FRET ) ."""

implementation:
em_rates_d , em_rates_a = em_rates_from_E_DA ( em_rate_tot , E_values )
return np . unique ( np . hstack ( [ em_rates_d , em_rates_a ] ) )


signature:
def em_rates_from_E_DA_mix ( em_rates_tot , E_values ) :
    """D and A emission rates for two populations ."""

implementation:
em_rates_d , em_rates_a = [ ] , [ ]
for em_rate_tot , E_value in zip ( em_rates_tot , E_values ) :
    em_rate_di , em_rate_ai = em_rates_from_E_DA ( em_rate_tot , E_value )
    em_rates_d . append ( em_rate_di )
    em_rates_a . append ( em_rate_ai )
return em_rates_d , em_rates_a


signature:
def populations_diff_coeff ( particles , populations ) :
    """Diffusion coefficients of the two specified populations ."""

implementation:
D_counts = particles . diffusion_coeff_counts
if len ( D_counts ) == 1 :
    pop_sizes = [ pop . stop - pop . start for pop in populations ]
    assert D_counts [ 0 ] [ 1 ] >= sum ( pop_sizes )
    D_counts = [ ( D_counts [ 0 ] [ 0 ] , ps ) for ps in pop_sizes ]
D_list = [ ]
D_pop_start = 0
# start index of diffusion - based populations
for pop , ( D , counts ) in zip ( populations , D_counts ) :
    D_list . append ( D )
    assert pop . start >= D_pop_start
    assert pop . stop <= D_pop_start + counts
    D_pop_start += counts
return D_list


signature:
def populations_slices ( particles , num_pop_list ) :
    """2 - tuple of slices for selection of two populations ."""

implementation:
slices = [ ]
i_prev = 0
for num_pop in num_pop_list :
    slices . append ( slice ( i_prev , i_prev + num_pop ) )
    i_prev += num_pop
return slices


signature:
def _calc_hash_da ( self , rs ) :
    """Compute hash of D and A timestamps for single - step D + A case ."""

implementation:
self . hash_d = hash_ ( rs . get_state ( ) ) [ : 6 ]
self . hash_a = self . hash_d


signature:
def run ( self , rs , overwrite = True , skip_existing = False , path = None , chunksize = None ) :
    """Compute timestamps for current populations ."""

implementation:
if path is None :
    path = str ( self . S . store . filepath . parent )
kwargs = dict ( rs = rs , overwrite = overwrite , path = path , timeslice = self . timeslice , skip_existing = skip_existing )
if chunksize is not None :
    kwargs [ 'chunksize' ] = chunksize
header = ' - Mixture Simulation:'
# Donor timestamps hash is from the input RandomState
self . hash_d = hash_ ( rs . get_state ( ) ) [ : 6 ]
# needed by merge _ da ( )
print ( '%s Donor timestamps -    %s' % ( header , ctime ( ) ) , flush = True )
self . S . simulate_timestamps_mix ( populations = self . populations , max_rates = self . em_rates_d , bg_rate = self . bg_rate_d , ** kwargs )
# Acceptor timestamps hash is from ' last _ random _ state ' attribute
# of the donor timestamps . This allows deterministic generation of
# donor + acceptor timestamps given the input random state .
ts_d , _ = self . S . get_timestamps_part ( self . name_timestamps_d )
rs . set_state ( ts_d . attrs [ 'last_random_state' ] )
self . hash_a = hash_ ( rs . get_state ( ) ) [ : 6 ]
# needed by merge _ da ( )
print ( '\n%s Acceptor timestamps - %s' % ( header , ctime ( ) ) , flush = True )
self . S . simulate_timestamps_mix ( populations = self . populations , max_rates = self . em_rates_a , bg_rate = self . bg_rate_a , ** kwargs )
print ( '\n%s Completed. %s' % ( header , ctime ( ) ) , flush = True )


signature:
def run_da ( self , rs , overwrite = True , skip_existing = False , path = None , chunksize = None ) :
    """Compute timestamps for current populations ."""

implementation:
if path is None :
    path = str ( self . S . store . filepath . parent )
kwargs = dict ( rs = rs , overwrite = overwrite , path = path , timeslice = self . timeslice , skip_existing = skip_existing )
if chunksize is not None :
    kwargs [ 'chunksize' ] = chunksize
header = ' - Mixture Simulation:'
# Donor timestamps hash is from the input RandomState
self . _calc_hash_da ( rs )
print ( '%s Donor + Acceptor timestamps - %s' % ( header , ctime ( ) ) , flush = True )
self . S . simulate_timestamps_mix_da ( max_rates_d = self . em_rates_d , max_rates_a = self . em_rates_a , populations = self . populations , bg_rate_d = self . bg_rate_d , bg_rate_a = self . bg_rate_a , ** kwargs )
print ( '\n%s Completed. %s' % ( header , ctime ( ) ) , flush = True )


signature:
def merge_da ( self ) :
    """Merge donor and acceptor timestamps , computes ` ts ` , ` a _ ch ` , ` part ` ."""

implementation:
print ( ' - Merging D and A timestamps' , flush = True )
ts_d , ts_par_d = self . S . get_timestamps_part ( self . name_timestamps_d )
ts_a , ts_par_a = self . S . get_timestamps_part ( self . name_timestamps_a )
ts , a_ch , part = merge_da ( ts_d , ts_par_d , ts_a , ts_par_a )
assert a_ch . sum ( ) == ts_a . shape [ 0 ]
assert ( ~ a_ch ) . sum ( ) == ts_d . shape [ 0 ]
assert a_ch . size == ts_a . shape [ 0 ] + ts_d . shape [ 0 ]
self . ts , self . a_ch , self . part = ts , a_ch , part
self . clk_p = ts_d . attrs [ 'clk_p' ]


signature:
def save_photon_hdf5 ( self , identity = None , overwrite = True , path = None ) :
    """Create a smFRET Photon - HDF5 file with current timestamps ."""

implementation:
filepath = self . filepath
if path is not None :
    filepath = Path ( path , filepath . name )
self . merge_da ( )
data = self . _make_photon_hdf5 ( identity = identity )
phc . hdf5 . save_photon_hdf5 ( data , h5_fname = str ( filepath ) , overwrite = overwrite )


signature:
def print_attrs ( data_file , node_name = '/' , which = 'user' , compress = False ) :
    """Print the HDF5 attributes for ` node _ name ` .
 Parameters :
 data _ file ( pytables HDF5 file object ) : the data file to print
 node _ name ( string ) : name of the path inside the file to be printed .
 Can be either a group or a leaf - node . Default : ' / ' , the root node .
 which ( string ) : Valid values are ' user ' for user - defined attributes ,
 ' sys ' for pytables - specific attributes and ' all ' to print both
 groups of attributes . Default ' user ' .
 compress ( bool ) : if True displays at most a line for each attribute .
 Default False ."""

implementation:
node = data_file . get_node ( node_name )
print ( 'List of attributes for:\n  %s\n' % node )
for attr in node . _v_attrs . _f_list ( ) :
    print ( '\t%s' % attr )
    attr_content = repr ( node . _v_attrs [ attr ] )
    if compress :
        attr_content = attr_content . split ( '\n' ) [ 0 ]
    print ( "\t    %s" % attr_content )


signature:
def print_children ( data_file , group = '/' ) :
    """Print all the sub - groups in ` group ` and leaf - nodes children of ` group ` .
 Parameters :
 data _ file ( pytables HDF5 file object ) : the data file to print
 group ( string ) : path name of the group to be printed .
 Default : ' / ' , the root node ."""

implementation:
base = data_file . get_node ( group )
print ( 'Groups in:\n  %s\n' % base )
for node in base . _f_walk_groups ( ) :
    if node is not base :
        print ( '    %s' % node )
print ( '\nLeaf-nodes in %s:' % group )
for node in base . _v_leaves . itervalues ( ) :
    info = node . shape
    if len ( info ) == 0 :
        info = node . read ( )
    print ( '\t%s, %s' % ( node . name , info ) )
    if len ( node . title ) > 0 :
        print ( '\t    %s' % node . title )


signature:
def fit ( self , trX , trY , batch_size = 64 , n_epochs = 1 , len_filter = LenFilter ( ) , snapshot_freq = 1 , path = None ) :
    """Train model on given training examples and return the list of costs after each minibatch is processed .
 Args :
 trX ( list ) - - Inputs
 trY ( list ) - - Outputs
 batch _ size ( int , optional ) - - number of examples in a minibatch ( default 64)
 n _ epochs ( int , optional ) - - number of epochs to train for ( default 1)
 len _ filter ( object , optional ) - - object to filter training example by length ( default LenFilter ( ) )
 snapshot _ freq ( int , optional ) - - number of epochs between saving model snapshots ( default 1)
 path ( str , optional ) - - prefix of path where model snapshots are saved .
 If None , no snapshots are saved ( default None )
 Returns :
 list - - costs of model after processing each minibatch"""

implementation:
if len_filter is not None :
    trX , trY = len_filter . filter ( trX , trY )
trY = standardize_targets ( trY , cost = self . cost )
n = 0.
t = time ( )
costs = [ ]
for e in range ( n_epochs ) :
    epoch_costs = [ ]
    for xmb , ymb in self . iterator . iterXY ( trX , trY ) :
        c = self . _train ( xmb , ymb )
        epoch_costs . append ( c )
        n += len ( ymb )
        if self . verbose >= 2 :
            n_per_sec = n / ( time ( ) - t )
            n_left = len ( trY ) - n % len ( trY )
            time_left = n_left / n_per_sec
            sys . stdout . write ( "\rEpoch %d Seen %d samples Avg cost %0.4f Time left %d seconds" % ( e , n , np . mean ( epoch_costs [ - 250 : ] ) , time_left ) )
            sys . stdout . flush ( )
    costs . extend ( epoch_costs )
    status = "Epoch %d Seen %d samples Avg cost %0.4f Time elapsed %d seconds" % ( e , n , np . mean ( epoch_costs [ - 250 : ] ) , time ( ) - t )
    if self . verbose >= 2 :
        sys . stdout . write ( "\r" + status )
        sys . stdout . flush ( )
        sys . stdout . write ( "\n" )
    elif self . verbose == 1 :
        print ( status )
    if path and e % snapshot_freq == 0 :
        save ( self , "{0}.{1}" . format ( path , e ) )
return costs


signature:
def plane_xz ( size = ( 10 , 10 ) , resolution = ( 10 , 10 ) ) -> VAO :
    """Generates a plane on the xz axis of a specific size and resolution .
 Normals and texture coordinates are also included .
 Args :
 size : ( x , y ) tuple
 resolution : ( x , y ) tuple
 Returns :
 A : py : class : ` demosys . opengl . vao . VAO ` instance"""

implementation:
sx , sz = size
rx , rz = resolution
dx , dz = sx / rx , sz / rz
# step
ox , oz = - sx / 2 , - sz / 2
# start offset
def gen_pos ( ) :
    for z in range ( rz ) :
        for x in range ( rx ) :
            yield ox + x * dx
            yield 0
            yield oz + z * dz
def gen_uv ( ) :
    for z in range ( rz ) :
        for x in range ( rx ) :
            yield x / ( rx - 1 )
            yield 1 - z / ( rz - 1 )
def gen_normal ( ) :
    for _ in range ( rx * rz ) :
        yield 0.0
        yield 1.0
        yield 0.0
def gen_index ( ) :
    for z in range ( rz - 1 ) :
        for x in range ( rx - 1 ) : # quad poly left
            yield z * rz + x + 1
            yield z * rz + x
            yield z * rz + x + rx
            # quad poly right
            yield z * rz + x + 1
            yield z * rz + x + rx
            yield z * rz + x + rx + 1
pos_data = numpy . fromiter ( gen_pos ( ) , dtype = numpy . float32 )
uv_data = numpy . fromiter ( gen_uv ( ) , dtype = numpy . float32 )
normal_data = numpy . fromiter ( gen_normal ( ) , dtype = numpy . float32 )
index_data = numpy . fromiter ( gen_index ( ) , dtype = numpy . uint32 )
vao = VAO ( "plane_xz" , mode = moderngl . TRIANGLES )
vao . buffer ( pos_data , '3f' , [ 'in_position' ] )
vao . buffer ( uv_data , '2f' , [ 'in_uv' ] )
vao . buffer ( normal_data , '3f' , [ 'in_normal' ] )
vao . index_buffer ( index_data , index_element_size = 4 )
return vao


signature:
def load ( self ) :
    """Deferred loading of the scene
 : param scene : The scene object
 : param file : Resolved path if changed by finder"""

implementation:
self . path = self . find_scene ( self . meta . path )
if not self . path :
    raise ValueError ( "Scene '{}' not found" . format ( self . meta . path ) )
self . scene = Scene ( self . path )
# Load gltf json file
if self . path . suffix == '.gltf' :
    self . load_gltf ( )
# Load binary gltf file
if self . path . suffix == '.glb' :
    self . load_glb ( )
self . meta . check_version ( )
self . meta . check_extensions ( self . supported_extensions )
self . load_images ( )
self . load_samplers ( )
self . load_textures ( )
self . load_materials ( )
self . load_meshes ( )
self . load_nodes ( )
self . scene . calc_scene_bbox ( )
self . scene . prepare ( )
return self . scene


signature:
def load_gltf ( self ) :
    """Loads a gltf json file"""

implementation:
with open ( self . path ) as fd :
    self . meta = GLTFMeta ( self . path , json . load ( fd ) )


signature:
def load_glb ( self ) :
    """Loads a binary gltf file"""

implementation:
with open ( self . path , 'rb' ) as fd : # Check header
    magic = fd . read ( 4 )
    if magic != GLTF_MAGIC_HEADER :
        raise ValueError ( "{} has incorrect header {} != {}" . format ( self . path , magic , GLTF_MAGIC_HEADER ) )
    version = struct . unpack ( '<I' , fd . read ( 4 ) ) [ 0 ]
    if version != 2 :
        raise ValueError ( "{} has unsupported version {}" . format ( self . path , version ) )
    # Total file size including headers
    _ = struct . unpack ( '<I' , fd . read ( 4 ) ) [ 0 ]
    # noqa
    # Chunk 0 - json
    chunk_0_length = struct . unpack ( '<I' , fd . read ( 4 ) ) [ 0 ]
    chunk_0_type = fd . read ( 4 )
    if chunk_0_type != b'JSON' :
        raise ValueError ( "Expected JSON chunk, not {} in file {}" . format ( chunk_0_type , self . path ) )
    json_meta = fd . read ( chunk_0_length ) . decode ( )
    # chunk 1 - binary buffer
    chunk_1_length = struct . unpack ( '<I' , fd . read ( 4 ) ) [ 0 ]
    chunk_1_type = fd . read ( 4 )
    if chunk_1_type != b'BIN\x00' :
        raise ValueError ( "Expected BIN chunk, not {} in file {}" . format ( chunk_1_type , self . path ) )
    self . meta = GLTFMeta ( self . path , json . loads ( json_meta ) , binary_buffer = fd . read ( chunk_1_length ) )


signature:
def _link_data ( self ) :
    """Add references"""

implementation:
# accessors - > buffer _ views - > buffers
for acc in self . accessors :
    acc . bufferView = self . buffer_views [ acc . bufferViewId ]
for buffer_view in self . buffer_views :
    buffer_view . buffer = self . buffers [ buffer_view . bufferId ]
# Link accessors to mesh primitives
for mesh in self . meshes :
    for primitive in mesh . primitives :
        if getattr ( primitive , "indices" , None ) is not None :
            primitive . indices = self . accessors [ primitive . indices ]
        for name , value in primitive . attributes . items ( ) :
            primitive . attributes [ name ] = self . accessors [ value ]
# Link buffer views to images
for image in self . images :
    if image . bufferViewId is not None :
        image . bufferView = self . buffer_views [ image . bufferViewId ]


signature:
def check_extensions ( self , supported ) :
    """" extensionsRequired " : [ " KHR _ draco _ mesh _ compression " ] ,
 " extensionsUsed " : [ " KHR _ draco _ mesh _ compression " ]"""

implementation:
if self . data . get ( 'extensionsRequired' ) :
    for ext in self . data . get ( 'extensionsRequired' ) :
        if ext not in supported :
            raise ValueError ( "Extension {} not supported" . format ( ext ) )
if self . data . get ( 'extensionsUsed' ) :
    for ext in self . data . get ( 'extensionsUsed' ) :
        if ext not in supported :
            raise ValueError ( "Extension {} not supported" . format ( ext ) )


signature:
def buffers_exist ( self ) :
    """Checks if the bin files referenced exist"""

implementation:
for buff in self . buffers :
    if not buff . is_separate_file :
        continue
    path = self . path . parent / buff . uri
    if not os . path . exists ( path ) :
        raise FileNotFoundError ( "Buffer {} referenced in {} not found" . format ( path , self . path ) )


signature:
def load_indices ( self , primitive ) :
    """Loads the index buffer / polygon list for a primitive"""

implementation:
if getattr ( primitive , "indices" ) is None :
    return None , None
_ , component_type , buffer = primitive . indices . read ( )
return component_type , buffer


signature:
def prepare_attrib_mapping ( self , primitive ) :
    """Pre - parse buffer mappings for each VBO to detect interleaved data for a primitive"""

implementation:
buffer_info = [ ]
for name , accessor in primitive . attributes . items ( ) :
    info = VBOInfo ( * accessor . info ( ) )
    info . attributes . append ( ( name , info . components ) )
    if buffer_info and buffer_info [ - 1 ] . buffer_view == info . buffer_view :
        if buffer_info [ - 1 ] . interleaves ( info ) :
            buffer_info [ - 1 ] . merge ( info )
            continue
    buffer_info . append ( info )
return buffer_info


signature:
def get_bbox ( self , primitive ) :
    """Get the bounding box for the mesh"""

implementation:
accessor = primitive . attributes . get ( 'POSITION' )
return accessor . min , accessor . max


signature:
def interleaves ( self , info ) :
    """Does the buffer interleave with this one ?"""

implementation: return info . byte_offset == self . component_type . size * self . components


signature:
def create ( self ) :
    """Create the VBO"""

implementation:
dtype = NP_COMPONENT_DTYPE [ self . component_type . value ]
data = numpy . frombuffer ( self . buffer . read ( byte_length = self . byte_length , byte_offset = self . byte_offset ) , count = self . count * self . components , dtype = dtype , )
return dtype , data


signature:
def read ( self ) :
    """Reads buffer data
 : return : component count , component type , data"""

implementation:
# ComponentType helps us determine the datatype
dtype = NP_COMPONENT_DTYPE [ self . componentType . value ]
return ACCESSOR_TYPE [ self . type ] , self . componentType , self . bufferView . read ( byte_offset = self . byteOffset , dtype = dtype , count = self . count * ACCESSOR_TYPE [ self . type ] , )


signature:
def info ( self ) :
    """Get underlying buffer info for this accessor
 : return : buffer , byte _ length , byte _ offset , component _ type , count"""

implementation:
buffer , byte_length , byte_offset = self . bufferView . info ( byte_offset = self . byteOffset )
return buffer , self . bufferView , byte_length , byte_offset , self . componentType , ACCESSOR_TYPE [ self . type ] , self . count


signature:
def info ( self , byte_offset = 0 ) :
    """Get the underlying buffer info
 : param byte _ offset : byte offset from accessor
 : return : buffer , byte _ length , byte _ offset"""

implementation: return self . buffer , self . byteLength , byte_offset + self . byteOffset


signature:
def set_position ( self , x , y , z ) :
    """Set the 3D position of the camera
 : param x : float
 : param y : float
 : param z : float"""

implementation: self . position = Vector3 ( [ x , y , z ] )


signature:
def view_matrix ( self ) :
    """: return : The current view matrix for the camera"""

implementation:
self . _update_yaw_and_pitch ( )
return self . _gl_look_at ( self . position , self . position + self . dir , self . _up )


signature:
def _update_yaw_and_pitch ( self ) :
    """Updates the camera vectors based on the current yaw and pitch"""

implementation:
front = Vector3 ( [ 0.0 , 0.0 , 0.0 ] )
front . x = cos ( radians ( self . yaw ) ) * cos ( radians ( self . pitch ) )
front . y = sin ( radians ( self . pitch ) )
front . z = sin ( radians ( self . yaw ) ) * cos ( radians ( self . pitch ) )
self . dir = vector . normalise ( front )
self . right = vector . normalise ( vector3 . cross ( self . dir , self . _up ) )
self . up = vector . normalise ( vector3 . cross ( self . right , self . dir ) )


signature:
def look_at ( self , vec = None , pos = None ) :
    """Look at a specific point
 : param vec : Vector3 position
 : param pos : python list [ x , y , x ]
 : return : Camera matrix"""

implementation:
if pos is None :
    vec = Vector3 ( pos )
if vec is None :
    raise ValueError ( "vector or pos must be set" )
return self . _gl_look_at ( self . position , vec , self . _up )


signature:
def _gl_look_at ( self , pos , target , up ) :
    """The standard lookAt method
 : param pos : current position
 : param target : target position to look at
 : param up : direction up"""

implementation:
z = vector . normalise ( pos - target )
x = vector . normalise ( vector3 . cross ( vector . normalise ( up ) , z ) )
y = vector3 . cross ( z , x )
translate = matrix44 . create_identity ( )
translate [ 3 ] [ 0 ] = - pos . x
translate [ 3 ] [ 1 ] = - pos . y
translate [ 3 ] [ 2 ] = - pos . z
rotate = matrix44 . create_identity ( )
rotate [ 0 ] [ 0 ] = x [ 0 ]
rotate [ 1 ] [ 0 ] = x [ 1 ]
rotate [ 2 ] [ 0 ] = x [ 2 ]
rotate [ 0 ] [ 1 ] = y [ 0 ]
rotate [ 1 ] [ 1 ] = y [ 1 ]
rotate [ 2 ] [ 1 ] = y [ 2 ]
rotate [ 0 ] [ 2 ] = z [ 0 ]
rotate [ 1 ] [ 2 ] = z [ 1 ]
rotate [ 2 ] [ 2 ] = z [ 2 ]
return matrix44 . multiply ( translate , rotate )


signature:
def move_state ( self , direction , activate ) :
    """Set the camera position move state
 : param direction : What direction to update
 : param activate : Start or stop moving in the direction"""

implementation:
if direction == RIGHT :
    self . _xdir = POSITIVE if activate else STILL
elif direction == LEFT :
    self . _xdir = NEGATIVE if activate else STILL
elif direction == FORWARD :
    self . _zdir = NEGATIVE if activate else STILL
elif direction == BACKWARD :
    self . _zdir = POSITIVE if activate else STILL
elif direction == UP :
    self . _ydir = POSITIVE if activate else STILL
elif direction == DOWN :
    self . _ydir = NEGATIVE if activate else STILL


signature:
def rot_state ( self , x , y ) :
    """Set the rotation state of the camera
 : param x : viewport x pos
 : param y : viewport y pos"""

implementation:
if self . last_x is None :
    self . last_x = x
if self . last_y is None :
    self . last_y = y
x_offset = self . last_x - x
y_offset = self . last_y - y
self . last_x = x
self . last_y = y
x_offset *= self . mouse_sensitivity
y_offset *= self . mouse_sensitivity
self . yaw -= x_offset
self . pitch += y_offset
if self . pitch > 85.0 :
    self . pitch = 85.0
if self . pitch < - 85.0 :
    self . pitch = - 85.0
self . _update_yaw_and_pitch ( )


implementation:
# Use separate time in camera so we can move it when the demo is paused
now = time . time ( )
# If the camera has been inactive for a while , a large time delta
# can suddenly move the camera far away from the scene
t = max ( now - self . _last_time , 0 )
self . _last_time = now
# X Movement
if self . _xdir == POSITIVE :
    self . position += self . right * self . velocity * t
elif self . _xdir == NEGATIVE :
    self . position -= self . right * self . velocity * t
# Z Movement
if self . _zdir == NEGATIVE :
    self . position += self . dir * self . velocity * t
elif self . _zdir == POSITIVE :
    self . position -= self . dir * self . velocity * t
# Y Movement
if self . _ydir == POSITIVE :
    self . position += self . up * self . velocity * t
elif self . _ydir == NEGATIVE :
    self . position -= self . up * self . velocity * t
return self . _gl_look_at ( self . position , self . position + self . dir , self . _up )


signature:
def _translate_string ( self , data , length ) :
    """Translate string into character texture positions"""

implementation:
for index , char in enumerate ( data ) :
    if index == length :
        break
    yield self . _meta . characters - 1 - self . _ct [ char ]


signature:
def _generate_character_map ( self ) :
    """Generate character translation map ( latin1 pos to texture pos )"""

implementation:
self . _ct = [ - 1 ] * 256
index = 0
for crange in self . _meta . character_ranges :
    for cpos in range ( crange [ 'min' ] , crange [ 'max' ] + 1 ) :
        self . _ct [ cpos ] = index
        index += 1


signature:
def buffer_format ( frmt : str ) -> BufferFormat :
    """Look up info about a buffer format
 : param frmt : format string such as ' f ' , ' i ' and ' u '
 : return : BufferFormat instance"""

implementation:
try :
    return BUFFER_FORMATS [ frmt ]
except KeyError :
    raise ValueError ( "Buffer format '{}' unknown. Valid formats: {}" . format ( frmt , BUFFER_FORMATS . keys ( ) ) )


signature:
def attribute_format ( frmt : str ) -> BufferFormat :
    """Look up info about an attribute format
 : param frmt : Format of an
 : return : BufferFormat instance"""

implementation:
try :
    return ATTRIBUTE_FORMATS [ frmt ]
except KeyError :
    raise ValueError ( "Buffer format '{}' unknown. Valid formats: {}" . format ( frmt , ATTRIBUTE_FORMATS . keys ( ) ) )


signature:
def init ( window = None , project = None , timeline = None ) :
    """Initialize , load and run
 : param manager : The effect manager to use"""

implementation:
from demosys . effects . registry import Effect
from demosys . scene import camera
window . timeline = timeline
# Inject attributes into the base Effect class
setattr ( Effect , '_window' , window )
setattr ( Effect , '_ctx' , window . ctx )
setattr ( Effect , '_project' , project )
# Set up the default system camera
window . sys_camera = camera . SystemCamera ( aspect = window . aspect_ratio , fov = 60.0 , near = 1 , far = 1000 )
setattr ( Effect , '_sys_camera' , window . sys_camera )
print ( "Loading started at" , time . time ( ) )
project . load ( )
# Initialize timer
timer_cls = import_string ( settings . TIMER )
window . timer = timer_cls ( )
window . timer . start ( )


signature:
def draw ( self , projection_matrix = None , camera_matrix = None , time = 0 ) :
    """Draw all the nodes in the scene
 : param projection _ matrix : projection matrix ( bytes )
 : param camera _ matrix : camera _ matrix ( bytes )
 : param time : The current time"""

implementation:
projection_matrix = projection_matrix . astype ( 'f4' ) . tobytes ( )
camera_matrix = camera_matrix . astype ( 'f4' ) . tobytes ( )
for node in self . root_nodes :
    node . draw ( projection_matrix = projection_matrix , camera_matrix = camera_matrix , time = time , )
self . ctx . clear_samplers ( 0 , 4 )


signature:
def draw_bbox ( self , projection_matrix = None , camera_matrix = None , all = True ) :
    """Draw scene and mesh bounding boxes"""

implementation:
projection_matrix = projection_matrix . astype ( 'f4' ) . tobytes ( )
camera_matrix = camera_matrix . astype ( 'f4' ) . tobytes ( )
# Scene bounding box
self . bbox_program [ "m_proj" ] . write ( projection_matrix )
self . bbox_program [ "m_view" ] . write ( self . _view_matrix . astype ( 'f4' ) . tobytes ( ) )
self . bbox_program [ "m_cam" ] . write ( camera_matrix )
self . bbox_program [ "bb_min" ] . write ( self . bbox_min . astype ( 'f4' ) . tobytes ( ) )
self . bbox_program [ "bb_max" ] . write ( self . bbox_max . astype ( 'f4' ) . tobytes ( ) )
self . bbox_program [ "color" ] . value = ( 1.0 , 0.0 , 0.0 )
self . bbox_vao . render ( self . bbox_program )
if not all :
    return
# Draw bounding box for children
for node in self . root_nodes :
    node . draw_bbox ( projection_matrix , camera_matrix , self . bbox_program , self . bbox_vao )


signature:
def apply_mesh_programs ( self , mesh_programs = None ) :
    """Applies mesh programs to meshes"""

implementation:
if not mesh_programs :
    mesh_programs = [ ColorProgram ( ) , TextureProgram ( ) , FallbackProgram ( ) ]
for mesh in self . meshes :
    for mp in mesh_programs :
        instance = mp . apply ( mesh )
        if instance is not None :
            if isinstance ( instance , MeshProgram ) :
                mesh . mesh_program = mp
                break
            else :
                raise ValueError ( "apply() must return a MeshProgram instance, not {}" . format ( type ( instance ) ) )
    if not mesh . mesh_program :
        print ( "WARING: No mesh program applied to '{}'" . format ( mesh . name ) )


signature:
def calc_scene_bbox ( self ) :
    """Calculate scene bbox"""

implementation:
bbox_min , bbox_max = None , None
for node in self . root_nodes :
    bbox_min , bbox_max = node . calc_global_bbox ( matrix44 . create_identity ( ) , bbox_min , bbox_max )
self . bbox_min = bbox_min
self . bbox_max = bbox_max
self . diagonal_size = vector3 . length ( self . bbox_max - self . bbox_min )


signature:
def points_random_3d ( count , range_x = ( - 10.0 , 10.0 ) , range_y = ( - 10.0 , 10.0 ) , range_z = ( - 10.0 , 10.0 ) , seed = None ) -> VAO :
    """Generates random positions inside a confied box .
 Args :
 count ( int ) : Number of points to generate
 Keyword Args :
 range _ x ( tuple ) : min - max range for x axis : Example ( - 10.0 . 10.0)
 range _ y ( tuple ) : min - max range for y axis : Example ( - 10.0 . 10.0)
 range _ z ( tuple ) : min - max range for z axis : Example ( - 10.0 . 10.0)
 seed ( int ) : The random seed
 Returns :
 A : py : class : ` demosys . opengl . vao . VAO ` instance"""

implementation:
random . seed ( seed )
def gen ( ) :
    for _ in range ( count ) :
        yield random . uniform ( * range_x )
        yield random . uniform ( * range_y )
        yield random . uniform ( * range_z )
data = numpy . fromiter ( gen ( ) , count = count * 3 , dtype = numpy . float32 )
vao = VAO ( "geometry:points_random_3d" , mode = moderngl . POINTS )
vao . buffer ( data , '3f' , [ 'in_position' ] )
return vao


signature:
def start ( self ) :
    """Play the music"""

implementation:
if self . initialized :
    mixer . music . unpause ( )
else :
    mixer . music . play ( )
    # FIXME : Calling play twice to ensure the music is actually playing
    mixer . music . play ( )
    self . initialized = True
self . paused = False


signature:
def pause ( self ) :
    """Pause the music"""

implementation:
mixer . music . pause ( )
self . pause_time = self . get_time ( )
self . paused = True


signature:
def get_time ( self ) -> float :
    """Get the current position in the music in seconds"""

implementation:
if self . paused :
    return self . pause_time
return mixer . music . get_pos ( ) / 1000.0


signature:
def set_time ( self , value : float ) :
    """Set the current time in the music in seconds causing the player
 to seek to this location in the file ."""

implementation:
if value < 0 :
    value = 0
# mixer . music . play ( start = value )
mixer . music . set_pos ( value )


signature:
def draw_buffers ( self , near , far ) :
    """Draw framebuffers for debug purposes .
 We need to supply near and far plane so the depth buffer can be linearized when visualizing .
 : param near : Projection near value
 : param far : Projection far value"""

implementation:
self . ctx . disable ( moderngl . DEPTH_TEST )
helper . draw ( self . gbuffer . color_attachments [ 0 ] , pos = ( 0.0 , 0.0 ) , scale = ( 0.25 , 0.25 ) )
helper . draw ( self . gbuffer . color_attachments [ 1 ] , pos = ( 0.5 , 0.0 ) , scale = ( 0.25 , 0.25 ) )
helper . draw_depth ( self . gbuffer . depth_attachment , near , far , pos = ( 1.0 , 0.0 ) , scale = ( 0.25 , 0.25 ) )
helper . draw ( self . lightbuffer . color_attachments [ 0 ] , pos = ( 1.5 , 0.0 ) , scale = ( 0.25 , 0.25 ) )


signature:
def add_point_light ( self , position , radius ) :
    """Add point light"""

implementation: self . point_lights . append ( PointLight ( position , radius ) )


signature:
def render_lights ( self , camera_matrix , projection ) :
    """Render light volumes"""

implementation:
# Draw light volumes from the inside
self . ctx . front_face = 'cw'
self . ctx . blend_func = moderngl . ONE , moderngl . ONE
helper . _depth_sampler . use ( location = 1 )
with self . lightbuffer_scope :
    for light in self . point_lights : # Calc light properties
        light_size = light . radius
        m_light = matrix44 . multiply ( light . matrix , camera_matrix )
        # Draw the light volume
        self . point_light_shader [ "m_proj" ] . write ( projection . tobytes ( ) )
        self . point_light_shader [ "m_light" ] . write ( m_light . astype ( 'f4' ) . tobytes ( ) )
        self . gbuffer . color_attachments [ 1 ] . use ( location = 0 )
        self . point_light_shader [ "g_normal" ] . value = 0
        self . gbuffer . depth_attachment . use ( location = 1 )
        self . point_light_shader [ "g_depth" ] . value = 1
        self . point_light_shader [ "screensize" ] . value = ( self . width , self . height )
        self . point_light_shader [ "proj_const" ] . value = projection . projection_constants
        self . point_light_shader [ "radius" ] . value = light_size
        self . unit_cube . render ( self . point_light_shader )
helper . _depth_sampler . clear ( location = 1 )


signature:
def render_lights_debug ( self , camera_matrix , projection ) :
    """Render outlines of light volumes"""

implementation:
self . ctx . enable ( moderngl . BLEND )
self . ctx . blend_func = moderngl . SRC_ALPHA , moderngl . ONE_MINUS_SRC_ALPHA
for light in self . point_lights :
    m_mv = matrix44 . multiply ( light . matrix , camera_matrix )
    light_size = light . radius
    self . debug_shader [ "m_proj" ] . write ( projection . tobytes ( ) )
    self . debug_shader [ "m_mv" ] . write ( m_mv . astype ( 'f4' ) . tobytes ( ) )
    self . debug_shader [ "size" ] . value = light_size
    self . unit_cube . render ( self . debug_shader , mode = moderngl . LINE_STRIP )
self . ctx . disable ( moderngl . BLEND )


signature:
def combine ( self ) :
    """Combine diffuse and light buffer"""

implementation:
self . gbuffer . color_attachments [ 0 ] . use ( location = 0 )
self . combine_shader [ "diffuse_buffer" ] . value = 0
self . lightbuffer . color_attachments [ 0 ] . use ( location = 1 )
self . combine_shader [ "light_buffer" ] . value = 1
self . quad . render ( self . combine_shader )


signature:
def load_shader ( self , shader_type : str , path : str ) :
    """Load a single shader"""

implementation:
if path :
    resolved_path = self . find_program ( path )
    if not resolved_path :
        raise ValueError ( "Cannot find {} shader '{}'" . format ( shader_type , path ) )
    print ( "Loading:" , path )
    with open ( resolved_path , 'r' ) as fd :
        return fd . read ( )


signature:
def load ( self ) :
    """Load a texture array"""

implementation:
self . _open_image ( )
width , height , depth = self . image . size [ 0 ] , self . image . size [ 1 ] // self . layers , self . layers
components , data = image_data ( self . image )
texture = self . ctx . texture_array ( ( width , height , depth ) , components , data , )
texture . extra = { 'meta' : self . meta }
if self . meta . mipmap :
    texture . build_mipmaps ( )
self . _close_image ( )
return texture


signature:
def draw ( self , projection_matrix = None , view_matrix = None , camera_matrix = None , time = 0 ) :
    """Draw the mesh using the assigned mesh program
 : param projection _ matrix : projection _ matrix ( bytes )
 : param view _ matrix : view _ matrix ( bytes )
 : param camera _ matrix : camera _ matrix ( bytes )"""

implementation:
if self . mesh_program :
    self . mesh_program . draw ( self , projection_matrix = projection_matrix , view_matrix = view_matrix , camera_matrix = camera_matrix , time = time )


signature:
def add_attribute ( self , attr_type , name , components ) :
    """Add metadata about the mesh
 : param attr _ type : POSITION , NORMAL etc
 : param name : The attribute name used in the program
 : param components : Number of floats"""

implementation: self . attributes [ attr_type ] = { "name" : name , "components" : components }


signature:
def set_time ( self , value : float ) :
    """Set the current time jumping in the timeline .
 Args :
 value ( float ) : The new time"""

implementation:
if value < 0 :
    value = 0
self . controller . row = self . rps * value


signature:
def draw ( self , time : float , frametime : float , target : moderngl . Framebuffer ) :
    """Draw function called by the system every frame when the effect is active .
 This method raises ` ` NotImplementedError ` ` unless implemented .
 Args :
 time ( float ) : The current time in seconds .
 frametime ( float ) : The time the previous frame used to render in seconds .
 target ( ` ` moderngl . Framebuffer ` ` ) : The target FBO for the effect ."""

implementation: raise NotImplementedError ( "draw() is not implemented" )


signature:
def get_program ( self , label : str ) -> moderngl . Program :
    """Get a program by its label
 Args :
 label ( str ) : The label for the program
 Returns : py : class : ` moderngl . Program ` instance"""

implementation: return self . _project . get_program ( label )


signature:
def get_texture ( self , label : str ) -> Union [ moderngl . Texture , moderngl . TextureArray , moderngl . Texture3D , moderngl . TextureCube ] :
    """Get a texture by its label
 Args :
 label ( str ) : The Label for the texture
 Returns :
 The py : class : ` moderngl . Texture ` instance"""

implementation: return self . _project . get_texture ( label )


signature:
def get_effect_class ( self , effect_name : str , package_name : str = None ) -> Type [ 'Effect' ] :
    """Get an effect class by the class name
 Args :
 effect _ name ( str ) : Name of the effect class
 Keyword Args :
 package _ name ( str ) : The package the effect belongs to . This is optional and only
 needed when effect class names are not unique .
 Returns :
 : py : class : ` Effect ` class"""

implementation: return self . _project . get_effect_class ( effect_name , package_name = package_name )


signature:
def create_projection ( self , fov : float = 75.0 , near : float = 1.0 , far : float = 100.0 , aspect_ratio : float = None ) :
    """Create a projection matrix with the following parameters .
 When ` ` aspect _ ratio ` ` is not provided the configured aspect
 ratio for the window will be used .
 Args :
 fov ( float ) : Field of view ( float )
 near ( float ) : Camera near value
 far ( float ) : Camrea far value
 Keyword Args :
 aspect _ ratio ( float ) : Aspect ratio of the viewport
 Returns :
 The projection matrix as a float32 : py : class : ` numpy . array `"""

implementation: return matrix44 . create_perspective_projection_matrix ( fov , aspect_ratio or self . window . aspect_ratio , near , far , dtype = 'f4' , )


signature:
def create_transformation ( self , rotation = None , translation = None ) :
    """Creates a transformation matrix woth rotations and translation .
 Args :
 rotation : 3 component vector as a list , tuple , or : py : class : ` pyrr . Vector3 `
 translation : 3 component vector as a list , tuple , or : py : class : ` pyrr . Vector3 `
 Returns :
 A 4x4 matrix as a : py : class : ` numpy . array `"""

implementation:
mat = None
if rotation is not None :
    mat = Matrix44 . from_eulers ( Vector3 ( rotation ) )
if translation is not None :
    trans = matrix44 . create_from_translation ( Vector3 ( translation ) )
    if mat is None :
        mat = trans
    else :
        mat = matrix44 . multiply ( mat , trans )
return mat


signature:
def create_normal_matrix ( self , modelview ) :
    """Creates a normal matrix from modelview matrix
 Args :
 modelview : The modelview matrix
 Returns :
 A 3x3 Normal matrix as a : py : class : ` numpy . array `"""

implementation:
normal_m = Matrix33 . from_matrix44 ( modelview )
normal_m = normal_m . inverse
normal_m = normal_m . transpose ( )
return normal_m


signature:
def available_templates ( value ) :
    """Scan for available templates in effect _ templates"""

implementation:
templates = list_templates ( )
if value not in templates :
    raise ArgumentTypeError ( "Effect template '{}' does not exist.\n Available templates: {} " . format ( value , ", " . join ( templates ) ) )
return value


signature:
def root_path ( ) :
    """Get the absolute path to the root of the demosys package"""

implementation:
module_dir = os . path . dirname ( globals ( ) [ '__file__' ] )
return os . path . dirname ( os . path . dirname ( module_dir ) )


signature:
def load ( self ) :
    """Load a file in text mode"""

implementation:
self . meta . resolved_path = self . find_data ( self . meta . path )
if not self . meta . resolved_path :
    raise ImproperlyConfigured ( "Data file '{}' not found" . format ( self . meta . path ) )
print ( "Loading:" , self . meta . path )
with open ( self . meta . resolved_path , 'r' ) as fd :
    return fd . read ( )


signature:
def get_finder ( import_path ) :
    """Get a finder class from an import path .
 Raises ` ` demosys . core . exceptions . ImproperlyConfigured ` ` if the finder is not found .
 This function uses an lru cache .
 : param import _ path : string representing an import path
 : return : An instance of the finder"""

implementation:
Finder = import_string ( import_path )
if not issubclass ( Finder , BaseFileSystemFinder ) :
    raise ImproperlyConfigured ( 'Finder {} is not a subclass of core.finders.FileSystemFinder' . format ( import_path ) )
return Finder ( )


signature:
def find ( self , path : Path ) :
    """Find a file in the path . The file may exist in multiple
 paths . The last found file will be returned .
 : param path : The path to find
 : return : The absolute path to the file or None if not found"""

implementation:
# Update paths from settings to make them editable runtime
# This is only possible for FileSystemFinders
if getattr ( self , 'settings_attr' , None ) :
    self . paths = getattr ( settings , self . settings_attr )
path_found = None
for entry in self . paths :
    abspath = entry / path
    if abspath . exists ( ) :
        path_found = abspath
return path_found


signature:
def update ( self , aspect_ratio = None , fov = None , near = None , far = None ) :
    """Update the internal projection matrix based on current values
 or values passed in if specified .
 : param aspect _ ratio : New aspect ratio
 : param fov : New field of view
 : param near : New near value
 : param far : New far value"""

implementation:
self . aspect_ratio = aspect_ratio or self . aspect_ratio
self . fov = fov or self . fov
self . near = near or self . near
self . far = far or self . far
self . matrix = Matrix44 . perspective_projection ( self . fov , self . aspect_ratio , self . near , self . far )


signature:
def projection_constants ( self ) :
    """Returns the ( x , y ) projection constants for the current projection .
 : return : x , y tuple projection constants"""

implementation: return self . far / ( self . far - self . near ) , ( self . far * self . near ) / ( self . near - self . far )


signature:
def draw ( self , projection_matrix = None , camera_matrix = None , time = 0 ) :
    """Draw node and children
 : param projection _ matrix : projection matrix ( bytes )
 : param camera _ matrix : camera _ matrix ( bytes )
 : param time : The current time"""

implementation:
if self . mesh :
    self . mesh . draw ( projection_matrix = projection_matrix , view_matrix = self . matrix_global_bytes , camera_matrix = camera_matrix , time = time )
for child in self . children :
    child . draw ( projection_matrix = projection_matrix , camera_matrix = camera_matrix , time = time )


signature:
def calc_global_bbox ( self , view_matrix , bbox_min , bbox_max ) :
    """Recursive calculation of scene bbox"""

implementation:
if self . matrix is not None :
    view_matrix = matrix44 . multiply ( self . matrix , view_matrix )
if self . mesh :
    bbox_min , bbox_max = self . mesh . calc_global_bbox ( view_matrix , bbox_min , bbox_max )
for child in self . children :
    bbox_min , bbox_max = child . calc_global_bbox ( view_matrix , bbox_min , bbox_max )
return bbox_min , bbox_max


signature:
def swap_buffers ( self ) :
    """Swaps buffers , incement the framecounter and pull events ."""

implementation:
self . frames += 1
glfw . swap_buffers ( self . window )
self . poll_events ( )


signature:
def resize ( self , width , height ) :
    """Sets the new size and buffer size internally"""

implementation:
self . width = width
self . height = height
self . buffer_width , self . buffer_height = glfw . get_framebuffer_size ( self . window )
self . set_default_viewport ( )


signature:
def check_glfw_version ( self ) :
    """Ensure glfw library version is compatible"""

implementation:
print ( "glfw version: {} (python wrapper version {})" . format ( glfw . get_version ( ) , glfw . __version__ ) )
if glfw . get_version ( ) < self . min_glfw_version :
    raise ValueError ( "Please update glfw binaries to version {} or later" . format ( self . min_glfw_version ) )


signature:
def key_event_callback ( self , window , key , scancode , action , mods ) :
    """Key event callback for glfw .
 Translates and forwards keyboard event to : py : func : ` keyboard _ event `
 : param window : Window event origin
 : param key : The key that was pressed or released .
 : param scancode : The system - specific scancode of the key .
 : param action : GLFW _ PRESS , GLFW _ RELEASE or GLFW _ REPEAT
 : param mods : Bit field describing which modifier keys were held down ."""

implementation: self . keyboard_event ( key , action , mods )


signature:
def ctx ( ) -> moderngl . Context :
    """ModernGL context"""

implementation:
win = window ( )
if not win . ctx :
    raise RuntimeError ( "Attempting to get context before creation" )
return win . ctx


signature:
def quad_2d ( width , height , xpos = 0.0 , ypos = 0.0 ) -> VAO :
    """Creates a 2D quad VAO using 2 triangles with normals and texture coordinates .
 Args :
 width ( float ) : Width of the quad
 height ( float ) : Height of the quad
 Keyword Args :
 xpos ( float ) : Center position x
 ypos ( float ) : Center position y
 Returns :
 A : py : class : ` demosys . opengl . vao . VAO ` instance ."""

implementation:
pos = numpy . array ( [ xpos - width / 2.0 , ypos + height / 2.0 , 0.0 , xpos - width / 2.0 , ypos - height / 2.0 , 0.0 , xpos + width / 2.0 , ypos - height / 2.0 , 0.0 , xpos - width / 2.0 , ypos + height / 2.0 , 0.0 , xpos + width / 2.0 , ypos - height / 2.0 , 0.0 , xpos + width / 2.0 , ypos + height / 2.0 , 0.0 , ] , dtype = numpy . float32 )
normals = numpy . array ( [ 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , ] , dtype = numpy . float32 )
uvs = numpy . array ( [ 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 1.0 , 1.0 , 0.0 , 1.0 , 1.0 , ] , dtype = numpy . float32 )
vao = VAO ( "geometry:quad" , mode = moderngl . TRIANGLES )
vao . buffer ( pos , '3f' , [ "in_position" ] )
vao . buffer ( normals , '3f' , [ "in_normal" ] )
vao . buffer ( uvs , '2f' , [ "in_uv" ] )
return vao


signature:
def translate_buffer_format ( vertex_format ) :
    """Translate the buffer format"""

implementation:
buffer_format = [ ]
attributes = [ ]
mesh_attributes = [ ]
if "T2F" in vertex_format :
    buffer_format . append ( "2f" )
    attributes . append ( "in_uv" )
    mesh_attributes . append ( ( "TEXCOORD_0" , "in_uv" , 2 ) )
if "C3F" in vertex_format :
    buffer_format . append ( "3f" )
    attributes . append ( "in_color" )
    mesh_attributes . append ( ( "NORMAL" , "in_color" , 3 ) )
if "N3F" in vertex_format :
    buffer_format . append ( "3f" )
    attributes . append ( "in_normal" )
    mesh_attributes . append ( ( "NORMAL" , "in_normal" , 3 ) )
buffer_format . append ( "3f" )
attributes . append ( "in_position" )
mesh_attributes . append ( ( "POSITION" , "in_position" , 3 ) )
return " " . join ( buffer_format ) , attributes , mesh_attributes


signature:
def load ( self ) :
    """Deferred loading"""

implementation:
path = self . find_scene ( self . meta . path )
if not path :
    raise ValueError ( "Scene '{}' not found" . format ( self . meta . path ) )
if path . suffix == '.bin' :
    path = path . parent / path . stem
data = pywavefront . Wavefront ( str ( path ) , create_materials = True , cache = True )
scene = Scene ( self . meta . resolved_path )
texture_cache = { }
for _ , mat in data . materials . items ( ) :
    mesh = Mesh ( mat . name )
    # Traditional loader
    if mat . vertices :
        buffer_format , attributes , mesh_attributes = translate_buffer_format ( mat . vertex_format )
        vbo = numpy . array ( mat . vertices , dtype = 'f4' )
        vao = VAO ( mat . name , mode = moderngl . TRIANGLES )
        vao . buffer ( vbo , buffer_format , attributes )
        mesh . vao = vao
        for attrs in mesh_attributes :
            mesh . add_attribute ( * attrs )
    # Binary cache loader
    elif hasattr ( mat , 'vao' ) :
        mesh = Mesh ( mat . name )
        mesh . vao = mat . vao
        for attrs in mat . mesh_attributes :
            mesh . add_attribute ( * attrs )
    else : # Empty
        continue
    scene . meshes . append ( mesh )
    mesh . material = Material ( mat . name )
    scene . materials . append ( mesh . material )
    mesh . material . color = mat . diffuse
    if mat . texture : # A texture can be referenced multiple times , so we need to cache loaded ones
        texture = texture_cache . get ( mat . texture . path )
        if not texture :
            print ( "Loading:" , mat . texture . path )
            texture = textures . load ( TextureDescription ( label = mat . texture . path , path = mat . texture . path , mipmap = True , ) )
            texture_cache [ mat . texture . path ] = texture
        mesh . material . mat_texture = MaterialTexture ( texture = texture , sampler = None , )
    node = Node ( mesh = mesh )
    scene . root_nodes . append ( node )
# Not supported yet for obj
# self . calc _ scene _ bbox ( )
scene . prepare ( )
return scene


signature:
def start ( self ) :
    """Start the timer by recoding the current ` ` time . time ( ) ` `
 preparing to report the number of seconds since this timestamp ."""

implementation:
if self . start_time is None :
    self . start_time = time . time ( )
# Play after pause
else : # Add the duration of the paused interval to the total offset
    pause_duration = time . time ( ) - self . pause_time
    self . offset += pause_duration
    # print ( " pause duration " , pause _ duration , " offset " , self . offset )
    # Exit the paused state
    self . pause_time = None


signature:
def stop ( self ) -> float :
    """Stop the timer
 Returns :
 The time the timer was stopped"""

implementation:
self . stop_time = time . time ( )
return self . stop_time - self . start_time - self . offset


signature:
def get_time ( self ) -> float :
    """Get the current time in seconds
 Returns :
 The current time in seconds"""

implementation:
if self . pause_time is not None :
    curr_time = self . pause_time - self . offset - self . start_time
    return curr_time
curr_time = time . time ( )
return curr_time - self . start_time - self . offset


signature:
def set_time ( self , value : float ) :
    """Set the current time . This can be used to jump in the timeline .
 Args :
 value ( float ) : The new time"""

implementation:
if value < 0 :
    value = 0
self . offset += self . get_time ( ) - value


signature:
def resolve_loader ( self , meta : SceneDescription ) :
    """Resolve scene loader based on file extension"""

implementation:
for loader_cls in self . _loaders :
    if loader_cls . supports_file ( meta ) :
        meta . loader_cls = loader_cls
        break
else :
    raise ImproperlyConfigured ( "Scene {} has no loader class registered. Check settings.SCENE_LOADERS" . format ( meta . path ) )


signature:
def on_key_press ( self , symbol , modifiers ) :
    """Pyglet specific key press callback .
 Forwards and translates the events to : py : func : ` keyboard _ event `"""

implementation: self . keyboard_event ( symbol , self . keys . ACTION_PRESS , modifiers )


signature:
def on_key_release ( self , symbol , modifiers ) :
    """Pyglet specific key release callback .
 Forwards and translates the events to : py : func : ` keyboard _ event `"""

implementation: self . keyboard_event ( symbol , self . keys . ACTION_RELEASE , modifiers )


signature:
def on_mouse_motion ( self , x , y , dx , dy ) :
    """Pyglet specific mouse motion callback .
 Forwards and traslates the event to : py : func : ` cursor _ event `"""

implementation:
# screen coordinates relative to the lower - left corner
self . cursor_event ( x , self . buffer_height - y , dx , dy )


signature:
def on_resize ( self , width , height ) :
    """Pyglet specific callback for window resize events ."""

implementation:
self . width , self . height = width , height
self . buffer_width , self . buffer_height = width , height
self . resize ( width , height )


signature:
def swap_buffers ( self ) :
    """Swap buffers , increment frame counter and pull events"""

implementation:
if not self . window . context :
    return
self . frames += 1
self . window . flip ( )
self . window . dispatch_events ( )


signature:
def sphere ( radius = 0.5 , sectors = 32 , rings = 16 ) -> VAO :
    """Creates a sphere .
 Keyword Args :
 radius ( float ) : Radius or the sphere
 rings ( int ) : number or horizontal rings
 sectors ( int ) : number of vertical segments
 Returns :
 A : py : class : ` demosys . opengl . vao . VAO ` instance"""

implementation:
R = 1.0 / ( rings - 1 )
S = 1.0 / ( sectors - 1 )
vertices = [ 0 ] * ( rings * sectors * 3 )
normals = [ 0 ] * ( rings * sectors * 3 )
uvs = [ 0 ] * ( rings * sectors * 2 )
v , n , t = 0 , 0 , 0
for r in range ( rings ) :
    for s in range ( sectors ) :
        y = math . sin ( - math . pi / 2 + math . pi * r * R )
        x = math . cos ( 2 * math . pi * s * S ) * math . sin ( math . pi * r * R )
        z = math . sin ( 2 * math . pi * s * S ) * math . sin ( math . pi * r * R )
        uvs [ t ] = s * S
        uvs [ t + 1 ] = r * R
        vertices [ v ] = x * radius
        vertices [ v + 1 ] = y * radius
        vertices [ v + 2 ] = z * radius
        normals [ n ] = x
        normals [ n + 1 ] = y
        normals [ n + 2 ] = z
        t += 2
        v += 3
        n += 3
indices = [ 0 ] * rings * sectors * 6
i = 0
for r in range ( rings - 1 ) :
    for s in range ( sectors - 1 ) :
        indices [ i ] = r * sectors + s
        indices [ i + 1 ] = ( r + 1 ) * sectors + ( s + 1 )
        indices [ i + 2 ] = r * sectors + ( s + 1 )
        indices [ i + 3 ] = r * sectors + s
        indices [ i + 4 ] = ( r + 1 ) * sectors + s
        indices [ i + 5 ] = ( r + 1 ) * sectors + ( s + 1 )
        i += 6
vbo_vertices = numpy . array ( vertices , dtype = numpy . float32 )
vbo_normals = numpy . array ( normals , dtype = numpy . float32 )
vbo_uvs = numpy . array ( uvs , dtype = numpy . float32 )
vbo_elements = numpy . array ( indices , dtype = numpy . uint32 )
vao = VAO ( "sphere" , mode = mlg . TRIANGLES )
# VBOs
vao . buffer ( vbo_vertices , '3f' , [ 'in_position' ] )
vao . buffer ( vbo_normals , '3f' , [ 'in_normal' ] )
vao . buffer ( vbo_uvs , '2f' , [ 'in_uv' ] )
vao . index_buffer ( vbo_elements , index_element_size = 4 )
return vao


signature:
def draw ( self , current_time , frame_time ) :
    """Calls the superclass ` ` draw ( ) ` ` methods and checks ` ` HEADLESS _ FRAMES ` ` / ` ` HEADLESS _ DURATION ` `"""

implementation:
super ( ) . draw ( current_time , frame_time )
if self . headless_duration and current_time >= self . headless_duration :
    self . close ( )


signature:
def swap_buffers ( self ) :
    """Headless window currently don ' t support double buffering .
 We only increment the frame counter here ."""

implementation:
self . frames += 1
if self . headless_frames and self . frames >= self . headless_frames :
    self . close ( )


signature:
def load ( self , meta : ResourceDescription ) -> Any :
    """Loads a resource or return existing one
 : param meta : The resource description"""

implementation:
self . _check_meta ( meta )
self . resolve_loader ( meta )
return meta . loader_cls ( meta ) . load ( )


signature:
def add ( self , meta ) :
    """Add a resource to this pool .
 The resource is loaded and returned when ` ` load _ pool ( ) ` ` is called .
 : param meta : The resource description"""

implementation:
self . _check_meta ( meta )
self . resolve_loader ( meta )
self . _resources . append ( meta )


signature:
def load_pool ( self ) :
    """Loads all the data files using the configured finders ."""

implementation:
for meta in self . _resources :
    resource = self . load ( meta )
    yield meta , resource
self . _resources = [ ]


signature:
def resolve_loader ( self , meta : ResourceDescription ) :
    """Attempts to assign a loader class to a resource description
 : param meta : The resource description instance"""

implementation: meta . loader_cls = self . get_loader ( meta , raise_on_error = True )


signature:
def get_loader ( self , meta : ResourceDescription , raise_on_error = False ) -> BaseLoader :
    """Attempts to get a loader
 : param meta : The resource description instance
 : param raise _ on _ error : Raise ImproperlyConfigured if the loader cannot be resolved
 : returns : The requested loader class"""

implementation:
for loader in self . _loaders :
    if loader . name == meta . loader :
        return loader
if raise_on_error :
    raise ImproperlyConfigured ( "Resource has invalid loader '{}': {}\nAvailiable loaders: {}" . format ( meta . loader , meta , [ loader . name for loader in self . _loaders ] ) )


signature:
def keyPressEvent ( self , event ) :
    """Pyqt specific key press callback function .
 Translates and forwards events to : py : func : ` keyboard _ event ` ."""

implementation: self . keyboard_event ( event . key ( ) , self . keys . ACTION_PRESS , 0 )


signature:
def keyReleaseEvent ( self , event ) :
    """Pyqt specific key release callback function .
 Translates and forwards events to : py : func : ` keyboard _ event ` ."""

implementation: self . keyboard_event ( event . key ( ) , self . keys . ACTION_RELEASE , 0 )


signature:
def resize ( self , width , height ) :
    """Pyqt specific resize callback ."""

implementation:
if not self . fbo :
    return
# pyqt reports sizes in actual buffer size
self . width = width // self . widget . devicePixelRatio ( )
self . height = height // self . widget . devicePixelRatio ( )
self . buffer_width = width
self . buffer_height = height
super ( ) . resize ( width , height )


signature:
def draw ( self , texture , pos = ( 0.0 , 0.0 ) , scale = ( 1.0 , 1.0 ) ) :
    """Draw texture using a fullscreen quad .
 By default this will conver the entire screen .
 : param pos : ( tuple ) offset x , y
 : param scale : ( tuple ) scale x , y"""

implementation:
if not self . initialized :
    self . init ( )
self . _texture2d_shader [ "offset" ] . value = ( pos [ 0 ] - 1.0 , pos [ 1 ] - 1.0 )
self . _texture2d_shader [ "scale" ] . value = ( scale [ 0 ] , scale [ 1 ] )
texture . use ( location = 0 )
self . _texture2d_sampler . use ( location = 0 )
self . _texture2d_shader [ "texture0" ] . value = 0
self . _quad . render ( self . _texture2d_shader )
self . _texture2d_sampler . clear ( location = 0 )


signature:
def draw_depth ( self , texture , near , far , pos = ( 0.0 , 0.0 ) , scale = ( 1.0 , 1.0 ) ) :
    """Draw depth buffer linearized .
 By default this will draw the texture as a full screen quad .
 A sampler will be used to ensure the right conditions to draw the depth buffer .
 : param near : Near plane in projection
 : param far : Far plane in projection
 : param pos : ( tuple ) offset x , y
 : param scale : ( tuple ) scale x , y"""

implementation:
if not self . initialized :
    self . init ( )
self . _depth_shader [ "offset" ] . value = ( pos [ 0 ] - 1.0 , pos [ 1 ] - 1.0 )
self . _depth_shader [ "scale" ] . value = ( scale [ 0 ] , scale [ 1 ] )
self . _depth_shader [ "near" ] . value = near
self . _depth_shader [ "far" ] . value = far
self . _depth_sampler . use ( location = 0 )
texture . use ( location = 0 )
self . _depth_shader [ "texture0" ] . value = 0
self . _quad . render ( self . _depth_shader )
self . _depth_sampler . clear ( location = 0 )


signature:
def _init_texture2d_draw ( self ) :
    """Initialize geometry and shader for drawing FBO layers"""

implementation:
if not TextureHelper . _quad :
    TextureHelper . _quad = geometry . quad_fs ( )
# Shader for drawing color layers
TextureHelper . _texture2d_shader = context . ctx ( ) . program ( vertex_shader = """
                #version 330

                in vec3 in_position;
                in vec2 in_uv;
                out vec2 uv;
                uniform vec2 offset;
                uniform vec2 scale;

                void main() {
                    uv = in_uv;
                    gl_Position = vec4((in_position.xy + vec2(1.0, 1.0)) * scale + offset, 0.0, 1.0);
                }
            """ , fragment_shader = """
                #version 330

                out vec4 out_color;
                in vec2 uv;
                uniform sampler2D texture0;

                void main() {
                    out_color = texture(texture0, uv);
                }
            """ )
TextureHelper . _texture2d_sampler = self . ctx . sampler ( filter = ( moderngl . LINEAR , moderngl . LINEAR ) , )


signature:
def _init_depth_texture_draw ( self ) :
    """Initialize geometry and shader for drawing FBO layers"""

implementation:
from demosys import geometry
if not TextureHelper . _quad :
    TextureHelper . _quad = geometry . quad_fs ( )
# Shader for drawing depth layers
TextureHelper . _depth_shader = context . ctx ( ) . program ( vertex_shader = """
                #version 330

                in vec3 in_position;
                in vec2 in_uv;
                out vec2 uv;
                uniform vec2 offset;
                uniform vec2 scale;

                void main() {
                    uv = in_uv;
                    gl_Position = vec4((in_position.xy + vec2(1.0, 1.0)) * scale + offset, 0.0, 1.0);
                }
            """ , fragment_shader = """
                #version 330

                out vec4 out_color;
                in vec2 uv;
                uniform sampler2D texture0;
                uniform float near;
                uniform float far;

                void main() {
                    float z = texture(texture0, uv).r;
                    float d = (2.0 * near) / (far + near - z * (far - near));
                    out_color = vec4(d);
                }
            """ )
TextureHelper . _depth_sampler = self . ctx . sampler ( filter = ( moderngl . LINEAR , moderngl . LINEAR ) , compare_func = '' , )


signature:
def draw ( self , current_time , frame_time ) :
    """Draws a frame . Internally it calls the
 configured timeline ' s draw method .
 Args :
 current _ time ( float ) : The current time ( preferrably always from the configured timer class )
 frame _ time ( float ) : The duration of the previous frame in seconds"""

implementation:
self . set_default_viewport ( )
self . timeline . draw ( current_time , frame_time , self . fbo )


signature:
def clear ( self ) :
    """Clear the window buffer"""

implementation: self . ctx . fbo . clear ( red = self . clear_color [ 0 ] , green = self . clear_color [ 1 ] , blue = self . clear_color [ 2 ] , alpha = self . clear_color [ 3 ] , depth = self . clear_depth , )


signature:
def clear_values ( self , red = 0.0 , green = 0.0 , blue = 0.0 , alpha = 0.0 , depth = 1.0 ) :
    """Sets the clear values for the window buffer .
 Args :
 red ( float ) : red compoent
 green ( float ) : green compoent
 blue ( float ) : blue compoent
 alpha ( float ) : alpha compoent
 depth ( float ) : depth value"""

implementation:
self . clear_color = ( red , green , blue , alpha )
self . clear_depth = depth


signature:
def keyboard_event ( self , key , action , modifier ) :
    """Handles the standard keyboard events such as camera movements ,
 taking a screenshot , closing the window etc .
 Can be overriden add new keyboard events . Ensure this method
 is also called if you want to keep the standard features .
 Arguments :
 key : The key that was pressed or released
 action : The key action . Can be ` ACTION _ PRESS ` or ` ACTION _ RELEASE `
 modifier : Modifiers such as holding shift or ctrl"""

implementation:
# The well - known standard key for quick exit
if key == self . keys . ESCAPE :
    self . close ( )
    return
# Toggle pause time
if key == self . keys . SPACE and action == self . keys . ACTION_PRESS :
    self . timer . toggle_pause ( )
# Camera movement
# Right
if key == self . keys . D :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_right ( True )
    elif action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_right ( False )
# Left
elif key == self . keys . A :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_left ( True )
    elif action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_left ( False )
# Forward
elif key == self . keys . W :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_forward ( True )
    if action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_forward ( False )
# Backwards
elif key == self . keys . S :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_backward ( True )
    if action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_backward ( False )
# UP
elif key == self . keys . Q :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_down ( True )
    if action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_down ( False )
# Down
elif key == self . keys . E :
    if action == self . keys . ACTION_PRESS :
        self . sys_camera . move_up ( True )
    if action == self . keys . ACTION_RELEASE :
        self . sys_camera . move_up ( False )
# Screenshots
if key == self . keys . X and action == self . keys . ACTION_PRESS :
    screenshot . create ( )
if key == self . keys . R and action == self . keys . ACTION_PRESS :
    project . instance . reload_programs ( )
if key == self . keys . RIGHT and action == self . keys . ACTION_PRESS :
    self . timer . set_time ( self . timer . get_time ( ) + 10.0 )
if key == self . keys . LEFT and action == self . keys . ACTION_PRESS :
    self . timer . set_time ( self . timer . get_time ( ) - 10.0 )
# Forward the event to the timeline
self . timeline . key_event ( key , action , modifier )


signature:
def cursor_event ( self , x , y , dx , dy ) :
    """The standard mouse movement event method .
 Can be overriden to add new functionality .
 By default this feeds the system camera with new values .
 Args :
 x : The current mouse x position
 y : The current mouse y position
 dx : Delta x postion ( x position difference from the previous event )
 dy : Delta y postion ( y position difference from the previous event )"""

implementation: self . sys_camera . rot_state ( x , y )


signature:
def set_default_viewport ( self ) :
    """Calculates the viewport based on the configured aspect ratio in settings .
 Will add black borders if the window do not match the viewport ."""

implementation:
# The expected height with the current viewport width
expected_height = int ( self . buffer_width / self . aspect_ratio )
# How much positive or negative y padding
blank_space = self . buffer_height - expected_height
self . fbo . viewport = ( 0 , blank_space // 2 , self . buffer_width , expected_height )


signature:
def start ( self ) :
    """Start the timer"""

implementation:
self . music . start ( )
if not self . start_paused :
    self . rocket . start ( )


signature:
def toggle_pause ( self ) :
    """Toggle pause mode"""

implementation:
self . controller . playing = not self . controller . playing
self . music . toggle_pause ( )


signature:
def supports_file ( cls , meta ) :
    """Check if the loader has a supported file extension"""

implementation:
path = Path ( meta . path )
for ext in cls . file_extensions :
    if path . suffixes [ : len ( ext ) ] == ext :
        return True
return False


signature:
def get ( self , name ) -> Track :
    """Get or create a Track object .
 : param name : Name of the track
 : return : Track object"""

implementation:
name = name . lower ( )
track = self . track_map . get ( name )
if not track :
    track = Track ( name )
    self . tacks . append ( track )
    self . track_map [ name ] = track
return track


signature:
def find_commands ( command_dir : str ) -> List [ str ] :
    """Get all command names in the a folder
 : return : List of commands names"""

implementation:
if not command_dir :
    return [ ]
return [ name for _ , name , is_pkg in pkgutil . iter_modules ( [ command_dir ] ) if not is_pkg and not name . startswith ( '_' ) ]


signature:
def execute_from_command_line ( argv = None ) :
    """Currently the only entrypoint ( manage . py , demosys - admin )"""

implementation:
if not argv :
    argv = sys . argv
# prog _ name = argv [ 0]
system_commands = find_commands ( system_command_dir ( ) )
project_commands = find_commands ( project_command_dir ( ) )
project_package = project_package_name ( )
command = argv [ 1 ] if len ( argv ) > 1 else None
# Are we running a core command ?
if command in system_commands :
    cmd = load_command_class ( 'demosys' , command )
    cmd . run_from_argv ( argv )
elif command in project_commands :
    cmd = load_command_class ( project_package , command )
    cmd . run_from_argv ( argv )
else :
    print ( "Available commands:" )
    for name in system_commands :
        print ( " - {}" . format ( name ) )
    for name in project_commands :
        print ( " - {}" . format ( name ) )


signature:
def update ( self , ** kwargs ) :
    """Override settings values"""

implementation:
for name , value in kwargs . items ( ) :
    setattr ( self , name , value )


signature:
def add_program_dir ( self , directory ) :
    """Hack in program directory"""

implementation:
dirs = list ( self . PROGRAM_DIRS )
dirs . append ( directory )
self . PROGRAM_DIRS = dirs


signature:
def add_texture_dir ( self , directory ) :
    """Hack in texture directory"""

implementation:
dirs = list ( self . TEXTURE_DIRS )
dirs . append ( directory )
self . TEXTURE_DIRS = dirs


signature:
def add_data_dir ( self , directory ) :
    """Hack in a data directory"""

implementation:
dirs = list ( self . DATA_DIRS )
dirs . append ( directory )
self . DATA_DIRS = dirs


signature:
def content ( self , attributes : List [ str ] ) :
    """Build content tuple for the buffer"""

implementation:
formats = [ ]
attrs = [ ]
for attrib_format , attrib in zip ( self . attrib_formats , self . attributes ) :
    if attrib not in attributes :
        formats . append ( attrib_format . pad_str ( ) )
        continue
    formats . append ( attrib_format . format )
    attrs . append ( attrib )
    attributes . remove ( attrib )
if not attrs :
    return None
return ( self . buffer , "{}{}" . format ( " " . join ( formats ) , '/i' if self . per_instance else '' ) , * attrs )


signature:
def render ( self , program : moderngl . Program , mode = None , vertices = - 1 , first = 0 , instances = 1 ) :
    """Render the VAO .
 Args :
 program : The ` ` moderngl . Program ` `
 Keyword Args :
 mode : Override the draw mode ( ` ` TRIANGLES ` ` etc )
 vertices ( int ) : The number of vertices to transform
 first ( int ) : The index of the first vertex to start with
 instances ( int ) : The number of instances"""

implementation:
vao = self . instance ( program )
if mode is None :
    mode = self . mode
vao . render ( mode , vertices = vertices , first = first , instances = instances )


signature:
def render_indirect ( self , program : moderngl . Program , buffer , mode = None , count = - 1 , * , first = 0 ) :
    """The render primitive ( mode ) must be the same as the input primitive of the GeometryShader .
 The draw commands are 5 integers : ( count , instanceCount , firstIndex , baseVertex , baseInstance ) .
 Args :
 program : The ` ` moderngl . Program ` `
 buffer : The ` ` moderngl . Buffer ` ` containing indirect draw commands
 Keyword Args :
 mode ( int ) : By default : py : data : ` TRIANGLES ` will be used .
 count ( int ) : The number of draws .
 first ( int ) : The index of the first indirect draw command ."""

implementation:
vao = self . instance ( program )
if mode is None :
    mode = self . mode
vao . render_indirect ( buffer , mode = mode , count = count , first = first )


signature:
def transform ( self , program : moderngl . Program , buffer : moderngl . Buffer , mode = None , vertices = - 1 , first = 0 , instances = 1 ) :
    """Transform vertices . Stores the output in a single buffer .
 Args :
 program : The ` ` moderngl . Program ` `
 buffer : The ` ` moderngl . buffer ` ` to store the output
 Keyword Args :
 mode : Draw mode ( for example ` ` moderngl . POINTS ` ` )
 vertices ( int ) : The number of vertices to transform
 first ( int ) : The index of the first vertex to start with
 instances ( int ) : The number of instances"""

implementation:
vao = self . instance ( program )
if mode is None :
    mode = self . mode
vao . transform ( buffer , mode = mode , vertices = vertices , first = first , instances = instances )


signature:
def buffer ( self , buffer , buffer_format : str , attribute_names , per_instance = False ) :
    """Register a buffer / vbo for the VAO . This can be called multiple times .
 adding multiple buffers ( interleaved or not )
 Args :
 buffer : The buffer data . Can be ` ` numpy . array ` ` , ` ` moderngl . Buffer ` ` or ` ` bytes ` ` .
 buffer _ format ( str ) : The format of the buffer . ( eg . ` ` 3f 3f ` ` for interleaved positions and normals ) .
 attribute _ names : A list of attribute names this buffer should map to .
 Keyword Args :
 per _ instance ( bool ) : Is this buffer per instance data for instanced rendering ?
 Returns :
 The ` ` moderngl . Buffer ` ` instance object . This is handy when providing ` ` bytes ` ` and ` ` numpy . array ` ` ."""

implementation:
if not isinstance ( attribute_names , list ) :
    attribute_names = [ attribute_names , ]
if not type ( buffer ) in [ moderngl . Buffer , numpy . ndarray , bytes ] :
    raise VAOError ( ( "buffer parameter must be a moderngl.Buffer, numpy.ndarray or bytes instance" "(not {})" . format ( type ( buffer ) ) ) )
if isinstance ( buffer , numpy . ndarray ) :
    buffer = self . ctx . buffer ( buffer . tobytes ( ) )
if isinstance ( buffer , bytes ) :
    buffer = self . ctx . buffer ( data = buffer )
formats = buffer_format . split ( )
if len ( formats ) != len ( attribute_names ) :
    raise VAOError ( "Format '{}' does not describe attributes {}" . format ( buffer_format , attribute_names ) )
self . buffers . append ( BufferInfo ( buffer , buffer_format , attribute_names , per_instance = per_instance ) )
self . vertex_count = self . buffers [ - 1 ] . vertices
return buffer


signature:
def index_buffer ( self , buffer , index_element_size = 4 ) :
    """Set the index buffer for this VAO
 Args :
 buffer : ` ` moderngl . Buffer ` ` , ` ` numpy . array ` ` or ` ` bytes ` `
 Keyword Args :
 index _ element _ size ( int ) : Byte size of each element . 1 , 2 or 4"""

implementation:
if not type ( buffer ) in [ moderngl . Buffer , numpy . ndarray , bytes ] :
    raise VAOError ( "buffer parameter must be a moderngl.Buffer, numpy.ndarray or bytes instance" )
if isinstance ( buffer , numpy . ndarray ) :
    buffer = self . ctx . buffer ( buffer . tobytes ( ) )
if isinstance ( buffer , bytes ) :
    buffer = self . ctx . buffer ( data = buffer )
self . _index_buffer = buffer
self . _index_element_size = index_element_size


signature:
def instance ( self , program : moderngl . Program ) -> moderngl . VertexArray :
    """Obtain the ` ` moderngl . VertexArray ` ` instance for the program .
 The instance is only created once and cached internally .
 Returns : ` ` moderngl . VertexArray ` ` instance"""

implementation:
vao = self . vaos . get ( program . glo )
if vao :
    return vao
program_attributes = [ name for name , attr in program . _members . items ( ) if isinstance ( attr , moderngl . Attribute ) ]
# Make sure all attributes are covered
for attrib_name in program_attributes : # Ignore built in attributes for now
    if attrib_name . startswith ( 'gl_' ) :
        continue
    # Do we have a buffer mapping to this attribute ?
    if not sum ( buffer . has_attribute ( attrib_name ) for buffer in self . buffers ) :
        raise VAOError ( "VAO {} doesn't have attribute {} for program {}" . format ( self . name , attrib_name , program . name ) )
vao_content = [ ]
# Pick out the attributes we can actually map
for buffer in self . buffers :
    content = buffer . content ( program_attributes )
    if content :
        vao_content . append ( content )
# Any attribute left is not accounted for
if program_attributes :
    for attrib_name in program_attributes :
        if attrib_name . startswith ( 'gl_' ) :
            continue
        raise VAOError ( "Did not find a buffer mapping for {}" . format ( [ n for n in program_attributes ] ) )
# Create the vao
if self . _index_buffer :
    vao = context . ctx ( ) . vertex_array ( program , vao_content , self . _index_buffer , self . _index_element_size )
else :
    vao = context . ctx ( ) . vertex_array ( program , vao_content )
self . vaos [ program . glo ] = vao
return vao


signature:
def release ( self , buffer = True ) :
    """Destroy the vao object
 Keyword Args :
 buffers ( bool ) : also release buffers"""

implementation:
for key , vao in self . vaos :
    vao . release ( )
if buffer :
    for buff in self . buffers :
        buff . buffer . release ( )
    if self . _index_buffer :
        self . _index_buffer . release ( )