<commit_before>'''
 Author      : DORIAN JAVA BROWN
 Version     : N/A
 Copyright   : All Rights Reserve; You may use, distribute and modify this code.
 Description :
 '''

Tip CAlC
<commit_msg>Update TipCalculator.py<commit_after>'''
 Author      : DORIAN JAVA BROWN
 Version     : N/A
 Copyright   : All Rights Reserve; You may use, distribute and modify this code.
 Description :
 '''

Tip CAlC
tip = 0.00
<|endoftext|>


<commit_before>"""
Entry module of the application.
"""

import sys
import pygame
from appstate import AppState
import settings
import events
from view import view
from view import agentevents
from controller import controller
import experiment.basic
import webserver

class HeartBeat(events.EventListener):
    """
    Class implementing the heartbeat of the application.
    """

    def run(self, slow = True, halt_fun = lambda _: False):
        """
        Process PyGame events until halt is true.

        :param slow: whether the simulation should be slowed for
                     visible ticks and renders.
        """

        self.halt = False

        print("Starting heartbeat.")
        time_elapsed = 0
        while not self.halt:
            if halt_fun(AppState.get_state().get_t()):
                self.halt = True
                continue

            AppState.get_state().get_event_manager().post_event(events.ControlEvent())

            ticked = False

            if not slow or (AppState.get_state().is_running() and time_elapsed >= settings.SIMULATION_STEP_TIME):
                print "------- t = %s" % AppState.get_state().get_t()

                AppState.get_state().get_event_manager().post_event(events.TickEvent())
                time_elapsed = 0
                ticked = True

            AppState.get_state().get_event_manager().post_event(events.DrawEvent(ticked and AppState.get_state().get_save_simulation_renders()))

            if slow:
                time_elapsed += AppState.get_state().get_clock().tick(settings.MAX_FPS)

            if ticked:
                AppState.get_state().increment_t()

    def notify(self, event):
        if isinstance(event, events.QuitEvent):
            self.halt = True

def init():
    """
    Initialize pygame.

    :returns: The surface of the pygame display.
    """

    print("Loading pygame modules.")
    pygame.display.init()
    AppState.get_state().set_clock(pygame.time.Clock())
    flags = pygame.DOUBLEBUF
    surface = pygame.display.set_mode(
        (
            AppState.get_state().get_world().get_width() * settings.CELL_WIDTH,
            AppState.get_state().get_world().get_height() * settings.CELL_HEIGHT,
        ),
        flags)
    surface.set_alpha(None)
    pygame.display.set_caption('Enactive Agents v2')

    return surface

def run_experiment(experiment_, render = True, interactive = True):
    """
    Run an experiment until it halts. Simulates the world defined
    by the experiment and handles control events.

    :param experiment_: An object of type Experiment.
    """

    if interactive:
        assert render, "render must be true if interactive mode is set"

    # Reset the app state
    AppState.get_state().reset()

    # Initialize the event manager.
    event_manager = events.EventManager()
    AppState.get_state().set_event_manager(event_manager)

    # Initialize and register the application heartbeat.
    heart_beat = HeartBeat()
    event_manager.register_listener(heart_beat)

    # Initialize and register the world.
    AppState.get_state().set_experiment(experiment_)
    world = experiment_.get_world()
    event_manager.register_listener(world)
    AppState.get_state().set_world(world)

    # Initialize pygame.
    surface = init()

    if render:
        # Initialize and register the view.
        main_view = view.View(surface)
        event_manager.register_listener(main_view)

    # Initialize the website trace history view.
    trace_view = agentevents.AgentEvents()
    event_manager.register_listener(trace_view)

    # Initialize and register the controller.
    main_controller = controller.Controller()
    event_manager.register_listener(main_controller)

    if interactive:
        # Add the experiment controller to the controller
        main_controller.set_experiment_controller(lambda e, coords: experiment_.controller(e, main_view.window_coords_to_world_coords(coords)))

    # Start the webserver.
    webserver.register({'traces': trace_view})
    webserver.start()

    # Start the heartbeat.
    heart_beat.run(slow = not render, halt_fun = experiment_.halt)

def main():
    """
    Main function of the application.
    """

    experiments = []
    experiments.append(experiment.basic.BasicRandomExperiment())
    experiments.append(experiment.basic.BasicVisionExperiment())

    for experiment_ in experiments:
        run_experiment(experiment_, render = False, interactive = False)

if __name__ == '__main__':
    """
    Application entry-point.
    """

    main()
<commit_msg>Fix bug where simulations would be slowed if and only if *not* rendering.<commit_after>"""
Entry module of the application.
"""

import sys
import pygame
from appstate import AppState
import settings
import events
from view import view
from view import agentevents
from controller import controller
import experiment.basic
import webserver

class HeartBeat(events.EventListener):
    """
    Class implementing the heartbeat of the application.
    """

    def run(self, slow = True, halt_fun = lambda _: False):
        """
        Process PyGame events until halt is true.

        :param slow: whether the simulation should be slowed for
                     visible ticks and renders.
        """

        self.halt = False

        print("Starting heartbeat.")
        time_elapsed = 0
        while not self.halt:
            if halt_fun(AppState.get_state().get_t()):
                self.halt = True
                continue

            AppState.get_state().get_event_manager().post_event(events.ControlEvent())

            ticked = False

            if not slow or (AppState.get_state().is_running() and time_elapsed >= settings.SIMULATION_STEP_TIME):
                print "------- t = %s" % AppState.get_state().get_t()

                AppState.get_state().get_event_manager().post_event(events.TickEvent())
                time_elapsed = 0
                ticked = True

            AppState.get_state().get_event_manager().post_event(events.DrawEvent(ticked and AppState.get_state().get_save_simulation_renders()))

            if slow:
                time_elapsed += AppState.get_state().get_clock().tick(settings.MAX_FPS)

            if ticked:
                AppState.get_state().increment_t()

    def notify(self, event):
        if isinstance(event, events.QuitEvent):
            self.halt = True

def init():
    """
    Initialize pygame.

    :returns: The surface of the pygame display.
    """

    print("Loading pygame modules.")
    pygame.display.init()
    AppState.get_state().set_clock(pygame.time.Clock())
    flags = pygame.DOUBLEBUF
    surface = pygame.display.set_mode(
        (
            AppState.get_state().get_world().get_width() * settings.CELL_WIDTH,
            AppState.get_state().get_world().get_height() * settings.CELL_HEIGHT,
        ),
        flags)
    surface.set_alpha(None)
    pygame.display.set_caption('Enactive Agents v2')

    return surface

def run_experiment(experiment_, render = True, interactive = True):
    """
    Run an experiment until it halts. Simulates the world defined
    by the experiment and handles control events.

    :param experiment_: An object of type Experiment.
    """

    if interactive:
        assert render, "render must be true if interactive mode is set"

    # Reset the app state
    AppState.get_state().reset()

    # Initialize the event manager.
    event_manager = events.EventManager()
    AppState.get_state().set_event_manager(event_manager)

    # Initialize and register the application heartbeat.
    heart_beat = HeartBeat()
    event_manager.register_listener(heart_beat)

    # Initialize and register the world.
    AppState.get_state().set_experiment(experiment_)
    world = experiment_.get_world()
    event_manager.register_listener(world)
    AppState.get_state().set_world(world)

    # Initialize pygame.
    surface = init()

    if render:
        # Initialize and register the view.
        main_view = view.View(surface)
        event_manager.register_listener(main_view)

    # Initialize the website trace history view.
    trace_view = agentevents.AgentEvents()
    event_manager.register_listener(trace_view)

    # Initialize and register the controller.
    main_controller = controller.Controller()
    event_manager.register_listener(main_controller)

    if interactive:
        # Add the experiment controller to the controller
        main_controller.set_experiment_controller(lambda e, coords: experiment_.controller(e, main_view.window_coords_to_world_coords(coords)))

    # Start the webserver.
    webserver.register({'traces': trace_view})
    webserver.start()

    # Start the heartbeat.
    heart_beat.run(slow = render, halt_fun = experiment_.halt)

def main():
    """
    Main function of the application.
    """

    experiments = []
    experiments.append(experiment.basic.BasicRandomExperiment())
    experiments.append(experiment.basic.BasicVisionExperiment())

    for experiment_ in experiments:
        run_experiment(experiment_, render = False, interactive = False)

if __name__ == '__main__':
    """
    Application entry-point.
    """

    main()
<|endoftext|>


<commit_before>import numpy as np

class BoltzmannMachine(object):
    def __init__(self, input_size, hidden_size, output_size):
        self.total_nodes = input_size + hidden_size + output_size
        self.state = np.random.randint(0, 2, self.total_nodes, dtype=int)  # Begin with a random 0-1 draw.
        self.state = (self.state - .5) * 2  # Convert to -1, +1 state.
        self.weights = self.create_random_weights()

    def print_current_state(self):
        print self.state

    def state_energy(self):
        agreement_matrix = np.outer(self.state, self.state)  # The (i,j) entry is 1 if i,j agree, else -1
        energy_contributions = agreement_matrix * self.weights
        energy = np.sum(energy_contributions) / 2  # Leaving off bias for now.
        return energy

    def state_prob(self):
        """
        The (non-normalized) probability of this state. Does the whole calculation rather than just over the
        affected subsets.
        :return: P( state ) * Z
        """
        return np.exp(-self.state_energy())

    def update(self, node):
        self.state[node] = 1
        plus_prob = self.state_prob()
        self.state[node] = -1
        minus_prob = self.state_prob()
        plus_prob = plus_prob / (plus_prob + minus_prob)
        # print plus_prob
        coin_flip = np.random.binomial(1, plus_prob, 1)
        result = 2*(coin_flip - .5)  # Convert biased coin flip to -1 or 1.
        # print result
        self.state[node] = result

    def run_machine(self):
        visit_list = np.arange(self.total_nodes)  # The array [0 1 ... n-1].
        np.random.shuffle(visit_list)  # Shuffle the array [0 1 ... n-1].
        for run in range(100):  # why hard-coded 100? What does it correspond to?
            node_to_update = visit_list[run % self.total_nodes]  # I don't understand this
            self.update(node_to_update)

    def create_random_weights(self):
        weights = np.random.normal(0, 1, size=(self.total_nodes, self.total_nodes))  # Random weights from N(0,1).
        weights = (weights + weights.T) / 2  # To make it symmetric.

        # The next few lines create a symmetric array of weights to zero out, and remove self-connections.
        disconnect = np.random.randint(0, 2, (self.total_nodes, self.total_nodes))  # Choose weights to zero out.
        disconnect_lower_triangle = np.tril(disconnect)
        disconnect = disconnect_lower_triangle + disconnect_lower_triangle.T
        weights = disconnect * weights  # Zero out the weights chosen by disconnect. Point-wise mult.
        return weights

