def test_step_one_infected_unity_rate_infects_other(self): self.two_in_contact[0].infected = True propagator = Propagator(self.two_in_contact, rate=1.0) propagator.step() self.assertTrue(self.two_in_contact[1].infected)
def test_results_has_length_of_steps_with_three_steps(self): propagator = Propagator(self.two_in_contact) n_steps = 3 propagator.step_n(n_steps) self.assertEqual(n_steps, len(propagator.results.day))
def test_results_days_are_consecutive_for_four_days(self): propagator = Propagator(self.two_in_contact) n_steps = 4 propagator.step_n(n_steps) self.assertEqual([0, 1, 2, 3], propagator.results.day)
def test_step_with_two_in_contact_and_zero_rate_does_nothing(self): propagator = Propagator(self.two_in_contact, rate=0.0) propagator.step() self.assertFalse(self.two_in_contact[0].infected) self.assertFalse(self.two_in_contact[1].infected)
def test_recovered_do_not_get_reinfected(self): self.two_in_contact[0].infected = True propagator = Propagator(self.two_in_contact, rate=1.0, infection_length=1) propagator.step_n(2) self.assertFalse(self.two_in_contact[0].infected)
def test_not_infected_with_mortality_1_dont_die(self): person = Person() propagator = Propagator([person], daily_mortality=1.0) propagator.step() self.assertFalse(person.dead)
def make_primitive_helper(*cells): inputs, output = cells[:-1], cells[-1] lifted_f = _lift_to_cell_contents(f) def to_do(): output.add_content(lifted_f(*[c.content for c in inputs])) return Propagator(inputs, to_do)
def test_results_recovered_count_recovered(self): self.two_in_contact[0].infected = True propagator = Propagator(self.two_in_contact, infection_length=1, daily_mortality=0) propagator.step_n(2) self.assertEqual([0, 1], propagator.results.recovered_count)
def test_none_in_contact_do_not_infect(self): people = [Person(), Person()] people[0].infected = True propagator = Propagator(people, rate=1.0) propagator.step() self.assertFalse(people[1].infected)
def test_all_infected_die_with_mortality_1(self): person = Person() person.infected = True propagator = Propagator([person], daily_mortality=1.0) propagator.step() self.assertTrue(person.dead)
def test_infected_given_infection_length_3_is_still_infected_after_2_steps(self): infected_person = Person() infected_person.infected = True propagator = Propagator([infected_person], infection_length=3) propagator.step_n(2) self.assertTrue(infected_person.infected)
def test_infected_recover_after_infection_length_steps_of_2(self): infected_person = Person() infected_person.infected = True propagator = Propagator([infected_person], infection_length=2) propagator.step_n(2) self.assertFalse(infected_person.infected)
def test_step_half_rate_infects_other_with_rng_zero(self, mock_random): mock_random.return_value = 0.0 self.two_in_contact[0].infected = True propagator = Propagator(self.two_in_contact, rate=0.5) propagator.step() self.assertTrue(self.two_in_contact[1].infected)
def test_results_dead_count_dead(self): self.two_in_contact[0].infected = True self.two_in_contact[1].dead = True propagator = Propagator(self.two_in_contact, infection_length=10, daily_mortality=1.0) propagator.step_n(2) self.assertEqual([1, 2], propagator.results.dead_count)
def test_those_that_die_do_not_recover(self, mock_random): mock_random.return_value = 0.0 person = Person() person.infected = True propagator = Propagator([person], daily_mortality=1.0, infection_length=1) propagator.step() self.assertFalse(person.recovered)
def test_the_dead_do_not_infect(self, mock_random): mock_random.return_value = 0.0 self.two_in_contact[0].dead = True self.two_in_contact[0].infected = True propagator = Propagator(self.two_in_contact, daily_mortality=1.0, rate=1.0) propagator.step() self.assertFalse(self.two_in_contact[1].infected)
def test_results_infected_count_infected(self): self.two_in_contact[0].infected = True self.two_in_contact[1].infected = True propagator = Propagator(self.two_in_contact, infection_length=1) propagator.step_n(2) self.assertEqual([2, 0], propagator.results.infected_count)
def test_all_infected_die_with_mortality_one_tenth_and_rng_0(self, mock_random): mock_random.return_value = 0.0 person = Person() person.infected = True propagator = Propagator([person], daily_mortality=0.1) propagator.step() self.assertTrue(person.dead)
def test_those_that_die_are_not_considered_infected(self, mock_random): mock_random.return_value = 0.0 person = Person() person.infected = True propagator = Propagator([person], daily_mortality=1.0) propagator.step() self.assertFalse(person.infected)
def conditional(p, if_true, if_false, output): def conditional_helper(): if p.content is not None: if p.content: output.add_content(if_true.content) else: output.add_content(if_false.content) return Propagator([p, if_true, if_false], conditional_helper)
def new_propagator_appends_function_to_neighbors(self): a = Cell() b = Cell() c = Cell() f = lambda x: x Propagator([a, b, c], f) for cell in [a, b, c]: self.assertEqual(cell.neighbors, [f])
def propagate(): action_help = """ Actions ======== info : print all info about the spacecraft get_all : get all data and return as a csv get_pass : quickly find upcoming pass(es) compute : compute pass details Ground station specification ============================ The ground station can be specified with the --gslat, --gslon, --gselev params, or alternatively by a simple text file with those three fields separated by comma. The file should either be called gs.txt or specified with --gs. Examples ======== $ libgs-propagate info Print info about current state of spacecraft described by TLE. Get TLE from stdin $ libgs-propagate -i tles.txt -w "2018-01-01 10:00" "2018-01-01 10:05" "2018-01-01 10:10" get_all Compute everything we can about the tles at the times specified and return a CSV $ libgs-propagate -i tles.txt -N 10 get_pass Get overview of next 10 passes and return a CSV $ libgs-propagate -i tles.txt --nid 25440 compute Compute upcoming pass for TLE 25440 and return a CSV with same fields as get_all """ parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='Propagate a TLE', epilog=action_help) parser.add_argument( "-i", "--input", help="Input file with TLE(s). Omit to get TLE(s) from stdin") parser.add_argument( "-n", "--nid", type=int, nargs="*", help= "Norad ID(s) of TLE(s) to propagate. If omitted does all provided TLEs" ) parser.add_argument("-w", "--when", type=str, nargs="*", help="Timestamps at which to propegate. Default=now") parser.add_argument("--gslat", type=float, help="Ground station latitiude (overrides --gs)") parser.add_argument("--gslon", type=float, help="Ground station longitude (overrides --gs)") parser.add_argument("--gselev", type=float, help="Ground station elevation (overrides --gs)") parser.add_argument( "-g", "--gs", type=str, default="gs.txt", help="Ground station specification file (use instead of gslat/lon/elev)" ) parser.add_argument("-H", "--horizon", type=float, default=5, help="Visibility horizon") parser.add_argument( "-N", type=int, default=1, help="(Only with get_pass action) Number of passes to get") parser.add_argument( "--dt", type=int, help="(Only with compute action) Time interval to compute data at") parser.add_argument("action", choices=["info", "get_all", "get_pass", "compute"], help="Action to take") parser.add_argument("-p", "--print", action="store_true", help="Pretty print output") parser.add_argument("-f", "--field", nargs="+", help="Filter output by one or more fields") parser.add_argument("--no-header", action="store_true", help="Dont output csv header") args = parser.parse_args() if args.input is not None: try: with open(args.input, "r") as fp: tles = fp.read() except Exception as e: _print("ERROR: Could not read file {}".format(args.input)) exit(1) else: _print("Enter TLE(s). EOF (Ctrl-D) to finish") tles = sys.stdin.read() tles = tles.strip() if (args.gslat is not None and args.gslon is not None and args.gselev is not None): pass elif args.gs is not None: try: with open(args.gs, "r") as fp: gslat, gslon, gselev = [float(x) for x in fp.read().split(',')] except Exception as e: _print( "ERROR: Could not parse groundstation definition file. Message ({}): {}" .format(e.__class__.__name__, e)) exit(1) else: _print( "ERROR: Ground station location needs to be defined (either with --gslat/--gslon/--gselev or wiht --gs file)" ) exit(1) if args.gslat is not None: gslat = args.gslat if args.gslon is not None: gslon = args.gslon if args.gselev is not None: gselev = args.gselev try: p = Propagator(tles=tles, gs_lat=gslat, gs_lon=gslon, gs_elev=gselev) except Exception as e: _print("ERROR: Could not create Propagator. Message ({}): {}".format( e.__class__.__name__, e)) raise exit(1) if args.nid is None: nids = p.nids_to_track # # try to extract NIDs from tle string # raw_tles = tles.replace('\r', '').split('\n') # raw_tles = [rtle.strip() for rtle in raw_tles] # # # do a tiny bit of error checking and extract nids # # if (not all([x[0] == '0' for x in raw_tles[0::3]])) or\ # (not all([x[0] == '1' for x in raw_tles[1::3]])) or\ # (not all([x[0] == '2' for x in raw_tles[2::3]])) : # _print("ERROR: Malformed TLE string") # exit(1) # # nids = [int(x.split(' ')[1]) for x in raw_tles[2::3]] else: nids = args.nid if len(nids) < 1: _print("ERROR: No valid TLEs and/or no NIDs. Dont know what to do") exit(1) if args.action == 'info': try: for nid in nids: for w in [None] if args.when is None else args.when: p.print_info(nid=nid, when=_fix_timestamp(w)) except Exception as e: _print("ERROR: action info. Message ({}):{}".format( e.__class__.__name__, e)) exit(1) exit(0) elif args.action == 'get_all': if len(nids) > 1: _print( "ERROR: get_all action only works with a single NID, you have specified {}" .format(nids)) exit(1) try: when = [_fix_timestamp(w) for w in args.when] data = p.get_all(nid=nids[0], when=when) data.tstamp_str = data.tstamp_str.apply(_rev_timestamp) if isinstance(data, pd.Series): data = pd.DataFrame(data).transpose() except Exception as e: _print("ERROR: action get_all. Message ({}):{}".format( e.__class__.__name__, e)) exit(1) elif args.action == 'get_pass': try: if args.when is not None and len(args.when) != 1: _print( "ERROR: get_pass requires when to be a single date. Use -N if you want to compute multiple passes" ) exit(1) data = p.get_passes(nid=nids, when=_fix_timestamp(args.when[0]) if args.when is not None else None, N=args.N, horizon=args.horizon) if isinstance(data, pd.Series): data = pd.DataFrame(data).transpose() data.index.name = "pass_no" data.rise_t = data.rise_t.apply(_rev_timestamp) data.max_elev_t = data.max_elev_t.apply(_rev_timestamp) data.set_t = data.set_t.apply(_rev_timestamp) except Exception as e: _print("ERROR: action get_pass. Message ({}):{}".format( e.__class__.__name__, e)) exit(1) elif args.action == 'compute': if len(nids) > 1: _print( "ERROR: compute action only works with a single NID, you have specified {}" .format(nids)) exit(1) if args.when is not None: if len(args.when) != 1: _print("ERROR: action compute. When must be a single value") exit(1) else: when = _fix_timestamp(args.when[0]) else: when = None try: data, psum = p.compute_pass(nid=nids[0], when=when, dt=args.dt) data.tstamp_str = data.tstamp_str.apply(_rev_timestamp) except Exception as e: _print("ERROR: action compute. Message ({}):{}".format( e.__class__.__name__, e)) exit(1) else: _print("ERROR: Invalid action {}".format(args.action)) exit(1) data = data.reset_index() if args.field is not None: try: data = data.loc[:, args.field] except Exception as e: _print("ERROR: Could not filter by {}. Message ({}):{}".format( args.field, e.__class__.__name__, e)) exit(1) if args.print: print(data) else: print(data.to_csv(index=False, header=not args.no_header)) exit(0)
def __init__(self, grid_size, sample, pattern_size): self.patterns = Pattern.from_sample(sample, pattern_size) self.grid = self._create_grid(grid_size) self.propagator = Propagator(self.patterns)
def test_results_has_length_of_steps_with_one_step(self): propagator = Propagator(self.two_in_contact) propagator.step() self.assertEqual(1, len(propagator.results.day))