""" Detecting the location of a lighthouse in an idiomatic style. """ # 3.3.1 Arrange your import statements in a standard order from dataclasses import dataclass import math import pickle import random import matplotlib from matplotlib import pyplot as plt import numpy matplotlib.interactive(True) # PEP-8 Formatting # Use new-style classes # Use dataclasses @dataclass class UFO: """ A UFO that shoots death rays. """ position: float = 2 height: float = 1 def emit_pulse(self): """ Returns ------- float Distance at which the pulse is detected. """ # Shadow name of built-in direction = random.uniform(0, 2 * 3.14159265) # # _U # /d|h # +---+l--+ # 0 1 2 # # tan(d) = (2 - l) / h # h * tan(d) = 2 - l # l = 2 - h * tan(d) h = 2 - self.height * math.tan(direction) return direction, h # PEP-8 Formatting def log_posterior_location(height, prior_location, hs): """ Get the log of the posterior of pos_shore. See Sivia-Skilling Data Analysis Bayesian Tutorial 2.38. Parameters ---------- height: float Known height of the UFO. prior_location: array_like Locations sampled from the prior. hs: array_like Measured locations. """ # 3.2.1 Follow the docstring conventions described in PEP-257 priors2, hs2 = numpy.meshgrid(prior_location, hs) ph2 = numpy.log(height ** 2 + (hs2 - priors2) ** 2) po3 = - ph2.sum(axis=0) # Remove outdated code, use version control for that. print(po3) return po3 # 3.5.1 Use the if __name__ == '__main__' pattern to allow a file to be both imported and run directly def main(): ufo = UFO() priorsh = numpy.linspace(-2, 10, 100) hs = [] metans = [] metahs = [] metaposts = [] for n in range(6): hs = [] for i in range(10**n): d, h = ufo.emit_pulse() hs.append(h) h_mean = sum(hs) / len(hs) log_post = log_posterior_location(ufo.height, priorsh, numpy.array(hs)) log_postmax = numpy.argmax(log_post) h_post = priorsh[log_postmax] metans.append(n) metahs.append(h_mean) metaposts.append(h_post) print(n, h_mean, h_post) # 2.8.1 Use a context manager to ensure resources are properly managed with open("detections.pickle", 'wb') as f: pickle.dump(hs, f) # Use object-oriented matplotlib # See https://pbpython.com/effective-matplotlib.html fig, ax = plt.subplots() ax.scatter(metans, metahs) ax.scatter(metans, metaposts) ax.axhline(ufo.position) fig.show() fig2, ax2 = plt.subplots() ax2.hist(hs, range=(0, 5), bins=100) fig2.show() # 3.5.1 Use the if __name__ == '__main__' pattern to allow a file to be both imported and run directly if __name__ == '__main__': main() # PEP-8: End with single empty line