BM = BoltzmannMachine(2, 4, 2)

BM.print_current_state()

for i in range(10):  # Do the update process 10 times, printing the end state each time.
    BM.run_machine()
    BM.print_current_state()<commit_msg>rewrite create_random_weights() method according to hw specs<commit_after>import numpy as np

class BoltzmannMachine(object):
    def __init__(self, input_size, hidden_size, output_size):
        self.total_nodes = input_size + hidden_size + output_size
        self.state = np.random.randint(0, 2, self.total_nodes, dtype=int)  # Begin with a random 0-1 draw.
        self.state = (self.state - .5) * 2  # Convert to -1, +1 state.
        self.weights = self.create_random_weights()

    def print_current_state(self):
        print self.state

    def state_energy(self):
        agreement_matrix = np.outer(self.state, self.state)  # The (i,j) entry is 1 if i,j agree, else -1
        energy_contributions = agreement_matrix * self.weights
        energy = np.sum(energy_contributions) / 2  # Leaving off bias for now.
        return energy

    def state_prob(self):
        """
        The (non-normalized) probability of this state. Does the whole calculation rather than just over the
        affected subsets.
        :return: P( state ) * Z
        """
        return np.exp(-self.state_energy())

    def update(self, node):
        self.state[node] = 1
        plus_prob = self.state_prob()
        self.state[node] = -1
        minus_prob = self.state_prob()
        plus_prob = plus_prob / (plus_prob + minus_prob)
        # print plus_prob
        coin_flip = np.random.binomial(1, plus_prob, 1)
        result = 2*(coin_flip - .5)  # Convert biased coin flip to -1 or 1.
        # print result
        self.state[node] = result

    def run_machine(self):
        visit_list = np.arange(self.total_nodes)  # The array [0 1 ... n-1].
        np.random.shuffle(visit_list)  # Shuffle the array [0 1 ... n-1].
        for run in range(100):  # why hard-coded 100? What does it correspond to?
            node_to_update = visit_list[run % self.total_nodes]  # I don't understand this
            self.update(node_to_update)

    def create_random_weights(self):
        weights = np.random.uniform(-1, 1, size=(self.total_nodes, self.total_nodes))  # Random weights ~ U([-1,1])
        weights = np.triu(weights, k=1)  # discard lower diagonal terms (and the diagonal to avoid self-connections)
        weights = weights + weights.T  # make the weights symmetric
        return weights

BM = BoltzmannMachine(0, 30, 0)

BM.print_current_state()

for i in range(10):  # Do the update process 10 times, printing the end state each time.
    BM.run_machine()
    BM.print_current_state()<|endoftext|>


<commit_before>__version__ = "1.0.1"
__author__ = "Daniel Schreij"

import QOpenScienceFramework.connection
import QOpenScienceFramework.manager
import QOpenScienceFramework.widgets<commit_msg>Bump to 1.0.2<commit_after>__version__ = "1.0.2"
__author__ = "Daniel Schreij"

import QOpenScienceFramework.connection
import QOpenScienceFramework.manager
import QOpenScienceFramework.widgets<|endoftext|>


<commit_before>### Creates tiles in which each natural non-mangrove non-planted forest biomass pixel is the number of years that trees are believed to have been growing there between 2001 and 2015.
### It is based on the annual Hansen loss data and the 2000-2012 Hansen gain data (as well as the 2000 tree cover density data).
### First it calculates rasters of gain years for non-mangrove non-planted forest biomass pixels that had loss only, gain only, neither loss nor gain, and both loss and gain.
### The gain years for each of these conditions are calculated according to rules that are found in the function called by the multiprocessor command.
### Then it combines those four rasters into a single gain year raster for each tile.
### Only the merged raster is used later in the model; the 4 intermediates are saved just for checking.
### If different input rasters for loss (e.g., 2001-2017) and gain (e.g., 2000-2018) are used, the constants in create_gain_year_count_natrl_forest.py must be changed.

import multiprocessing
import gain_year_count_natrl_forest
import sys
sys.path.append('../')
import constants_and_names as cn
import universal_util as uu

# The list of tiles to iterate through
biomass_tile_list = uu.tile_list(cn.WHRC_biomass_2000_non_mang_non_planted_dir)
# biomass_tile_list = ["00N_000E", "00N_050W", "00N_060W", "00N_010E", "00N_020E", "00N_030E", "00N_040E", "10N_000E", "10N_010E", "10N_010W", "10N_020E", "10N_020W"] # test tiles
biomass_tile_list = ['00N_110E'] # test tile
print biomass_tile_list
print "There are {} tiles to process".format(str(len(biomass_tile_list)))

# For downloading all tiles in the folders
download_list = [cn.loss_dir, cn.gain_dir, cn.tcd_dir, cn.WHRC_biomass_2000_non_mang_non_planted_dir]

# for input in download_list:
#     uu.s3_folder_download(input, '.')

# For copying individual tiles to s3 for testing
for tile in biomass_tile_list:

    uu.s3_file_download('{0}{1}.tif'.format(cn.loss_dir, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.gain_dir, cn.pattern_gain, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.tcd_dir, cn.pattern_tcd, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.WHRC_biomass_2000_non_mang_non_planted_dir, tile, cn.pattern_WHRC_biomass_2000_non_mang_non_planted), '.')

# # Creates gain year count tiles using only pixels that had only loss
# # count/3 uses about 220 GB on an r4.16xlarge machine
# # count/2 uses about 330 GB on an r4.16xlarge machine
# count = multiprocessing.cpu_count()
# pool = multiprocessing.Pool(count/2)
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_loss_only, biomass_tile_list)
#
# # Creates gain year count tiles using only pixels that had only gain
# # count/2 uses about 200 GB on an r4.16xlarge machine
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_gain_only, biomass_tile_list)
#
# # Creates gain year count tiles using only pixels that had neither loss nor gain pixels
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_no_change, biomass_tile_list)
#
# # Creates gain year count tiles using only pixels that had both loss and gain pixels
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_loss_and_gain, biomass_tile_list)
#
# # Merges the four above gain year count tiles for each Hansen tile into a single output tile
# count = multiprocessing.cpu_count()
# pool = multiprocessing.Pool(count/6)
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_merge, biomass_tile_list)
# pool.close()
# pool.join()

# For single processor use
for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_loss_only(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_gain_only(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_no_change(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_loss_and_gain(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_merge(tile)

# Intermediate output tiles for checking outputs
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_loss_only")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_gain_only")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_no_change")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_loss_and_gain")

# This is the final output used later in the model
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, cn.pattern_gain_year_count_natrl_forest)<commit_msg>Correcting natural forest gain year count and age category for model v1.1.1. Didn't mask out plantations and mangroves properly before.<commit_after>### Creates tiles in which each natural non-mangrove non-planted forest biomass pixel is the number of years that trees are believed to have been growing there between 2001 and 2015.
### It is based on the annual Hansen loss data and the 2000-2012 Hansen gain data (as well as the 2000 tree cover density data).
### First it calculates rasters of gain years for non-mangrove non-planted forest biomass pixels that had loss only, gain only, neither loss nor gain, and both loss and gain.
### The gain years for each of these conditions are calculated according to rules that are found in the function called by the multiprocessor command.
### Then it combines those four rasters into a single gain year raster for each tile.
### Only the merged raster is used later in the model; the 4 intermediates are saved just for checking.
### If different input rasters for loss (e.g., 2001-2017) and gain (e.g., 2000-2018) are used, the constants in create_gain_year_count_natrl_forest.py must be changed.

import multiprocessing
import gain_year_count_natrl_forest
import sys
sys.path.append('../')
import constants_and_names as cn
import universal_util as uu

# The list of tiles to iterate through
tile_list = uu.tile_list(cn.WHRC_biomass_2000_non_mang_non_planted_dir)
# tile_list = ["00N_000E", "00N_050W", "00N_060W", "00N_010E", "00N_020E", "00N_030E", "00N_040E", "10N_000E", "10N_010E", "10N_010W", "10N_020E", "10N_020W"] # test tiles
tile_list = ['00N_110E'] # test tile
print tile_list
print "There are {} tiles to process".format(str(len(tile_list)))

# For downloading all tiles in the folders
download_list = [cn.loss_dir, cn.gain_dir, cn.tcd_dir, cn.WHRC_biomass_2000_non_mang_non_planted_dir]

# for input in download_list:
#     uu.s3_folder_download(input, '.')

# For copying individual tiles to s3 for testing
for tile in tile_list:

    uu.s3_file_download('{0}{1}.tif'.format(cn.loss_dir, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.gain_dir, cn.pattern_gain, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.tcd_dir, cn.pattern_tcd, tile), '.')
    uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.WHRC_biomass_2000_non_mang_non_planted_dir, tile, cn.pattern_WHRC_biomass_2000_non_mang_non_planted), '.')

# # Creates gain year count tiles using only pixels that had only loss
# # count/3 uses about 220 GB on an r4.16xlarge machine
# # count/2 uses about 330 GB on an r4.16xlarge machine
# count = multiprocessing.cpu_count()
# pool = multiprocessing.Pool(count/2)
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_loss_only, tile_list)
#
# # Creates gain year count tiles using only pixels that had only gain
# # count/2 uses about 200 GB on an r4.16xlarge machine
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_gain_only, tile_list)
#
# # Creates gain year count tiles using only pixels that had neither loss nor gain pixels
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_no_change, tile_list)
#
# # Creates gain year count tiles using only pixels that had both loss and gain pixels
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_loss_and_gain, tile_list)
#
# # Merges the four above gain year count tiles for each Hansen tile into a single output tile
# count = multiprocessing.cpu_count()
# pool = multiprocessing.Pool(count/6)
# pool.map(gain_year_count_natrl_forest.create_gain_year_count_merge, tile_list)
# pool.close()
# pool.join()

# For single processor use
for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_loss_only(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_gain_only(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_no_change(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_loss_and_gain(tile)

for tile in tile_list:
    gain_year_count_natrl_forest.create_gain_year_count_merge(tile)

# Intermediate output tiles for checking outputs
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_loss_only")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_gain_only")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_no_change")
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, "growth_years_loss_and_gain")

# This is the final output used later in the model
uu.upload_final_set(cn.gain_year_count_natrl_forest_dir, cn.pattern_gain_year_count_natrl_forest)<|endoftext|>


<commit_before>import numpy as nu
import ctypes
import ctypes.util
from numpy.ctypeslib import ndpointer
import os
from galpy import potential, potential_src
#Find and load the library
_lib = None
_libname = ctypes.util.find_library('galpy_integrate_c')
if _libname:
    _lib = ctypes.CDLL(_libname)
if _lib is None:
    import sys
for path in sys.path:
    try:
        _lib = ctypes.CDLL(os.path.join(path,'galpy_integrate_c.so'))
    except OSError:
        _lib = None
    else:
        break
if _lib is None:
    raise IOError('galpy integration module not found')

def integratePlanarOrbit_c(pot,yo,t,int_method,rtol=None,atol=None):
    """
    NAME:
       integratePlanarOrbit_leapfrog
    PURPOSE:
       leapfrog integrate an ode for a planarOrbit
    INPUT:
       pot - Potential or list of such instances
       yo - initial condition [q,p]
       t - set of times at which one wants the result
       int_method= 'leapfrog_c', 'rk4_c', 'rk6_c', 'symplec4_c'
       rtol, atol
    OUTPUT:
       y : array, shape (len(y0), len(t))
       Array containing the value of y for each desired time in t, \
       with the initial value y0 in the first row.
    HISTORY:
       2011-10-03 - Written - Bovy (IAS)
    """
    #Process atol and rtol
    if rtol is None:
        rtol= nu.log(1.49012*10.**-8.)
    if atol is None:
        atol= nu.log(1.49012*10.**-8.)
    #Figure out what's in pot
    if not isinstance(pot,list):
        pot= [pot]
    #Initialize everything
    pot_type= []
    pot_args= []
    npot= len(pot)
    for p in pot:
        if isinstance(p,potential.LogarithmicHaloPotential):
            pot_type.append(0)
            pot_args.extend([p._amp,p._core2])
        elif isinstance(p,potential_src.planarPotential.planarPotentialFromRZPotential) \
                 and isinstance(p._RZPot,potential.LogarithmicHaloPotential):
            pot_type.append(0)
            pot_args.extend([p._RZPot._amp,p._RZPot._core2])
        elif isinstance(p,potential.DehnenBarPotential):
            pot_type.append(1)
            pot_args.extend([p._amp,p._tform,p._tsteady,p._rb,p._af,p._omegab,
                             p._barphi])
        elif isinstance(p,potential.TransientLogSpiralPotential):
            pot_type.append(2)
            pot_args.extend([p._amp,p._A,p._to,p._sigma2,p._alpha,p._m,
                             p._omegas,p._gamma])
        elif isinstance(p,potential.SteadyLogSpiralPotential):
            pot_type.append(3)
            if p._tform is None:
                pot_args.extend([p._amp,p._tform,p._tsteady,p._A,p._alpha,p._m,
                                 p._omegas,p._gamma])
            else:
                pot_args.extend([p._amp,float('nan'), float('nan'),
                                 p._A,p._alpha,p._m,
                                 p._omegas,p._gamma])
    pot_type= nu.array(pot_type,dtype=nu.int32,order='C')
    pot_args= nu.array(pot_args,dtype=nu.float64,order='C')

    #Pick integrator
    if int_method.lower() == 'rk4_c':
        int_method_c= 1
    elif int_method.lower() == 'rk6_c':
        int_method_c= 2
    elif int_method.lower() == 'symplec4_c':
        int_method_c= 3
    else:
        int_method_c= 0

    #Set up result array
    result= nu.empty((len(t),4))

    #Set up the C code
    ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE')
    integrationFunc= _lib.integratePlanarOrbit
    integrationFunc.argtypes= [ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int,
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int,
                               ndpointer(dtype=nu.int32,flags=ndarrayFlags),
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_double,
                               ctypes.c_double,
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int]

    #Array requirements, first store old order
    f_cont= [yo.flags['F_CONTIGUOUS'],
             t.flags['F_CONTIGUOUS']]
    yo= nu.require(yo,dtype=nu.float64,requirements=['C','W'])
    t= nu.require(t,dtype=nu.float64,requirements=['C','W'])
    result= nu.require(result,dtype=nu.float64,requirements=['C','W'])

    #Run the C code
    integrationFunc(yo,
                    ctypes.c_int(len(t)),
                    t,
                    ctypes.c_int(npot),
                    pot_type,
                    pot_args,
                    ctypes.c_double(rtol),ctypes.c_double(atol),
                    result,
                    ctypes.c_int(int_method_c))

    #Reset input arrays
    if f_cont[0]: yo= nu.asfortranarray(yo)
    if f_cont[1]: t= nu.asfortranarray(t)

    return result
<commit_msg>6th order symplectic integrator<commit_after>import numpy as nu
import ctypes
import ctypes.util
from numpy.ctypeslib import ndpointer
import os
from galpy import potential, potential_src
#Find and load the library
_lib = None
_libname = ctypes.util.find_library('galpy_integrate_c')
if _libname:
    _lib = ctypes.CDLL(_libname)
if _lib is None:
    import sys
for path in sys.path:
    try:
        _lib = ctypes.CDLL(os.path.join(path,'galpy_integrate_c.so'))
    except OSError:
        _lib = None
    else:
        break
if _lib is None:
    raise IOError('galpy integration module not found')

def integratePlanarOrbit_c(pot,yo,t,int_method,rtol=None,atol=None):
    """
    NAME:
       integratePlanarOrbit_leapfrog
    PURPOSE:
       leapfrog integrate an ode for a planarOrbit
    INPUT:
       pot - Potential or list of such instances
       yo - initial condition [q,p]
       t - set of times at which one wants the result
       int_method= 'leapfrog_c', 'rk4_c', 'rk6_c', 'symplec4_c'
       rtol, atol
    OUTPUT:
       y : array, shape (len(y0), len(t))
       Array containing the value of y for each desired time in t, \
       with the initial value y0 in the first row.
    HISTORY:
       2011-10-03 - Written - Bovy (IAS)
    """
    #Process atol and rtol
    if rtol is None:
        rtol= nu.log(1.49012*10.**-8.)
    if atol is None:
        atol= nu.log(1.49012*10.**-8.)
    #Figure out what's in pot
    if not isinstance(pot,list):
        pot= [pot]
    #Initialize everything
    pot_type= []
    pot_args= []
    npot= len(pot)
    for p in pot:
        if isinstance(p,potential.LogarithmicHaloPotential):
            pot_type.append(0)
            pot_args.extend([p._amp,p._core2])
        elif isinstance(p,potential_src.planarPotential.planarPotentialFromRZPotential) \
                 and isinstance(p._RZPot,potential.LogarithmicHaloPotential):
            pot_type.append(0)
            pot_args.extend([p._RZPot._amp,p._RZPot._core2])
        elif isinstance(p,potential.DehnenBarPotential):
            pot_type.append(1)
            pot_args.extend([p._amp,p._tform,p._tsteady,p._rb,p._af,p._omegab,
                             p._barphi])
        elif isinstance(p,potential.TransientLogSpiralPotential):
            pot_type.append(2)
            pot_args.extend([p._amp,p._A,p._to,p._sigma2,p._alpha,p._m,
                             p._omegas,p._gamma])
        elif isinstance(p,potential.SteadyLogSpiralPotential):
            pot_type.append(3)
            if p._tform is None:
                pot_args.extend([p._amp,p._tform,p._tsteady,p._A,p._alpha,p._m,
                                 p._omegas,p._gamma])
            else:
                pot_args.extend([p._amp,float('nan'), float('nan'),
                                 p._A,p._alpha,p._m,
                                 p._omegas,p._gamma])
    pot_type= nu.array(pot_type,dtype=nu.int32,order='C')
    pot_args= nu.array(pot_args,dtype=nu.float64,order='C')

    #Pick integrator
    if int_method.lower() == 'rk4_c':
        int_method_c= 1
    elif int_method.lower() == 'rk6_c':
        int_method_c= 2
    elif int_method.lower() == 'symplec4_c':
        int_method_c= 3
    elif int_method.lower() == 'symplec6_c':
        int_method_c= 4
    else:
        int_method_c= 0

    #Set up result array
    result= nu.empty((len(t),4))

    #Set up the C code
    ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE')
    integrationFunc= _lib.integratePlanarOrbit
    integrationFunc.argtypes= [ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int,
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int,
                               ndpointer(dtype=nu.int32,flags=ndarrayFlags),
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_double,
                               ctypes.c_double,
                               ndpointer(dtype=nu.float64,flags=ndarrayFlags),
                               ctypes.c_int]

    #Array requirements, first store old order
    f_cont= [yo.flags['F_CONTIGUOUS'],
             t.flags['F_CONTIGUOUS']]
    yo= nu.require(yo,dtype=nu.float64,requirements=['C','W'])
    t= nu.require(t,dtype=nu.float64,requirements=['C','W'])
    result= nu.require(result,dtype=nu.float64,requirements=['C','W'])

    #Run the C code
    integrationFunc(yo,
                    ctypes.c_int(len(t)),
                    t,
                    ctypes.c_int(npot),
                    pot_type,
                    pot_args,
                    ctypes.c_double(rtol),ctypes.c_double(atol),
                    result,
                    ctypes.c_int(int_method_c))

    #Reset input arrays
    if f_cont[0]: yo= nu.asfortranarray(yo)
    if f_cont[1]: t= nu.asfortranarray(t)

    return result
<|endoftext|>


<commit_before># coding: utf-8

""" Test action-angle stuff """

from __future__ import division, print_function

__author__ = "adrn <adrn@astro.columbia.edu>"

# Standard library
import os, sys
import logging

# Third-party
import matplotlib.pyplot as plt
import numpy as np
from astropy import log as logger
import astropy.units as u
from scipy.linalg import solve
import pytest

# Project
from ...integrate import LeapfrogIntegrator, DOPRI853Integrator
from ...potential import LogarithmicPotential
from ...potential import NFWPotential, IsochronePotential
from ...potential.apw import PW14Potential
from ...potential.lm10 import LM10Potential
from ..actionangle import *
from ..core import *
from ..plot import *
from .helpers import *

# HACK:
if "/Users/adrian/projects/genfunc" not in sys.path:
    sys.path.append("/Users/adrian/projects/genfunc")
import genfunc_3d

logger.setLevel(logging.DEBUG)

plot_path = "plots/tests/dynamics/actionangle"
if not os.path.exists(plot_path):
    os.makedirs(plot_path)

this_path = os.path.split(os.path.abspath(__file__))[0]

class ActionsBase(object):

    def test_classify(self):
        # my classify
        orb_type = classify_orbit(self.w)

        # compare to Sanders'
        for j in range(self.N):
            sdrs = genfunc_3d.assess_angmom(self.w[:,j])
            logger.debug("APW: {}, Sanders: {}".format(orb_type[j], sdrs))
            assert np.all(orb_type[j] == sdrs)

    def test_actions(self, plot=False):
        t = self.t[::10]

        N_max = 6
        for n in range(self.N):
            print("\n\n")
            logger.info("======================= Orbit {} =======================".format(n))
            w = self.w[::10,n]

            # get values from Sanders' code
            logger.debug("Computing actions from genfunc...")
            s_actions,s_angles,s_freqs,toy_potential = sanders_act_ang_freq(t, w, N_max=N_max)

            logger.debug("Computing actions...")
            actions,angles,freqs = find_actions(t, w, N_max=N_max, units=self.units,
                                                toy_potential=toy_potential)

            logger.info("Action ratio: {}".format(actions / s_actions))
            logger.info("Angle ratio: {}".format(angles / s_angles))
            logger.info("Freq ratio: {}".format(freqs / s_freqs))

            assert np.allclose(actions, s_actions, rtol=1E-5)
            assert np.allclose(angles, s_angles, rtol=1E-5)
            assert np.allclose(freqs, s_freqs, rtol=1E-5)

            if plot:
                logger.debug("Plotting orbit...")
                fig = plot_orbits(w, marker='.', alpha=0.2, linestyle='none')
                fig.savefig(os.path.join(self.plot_path,"orbit_{}.png".format(n)))

                fig = plot_angles(t,angles,freqs)
                fig.savefig(os.path.join(self.plot_path,"angles_{}.png".format(n)))

                fig = plot_angles(t,s_angles,s_freqs)
                fig.savefig(os.path.join(self.plot_path,"angles_sanders_{}.png".format(n)))

                plt.close('all')

class TestActions(ActionsBase):

    def setup(self):
        self.plot_path = os.path.join(plot_path, 'normal')
        if not os.path.exists(self.plot_path):
            os.makedirs(self.plot_path)

        self.units = (u.kpc, u.Msun, u.Myr)
        self.potential = PW14Potential()
        self.N = 100
        np.random.seed(42)
        w0 = isotropic_w0(N=self.N)
        nsteps = 200000

        if not os.path.exists(os.path.join(this_path, "w.npy")):
            logger.debug("Integrating orbits")
            t,w = self.potential.integrate_orbit(w0, dt=0.2, nsteps=nsteps, Integrator=DOPRI853Integrator)

            logger.debug("Saving orbits")
            np.save(os.path.join(this_path, "t.npy"), t)
            np.save(os.path.join(this_path, "w.npy"), w)
        else:
            logger.debug("Loaded orbits")
            t = np.load(os.path.join(this_path, "t.npy"))
            w = np.load(os.path.join(this_path, "w.npy"))

        self.t = t
        self.w = w

class TestHardActions(ActionsBase):

    def setup(self):
        self.plot_path = os.path.join(plot_path, 'hard')
        if not os.path.exists(self.plot_path):
            os.makedirs(self.plot_path)

        self.units = (u.kpc, u.Msun, u.Myr)
        params = {'a': 6.5, 'q1': 1.3, 'c': 0.3, 'b': 0.26, 'q3': 0.8, 'r_h': 30.0,
                  'm_disk': 65000000000.0, 'psi': 1.570796, 'q2': 1.0, 'theta': 1.570796,
                  'phi': 1.570796, 'm_spher': 20000000000.0, 'v_h': 0.5600371815834104}
        self.potential = PW14Potential(**params)
        self.N = 100

        w0 = np.loadtxt(os.path.join(this_path, "w0.txt"))
        nsteps = 200000

        if not os.path.exists(os.path.join(this_path, "w_hard.npy")):
            logger.debug("Integrating orbits")
            t,w = self.potential.integrate_orbit(w0, dt=0.2, nsteps=nsteps, Integrator=DOPRI853Integrator)

            logger.debug("Saving orbits")
            np.save(os.path.join(this_path, "t_hard.npy"), t)
            np.save(os.path.join(this_path, "w_hard.npy"), w)
        else:
            logger.debug("Loaded orbits")
            t = np.load(os.path.join(this_path, "t_hard.npy"))
            w = np.load(os.path.join(this_path, "w_hard.npy"))

        self.t = t
        self.w = w

def test_nvecs():
    nvecs = generate_n_vectors(N_max=6, dx=2, dy=2, dz=2)
    nvecs_sanders = sanders_nvecs(N_max=6, dx=2, dy=2, dz=2)
    assert np.all(nvecs == nvecs_sanders)

    nvecs = generate_n_vectors(N_max=6, dx=1, dy=1, dz=1)
    nvecs_sanders = sanders_nvecs(N_max=6, dx=1, dy=1, dz=1)
    assert np.all(nvecs == nvecs_sanders)

def test_compare_action_prepare():

    from ..actionangle import _action_prepare, _angle_prepare
    import solver
    logger.setLevel(logging.ERROR)
    AA = np.random.uniform(0., 100., size=(1000,6))
    t = np.linspace(0., 100., 1000)

    act_san,n_vectors = solver.solver(AA, N_max=6, symNx=2)
    A2,b2,n = _action_prepare(AA, N_max=6, dx=2, dy=2, dz=2)
    act_apw = np.array(solve(A2,b2))

    ang_san = solver.angle_solver(AA, t, N_max=6, symNx=2, sign=1)
    A2,b2,n = _angle_prepare(AA, t, N_max=6, dx=2, dy=2, dz=2)
    ang_apw = np.array(solve(A2,b2))

    assert np.allclose(act_apw, act_san)
    assert np.allclose(ang_apw, ang_san)

# class TestFrequencyMap(object):

#     def setup(self):
#         self.units = (u.kpc, u.Msun, u.Myr)
#         self.potential = LogarithmicPotential(v_c=1., r_h=np.sqrt(0.1),
#                                               q1=1., q2=1., q3=0.7, phi=0.)
#         acc = lambda t,x: self.potential.acceleration(x)
#         self.integrator = LeapfrogIntegrator(acc)

#         n = 3
#         phis = np.linspace(0.1,1.95*np.pi,n)
#         thetas = np.arccos(2*np.linspace(0.05,0.95,n) - 1)
#         p,t = np.meshgrid(phis, thetas)
#         phis = p.ravel()
#         thetas = t.ravel()

#         sinp,cosp = np.sin(phis),np.cos(phis)
#         sint,cost = np.sin(thetas),np.cos(thetas)

#         rh2 = self.potential.parameters['r_h']**2
#         q2 = self.potential.parameters['q2']
#         q3 = self.potential.parameters['q3']
#         r2 = (np.e - rh2) / (sint**2*cosp**2 + sint**2*sinp**2/q2**2 + cost**2/q3**2)
#         r = np.sqrt(r2)

#         x = r*cosp*sint
#         y = r*sinp*sint
#         z = r*cost
#         v = np.zeros_like(x)

#         E = self.potential.total_energy(np.vstack((x,y,z)).T, np.vstack((v,v,v)).T)
#         assert np.allclose(E, 0.5)

#         self.grid = np.vstack((x,y,z,v,v,v)).T

#     def test(self):
#         N_max = 6
#         logger.debug("Integrating orbits...")
#         t,w = self.integrator.run(self.grid, dt=0.05, nsteps=100000)
#         logger.debug("...done!")

#         fig,axes = plt.subplots(1,3,figsize=(16,5))
#         all_freqs = []
#         for n in range(w.shape[1]):
#             try:
#                 actions,angles,freqs = cross_validate_actions(t, w[:,n], N_max=N_max,
#                                                             units=self.units, skip_failures=True)
#                 failed = False
#             except ValueError as e:
#                 print("FAILED: {}".format(e))
#                 failed = True

#             if not failed:
#                 all_freqs.append(freqs)

#             fig = plot_orbits(w, ix=n, axes=axes, linestyle='none', marker='.', alpha=0.1)
#             fig.axes[1].set_title("Failed: {}".format(failed),fontsize=24)
#             fig.savefig(os.path.join(plot_path,"orbit_{}.png".format(n)))
#             for i in range(3): axes[i].cla()

#         # for freqs in all_freqs:
#         #     print(np.median(freqs,axis=0))
#         #     print(np.std(freqs,axis=0))

#         all_freqs = np.array(all_freqs)

#         plt.clf()
#         plt.figure(figsize=(6,6))
#         plt.plot(all_freqs[:,1]/all_freqs[:,0], all_freqs[:,2]/all_freqs[:,0],
#                  linestyle='none', marker='.')
#         # plt.xlim(0.9, 1.5)
#         # plt.ylim(1.1, 2.1)
#         plt.savefig(os.path.join(plot_path,"freq_map.png"))
<commit_msg>move file to test data<commit_after># coding: utf-8

""" Test action-angle stuff """

from __future__ import division, print_function

__author__ = "adrn <adrn@astro.columbia.edu>"

# Standard library
import os, sys
import logging

# Third-party
import matplotlib.pyplot as plt
import numpy as np
from astropy import log as logger
import astropy.units as u
from scipy.linalg import solve
import pytest

# Project
from ...integrate import LeapfrogIntegrator, DOPRI853Integrator
from ...potential import LogarithmicPotential
from ...potential import NFWPotential, IsochronePotential
from ...potential.apw import PW14Potential
from ...potential.lm10 import LM10Potential
from ..actionangle import *
from ..core import *
from ..plot import *
from .helpers import *

# HACK:
if "/Users/adrian/projects/genfunc" not in sys.path:
    sys.path.append("/Users/adrian/projects/genfunc")
import genfunc_3d

logger.setLevel(logging.DEBUG)

plot_path = "plots/tests/dynamics/actionangle"
if not os.path.exists(plot_path):
    os.makedirs(plot_path)

this_path = os.path.split(os.path.abspath(__file__))[0]

# TODO: config item to specify path to test data?
test_data_path = os.path.abspath(os.path.join(os.path.split(__file__)[0],
                                 "../../../test-data/actionangle"))

class ActionsBase(object):

    def test_classify(self):
        # my classify
        orb_type = classify_orbit(self.w)

        # compare to Sanders'
        for j in range(self.N):
            sdrs = genfunc_3d.assess_angmom(self.w[:,j])
            logger.debug("APW: {}, Sanders: {}".format(orb_type[j], sdrs))
            assert np.all(orb_type[j] == sdrs)

    def test_actions(self, plot=False):
        t = self.t[::10]

        N_max = 6
        for n in range(self.N):
            print("\n\n")
            logger.info("======================= Orbit {} =======================".format(n))
            w = self.w[::10,n]

            # get values from Sanders' code
            logger.debug("Computing actions from genfunc...")
            s_actions,s_angles,s_freqs,toy_potential = sanders_act_ang_freq(t, w, N_max=N_max)

            logger.debug("Computing actions...")
            actions,angles,freqs = find_actions(t, w, N_max=N_max, units=self.units,
                                                toy_potential=toy_potential)

            logger.info("Action ratio: {}".format(actions / s_actions))
            logger.info("Angle ratio: {}".format(angles / s_angles))
            logger.info("Freq ratio: {}".format(freqs / s_freqs))

            assert np.allclose(actions, s_actions, rtol=1E-5)
            assert np.allclose(angles, s_angles, rtol=1E-5)
            assert np.allclose(freqs, s_freqs, rtol=1E-5)

            if plot:
                logger.debug("Plotting orbit...")
                fig = plot_orbits(w, marker='.', alpha=0.2, linestyle='none')
                fig.savefig(os.path.join(self.plot_path,"orbit_{}.png".format(n)))

                fig = plot_angles(t,angles,freqs)
                fig.savefig(os.path.join(self.plot_path,"angles_{}.png".format(n)))

                fig = plot_angles(t,s_angles,s_freqs)
                fig.savefig(os.path.join(self.plot_path,"angles_sanders_{}.png".format(n)))

                plt.close('all')

class TestActions(ActionsBase):

    def setup(self):
        self.plot_path = os.path.join(plot_path, 'normal')
        if not os.path.exists(self.plot_path):
            os.makedirs(self.plot_path)

        self.units = (u.kpc, u.Msun, u.Myr)
        self.potential = PW14Potential()
        self.N = 100
        np.random.seed(42)
        w0 = isotropic_w0(N=self.N)
        nsteps = 200000

        if not os.path.exists(os.path.join(this_path, "w.npy")):
            logger.debug("Integrating orbits")
            t,w = self.potential.integrate_orbit(w0, dt=0.2, nsteps=nsteps, Integrator=DOPRI853Integrator)

            logger.debug("Saving orbits")
            np.save(os.path.join(this_path, "t.npy"), t)
            np.save(os.path.join(this_path, "w.npy"), w)
        else:
            logger.debug("Loaded orbits")
            t = np.load(os.path.join(this_path, "t.npy"))
            w = np.load(os.path.join(this_path, "w.npy"))

        self.t = t
        self.w = w

class TestHardActions(ActionsBase):

    def setup(self):
        self.plot_path = os.path.join(plot_path, 'hard')
        if not os.path.exists(self.plot_path):
            os.makedirs(self.plot_path)

        self.units = (u.kpc, u.Msun, u.Myr)
        params = {'a': 6.5, 'q1': 1.3, 'c': 0.3, 'b': 0.26, 'q3': 0.8, 'r_h': 30.0,
                  'm_disk': 65000000000.0, 'psi': 1.570796, 'q2': 1.0, 'theta': 1.570796,
                  'phi': 1.570796, 'm_spher': 20000000000.0, 'v_h': 0.5600371815834104}
        self.potential = PW14Potential(**params)
        self.N = 100

        w0 = np.loadtxt(os.path.join(test_data_path, "w0.txt"))
        nsteps = 200000

        if not os.path.exists(os.path.join(this_path, "w_hard.npy")):
            logger.debug("Integrating orbits")
            t,w = self.potential.integrate_orbit(w0, dt=0.2, nsteps=nsteps, Integrator=DOPRI853Integrator)

            logger.debug("Saving orbits")
            np.save(os.path.join(this_path, "t_hard.npy"), t)
            np.save(os.path.join(this_path, "w_hard.npy"), w)
        else:
            logger.debug("Loaded orbits")
            t = np.load(os.path.join(this_path, "t_hard.npy"))
            w = np.load(os.path.join(this_path, "w_hard.npy"))

        self.t = t
        self.w = w

def test_nvecs():
    nvecs = generate_n_vectors(N_max=6, dx=2, dy=2, dz=2)
    nvecs_sanders = sanders_nvecs(N_max=6, dx=2, dy=2, dz=2)
    assert np.all(nvecs == nvecs_sanders)

    nvecs = generate_n_vectors(N_max=6, dx=1, dy=1, dz=1)
    nvecs_sanders = sanders_nvecs(N_max=6, dx=1, dy=1, dz=1)
    assert np.all(nvecs == nvecs_sanders)

def test_compare_action_prepare():

    from ..actionangle import _action_prepare, _angle_prepare
    import solver
    logger.setLevel(logging.ERROR)
    AA = np.random.uniform(0., 100., size=(1000,6))
    t = np.linspace(0., 100., 1000)

    act_san,n_vectors = solver.solver(AA, N_max=6, symNx=2)
    A2,b2,n = _action_prepare(AA, N_max=6, dx=2, dy=2, dz=2)
    act_apw = np.array(solve(A2,b2))

    ang_san = solver.angle_solver(AA, t, N_max=6, symNx=2, sign=1)
    A2,b2,n = _angle_prepare(AA, t, N_max=6, dx=2, dy=2, dz=2)
    ang_apw = np.array(solve(A2,b2))

    assert np.allclose(act_apw, act_san)
    assert np.allclose(ang_apw, ang_san)

# class TestFrequencyMap(object):

#     def setup(self):
#         self.units = (u.kpc, u.Msun, u.Myr)
#         self.potential = LogarithmicPotential(v_c=1., r_h=np.sqrt(0.1),
#                                               q1=1., q2=1., q3=0.7, phi=0.)
#         acc = lambda t,x: self.potential.acceleration(x)
#         self.integrator = LeapfrogIntegrator(acc)

#         n = 3
#         phis = np.linspace(0.1,1.95*np.pi,n)
#         thetas = np.arccos(2*np.linspace(0.05,0.95,n) - 1)
#         p,t = np.meshgrid(phis, thetas)
#         phis = p.ravel()
#         thetas = t.ravel()

#         sinp,cosp = np.sin(phis),np.cos(phis)
#         sint,cost = np.sin(thetas),np.cos(thetas)

#         rh2 = self.potential.parameters['r_h']**2
#         q2 = self.potential.parameters['q2']
#         q3 = self.potential.parameters['q3']
#         r2 = (np.e - rh2) / (sint**2*cosp**2 + sint**2*sinp**2/q2**2 + cost**2/q3**2)
#         r = np.sqrt(r2)

#         x = r*cosp*sint
#         y = r*sinp*sint
#         z = r*cost
#         v = np.zeros_like(x)

#         E = self.potential.total_energy(np.vstack((x,y,z)).T, np.vstack((v,v,v)).T)
#         assert np.allclose(E, 0.5)

#         self.grid = np.vstack((x,y,z,v,v,v)).T

#     def test(self):
#         N_max = 6
#         logger.debug("Integrating orbits...")
#         t,w = self.integrator.run(self.grid, dt=0.05, nsteps=100000)
#         logger.debug("...done!")

#         fig,axes = plt.subplots(1,3,figsize=(16,5))
#         all_freqs = []
#         for n in range(w.shape[1]):
#             try:
#                 actions,angles,freqs = cross_validate_actions(t, w[:,n], N_max=N_max,
#                                                             units=self.units, skip_failures=True)
#                 failed = False
#             except ValueError as e:
#                 print("FAILED: {}".format(e))
#                 failed = True

#             if not failed:
#                 all_freqs.append(freqs)

#             fig = plot_orbits(w, ix=n, axes=axes, linestyle='none', marker='.', alpha=0.1)
#             fig.axes[1].set_title("Failed: {}".format(failed),fontsize=24)
#             fig.savefig(os.path.join(plot_path,"orbit_{}.png".format(n)))
#             for i in range(3): axes[i].cla()

#         # for freqs in all_freqs:
#         #     print(np.median(freqs,axis=0))
#         #     print(np.std(freqs,axis=0))

#         all_freqs = np.array(all_freqs)

#         plt.clf()
#         plt.figure(figsize=(6,6))
#         plt.plot(all_freqs[:,1]/all_freqs[:,0], all_freqs[:,2]/all_freqs[:,0],
#                  linestyle='none', marker='.')
#         # plt.xlim(0.9, 1.5)
#         # plt.ylim(1.1, 2.1)
#         plt.savefig(os.path.join(plot_path,"freq_map.png"))
<|endoftext|>


<commit_before>import json
from multiprocessing.connection import Listener, Client

class ConnectionWrapper(object):
    def __init__(self, conn):
        self._conn = conn

        for attr in ('fileno', 'close', 'poll', 'recv_bytes', 'send_bytes'):
            obj = getattr(conn, attr)
            setattr(self, attr, obj)

    def send(self, obj):
        s = json.dumps(obj)
        self._conn.send_bytes(s.encode("utf-8"))

    def recv(self):
        s = self._conn.recv_bytes()
        try:
            return json.loads(s.decode("utf-8"))
        except ValueError as e:
            print(e, str(s))

class JsonListener(Listener):
    def accept(self):
        obj = Listener.accept(self)
        return ConnectionWrapper(obj)

def JsonClient(*args, **kwds):
    return ConnectionWrapper(Client(*args, **kwds))
<commit_msg>fixed AuthenticationError issue happening when debugging python2. the issue was because py2 multiprocessing uses MD5 for digest, but py3 multiprocessing uses SHA256, therefore, connections between both versions are not compatible. Had to monkey patch authentication methods, ugly, but the only way I see it possible..<commit_after>import json
from multiprocessing.connection import Listener, Client

class ConnectionWrapper(object):
    def __init__(self, conn):
        self._conn = conn

        for attr in ('fileno', 'close', 'poll', 'recv_bytes', 'send_bytes'):
            obj = getattr(conn, attr)
            setattr(self, attr, obj)

    def send(self, obj):
        s = json.dumps(obj)
        self._conn.send_bytes(s.encode("utf-8"))

    def recv(self):
        s = self._conn.recv_bytes()
        try:
            return json.loads(s.decode("utf-8"))
        except ValueError as e:
            print(e, str(s))

class JsonListener(Listener):
    def accept(self):
        obj = Listener.accept(self)
        return ConnectionWrapper(obj)

def JsonClient(*args, **kwds):
    return ConnectionWrapper(Client(*args, **kwds))

# Ugly patching to fixe py2<->py3 multiprocessing compatibility
# Reference: http://bugs.python.org/review/17258/patch/7414/27889

from py3compat import PY3
from multiprocessing import connection, AuthenticationError
from multiprocessing.connection import CHALLENGE, WELCOME, \
    MESSAGE_LENGTH, FAILURE
import os
import hashlib

def answer_challenge(conn, authkey):
    import hmac
    message = conn.recv_bytes(256)         # reject large message
    assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message
    message = message[len(CHALLENGE):]
    digest = hmac.new(authkey, message, hashlib.sha256).digest()
    conn.send_bytes(digest)
    response = conn.recv_bytes(256)        # reject large message
    if response != WELCOME:
        raise AuthenticationError('digest sent was rejected')

def deliver_challenge(conn, authkey):
    import hmac
    message = os.urandom(MESSAGE_LENGTH)
    conn.send_bytes(CHALLENGE + message)
    digest = hmac.new(authkey, message, hashlib.sha256).digest()
    response = conn.recv_bytes(256)        # reject large message
    if response == digest:
        conn.send_bytes(WELCOME)
    else:
        conn.send_bytes(FAILURE)
        raise AuthenticationError('digest received was wrong')

connection.deliver_challenge = deliver_challenge
connection.answer_challenge = answer_challenge<|endoftext|>


<commit_before># coding: utf-8
"""Utilities for installing jupyter_nbextensions_configurator."""

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from __future__ import print_function

import copy
import sys

from jupyter_contrib_core.notebook_compat import nbextensions, serverextensions

from jupyter_nbextensions_configurator import __version__

class ToggleJupyterNbextensionsConfiguratorApp(
        serverextensions.ToggleServerExtensionApp):
    """An App that toggles the jupyter_nbextensions_configurator extension."""

    flags = copy.deepcopy(serverextensions.ToggleServerExtensionApp.flags)
    flags['sys-prefix'] = ({
        'ToggleServerExtensionApp': {
            'sys_prefix': True,
            'user': False,
        }},
        'Use sys.prefix as the prefix for configuring the server extension')
    for f in ('py', 'python'):
        flags.pop(f, None)

    def parse_command_line(self, argv=None):
        """
        Overriden to check for conflicting flags

        Since notebook version doesn't do it well (or, indeed, at all)
        """
        conflicting_flags = set(['--user', '--system', '--sys-prefix'])

        if len(conflicting_flags.intersection(set(argv))) > 1:
            raise serverextensions.ArgumentConflict(
                'cannot specify more than one of user, sys_prefix, or system')
        return super(ToggleJupyterNbextensionsConfiguratorApp,
                     self).parse_command_line(argv)

    @property
    def name(self):
        return 'jupyter_nbextensions_configurator {}'.format(
            'enable' if self._toggle_value else 'disable')

    @property
    def description(self):
        return """
Enable the jupyter_nbextensions_configurator server extension in configuration.

Usage
    jupyter_nbextensions_configurator {} [--system|--sys-prefix|--user]
""".format('enable' if self._toggle_value else 'disable')

    def start(self):
        """Perform the App's actions as configured."""
        if self.extra_args:
            sys.exit('{} takes no extra arguments'.format(self.name))
        else:
            self.toggle_server_extension_python(
                'jupyter_nbextensions_configurator')
            enabled = self._toggle_value
            nbextensions._set_nbextension_state(
                'notebook', 'nbextensions_configurator/config_menu/main',
                enabled,
                user=self.user, sys_prefix=self.sys_prefix, logger=self.log)
            nbextensions._set_nbextension_state(
                'tree', 'nbextensions_configurator/tree_tab/main', enabled,
                user=self.user, sys_prefix=self.sys_prefix, logger=self.log)

class EnableJupyterNbextensionsConfiguratorApp(
        ToggleJupyterNbextensionsConfiguratorApp):
    """An App that enables the jupyter_nbextensions_configurator extension."""
    name = 'jupyter nbextensions_configurator enable'
    _toggle_value = True

class DisableJupyterNbextensionsConfiguratorApp(
        ToggleJupyterNbextensionsConfiguratorApp):
    """An App that disables the jupyter_nbextensions_configurator extension."""
    name = 'jupyter nbextensions_configurator disable'
    _toggle_value = False

class JupyterNbextensionsConfiguratorApp(nbextensions.BaseNBExtensionApp):
    """Root level jupyter_nbextensions_configurator app."""

    name = 'jupyter nbextensions_configurator'
    version = __version__
    description = (
        'Enable or disable '
        'the jupyter_nbextensions_configurator server extension')
    subcommands = dict(
        enable=(
            EnableJupyterNbextensionsConfiguratorApp,
            'Enable the jupyter_nbextensions_configurator server extension.'),
        disable=(
            DisableJupyterNbextensionsConfiguratorApp,
            'Disable the jupyter_nbextensions_configurator server extension.'),
    )
    examples = '\n'.join([
        'jupyter nbextensions_configurator enable  # Enable the jupyter_nbextensions_configurator server extension.',  # noqa
        'jupyter nbextensions_configurator disable # Disable the jupyter_nbextensions_configurator server extension.',  # noqa
    ])

    def start(self):
        """Perform the App's actions as configured"""
        super(JupyterNbextensionsConfiguratorApp, self).start()

        # The above should have called a subcommand and raised NoStart; if we
        # get here, it didn't, so we should self.log.info a message.
        subcmds = ", ".join(sorted(self.subcommands))
        sys.exit("Please supply at least one subcommand: %s" % subcmds)

main = JupyterNbextensionsConfiguratorApp.launch_instance

if __name__ == '__main__':  # pragma: no cover
    main()
<commit_msg>alter logging for en/disabling configurator nbextensions do our own logging, rather than pass logger to notebook functions, as otherwise we get warnings about not being able to find the require files (which are added to path at run-time, so the check doesn't make sense).<commit_after># coding: utf-8
"""Utilities for installing jupyter_nbextensions_configurator."""

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from __future__ import print_function

import copy
import sys

from jupyter_contrib_core.notebook_compat import nbextensions, serverextensions

from jupyter_nbextensions_configurator import __version__

class ToggleJupyterNbextensionsConfiguratorApp(
        serverextensions.ToggleServerExtensionApp):
    """An App that toggles the jupyter_nbextensions_configurator extension."""

    flags = copy.deepcopy(serverextensions.ToggleServerExtensionApp.flags)
    flags['sys-prefix'] = ({
        'ToggleServerExtensionApp': {
            'sys_prefix': True,
            'user': False,
        }},
        'Use sys.prefix as the prefix for configuring the server extension')
    for f in ('py', 'python'):
        flags.pop(f, None)

    def parse_command_line(self, argv=None):
        """
        Overriden to check for conflicting flags

        Since notebook version doesn't do it well (or, indeed, at all)
        """
        conflicting_flags = set(['--user', '--system', '--sys-prefix'])

        if len(conflicting_flags.intersection(set(argv))) > 1:
            raise serverextensions.ArgumentConflict(
                'cannot specify more than one of user, sys_prefix, or system')
        return super(ToggleJupyterNbextensionsConfiguratorApp,
                     self).parse_command_line(argv)

    @property
    def name(self):
        return 'jupyter_nbextensions_configurator {}'.format(
            'enable' if self._toggle_value else 'disable')

    @property
    def description(self):
        return """
Enable the jupyter_nbextensions_configurator server extension in configuration.

Usage
    jupyter_nbextensions_configurator {} [--system|--sys-prefix|--user]
""".format('enable' if self._toggle_value else 'disable')

    def start(self):
        """Perform the App's actions as configured."""
        if self.extra_args:
            sys.exit('{} takes no extra arguments'.format(self.name))
        else:
            self.toggle_server_extension_python(
                'jupyter_nbextensions_configurator')
            nbexts = [
                ('notebook', 'nbextensions_configurator/config_menu/main'),
                ('tree', 'nbextensions_configurator/tree_tab/main'),
            ]
            for section, require in nbexts:
                enabled = self._toggle_value
                self.log.info('{} {} extension {}...'.format(
                    'Enabling' if enabled else 'Disabling', section, require))
                nbextensions._set_nbextension_state(
                    section, require, enabled,
                    user=self.user, sys_prefix=self.sys_prefix)

class EnableJupyterNbextensionsConfiguratorApp(
        ToggleJupyterNbextensionsConfiguratorApp):
    """An App that enables the jupyter_nbextensions_configurator extension."""
    name = 'jupyter nbextensions_configurator enable'
    _toggle_value = True

class DisableJupyterNbextensionsConfiguratorApp(
        ToggleJupyterNbextensionsConfiguratorApp):
    """An App that disables the jupyter_nbextensions_configurator extension."""
    name = 'jupyter nbextensions_configurator disable'
    _toggle_value = False

class JupyterNbextensionsConfiguratorApp(nbextensions.BaseNBExtensionApp):
    """Root level jupyter_nbextensions_configurator app."""

    name = 'jupyter nbextensions_configurator'
    version = __version__
    description = (
        'Enable or disable '
        'the jupyter_nbextensions_configurator server extension')
    subcommands = dict(
        enable=(
            EnableJupyterNbextensionsConfiguratorApp,
            'Enable the jupyter_nbextensions_configurator server extension.'),
        disable=(
            DisableJupyterNbextensionsConfiguratorApp,
            'Disable the jupyter_nbextensions_configurator server extension.'),
    )
    examples = '\n'.join([
        'jupyter nbextensions_configurator enable  # Enable the jupyter_nbextensions_configurator server extension.',  # noqa
        'jupyter nbextensions_configurator disable # Disable the jupyter_nbextensions_configurator server extension.',  # noqa
    ])

    def start(self):
        """Perform the App's actions as configured"""
        super(JupyterNbextensionsConfiguratorApp, self).start()

        # The above should have called a subcommand and raised NoStart; if we
        # get here, it didn't, so we should self.log.info a message.
        subcmds = ", ".join(sorted(self.subcommands))
        sys.exit("Please supply at least one subcommand: %s" % subcmds)

main = JupyterNbextensionsConfiguratorApp.launch_instance

if __name__ == '__main__':  # pragma: no cover
    main()
<|endoftext|>


<commit_before>from datetime import datetime

from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.conf import settings

from basenode import BaseNode
from node import Node
from period import Period
from abstract_is_examiner import AbstractIsExaminer
from abstract_is_candidate import AbstractIsCandidate
from candidate import Candidate
from model_utils import *
from custom_db_fields import ShortNameField, LongNameField
from model_utils import Etag

import deliverytypes

class Assignment(models.Model, BaseNode, AbstractIsExaminer, AbstractIsCandidate, Etag):
    """

    .. attribute:: parentnode

        A django.db.models.ForeignKey_ that points to the parent node,
        which is always a `Period`_.

    .. attribute:: publishing_time

        A django.db.models.DateTimeField_ representing the publishing time of
        the assignment.

    .. attribute:: anonymous

        A models.BooleanField specifying if the assignment should be
        anonymously for correcters.

    .. attribute:: admins

        A django.db.models.ManyToManyField_ that holds all the admins of the
        Node.

    .. attribute:: assignmentgroups

        A set of :class:`assignmentgroups <devilry.apps.core.models.AssignmentGroup>` for this assignment

    .. attribute:: examiners_publish_feedbacks_directly

       Should feedbacks published by examiners be made avalable to the
       students immediately? If not, an administrator have to publish
       feedbacks. See also :attr:`Deadline.feedbacks_published`.

    .. attribute:: scale_points_percent

        Percent to scale points on this assignment by for period overviews. The default is 100, which means no change to the points.

    .. attribute:: delivery_types

        An integer identifying the type of deliveries allowed. Possible values:

            0
                Electronic deliveries using Devilry
            1
                Non-electronic deliveries, or deliveries made through another
                electronic system.
            2
                An alias/link to a delivery made in another Period.

    .. attribute:: deadline_handling

        An integer identifying how deadlines are handled.

            0
                Soft deadlines. Deliveries can be added until groups are closed.
            1
                Hard deadlines. Deliveries can not be added after the deadline
                has expired.

    .. attribute:: etag

        A DateTimeField containing the etag for this object.

    .. attribute:: first_deadline

        A DateTimeField containing an optional first deadline for this
        assignment. This is metadata that the UI can use where it is
        natural.
    """
    class Meta:
        app_label = 'core'
        unique_together = ('short_name', 'parentnode')
        ordering = ['short_name']

    short_name = ShortNameField()
    long_name = LongNameField()
    parentnode = models.ForeignKey(Period, related_name='assignments',
                                   verbose_name='Period')
    etag = models.DateTimeField(auto_now_add=True)
    publishing_time = models.DateTimeField(verbose_name="Publishing time",
                                           help_text='The time when the assignment is to be published (visible to students and examiners).')
    anonymous = models.BooleanField(default=False,
                                    verbose_name="Anonymous",
                                    help_text='Specifies if this assignment is anonymous.')
    students_can_see_points = models.BooleanField(default=True,
            verbose_name="Students can see points")
    admins = models.ManyToManyField(User, blank=True,
            verbose_name="Administrators")
    examiners_publish_feedbacks_directly = models.BooleanField(default=True,
                                                     verbose_name="Examiners publish directly?",
                                                     help_text=('Should feedbacks published by examiners be made '
                                                                'avalable to the students immediately? If not, an '
                                                                'administrator have to publish feedbacks '
                                                                'manually.'))
    delivery_types = models.PositiveIntegerField(default=deliverytypes.ELECTRONIC,
                                                 choices=deliverytypes.as_choices_tuple(),
                                                 help_text='This option controls what types of deliveries this assignment accepts. See the Delivery documentation for more info.')
    deadline_handling = models.PositiveIntegerField(default=settings.DEFAULT_DEADLINE_HANDLING_METHOD,
                                                    help_text='This option controls how devilry handles deadlines. 0=Soft, 1=Hard. See the Delivery documentation for more info.')
    scale_points_percent = models.PositiveIntegerField(default=100,
                                                       help_text='Percent to scale points on this assignment by for period overviews. The default is 100, which means no change to the points.')
    first_deadline = models.DateTimeField(blank=True, null=True)

    @classmethod
    def q_published(cls, old=True, active=True):
        now = datetime.now()
        q = Q(publishing_time__lt=now)
        if not active:
            q &= ~Q(parentnode__end_time__gte=now)
        if not old:
            q &= ~Q(parentnode__end_time__lt=now)
        return q

    @classmethod
    def q_is_candidate(cls, user_obj):
        return Q(assignmentgroups__candidates__student=user_obj)

    def save(self, *args, **kwargs):
        if self.pk:
            # Only when assignment already exists in the database
            self.update_candidates_identifer()
        super(Assignment, self).save(*args, **kwargs)

    def update_candidates_identifer(self):
        """ If the anonymous flag is changed, update the identifer on all
        the candidates on this assignment.
        """
        # Get current value stored in the db
        db_assignment = Assignment.objects.get(id=self.id)
        # No change, so return
        if self.anonymous == db_assignment.anonymous:
            return
        # Get all candidates on assignmentgroups for this assignment
        candidates = Candidate.objects.filter(Q(assignment_group__parentnode__id=self.id))
        for cand in candidates:
            #cand.update_identifier(self.anonymous)
            cand.save(anonymous=self.anonymous)

    @classmethod
    def q_is_admin(cls, user_obj):
        return Q(admins=user_obj) | \
                Q(parentnode__admins=user_obj) | \
                Q(parentnode__parentnode__admins=user_obj) | \
                Q(parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))

    @classmethod
    def q_is_examiner(cls, user_obj):
        return Q(assignmentgroups__examiners__user=user_obj)

    def _clean_first_deadline(self):
        self.first_deadline = self.first_deadline.replace(microsecond=0, tzinfo=None) # NOTE: We want this so a unique deadline is a deadline which matches with second-specition.
        datetimeformat = '%Y-%m-%d %H:%M'
        if self.first_deadline < self.publishing_time:
            msg = _('Submission date can not be before the publishing time ({publishing_time}) of the assignment.')
            raise ValidationError(msg.format(publishing_time = self.publishing_time.strftime(datetimeformat)))
        if self.first_deadline > self.parentnode.end_time:
            msg = _("Submission date must be within it's {period_term} ({start_time} - {end_time}).")
            raise ValidationError(msg.format(period_term=_('period'),
                                             start_time=self.parentnode.start_time.strftime(datetimeformat),
                                             end_time=self.parentnode.end_time.strftime(datetimeformat)))

    def clean(self, *args, **kwargs):
        """Validate the assignment.

        Always call this before save()! Read about validation here:
        http://docs.djangoproject.com/en/dev/ref/models/instances/#id1

        Raises ValidationError if ``publishing_time`` is not between
        :attr:`Period.start_time` and ``Period.end_time``.
        """
        super(Assignment, self).clean(*args, **kwargs)
        if self.publishing_time != None and self.parentnode_id != None:
            if self.publishing_time < self.parentnode.start_time  or \
                    self.publishing_time > self.parentnode.end_time:
                raise ValidationError(
                      _("The publishing time, {publishing_time}, is invalid. "
                        "It must be within it's period, {period}, "
                        "which lasts from {start_time} to {end_time}").format(publishing_time = self.publishing_time,
                                                                              period=unicode(self.parentnode),
                                                                              end_time=self.parentnode.end_time,
                                                                              start_time=self.parentnode.start_time))
        if self.first_deadline:
            self._clean_first_deadline()

    def is_empty(self):
        """
        Returns ``True`` if this Assignment does not contain any deliveries.
        """
        from .delivery import Delivery
        return Delivery.objects.filter(deadline__assignment_group__parentnode=self).count() == 0

    def is_active(self):
        """
        Returns ``True`` if this assignment is published, and the period has not ended yet.
        """
        now = datetime.now()
        return self.publishing_time < now and self.parentnode.end_time > now<commit_msg>apps.core.models.assignment: Added variables for deadline_handling.<commit_after>from datetime import datetime

from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.conf import settings

from basenode import BaseNode
from node import Node
from period import Period
from abstract_is_examiner import AbstractIsExaminer
from abstract_is_candidate import AbstractIsCandidate
from candidate import Candidate
from model_utils import *
from custom_db_fields import ShortNameField, LongNameField
from model_utils import Etag

import deliverytypes

class Assignment(models.Model, BaseNode, AbstractIsExaminer, AbstractIsCandidate, Etag):
    """

    .. attribute:: parentnode

        A django.db.models.ForeignKey_ that points to the parent node,
        which is always a `Period`_.

    .. attribute:: publishing_time

        A django.db.models.DateTimeField_ representing the publishing time of
        the assignment.

    .. attribute:: anonymous

        A models.BooleanField specifying if the assignment should be
        anonymously for correcters.

    .. attribute:: admins

        A django.db.models.ManyToManyField_ that holds all the admins of the
        Node.

    .. attribute:: assignmentgroups

        A set of :class:`assignmentgroups <devilry.apps.core.models.AssignmentGroup>` for this assignment

    .. attribute:: examiners_publish_feedbacks_directly

       Should feedbacks published by examiners be made avalable to the
       students immediately? If not, an administrator have to publish
       feedbacks. See also :attr:`Deadline.feedbacks_published`.

    .. attribute:: scale_points_percent

        Percent to scale points on this assignment by for period overviews. The default is 100, which means no change to the points.

    .. attribute:: delivery_types

        An integer identifying the type of deliveries allowed. Possible values:

            0
                Electronic deliveries using Devilry
            1
                Non-electronic deliveries, or deliveries made through another
                electronic system.
            2
                An alias/link to a delivery made in another Period.

    .. attribute:: deadline_handling

        An integer identifying how deadlines are handled.

            0
                Soft deadlines. Deliveries can be added until groups are closed.
            1
                Hard deadlines. Deliveries can not be added after the deadline
                has expired.

    .. attribute:: etag

        A DateTimeField containing the etag for this object.

    .. attribute:: first_deadline

        A DateTimeField containing an optional first deadline for this
        assignment. This is metadata that the UI can use where it is
        natural.
    """

    DEADLINEHANDLING_SOFT = 0
    DEADLINEHANDLING_HARD = 1

    class Meta:
        app_label = 'core'
        unique_together = ('short_name', 'parentnode')
        ordering = ['short_name']

    short_name = ShortNameField()
    long_name = LongNameField()
    parentnode = models.ForeignKey(Period, related_name='assignments',
                                   verbose_name='Period')
    etag = models.DateTimeField(auto_now_add=True)
    publishing_time = models.DateTimeField(verbose_name="Publishing time",
                                           help_text='The time when the assignment is to be published (visible to students and examiners).')
    anonymous = models.BooleanField(default=False,
                                    verbose_name="Anonymous",
                                    help_text='Specifies if this assignment is anonymous.')
    students_can_see_points = models.BooleanField(default=True,
            verbose_name="Students can see points")
    admins = models.ManyToManyField(User, blank=True,
            verbose_name="Administrators")
    examiners_publish_feedbacks_directly = models.BooleanField(default=True,
                                                     verbose_name="Examiners publish directly?",
                                                     help_text=('Should feedbacks published by examiners be made '
                                                                'avalable to the students immediately? If not, an '
                                                                'administrator have to publish feedbacks '
                                                                'manually.'))
    delivery_types = models.PositiveIntegerField(default=deliverytypes.ELECTRONIC,
                                                 choices=deliverytypes.as_choices_tuple(),
                                                 help_text='This option controls what types of deliveries this assignment accepts. See the Delivery documentation for more info.')
    deadline_handling = models.PositiveIntegerField(default=settings.DEFAULT_DEADLINE_HANDLING_METHOD,
                                                    help_text='This option controls how devilry handles deadlines. 0=Soft, 1=Hard. See the Delivery documentation for more info.')
    scale_points_percent = models.PositiveIntegerField(default=100,
                                                       help_text='Percent to scale points on this assignment by for period overviews. The default is 100, which means no change to the points.')
    first_deadline = models.DateTimeField(blank=True, null=True)

    @classmethod
    def q_published(cls, old=True, active=True):
        now = datetime.now()
        q = Q(publishing_time__lt=now)
        if not active:
            q &= ~Q(parentnode__end_time__gte=now)
        if not old:
            q &= ~Q(parentnode__end_time__lt=now)
        return q

    @classmethod
    def q_is_candidate(cls, user_obj):
        return Q(assignmentgroups__candidates__student=user_obj)

    def save(self, *args, **kwargs):
        if self.pk:
            # Only when assignment already exists in the database
            self.update_candidates_identifer()
        super(Assignment, self).save(*args, **kwargs)

    def update_candidates_identifer(self):
        """ If the anonymous flag is changed, update the identifer on all
        the candidates on this assignment.
        """
        # Get current value stored in the db
        db_assignment = Assignment.objects.get(id=self.id)
        # No change, so return
        if self.anonymous == db_assignment.anonymous:
            return
        # Get all candidates on assignmentgroups for this assignment
        candidates = Candidate.objects.filter(Q(assignment_group__parentnode__id=self.id))
        for cand in candidates:
            #cand.update_identifier(self.anonymous)
            cand.save(anonymous=self.anonymous)

    @classmethod
    def q_is_admin(cls, user_obj):
        return Q(admins=user_obj) | \
                Q(parentnode__admins=user_obj) | \
                Q(parentnode__parentnode__admins=user_obj) | \
                Q(parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))

    @classmethod
    def q_is_examiner(cls, user_obj):
        return Q(assignmentgroups__examiners__user=user_obj)

    def _clean_first_deadline(self):
        self.first_deadline = self.first_deadline.replace(microsecond=0, tzinfo=None) # NOTE: We want this so a unique deadline is a deadline which matches with second-specition.
        datetimeformat = '%Y-%m-%d %H:%M'
        if self.first_deadline < self.publishing_time:
            msg = _('Submission date can not be before the publishing time ({publishing_time}) of the assignment.')
            raise ValidationError(msg.format(publishing_time = self.publishing_time.strftime(datetimeformat)))
        if self.first_deadline > self.parentnode.end_time:
            msg = _("Submission date must be within it's {period_term} ({start_time} - {end_time}).")
            raise ValidationError(msg.format(period_term=_('period'),
                                             start_time=self.parentnode.start_time.strftime(datetimeformat),
                                             end_time=self.parentnode.end_time.strftime(datetimeformat)))

    def clean(self, *args, **kwargs):
        """Validate the assignment.

        Always call this before save()! Read about validation here:
        http://docs.djangoproject.com/en/dev/ref/models/instances/#id1

        Raises ValidationError if ``publishing_time`` is not between
        :attr:`Period.start_time` and ``Period.end_time``.
        """
        super(Assignment, self).clean(*args, **kwargs)
        if self.publishing_time != None and self.parentnode_id != None:
            if self.publishing_time < self.parentnode.start_time  or \
                    self.publishing_time > self.parentnode.end_time:
                raise ValidationError(
                      _("The publishing time, {publishing_time}, is invalid. "
                        "It must be within it's period, {period}, "
                        "which lasts from {start_time} to {end_time}").format(publishing_time = self.publishing_time,
                                                                              period=unicode(self.parentnode),
                                                                              end_time=self.parentnode.end_time,
                                                                              start_time=self.parentnode.start_time))
        if self.first_deadline:
            self._clean_first_deadline()

    def is_empty(self):
        """
        Returns ``True`` if this Assignment does not contain any deliveries.
        """
        from .delivery import Delivery
        return Delivery.objects.filter(deadline__assignment_group__parentnode=self).count() == 0

    def is_active(self):
        """
        Returns ``True`` if this assignment is published, and the period has not ended yet.
        """
        now = datetime.now()
        return self.publishing_time < now and self.parentnode.end_time > now
<|endoftext|>


<commit_before>"""Evaluation and Control implementations of Relative Value Iteration."""

from absl import logging

import numpy as np
from differential_value_iteration.algorithms import algorithm
from differential_value_iteration.environments import structure

class Evaluation(algorithm.Evaluation):
  def __init__(
      self,
      mrp: structure.MarkovRewardProcess,
      initial_values: np.ndarray,
      step_size: float,
      reference_index: int,
      synchronized: bool):
    self.mrp = mrp
    self.initial_values = initial_values.copy()
    self.step_size = step_size
    self.reference_index = reference_index
    self.index = 0
    self.synchronized = synchronized
    self.reset()

  def reset(self):
    self.current_values = self.initial_values.copy()

  def diverged(self)->bool:
    if not np.isfinite(self.current_values).all():
      logging.warn('Current values not finite in RVI.')
      return True
    return False

  def update(self)->np.ndarray:
    if self.synchronized:
      return self.update_sync()
    return self.update_async()

  def update_sync(self):
    changes = self.mrp.rewards + np.dot(
        self.mrp.transitions,
        self.current_values - self.current_values[self.reference_index]) - self.current_values
    self.current_values += self.step_size * changes
    return changes

  def update_async(self):
    change = self.mrp.rewards[self.index] + np.dot(
        self.mrp.transitions[self.index],
        self.current_values - self.current_values[
          self.reference_index])- self.current_values[self.index]
    self.current_values[self.index] += self.step_size * change
    self.index = (self.index + 1) % self.mrp.num_states
    return change
<commit_msg>Partial progress.<commit_after>"""Evaluation and Control implementations of Relative Value Iteration."""

from absl import logging

import numpy as np
from differential_value_iteration.algorithms import algorithm
from differential_value_iteration.environments import structure

class Evaluation(algorithm.Evaluation):
  def __init__(
      self,
      mrp: structure.MarkovRewardProcess,
      initial_values: np.ndarray,
      step_size: float,
      reference_index: int,
      synchronized: bool):
    self.mrp = mrp
    self.initial_values = initial_values.copy()
    self.step_size = step_size
    self.reference_index = reference_index
    self.index = 0
    self.synchronized = synchronized
    self.reset()

  def reset(self):
    self.current_values = self.initial_values.copy()

  def diverged(self)->bool:
    if not np.isfinite(self.current_values).all():
      logging.warn('Current values not finite in RVI.')
      return True
    return False

  def update(self)->np.ndarray:
    if self.synchronized:
      return self.update_sync()
    return self.update_async()

  def update_sync(self):
    changes = self.mrp.rewards + np.dot(
        self.mrp.transitions,
        self.current_values - self.current_values[self.reference_index]) - self.current_values
    self.current_values += self.step_size * changes
    return changes

  def update_async(self):
    change = self.mrp.rewards[self.index] + np.dot(
        self.mrp.transitions[self.index],
        self.current_values - self.current_values[
          self.reference_index])- self.current_values[self.index]
    self.current_values[self.index] += self.step_size * change
    self.index = (self.index + 1) % self.mrp.num_states
    return change

class Control:
  def __init__(
      self,
      mdp: structure.MarkovDecisionProcess,
      STOPPED HERE
      initial_values: np.ndarray,
      step_size: float,
      reference_index: int,
      synchronized: bool):
    self.mrp = mrp
    self.initial_values = initial_values.copy()
    self.step_size = step_size
    self.reference_index = reference_index
    self.index = 0
    self.synchronized = synchronized
    self.reset()<|endoftext|>


<commit_before><commit_msg>add license header<commit_after><|endoftext|>