\n",
+ "\n",
+ "#### **Important**\n",
+ "\n",
+ "\n",
+ "Furthermore, the optional parameters (which define the uncertainties) can be passed in a few different ways:\n",
+ "\n",
+ "- **As a single value:** This will define the standard deviation for that parameter. The default distribuition used will be a normal distribuition and the nominal value will be the value of that same parameter from the standard object.\n",
+ "\n",
+ "- **As a tuple of two numbers:** The first number will define the nominal value of the distribuition, and the second number will define the standard deviation. The default distribuition used will be a normal distribuition.\n",
+ "\n",
+ "- **As a tuple of two numbers and a string:** The first number will define the nominal value of the distribuition, the second number will define the standard deviation, and the string will define the distribuition type. The distribuition type can be distributions *\"normal\"*, *\"binomial\"*, *\"chisquare\"*, *\"exponential\"*, *\"gamma\"*, *\"gumbel\"*, *\"laplace\"*, *\"logistic\"*, *\"poisson\"*, *\"uniform\"* and *\"wald\"*.\n",
+ "\n",
+ "- **As a tuple of a number and a string:** The number will define the standard deviation, and the string will define the distribuition type. The nominal value will be the value of that same parameter from the standard object.\n",
+ "\n",
+ "- **As a list of values:** The values will be randomly chosen from this and used as the parameter value during the simulation. You can not define standard deviations when using lists.\n",
+ "\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "Starting with the `Environment` object, we will create a `StochasticEnvironment` to specify its uncertainties.\n",
+ "\n",
+ "In this first example, we will specify the ensemble member and wind velocities factor.\n",
+ "\n",
+ "Since the ensemble member is a discrete value, **only list type inputs are permitted**. The list will contain the ensemble numbers to be randomly selected during the Monte Carlo simulation. This means that in each iteration, a different ensemble member will be chosen.\n",
+ "\n",
+ "The wind velocities factor are also special inputs. They are used to scale the wind velocities in each axis. The factor inputs can only be tuples or lists, since it has no nominal value to get from the standard. Lets scale the wind by a factor of 1.00000 ± 0.2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "object: \n",
+ "last_rnd_dict: {}\n",
+ "elevation: [113]\n",
+ "gravity: ['Function from R1 to R1 : (height (m)) → (gravity (m/s²))']\n",
+ "latitude: [39.3897]\n",
+ "longitude: [-8.288964]\n",
+ "wind_velocity_x_factor: 1.00000 ± 0.20000 (numpy.random.normal)\n",
+ "wind_velocity_y_factor: 1.00000 ± 0.20000 (numpy.random.normal)\n",
+ "datum: ['SIRGAS2000']\n",
+ "timezone: ['UTC']\n",
+ "ensemble_member: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]"
+ ]
+ },
+ "execution_count": 44,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "stochastic_env = StochasticEnvironment(\n",
+ " environment=env,\n",
+ " ensemble_member=list(range(env.num_ensemble_members)),\n",
+ " wind_velocity_x_factor=(1, 0.2),\n",
+ " wind_velocity_y_factor=(1, 0.2),\n",
+ ")\n",
+ "\n",
+ "stochastic_env"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "\n",
+ "#### NOTE\n",
+ "\n",
+ "Always check the printing of the object to see if the uncertainties were correctly set.\n",
+ "\n",
+ "
\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Just to illustrate the potential of this technique, let's randomly generate 5 instances of the environment using the `create_object` method.\n",
+ "\n",
+ "For each instance, we will calculate the wind speed at 1km altitude and store the results in a list."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[3.740092684250815, 4.9381130538062425, 3.9988061871142895, 2.767140726386856, 3.6032724506858345]\n"
+ ]
+ }
+ ],
+ "source": [
+ "wind_speed_at_1000m = []\n",
+ "for i in range(5):\n",
+ " rnd_env = stochastic_env.create_object()\n",
+ " wind_speed_at_1000m.append(rnd_env.wind_velocity_x(1000))\n",
+ "\n",
+ "print(wind_speed_at_1000m)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As you can see, the wind speed varies between ensemble members.\n",
+ "This demonstrates how the Monte Carlo simulation can capture the variability in wind conditions due to different ensemble members.\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Motor\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can now create a `StochasticSolidMotor` object to define the uncertainties associated with the motor.\n",
+ "In this example, we will apply more complex uncertainties to the motor parameters.\n",
+ "\n",
+ "The `StochasticSolidMotor` also has one special parameter which is the `total_impulse`. It lets us alter the total impulse of the motor while maintaining the thrust curve shape. This is particularly useful for motor uncertainties."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "object: \n",
+ "last_rnd_dict: {}\n",
+ "thrust_source: ['../../../data/motors/Cesaroni_M1670.eng', [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]], 'Function from R1 to R1 : (Scalar) → (Scalar)']\n",
+ "total_impulse: 6500.00000 ± 1000.00000 (numpy.random.normal)\n",
+ "burn_start_time: 0.00000 ± 0.10000 (numpy.random.binomial)\n",
+ "burn_out_time: [3.9]\n",
+ "dry_mass: [1.815]\n",
+ "dry_I_11: [0.125]\n",
+ "dry_I_22: [0.125]\n",
+ "dry_I_33: [0.002]\n",
+ "dry_I_12: [0]\n",
+ "dry_I_13: [0]\n",
+ "dry_I_23: [0]\n",
+ "nozzle_radius: 0.03300 ± 0.00050 (numpy.random.normal)\n",
+ "grain_number: [5]\n",
+ "grain_density: 1815.00000 ± 50.00000 (numpy.random.normal)\n",
+ "grain_outer_radius: 0.03300 ± 0.00038 (numpy.random.normal)\n",
+ "grain_initial_inner_radius: 0.01500 ± 0.00038 (numpy.random.normal)\n",
+ "grain_initial_height: 0.12000 ± 0.00100 (numpy.random.normal)\n",
+ "grain_separation: 0.00500 ± 0.00100 (numpy.random.normal)\n",
+ "grains_center_of_mass_position: 0.39700 ± 0.00100 (numpy.random.normal)\n",
+ "center_of_dry_mass_position: [0.317]\n",
+ "nozzle_position: 0.00000 ± 0.00100 (numpy.random.normal)\n",
+ "throat_radius: 0.01100 ± 0.00050 (numpy.random.normal)\n",
+ "interpolate: ['linear']\n",
+ "coordinate_system_orientation: ['nozzle_to_combustion_chamber']"
+ ]
+ },
+ "execution_count": 51,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "stochastic_motor = StochasticSolidMotor(\n",
+ " solid_motor=motor,\n",
+ " thrust_source=[\n",
+ " \"../../../data/motors/Cesaroni_M1670.eng\",\n",
+ " [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]],\n",
+ " Function([[0, 5900], [1, 6000], [2, 6100], [3, 5900], [4, 5800]]),\n",
+ " ],\n",
+ " burn_start_time=(0, 0.1, \"binomial\"),\n",
+ " grains_center_of_mass_position=0.001,\n",
+ " grain_density=50,\n",
+ " grain_separation=1 / 1000,\n",
+ " grain_initial_height=1 / 1000,\n",
+ " grain_initial_inner_radius=0.375 / 1000,\n",
+ " grain_outer_radius=0.375 / 1000,\n",
+ " total_impulse=(6500, 1000),\n",
+ " throat_radius=0.5 / 1000,\n",
+ " nozzle_radius=0.5 / 1000,\n",
+ " nozzle_position=0.001,\n",
+ ")\n",
+ "stochastic_motor"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "\n",
+ "#### NOTE\n",
+ "\n",
+ "Pay special attention to how different input types are interpreted in the `StochasticSolidMotor` object by checking the printed object:\n",
+ "\n",
+ "\n",
+ "- ``thrust_source`` was given as a list of 3 items, and is saved as is. This means that the simulation will randomly chose one item of that list, as desired\n",
+ "\n",
+ "- ``burn_start_time`` was given as a tuple of 3 items, specifying the nominal value, the standard deviation and the distribuition type\n",
+ "\n",
+ "- ``total_impulse`` was given as a tuple of 2 numbers, so the distribuition type was set to the default: `normal`\n",
+ "\n",
+ "- All other values set for the other parameters in the constructor are simple values, which means they are interpreted as standard deviation and the nominal value is taken from the ``motor``\n",
+ "\n",
+ "- The remaining parameters that are printed are just the nominal values from the ``motor``. In the ``Stochastic`` object they are saved as a list of one item\n",
+ "\n",
+ "
\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Once again, we can illustrate the power of stochastic modeling by generating multiple instances of the `SolidMotor` class using the `StochasticSolidMotor` object.\n",
+ "For each instance, we will calculate the total impulse and store the results in a list. This will show how the uncertainties in the motor parameters affect the total impulse over multiple iterations.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 56,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[5922.730109775586, 5397.418437730037, 8888.401049795124, 2867.149759762836, 6583.48945300187]\n"
+ ]
+ }
+ ],
+ "source": [
+ "total_impulse = []\n",
+ "for i in range(5):\n",
+ " rnd_motor = stochastic_motor.create_object()\n",
+ " total_impulse.append(rnd_motor.total_impulse)\n",
+ "\n",
+ "print(total_impulse)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Rocket\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can now create a `StochasticRocket` object to define the uncertainties associated with the rocket."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 60,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "object: \n",
+ "last_rnd_dict: {}\n",
+ "radius: 0.06350 ± 0.00001 (numpy.random.normal)\n",
+ "mass: 15.42600 ± 0.50000 (numpy.random.normal)\n",
+ "I_11_without_motor: 6.32100 ± 0.00000 (numpy.random.normal)\n",
+ "I_22_without_motor: 6.32100 ± 0.01000 (numpy.random.normal)\n",
+ "I_33_without_motor: 0.03400 ± 0.01000 (numpy.random.normal)\n",
+ "I_12_without_motor: [0]\n",
+ "I_13_without_motor: [0]\n",
+ "I_23_without_motor: [0]\n",
+ "power_off_drag: ['Function from R1 to R1 : (Mach Number) → (Drag Coefficient with Power Off)']\n",
+ "power_on_drag: ['Function from R1 to R1 : (Mach Number) → (Drag Coefficient with Power On)']\n",
+ "power_off_drag_factor: 1.00000 ± 0.00000 (numpy.random.normal)\n",
+ "power_on_drag_factor: 1.00000 ± 0.00000 (numpy.random.normal)\n",
+ "center_of_mass_without_motor: 0.00000 ± 0.00000 (numpy.random.normal)\n",
+ "coordinate_system_orientation: ['tail_to_nose']\n",
+ "motors: Components:\n",
+ "\n",
+ "aerodynamic_surfaces: Components:\n",
+ "\n",
+ "rail_buttons: Components:\n",
+ "\n",
+ "parachutes: []"
+ ]
+ },
+ "execution_count": 60,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "stochastic_rocket = StochasticRocket(\n",
+ " rocket=rocket,\n",
+ " radius=0.0127 / 2000,\n",
+ " mass=(15.426, 0.5, \"normal\"),\n",
+ " inertia_11=(6.321, 0),\n",
+ " inertia_22=0.01,\n",
+ " inertia_33=0.01,\n",
+ " center_of_mass_without_motor=0,\n",
+ ")\n",
+ "stochastic_rocket"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The `StochasticRocket` still needs to have its aerodynamic surfaces and parachutes added. \n",
+ "\n",
+ "We can also create stochastic models for each aerodynamic surface, although this is not mandatory."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 61,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stochastic_nose_cone = StochasticNoseCone(\n",
+ " nosecone=nose_cone,\n",
+ " length=0.001,\n",
+ ")\n",
+ "\n",
+ "stochastic_fin_set = StochasticTrapezoidalFins(\n",
+ " trapezoidal_fins=fin_set,\n",
+ " root_chord=0.0005,\n",
+ " tip_chord=0.0005,\n",
+ " span=0.0005,\n",
+ ")\n",
+ "\n",
+ "stochastic_tail = StochasticTail(\n",
+ " tail=tail,\n",
+ " top_radius=0.001,\n",
+ " bottom_radius=0.001,\n",
+ " length=0.001,\n",
+ ")\n",
+ "\n",
+ "stochastic_rail_buttons = StochasticRailButtons(\n",
+ " rail_buttons=rail_buttons, buttons_distance=0.001\n",
+ ")\n",
+ "\n",
+ "stochastic_main = StochasticParachute(\n",
+ " parachute=Main,\n",
+ " cd_s=0.1,\n",
+ " lag=0.1,\n",
+ ")\n",
+ "\n",
+ "stochastic_drogue = StochasticParachute(\n",
+ " parachute=Drogue,\n",
+ " cd_s=0.07,\n",
+ " lag=0.2,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Then we must add them to our stochastic rocket, much like we do in the normal Rocket.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 62,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stochastic_rocket.add_motor(stochastic_motor, position=0.001)\n",
+ "stochastic_rocket.add_nose(stochastic_nose_cone, position=(1.134, 0.001))\n",
+ "stochastic_rocket.add_trapezoidal_fins(stochastic_fin_set, position=(0.001, \"normal\"))\n",
+ "stochastic_rocket.add_tail(stochastic_tail)\n",
+ "stochastic_rocket.set_rail_buttons(\n",
+ " stochastic_rail_buttons, lower_button_position=(0.001, \"normal\")\n",
+ ")\n",
+ "stochastic_rocket.add_parachute(stochastic_main)\n",
+ "stochastic_rocket.add_parachute(stochastic_drogue)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "\n",
+ "#### NOTE\n",
+ "\n",
+ "The `position` arguments behave just like the other ``Stochastic`` classes parameters\n",
+ "\n",
+ "
\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now lets check how the `StochasticRocket` handled all these additions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 66,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "object: \n",
+ "last_rnd_dict: {}\n",
+ "radius: 0.06350 ± 0.00001 (numpy.random.normal)\n",
+ "mass: 15.42600 ± 0.50000 (numpy.random.normal)\n",
+ "I_11_without_motor: 6.32100 ± 0.00000 (numpy.random.normal)\n",
+ "I_22_without_motor: 6.32100 ± 0.01000 (numpy.random.normal)\n",
+ "I_33_without_motor: 0.03400 ± 0.01000 (numpy.random.normal)\n",
+ "I_12_without_motor: [0]\n",
+ "I_13_without_motor: [0]\n",
+ "I_23_without_motor: [0]\n",
+ "power_off_drag: ['Function from R1 to R1 : (Mach Number) → (Drag Coefficient with Power Off)']\n",
+ "power_on_drag: ['Function from R1 to R1 : (Mach Number) → (Drag Coefficient with Power On)']\n",
+ "power_off_drag_factor: 1.00000 ± 0.00000 (numpy.random.normal)\n",
+ "power_on_drag_factor: 1.00000 ± 0.00000 (numpy.random.normal)\n",
+ "center_of_mass_without_motor: 0.00000 ± 0.00000 (numpy.random.normal)\n",
+ "coordinate_system_orientation: ['tail_to_nose']\n",
+ "motors: Components:\n",
+ "\tComponent: object: \n",
+ "last_rnd_dict: {}\n",
+ "thrust_source: ['../../../data/motors/Cesaroni_M1670.eng', [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]], 'Function from R1 to R1 : (Scalar) → (Scalar)']\n",
+ "total_impulse: 6500.00000 ± 1000.00000 (numpy.random.normal)\n",
+ "burn_start_time: 0.00000 ± 0.10000 (numpy.random.normal)\n",
+ "burn_out_time: [3.9]\n",
+ "dry_mass: [1.815]\n",
+ "dry_I_11: [0.125]\n",
+ "dry_I_22: [0.125]\n",
+ "dry_I_33: [0.002]\n",
+ "dry_I_12: [0]\n",
+ "dry_I_13: [0]\n",
+ "dry_I_23: [0]\n",
+ "nozzle_radius: 0.03300 ± 0.00050 (numpy.random.normal)\n",
+ "grain_number: [5]\n",
+ "grain_density: 1815.00000 ± 50.00000 (numpy.random.normal)\n",
+ "grain_outer_radius: 0.03300 ± 0.00038 (numpy.random.normal)\n",
+ "grain_initial_inner_radius: 0.01500 ± 0.00038 (numpy.random.normal)\n",
+ "grain_initial_height: 0.12000 ± 0.00100 (numpy.random.normal)\n",
+ "grain_separation: 0.00500 ± 0.00100 (numpy.random.normal)\n",
+ "grains_center_of_mass_position: 0.39700 ± 0.00100 (numpy.random.normal)\n",
+ "center_of_dry_mass_position: [0.317]\n",
+ "nozzle_position: 0.00000 ± 0.00100 (numpy.random.normal)\n",
+ "throat_radius: 0.01100 ± 0.00050 (numpy.random.normal)\n",
+ "interpolate: ['linear']\n",
+ "coordinate_system_orientation: ['nozzle_to_combustion_chamber'] Position: (-1.255, 0.001, )\n",
+ "aerodynamic_surfaces: Components:\n",
+ "\tComponent: object: \n",
+ "last_rnd_dict: {}\n",
+ "length: 0.55829 ± 0.00100 (numpy.random.normal)\n",
+ "kind: ['vonKarman']\n",
+ "base_radius: [0.0635]\n",
+ "bluffness: [0]\n",
+ "rocket_radius: [0.0635]\n",
+ "name: ['Nose Cone'] Position: (1.134, 0.001, )\n",
+ "\tComponent: object: \n",
+ "last_rnd_dict: {}\n",
+ "n: [4]\n",
+ "root_chord: 0.12000 ± 0.00050 (numpy.random.normal)\n",
+ "tip_chord: 0.06000 ± 0.00050 (numpy.random.normal)\n",
+ "span: 0.11000 ± 0.00050 (numpy.random.normal)\n",
+ "rocket_radius: [0.0635]\n",
+ "cant_angle: [0.5]\n",
+ "sweep_length: [0.06]\n",
+ "sweep_angle: [None]\n",
+ "airfoil: [('../../../data/calisto/NACA0012-radians.csv', 'radians')]\n",
+ "name: ['Fins'] Position: (-1.04956, 0.001, )\n",
+ "\tComponent: object: \n",
+ "last_rnd_dict: {}\n",
+ "top_radius: 0.06350 ± 0.00100 (numpy.random.normal)\n",
+ "bottom_radius: 0.04350 ± 0.00100 (numpy.random.normal)\n",
+ "length: 0.06000 ± 0.00100 (numpy.random.normal)\n",
+ "rocket_radius: [0.0635]\n",
+ "name: ['Tail'] Position: [-1.194656]\n",
+ "rail_buttons: Components:\n",
+ "\tComponent: object: \n",
+ "last_rnd_dict: {}\n",
+ "buttons_distance: 0.69980 ± 0.00100 (numpy.random.normal)\n",
+ "angular_position: [45]\n",
+ "name: ['Rail Buttons'] Position: (-0.618, 0.001, )\n",
+ "parachutes: [StochasticParachute(parachute=Parachute Main with a cd_s of 10.0000 m2, cd_s=(10.0, 0.1, ), trigger=[800], sampling_rate=[105], lag=(1.5, 0.1, ), noise=[(0, 8.3, 0.5)]), StochasticParachute(parachute=Parachute Drogue with a cd_s of 1.0000 m2, cd_s=(1.0, 0.07, ), trigger=['apogee'], sampling_rate=[105], lag=(1.5, 0.2, ), noise=[(0, 8.3, 0.5)])]"
+ ]
+ },
+ "execution_count": 66,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "stochastic_rocket"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "### Flight\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "After defining the `Flight`, we can create the corresponding `Stochastic` object to define the uncertainties of the input parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 67,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "object: , environment= , rail_length= 5, inclination= 84, heading = 133,name= Flight)>\n",
+ "last_rnd_dict: {}\n",
+ "rail_length: [5]\n",
+ "inclination: 84.70000 ± 1.00000 (numpy.random.normal)\n",
+ "heading: 53.00000 ± 2.00000 (numpy.random.normal)\n",
+ "initial_solution: None\n",
+ "terminate_on_apogee: None"
+ ]
+ },
+ "execution_count": 67,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "stochastic_flight = StochasticFlight(\n",
+ " flight=test_flight,\n",
+ " inclination=(84.7, 1), # mean= 84.7, std=1\n",
+ " heading=(53, 2), # mean= 53, std=2\n",
+ ")\n",
+ "stochastic_flight"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Step 2: Starting the Monte Carlo Simulations\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First, let's invoke the `MonteCarlo` class, we are going to need a filename to initialize it.\n",
+ "The filename will be used either to save the results of the simulations or to load them\n",
+ "from a previous ran simulation.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "c:\\mateus\\github\\rocketpy\\rocketpy\\simulation\\monte_carlo.py:97: UserWarning: This class is still under testing and some attributes may be changed in next versions\n",
+ " warnings.warn(\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The following input file was imported: monte_carlo_analysis_outputs/monte_carlo_class_example.inputs.txt\n",
+ "A total of 1000 simulations results were loaded from the following output file: monte_carlo_analysis_outputs/monte_carlo_class_example.outputs.txt\n",
+ "\n",
+ "The following error file was imported: monte_carlo_analysis_outputs/monte_carlo_class_example.errors.txt\n"
+ ]
+ }
+ ],
+ "source": [
+ "test_dispersion = MonteCarlo(\n",
+ " filename=\"monte_carlo_analysis_outputs/monte_carlo_class_example\",\n",
+ " environment=stochastic_env,\n",
+ " rocket=stochastic_rocket,\n",
+ " flight=stochastic_flight,\n",
+ ")"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, let's simulate our flights. \n",
+ "We can run the simulations using the method `MonteCarlo.simulate()`.\n",
+ "\n",
+ "Set `append=False` to overwrite the previous results, or `append=True` to add the new results to the previous ones.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Keyboard Interrupt, files saved.age Time per Iteration: 2.184 s | Estimated time left: 2116 s\n",
+ "Completed 32 iterations. Total CPU time: 68.9 s. Total wall time: 69.6 s\n",
+ "Saving results. \n",
+ "Results saved to monte_carlo_analysis_outputs/monte_carlo_class_example.outputs.txt\n"
+ ]
+ }
+ ],
+ "source": [
+ "test_dispersion.simulate(number_of_simulations=1000, append=False)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Visualizing the results\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we finally have the results of our Monte Carlo simulations loaded!\n",
+ "Let's play with them.\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First, we can print numerical information regarding the results of the simulations.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# You only need to import results if you did not run the simulations\n",
+ "# test_dispersion.import_results()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "31"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "test_dispersion.num_of_loaded_sims"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Monte Carlo Simulation by RocketPy\n",
+ "Data Source: monte_carlo_analysis_outputs/monte_carlo_class_example\n",
+ "Number of simulations: 31\n",
+ "Results: \n",
+ "\n",
+ " Parameter Mean Std. Dev.\n",
+ "------------------------------------------------------------\n",
+ " out_of_rail_velocity 23.690 2.184\n",
+ " x_impact 1514.914 386.644\n",
+ " apogee_time 25.657 2.347\n",
+ " impact_velocity -5.322 0.066\n",
+ " y_impact -283.937 203.440\n",
+ " out_of_rail_time 0.341 0.064\n",
+ " frontal_surface_wind 0.887 0.591\n",
+ " apogee_y 751.781 141.018\n",
+ " t_final 304.216 37.176\n",
+ " max_mach_number 0.866 0.144\n",
+ " apogee_x 87.831 126.183\n",
+ " lateral_surface_wind -5.351 0.415\n",
+ " apogee 3367.587 688.136\n"
+ ]
+ }
+ ],
+ "source": [
+ "test_dispersion.prints.all()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Secondly, we can plot the results of the simulations.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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vKjjx4/r+PHjdr9sd+3aVYcPH9bIkSPVqFEj+fv7KzY2Vt7e3rrzzjv1zDPPaPHixTm+Ze16TZs21f79+zVv3jw99thjCgsLk4+Pj+Lj41WqVCk1a9ZMb731lqKjo/W///1Pnp6eNu1d+b4wu1mv443OS+fOnbvhbQvO4uXlpdWrV+s///mPwsPDde3aNQUGBuqBBx7Q8uXLHXapf+edd/T555/rkUceUa1ateTh4aGEhASVK1dObdu21ddff61169bJz8/Prm1ej8P8bDMvzL1KAgMD1a5duxy1ueOOO1S7dm2b9tbysq/N8npsenh46IcfftD06dMt7620tDTdc889ltm/zD0TsvrVPz/njoI879yqn6X5wT6x54z3QEFy1feH7OTku8XNPifj5jMZRh5GrQFQ4MaOHat33nlHzZo1U2RkpKvDAYBbTsuWLbV+/XqNHDmS2QoKWGHe14ZhqHLlyjp16pTmzJmjJ554wtUhATcV7wHAMXqWAIXUmjVrJGU9GBcAAMi/uXPn6tSpU/Lw8FCbNm1cHQ5w0/EeABwjWQIUQteuXdOmTZvUoUMHRUREuDocAACKtL59+2rBggW6cOGCpezcuXP64IMPLFOwP/nkk6pQoYKrQgQKFO8BIPc8XB0AAHve3t43fWo5AABuVb/88ou+++47SVKJEiXk6elpM3V3RESEPv30U1eFBxQ43gNA7pEsAQAAwC3t888/1y+//KKdO3cqJiZGCQkJKlu2rBo0aKA+ffroiSeesBtwGbiV8B4Acq9YD/D6ySef6Pfff9dff/2lmJgYJScnq3z58mrRooVee+013XHHHQ7bzZo1S5MnT9a+ffvk5eWlxo0b6+2339b999+f5baioqL0/vvva/PmzUpJSVGdOnU0ePBgPfnkk1m2OXXqlN555x399ttvunTpkipXrqy+ffvqzTfflI+PT76fPwAAAAAAsFeskyVlypRRYmKi6tevr9tuu02StHfvXh08eFCenp5atGiROnXqZNPmpZde0sSJE+Xr66t27dopOTlZq1evlmEYWrBggbp27Wq3nYULF6p3797KyMhQ8+bNVaZMGa1evVqxsbEaNmyYPv74Y7s2hw8fVpMmTXThwgXVq1dPderU0bZt23TkyBE1bdpUq1evlre3d4HsFwAAAAAAirNinSyJiorS3XffbddLY/LkyRo0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JqvEQU6XF0blypVTYGCg9uzZo6ioKEt5enq6Xn/9dYfJEClz0FtJGjdunNLT0y3l8+bN07x585wW3xtvvCFJeuWVV7R7926bZdbT9xYGL774oqTMWM+fP28pP3v2rF577TVJ0tChQwts++beLQcOHCiwbQCuRrIEAAAAKGSskyGdO3fW/v371blzZ0vZokWLXBFWtho3bpzlY/r06fLw8NDw4cOVlpamFi1aqF27durTp4/CwsL05ZdfatCgQQ7XO2jQIJUtW1YLFixQnTp11LNnTzVo0EBPPPGEUxMCTz75pF588UWdPn1aDRs2VEREhB599FG1atVKFSpUsCQhCoOXX35ZDz74oHbv3q0aNWqoW7dueuSRR1SzZk1FR0era9eueuGFFwps++Zj8dFHH1XPnj31zDPP6Jlnnimw7QGuwJglAAAAQCFTsmRJ+fj4aMKECXr++edlMpn0448/avLkyXr11VcVGBjo6hDtbNmyJctlHTp0kCSNGDFClSpV0meffaaoqCj5+vqqWbNmeu+997Rjxw6HbUNCQrRhwwa99tprWr9+vU6fPq27775bK1eulMlk0qeffuq05/D555+rTZs2mjx5sv744w9t3bpV5cqVU7NmzfT00087bTv55e7urp9++kmTJ0/WrFmz9Ntvv0mS6tSpo6eeekrPPfdcgQ7Y2q1bN3366aeaNm2ali5dapktZ/r06QW2TeBmMxm5GW4at5S6detKkvbu3eviSAAAKFpSU1Pl5eWllJSUIjl2BPImIyPDcttBeHh4gV6MpqSkKD09Xb6+vnbLrl69Knd3d8u4EQDgark5PxaV61B6lgAAAACFTHaJEEcJFACAczFmCQAAAAAAgBWSJQAAAAAAAFZIlgAAAAAAAFghWQIAAAAAAGCFZAkAAAAAAIAVkiUAAAAAAABWSJYAAAAAAABYIVkCAAAAAABghWQJAAAAAACAFZIlAAAAAAAAVkiWAAAAAAAAWCFZAgAAAAAAYIVkCQAAAAAAgBWSJQAAAADyZe3aterevbtuu+02eXl5KTg4WOHh4erZs6e++OILXblyxaZ+y5YtZTKZdOzYMdcEnI1Ro0bJZDJp1qxZrg4l12bNmiWTyaRRo0blqf3WrVtlMplkMpn03nvvOTc4oIghWQIAAAAgz9577z21bt1aixYtUmBgoDp16qR27drJ19dXixYt0osvvqjo6GhXh+kSJpNJVapUcXUYOTZ37lzL/7/99lsXRgK4noerAwAAAABQNG3fvl2jRo2Sp6enfvjhB3Xt2tVm+dmzZ/XNN98oKCjIpnzOnDlKSkrSbbfddvOCRbZSU1P13XffSZLKly+vgwcPasuWLbrvvvtcHBngGvQsAQAAAJAnixYtkmEY6tWrl12iRMq86H711VdVq1Ytm/LKlSurVq1a8vT0vEmR4kZ+/fVXXbhwQU2bNtULL7wgybanCVDckCwBAAAAkCfnz5+XJJUtWzZX7bIas8R820paWprGjBmjsLAw+fr6qnbt2po5c6al3po1a9SqVSuVLFlSwcHBevLJJ3Xx4kW77VSpUkUmk8lhDOvWrZPJZFL//v1zFPPhw4c1atQoNWnSROXLl5eXl5cqVaqkJ598UgcPHrSpax47RJKOHz9uGQfEZDKpZcuWNnWTkpI0btw43XXXXfL395e/v78aN26s2bNnZxlLVFSU2rRpo4CAAAUFBal9+/basmVLjp5HVr755htJ0uOPP67HH39ckvT9998rNTXVYX3zvjUMQxMnTlSdOnXk4+Oj2267TUOGDFFsbKzDdklJSRozZozq1asnX19fBQYGqnnz5pZeLY7s3r1bDz/8sIKCghQQEKDmzZtr5cqV2b6GhmFo3rx5at26tYKDg+Xj46PatWtr1KhRSkpKcridtLQ0TZkyRU2aNFHJkiXl6+urBg0a6LPPPlNaWlo2ew+3IpIlAAAAAPLk9ttvlyQtXLhQMTExTltvr169NGHCBN1xxx1q3ry5jh49qqefflozZ87UggUL1L59e6Wlpal9+/by8/PT3Llz1bVrVxmG4bQYrjd9+nS99957SkxM1L333qvOnTurZMmSmjt3ru69917t3r3bUjcsLEz9+vWTJPn5+alfv36WR4cOHSz1YmJi1KRJE40YMUJnz55VixYt1Lx5c+3fv1/9+/fXiy++aBfHsmXL1LJlS61evVp16tTRgw8+qJMnT6p58+batGlTnp7blStX9NNPP8nLy0u9evVS1apVdf/99+vChQv69ddfs2374osv6rXXXlOlSpXUpUsXpaena9KkSWrRooXi4uJs6sbHx6t58+Z69913FRMTo06dOqlp06baunWr+vbtq6FDh9qtf9OmTWrSpImWLVum0NBQderUScnJyerQoYMWLVrkMKaMjAw99thjevTRR/XHH3+oQYMG6tixoxITEzV69Gi1atVKV69etWlz9epVtWvXTi+88IIOHjyoxo0bq23btjpz5oxefvllde/eXRkZGbncsyjSDBRbderUMerUqePqMAAAKHJSUlIMSUZKSoqrQ8FNlJ6ebuzbt8/Yt2+fkZ6e7upwCoW///7b8PX1NSQZAQEBRr9+/Yxp06YZO3bsMNLS0rJs16JFC0OScfToUZtySYYko169ekZMTIylfM2aNYYko0KFCkbp0qWNZcuWWZZduXLFqFu3riHJWLNmjc36QkNDjawuedauXWtIMvr162dTPnLkSEOSMXPmTJvyTZs2GUeOHLFbz9dff21IMlq1amW3TJIRGhrqcPuGYRgdO3Y0JBlDhw41kpOTLeVnz5417rnnHkOS8csvv1jK4+LijLJlyxqSjK+//tpSnpGRYbz++uuW/Tdy5Mgst+nI9OnTDUlGly5dLGWTJ082JBk9e/Z02Ma8b0uWLGls27bNUh4fH2+0bt3a8rysDR482LKv4uLiLOXR0dFGuXLlDEnG0qVLLeXp6elGzZo1DUnG+++/7zBmR6/h+PHjDUlGy5YtjTNnzljKr127ZgwYMMCQZLz++us2bV544QVDktG7d28jNjbWUh4XF2d5naZMmeJ4ByJX58eich1KsqQYKyoHKQAAhQ3JkuLJVcmSDcc2GPd+da+x4diGm7bN3Fi1apVx++23Wy5czY+goCDj+eefN/755x+7NjdKlqxatcquzV133WVIMh5//HG7ZRMnTnSYJHBmsiQ7TZs2NUwmk81Ftvn5ZJUs2blzpyHJuPfeex0eTzt27DAkGZ07d7aUmRMzzZs3t6ufkpJiVKpUKU/JEvPrMX/+fEvZhQsXDE9PT8PHx8fueRnGv/t2xIgRdsv27t1rmEwmw9/f37h69aphGIaRkJBg+Pr6Gm5ubkZ0dLRdm88//9yQZLRp08ZStnLlSkOSUaNGDYf7qGnTpnavYWpqqlGmTBnDz8/POHv2rF2bpKQko3z58kZwcLBlnefOnTM8PT2N22+/3UhKSrJrc+bMGcPLy8uoX7++3TJkuhWTJdyGAwAAABRSGUaGnl/+vP745w+98PMLyjAK320ADzzwgA4fPqxFixZp4MCBatiwoTw8PBQbG6spU6aoQYMGOnDgQI7X5+npaTeuhyRVq1ZNktSuXbssl505cyZvTyKHEhISNG/ePL3++ut69tln1b9/f/Xv319nzpyRYRj6+++/c7yuFStWSJK6du0qNzf7yzLzGCZbt261lEVGRkqS+vTpY1ff09NTPXr0yO1T0okTJ7RhwwYFBQXp4YcftpSXLl1aHTt2VHJysubPn59le0ex1KlTR3feeacSEhK0c+dOSZkzJ129elUNGza0G/BXkp544glJmeOxmG93iYqKkiR1797d4T7q3bu3XdmOHTt04cIF3X///QoJCbFb7uvrq7vvvluXL1/WoUOHJGWOX5OamqoOHTrI19fXrk358uVVo0YN/fXXX3a37+DWRbIEAAAAKKQW7luovef3SpL2xOzRomjHYzS4mpeXlx555BFNmTJF27dv1/nz5zVlyhQFBwcrJiZGgwcPzvG6ypcvL3d3d7tyf39/SXI43bB52bVr1/L4DG5szZo1qlatmh599FGNHz9e06dP1+zZszV79mwdOXJEUuaYHDllHtz2rbfeshkA1vqRkJCgCxcuWNr8888/kqTQ0FCH66xSpUqun9e3334rwzDUo0cPeXt72ywzD/RqHvzVkRvFYo7Z/G9WMQYFBSkwMFBXr17V5cuXJf2b/DKPjXO9ypUr25WZ9+vKlSuz3K/Lly+XJMu+NbeZNm1alm327t0rwzB06dKlLPcFbi0erg4AAAAAgL0MI0Oj14+2KRu9frS61e4mN1Ph/s0zKChIAwcOVMWKFdWlSxetXbtWSUlJKlGixA3bOupBkJvlOZWbwToTEhLUq1cvXbp0Se+++6769Omj0NBQ+fr6ymQy6dFHH9W8efNyNcCsefvNmjVT9erVcx2/s5inB163bp2aNWtmsywlJUWStGHDBh0/fjzLxIizZDVzUW6Y92tYWJiaNm2abd3SpUvbtGnQoIHuvPPObNtcn1DCrYtkCQAAAFAIWfcqMTP3LulRJ/e3W7hC69atJUnp6emKjY3NUbLEmby8vCRlJjvMvU/MTp48meP1REZG6uLFi+rRo4dGjx5tt9zcsyQ3KlWqJCnzNpxhw4blqE2FChUkZU5H7EhW5VnZvn27oqOjJWVOjXz48GGH9QzD0LfffqsRI0Y43OYdd9yRZSwVK1a0+TerGK9cuaLY2Fj5+voqODhY0r/PN6vXylG5eb/WqlVLs2bNctguqzbNmjXTpEmTctQGt77CnZIGAAAAiqlJWx1ftGVV7go36klhvvj28vJSmTJlbkZINswX2wcPHrRbtnLlyhyvx3xbiPmi2trhw4e1Y8cOh+08PT2VlpbmcFnbtm0lSYsXL85xHBEREZKkH374wW5ZWlqaFi5cmON1Sf/eXvPqq6/KyJz8w+6xbt06m7rXcxTL/v379eeff8rf318NGjSQJN19993y9fXV9u3bLWOFOIqladOmlt5D5p4hixcvdnisOdr2vffeq8DAQK1fvz7Ht8y0atVK7u7uWrZsmVJTU3PUBrc+kiUAAABAIdQhrIOqBlVVlaAqlkfVoKpqX729q0OzeOedd/Taa685HNj09OnTeu655yRJnTt3tvTyuJlatGghSRo3bpzS09Mt5fPmzdO8efNyvJ6aNWtKkhYtWqTz589bymNjYzVgwIAsL7ArVqyoc+fOKTY21m7Zfffdp7Zt2yoqKkqDBg1SXFycXZ1du3bp119/tfzds2dPlS5dWuvWrdPs2bMt5YZhaOTIkTpx4kSOn1N6erplH/Tt2zfLehEREbrtttsUHR2t7du32y2fNGmSZRBXSUpKStKLL74owzD01FNPWQZM9fPz09NPP62MjAwNGjRIiYmJljYHDx7U2LFjJUlDhgyxlLdu3Vo1atTQgQMHNH78eJvtzpo1yzLgrTVvb28NHz5c8fHx6tatm8NeP6dPn7bcfiRljoPz9NNP69ixY+rbt6/OnTtn1+bw4cO5TkahaOM2HAAAAKAQGhExQiMi7G97KEwSEhI0ceJEffzxx6pZs6bq1KkjHx8fnTp1Slu2bFFqaqrCwsL02WefuSS+QYMG6csvv9SCBQtUp04d1a9fX4cOHdKePXs0dOhQffrppzlazz333KO2bdtq5cqVqlmzpmW2nnXr1qlMmTLq0qWLlixZYteuc+fOmjRpkho2bKj7779fPj4+Cg8P12uvvSYpszdFhw4dNHnyZP3vf/9TgwYNVLFiRV25ckW7d+/WyZMnNXToUHXo0EGSFBAQoBkzZqh79+7q37+/pkyZomrVqmnXrl06dOiQnn32WU2bNi1Hz2nFihU6d+6catasqYYNG2ZZz83NTb1799Ynn3yiuXPn6u6777ZZ/vjjj+u+++5T69atFRgYqA0bNujs2bOqW7euxowZY1N33Lhx2rx5s1auXKlq1aqpRYsWSkxM1Jo1a5ScnKwhQ4bYzMjj5uam2bNnq02bNnrjjTc0b9481alTR3///bf++OMPDRo0SP/973/tEnFvvPGG9u/fr7lz56p27dq66667VLVqVaWkpOjAgQPat2+f6tevb5mBR5ImTpyoY8eOaeHChfr111/VoEEDVa5cWYmJidq3b58OHz6sLl26qHv37jnavyj66FkCAAAAIE/efvttzZ07V48//ri8vb0VGRmpBQsWaN++fWrUqJHGjx+vP//80+EMNjdDSEiINmzYoE6dOunMmTP65ZdfFBgYqJUrV6pz5865WteSJUv01ltvqWzZsvrll1+0fft29enTR5s3b1ZQUJDDNuPGjdPgwYOVlpam77//XjNmzLDMxCJJ5cqV08aNG/X555+rTp062rlzpxYsWKDdu3erWrVq+uijj/Tqq6/arNM8YG6rVq20Z88eLV++XBUqVND69et1//335/j5mHtWZNerxMxcZ968eXa3FX3++ecaN26cjh8/riVLlshkMmnQoEGKjIxUYGCgTd2AgACtX79eo0ePVpkyZfTTTz8pMjJS99xzj/73v/9p4sSJdttu0qSJNm7cqE6dOuno0aP66aef5OnpqZ9//llNmjSR9O9ArWZubm6aM2eOlixZorZt2+ro0aNauHChfv/9d/n4+Oi1117T119/bdPG19dXv/zyi2bPnq377rtP0dHRWrBggbZt26ayZctq9OjRdr1bcGszGbkZshm3lLp160qS9u7de4OaAADAWmpqqry8vJSSkiJPT09Xh4ObJCMjQwcOHJAkhYeHO21WFqAoqlKlio4fP56rGYCcbeDAgZo6daq+++479e7d22VxIHfnx6JyHcoZHgAAAABQKF26dEnHjh2zK//+++81ffp0BQUFqVOnTjc/MNzyGLMEAAAAAFAoHTx4UE2aNFH9+vVVrVo1SVJ0dLQOHDggd3d3TZ06VX5+fi6OErciepYAAAAAAAqlatWqadCgQUpNTdXatWu1bNkyXblyRd26dVNkZKR69erl6hBxi6JnCQAAAAAgVxzdGlMQypUrpy+++OKmbAuwRs8SAAAAAAAAKyRLAAAAAAAArJAsAQAAAAAAsEKyBAAAAAAAwArJEgAAAAAAACskSwAAAAAAAKyQLAEAAAAAALBCsgQAAAAAAMAKyRIAAAAAAAArJEsAAAAA5MvatWvVvXt33XbbbfLy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vHhRKSkpKlu2rHx8fBy2qVy5cp6SJdWrV7fMduPp6amQkBBFRESobdu2loSZ+fln9TzN5adPn87xdrN77lLBvm+KMpIlAAAAQCHUvbtUt660d++/ZfXqSd26uS6mnAoKCtLAgQNVsWJFdenSRWvXrlVSUpLNLRVZcdTLIjfLcyojIyPHdRMSEtSrVy9dunRJ7777rvr06aPQ0FD5+vrKZDLp0Ucf1bx587KcqSW77Tdr1qzITPv6zDPPaNeuXerevbuGDx+u8PBwBQQEyM3NTV999ZWee+65LPeBs163vHL19qXM13rWrFn5WkdeBjAuDM+9KCJZAgAAABRCbm7SyJFSr17/lo0cmVleVLRu3VpS5q0bsbGxOUqWOJN5vIeEhARL7xMz62labyQyMlIXL15Ujx49NHr0aLvlR44cyXVs5l/7u3btqmHDhuWoTYUKFSRlTuvqSFblzpCYmKiVK1cqJCRE33//vV3vn7zsA0dc+RylzFtzPD09deHCBSUnJzvsXZKbYye3KlasKCnr52nukeSohxWcqwidagEAAIDixdy7RCqcvUpu1JPCPM2rl5eXypQpczNCsmG+8D548KDdspzeFiRlTmUrOb6d4fDhw9qxY4fDdp6enkpLS3O4rG3btpKkxYsX5ziOiIgISdIPP/xgtywtLU0LFy7M8bpy68qVK8rIyFCFChXsEiWpqam5eh7Zufvuu+Xr66vt27c7TMB89913TtlOVjw9PdWoUSMZhqFFixbZLV+zZo0uXrxYYNs336bz66+/KjY21m75N998I+nfY6EgZHfcFickSwAAAIBCys1NmjJFuvdeafLkwter5J133tFrr72mv//+227Z6dOn9dxzz0mSOnfubDOrx83SokULSdK4ceOUnp5uKZ83b57mzZuX4/WYB8JctGiRzZglsbGxGjBggGWg1+tVrFhR586dc3jRe99996lt27aKioqyzCRzvV27dunXX3+1/N2zZ0+VLl1a69atsxko1DAMjRw5UidOnMjxc8qtcuXKKTAwUHv27FFUVJSlPD09Xa+//rrDhFRe+Pv764knnlB6erpefPFFXb161bJs27Zt+uKLL5yynewMHDhQkvTuu+/ajA1y6dIlvfbaawW67WrVqumhhx5SfHy8hg4danNsbdq0SVOmTJG7u3ueZwXKieyO2+KkkJ1uAQAAAFiLiJC2bs38t7BJSEjQxx9/rLCwMIWHh+uRRx5R3759FRERoapVq2rr1q0KCwsr8BlasjJo0CCVLVtWCxYsUJ06ddSzZ081aNBATzzxhIYOHZrj9dxzzz1q27atTpw4oZo1a1oGs61atar++ecfdenSxWG7zp07Ky0tTQ0bNtTjjz+uZ555xmbq2W+++UZ33XWXJk+erNDQULVq1UqPPfaYOnXqpMqVK6tBgwY2yZKAgADNmDFD7u7u6t+/vxo3bqxHH31U9erV00cffaRnn302z/uqcePGWT6mT58uDw8PDR8+XGlpaWrRooXatWunPn36KCwsTF9++aVTL97HjRun8PBw/fzzz6pevbr69Omj9u3bq0mTJnryySedtp2sPPbYY3rkkUf0999/q1atWuratau6d++usLAwubm5WaZPLqgE4NSpU1W1alXNmTNHNWrUUN++fdWmTRtFREQoMTFR48ePV4MGDQpk29KNj9vigmQJAAAAgDx5++23NXfuXD3++OPy9vZWZGSkFixYoH379qlRo0YaP368/vzzT5eNrxASEqINGzaoU6dOOnPmjH755RcFBgZq5cqV6ty5c67WtWTJEr311lsqW7asfvnlF23fvl19+vTR5s2bFRQU5LDNuHHjNHjwYKWlpen777/XjBkztHz5csvycuXKaePGjfr8889Vp04d7dy5UwsWLNDu3btVrVo1ffTRR3r11Vdt1mkeMLdVq1bas2ePli9frgoVKmj9+vW6//77c72PzLZs2ZLl49SpU5KkESNGaPbs2apfv76ioqK0atUq3Xnnndq8ebPuueeePG/7eqVKlVJUVJSef/55GYahH3/8USdOnNAHH3ygSZMmOW07WTGZTPr+++81btw4VahQQb/88ou2bNmixx9/XGvWrNGFCxdkMpkUHBxcINu/7bbb9Mcff2jYsGHy8PDQokWLtH37dj3wwAP67bff9MorrxTIds1udNwWFyYjN0M245ZS9/9ugN1rPcQ6AAC4odTUVHl5eSklJUWenp6uDgc3SUZGhg4cOCBJCg8PZ4YJoBg6deqUqlatqrCwMEVHR7s6nEIjN+fHonIdyhkeAAAAAAAru3fvthuL5ty5c+rfv7/S0tL0+OOPuygy3CxMHQwAAAAAgJXhw4dr69atatCggUJCQnTmzBlt375dCQkJuvfee3M83TOKLpIl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rJAsAQAAAAAAsEKyBAAAAAAAwArJEgAAAAAAACskSwAAAAAAAKx4OHuFx48f159//qnz588rNjZWQUFBKlu2rBo0aKDQ0FBnbw4AACBHIo9HatiKYZrQboIiQiNcHQ4AACjEnJIs2bVrl7766istX75cJ0+ezLLe7bffrk6dOumZZ55RgwYNnLFpAACAG8owMvT88ue19/xevfDzC9o1cJfcTHSwBQAAjuUrWbJu3Tq9+eab2rp1qwzDkKenpxo2bKhatWqpVKlSKlmypK5cuaLLly8rOjpaf/31lyZPnqwpU6bovvvu07hx49SiRQtnPRcAAACHFu5bqL3n90qS9sTs0aLoRepRp4eLowIAAIVVnpMlnTp10i+//KLAwEA9/fTTevTRR3X//ffL29s7yzbXrl1TVFSUvv32Wy1evFitW7dWx44dtXTp0ryGAQAAkK0MI0Oj14+2KRu9frS61e5G7xIAAOBQnr8h7NixQxMmTNA///yjadOmqVWrVtkmSiTJ29tbrVu31owZM/TPP//o448/1vbt2/MaAgAAwA1Z9yoxM/cuAQAAcMRkGIaRl4bJycny8fHJdwDOWg9yr27dupKkvXv33qAmAABFV/OZzRV5ItK+PLS51vdfn6d1pqamysvLSykpKfL09MxviAAAFBtF5To0z7fhOCvBQaIEAAAUpA5hHXQq7pQM/fv7kEkmta/e3oVRAQCAwizPPUtQ9BWVjB4AAIUNPUsAAMibonId6pSpg60lJSVp27ZtOnPmjK5du5ZlvSeffNLZmwYAAAAAAMg3pyVLDMPQu+++q88++0xJSUnZ1jOZTCRLAAAAAABAoeS0ZMl7772n999/X15eXuratauqVasmf39/Z60eAAAAAADgpnBasmTGjBkqWbKkNm3apNq1aztrtQAAAAAAADeVm7NWdOHCBbVo0YJECQAAAAAAKNKcliypUaOGMjIynLU6AAAAAAAAl3BasuT555/X2rVrdezYMWetEgAAAAAA4KZzWrJk4MCBGjBggCIiIjRr1iydPn3aWasGAAAAAAC4aZyWLJGk5557ToGBgRowYIAqV64sd3d3hw8PD6eNKwsAAAAAAOBUTstabNq0Se3atVNiYqJMJpNKlSrF1MEAAAAAAKDIcVqyZPjw4UpMTNTIkSP18ssvq2TJks5aNQAAAAAAwE3jtGTJzp071bhxY40cOdJZqwQAAAAAALjpnDZmSUBAgKpUqeKs1QEAAAAAALiE05IlHTt21ObNm5Wenu6sVQIAAAAAANx0TkuWfPDBB3Jzc9OAAQN05coVZ60WAAAAAADgpnLamCWvv/667rjjDs2dO1dLlizRPffco9tuu01ubvb5GJPJpBkzZjhr0wAAAAAAAE5jMgzDcMaKHCVFstyoycTtOoVA3bp1JUl79+51cSQAABQtqamp8vLyUkpKijw9PV0dDgAARUZRuQ51Ws+StWvXOmtVAAAAAAAALuO0ZEmLFi2ctSoAAAAAAACXcdoArwAAAAAAALeCPCdLUlNTnRKAs9YDAAAAAADgDHlOllSvXl1Tp05VWlpantqnpqZq8uTJql69el5DAAAAAAAAcLo8J0vCwsL0/PPPq1KlSnrppZe0efNmZWRkZNsmIyNDmzZt0osvvqhKlSpp8ODBqlGjRl5DAAAAAAAAcLp8TR28fPlyjRgxQn/99ZdMJpN8fX111113KTw8XMHBwQoICFB8fLwuXbqkAwcO6M8//9TVq1dlGIYaNGig999/Xw8++KAznw9yoahM2QQAQGHD1MEAAORNUbkOzVeyxCwqKkrTp0/Xzz//rPPnz2dZr1y5curYsaOeffZZNWnSJL+bRT4VlYMUAIDChmQJAAB5U1SuQ50ydXDTpk3VtGlTSdKBAwe0e/duxcTE6MqVKwoMDFS5cuV05513qmbNms7YHAAAAAAAQIFxSrLEWnh4uMLDw529WgAAAAAAgJsizwO8AgAAAAAA3IpIlgAAAAAAAFghWQIAAAAAt5D335eqVZOqVv33Ua1aZjmAnCFZAgAAAMAluKgvGL/9Jh09Kh079u/j6FFpxQoXBwYUISRLAAAAALgEF/UF48UXc1cOwB7JkkLu6tWrevfdd1WzZk35+PioYsWKevrpp3X69GlXhwYAAADkCxf1BaN7d6luXduyevWkbt1cEw9QFJEsKcSSk5PVunVrjRkzRgkJCerSpYtuv/12zZw5U3fddZeOHDni6hABACiWDMOw+RcobIrK7S1c1BcMNzdp5EjbspEjM8sB5Axvl0Js7Nix2rx5s5o0aaKDBw/q+++/15YtWzRhwgSdP39eTz/9tKtDBACgWJo0aZLNv0BhU1Rub+GivuBYJ6JIQAG5ZzKc/JNIUlKStm3bpjNnzujatWtZ1nvyySedudlbTkpKisqVK6crV65ox44duuuuu2yW33nnndq9e7e2bdumu+++O0/bqPt/Z8+9e/fmO14AAIqTunXrat++fapbt6727Nnj6nAAO/PnS716OS7v0ePmx5OdjAypfn1p797Mi/pdu0iWOEtkpDRsmDRhghQR4epogExF5TrUw5kre/fdd/Xpp58qKSkpyzqGYchkMpEsuYGoqChduXJF1atXt0uUSFKPHj20e/duLV26NM/JEgAAkHv79+/Xvn37JGV+0Ttw4IDCw8NdHBVgy9yrwPpapLD2LnBzk6ZM+feinkSJ80RESFu3ujoKoGhyWrJk/PjxGjt2rNzd3fXQQw+pZs2aCggIcNbqi51du3ZJkho2bOhwubl89+7dNy0mAACKo5iYGG3evNny99KlS22WT5gwQZ06dbL83bhxY5UrV+6mxQc4Yr69xbp3SWG+vYWLegCFjdOSJdOmTZOvr68iIyOzvMBHzp04cUKSVKlSJYfLzeXHjx+/aTEBAFActWjRQvv3789y+bRp0zRt2jTL37Vq1VJ0dPTNCA3IlnXvksLaqwQACiunJUtOnjyp1q1bkyhxkoSEBElSiRIlHC738/OTJMXHx99wXXWvH2L8//z999+qVq2aUlNT8xglAAC3vq5du+qDDz7IVX0+W1FYTJokvfaa9NFHUnp65gPIrXHjpJkzJevRLk0m6amnpDffzHtdFE/moTkKO6clS8qXL2+5gEfRER0dLS8vL1eHAQDALeODDz7IVXIFuBlat3Z1BLgVjRxpP5uRM+ri1lenTh1Xh3BDTkuW9OnTRzNmzFBiYiJJEyfw9/eXpCwHy01MTJSkHI0Lk9Uow3Xr1pVhGJbxUQAAQNaOHTumRo0aKTY21m5ZUFCQtm7dqipVqtz0uAAgv1q1kqKi7MubNZPWrJEWLJAefdR++bx5mbd7WctNXRRPd955p6tDyBGnJUtGjRqljRs3qnPnzpo6darCwsKctepiqXLlypKkU6dOOVxuLg8NDc3Xdkwmkzw9PfO1DgAAigNfX1+HiRJJio2NVYkSJfhMBVAkDR3qOFkydKjk6Sn17i29/7797Eq9etkPGpybuiieisItOFI+kiWtHfTly8jI0Lp161S7dm2FhoaqUqVKcnPwjjCZTFq9enVeN10smLNtO3bscLjcXF6/fv2bFhMAAMXZ4sWLb7h88ODBNykaAHCeG001nZvZlYraTExAVkyGYT30Ts45SoLkeKMmk9IZXSpbKSkpKleunK5cuaKdO3eqQYMGNsvvvPNO7d69W9u2bdPdd9+dp22YB37N6jYdAADwr9atW2vt2rWSpE6dOmnZsmWWfyWpVatWWrNmjStDBIA8mz/fNsExf77Uo8e/f2dkSPXr/zu70q5dWSdAclMXxU9RuQ7Nc8+So0ePOjMOXMfLy0uDBw/W+++/r0GDBmnFihWWsWA++eQT7d69Wy1atMhzogQAAOROyZIl5ePjowkTJuiZZ56Rt7e3Fi5cqGnTpunVV19VYGCgq0MEgDy70VTTbm7SlCnSsGHShAnZJz9yUxcorPLcswQFLzk5WS1bttSWLVtUoUIFRURE6Pjx49qyZYvKli2rzZs3q1q1anlef1HJ6AEAUBikpKQoPT1dvr6+Sk1NlZeXl1JSUuTp6amrV6/K3d2dGeYAFGmRkf8mOCIiXB0NblVF5TrUacmS9957Tw0aNFDnzp2zrbd06VLt3LlT7777rjM2e8u7evWqxo0bp//97386efKkSpUqpQ4dOmjMmDGqVKlSvtZdVA5SAAAKm+uTJQCKtoMHD2rt2rWKjo5WfHy8EhISlJiYqKSkJF29elXJyclKTk5WSkqKUlJSlJqaqrS0NHl4eMjX11f+/v4qWbKkgoODVbp0aYWEhKh8+fIKDQ1VlSpVFB4ebpntEijuisp1qNOSJW5uburfv7++/vrrbOs9++yz+vrrrxmzpBAoKgcpAACFDckSoGhISEjQhg0btGnTJu3Zs0fHjh1TTEyM4uLilJycrLS0tJsaj4eHh/z8/BQSEqLatWura9eu6t27t3x9fW9qHIArFZXrUKdNHZxT6enp+RocFgAAAACsnT17Vt9++61WrFihffv26fz587p27VoOW4+QNECS6f8eZt/IzW2iTCYPmUzuMpk85ObmKTc3L7m7e8rNzVPp6SlKT09Sevo1ZWRcU0ZGqgwjVVLa/z3SJf3723RaWpquXLmiK1eu6ODBg1qyZImeeuopubm5yd/fX/Xr19eYMWPUsmVLp+yXnHr/fWnGDMn6Z3STSRowQHrrrZsaClBo3PRkyd69exUcHHyzNwsAAADgFrB161ZNnz5dkZGROnnypJKSknTjzvJeMpl85ObmJy+vIJUoUVYlS1ZSqVJhOnp0kC5dKmfXIjT0bQ0Y8Ha+47169f+3d+fxVVT3/8ffN3tCyAYBgkgggaAQQUQCIUQWERBLIaD401Zk6WIVkILfoiLEBYrYQhtAwVoUsbWlpMUasewaIcgiKotACGEHgYAJa3bm90fMda65CVlulpu8no9HHsqZ+cycG45j5p0zZy7r9Ol9Onx4s86c2a3MzHRdv35W+fmZkq5KMnTjxg1dvnxZW7ZsUb9+/eTi4qK2bdvqN7/5jSZPnixXV9cq96Msa9dK9t7fsW4dYQkariqFJePGjbP585YtW0q0FSsoKFBqaqq++OILDR8+vCqnBQAAANAAFBYW6u9//7sWL16sPXv26Pr162Xs7SqLxVceHsEKCAhTy5bddPvtAxUW1lMeHl6lVu3bJ/3rXyXbe/asev8lydvbT+3a9VK7dr1KbMvLy9HevR/pwIG1+vbbL3XlSpqkK7px44bS09P1zDPP6JlnnlFQUJB+8pOfaMmSJdXyyM7EiUWLu9prBxqqKq1ZYn6cxmKxlCPRlTp37qz//Oc/VXqLCxzDWZ4VAwCgrmHNEqD6rFy5UgsWLNDXX3+tq1evlrKXl9zcgtS4cVu1atVDXboMV3h4r0rNwLhxQ3rjDen8+R/amjWTnnyyfK+8TU6Wvvyy5CMsd90l9elT4e7o0KHN+uSTeTp7dpsKCzMk3bDZPmDAAH344YcODU1u3JA6dy56bXCxyEhp925e+wvHc5b70CrNLPnkk08kSYZhqH///ho8eLCmTZtmd18PDw+1bNlSoaGhVTklAAAAgHrko48+0vz587Vr1y5dvnzZzh4WWSz+8vOLULt2gxUd/XM1a9beYed3cZH69rWdXdKvX/lDgsOHpcxM++2VCUsiImIVEVH03t6srDNat+41HT78sXJyjkgq1IYNG+Tj46NBgwZp1apVDglNXFyk+Hhp1Kgf2uLjCUrQsDnsbThjx45VbGxsqY/hoO5xlkQPAIC6hpklQNW89dZb+v3vf6/jx4/bnZ1usfjL1zdc7dsPVt++TykgoGW19sc8u6Qis0qk0h/jadRI8vCo/AyTH7tw4Zjee+8xZWZ+rqKFY4tm97/++uv6zW9+U+Xjm2eXMKsE1clZ7kMdFpZ07dpV4eHhSkxMdMThUAOcZZACAFDXEJYAFfe3v/1NL730ktLT0+0EJI3l6xuu8PD71LfvBDVp0rrG+3fsWNFCp4MGSW3alL/O3mM8ZqGhRW+VcZTz54/ob397TFlZ21Ucmtx9993atm1blReC3bxZmjpVmjdPio11QGcBO5zlPtRhYUmjRo00bNgwvf/++444HGqAswxSAADqGsISoHz+/e9/64UXXtChQ4d044bt2hsuLsFq3bq/Bg+OV8uWt9dSDx2jtNklkvTww9L3P3Y71OHDW/W3vw3TjRsXJEkhISE6efJktb85B6gqZ7kPddirg9u3b6+LFy866nAAAAAAnNDXX3+t0aNH65tvvrETkDTRLbfco8GDX9Ktt95RSz10vI4dpeBgKSPDtr1ZM+n2asqB2rXrpRdeOK3XXx+oixeT9e233yo0NFSnTp2qnhMCDYzDnkIbP368kpOTdfDgQUcdEgAAAKg2s2dLYWFS27Y/fIWFFbWj4t5//30FBwera9eu2rt3rzUocXEJVEjITzRu3E69+OIF/fKX/6lXQYlUtLbH0KFSUJBte0UWiq0MNzcPPf30p2rR4n5J0unTp/XQQw9V3wmBBsRhj+FI0hNPPKFVq1bp2Wef1dChQ9W6dWt5eHg46vBwMGeZ/gQAQF3DYzj1wz33FK3RYK89Obnm++OMCgsL9dxzz2nhwoXKyckxbWmk5s17a9CgmWrXrlet9a+mVWWh2Kp67bU7dfXqbknS/v37dXt1TWkBqshZ7kMdFpYUPxtnGIYsFkvZJ7VYVFBQ4IjTogqcZZACAFDXEJbUDytX2r4q1dz+4IM13x9ncvXqVT388MNas2aNzaM2Li7BuvPOX2ro0Jcb7NoZlV0otqouXTqnefPaSMpRRESEUlNTa+7kQAU4y32ow9YsufXWW28akgAAAAB1xciRRQtvmn9ej4yURoyovT7VdUePHtVPf/pT7du3z9RqkadnmO69N149ez5Wa32rK9q0kX7965o/r79/c9166/06eXKV0tLSar4DQD3jsLDk2LFjjjoUAAAAUO1cXKT4eNvZJfHxNffYhDPJy8vT4MGD9cknn5ha3eTvf5dGjFiotm2jaq1v+MHAgTO0dOkqGYahPXv2qHPnzrXdJcBp8b8CAAAANFjFs0skZpWU5plnnpG3t7cpKPFUq1Zxmjr1lKZO3U5QUoeEhnZV8S0ej+EAVeOwmSX2ZGZmSpICAwOr8zQAAABApbi4SIsXS1OnSvPmMavEbNu2bRo4cKCuXLnyfYuLmjSJ1bhxK9W4cXCt9s0ZJSdLX34pmVeMtFiku+6S+vRx5JmKlkY4d+6cIw8KNDgOD0s+/vhjJSQkKCUlRdnZ2ZIkb29v9e7dW5MmTdKQIUMcfUoAAACg0mJjpR07arsXdUdhYaHuu+8+m0duPD3b6dFH/64TJ6L017/WxA1//XP4sPT975JLtDvqe3f8+FeSCiVJvXv3dsxBgQbKodn5b3/7Ww0dOlTr16/X9evX5efnJ39/f12/fl3r1q3T0KFDNWXKFEeeEgAAAICD7Nix40eP3DRSbOw8TZ+eprZto6w3/FlZP3xlZhbd8KNsPXrYb+/Z03Hn+PzzpZKK3j565513Ou7AQAPksLBkxYoVSkhIUHBwsBYsWKDMzExlZmbqu+++U1ZWlhYuXKhmzZopISFB//rXvxx1WgAAAAAOsHDhQvXo0UP5+fmSLGrS5B4999wZ3XffD7/srIkb/vqqY0epWTPbtmbNpNtvd9w5UlNXSpKCgoIcd1CggXJYWPLGG2/Iy8tLn332mSZMmCB/f3/rNj8/Pz311FNKTk6Wp6en3njjDUedFgAAAEAVPfzww5o0adL3f/LU4MHL9PTTyfL29rPZryZu+OsrFxepb1/btn79HLdOTkrKOyosPC9Jmj9/vmMOCjRgDluzZPfu3erfv78iIiJK3SciIkL9+/fXli1bHHVaAAAAAJVUWFio2267TYe/f47GxSVQ48cn69Zb77C7f/ENv3mi+NWr0p//zNol5VEcNp0/79iQKTf3mtat+62kovUiR48e7ZgDAw2Yw2aW5OXlqVGjRjfdr1GjRsrLy3PUaQEAAABUUmhoqDUo8fKK0LRpx0oNSop17Ci5u//w5+vXWbukvFxcpJ/8RLrllqJ/OmpWyeuv3yfDuCRJeu+99xxzUKCBc9jMkvDwcCUnJ+vatWulhibXr19XcnKywsPDHXVaAAAAAJVw22236fTp05KkZs3u04QJ68pV5+Ii9e4tmV6WY1WZtUtq7pW6dUObNtKvf+24473//pPKyvpckjRgwACNHDlSs2dLS5eW/J6OHy9Nn+64cwP1mcNmlowaNUrnz5/X8OHDlZaWVmJ7enq6RowYoYyMDD388MOOOi0AAACAChowYIBSU1MlSU2a9Cl3UFKsTx/HrV3CG3Yqb9Wq53Xw4BJJRetErl+/XpK0dq109Kh07NgPX0ePSusq9tcMNGgOm1nyzDPP6L///a82btyojh076q677lKbNm0kScePH9euXbtUWFiou+++W1OnTnXUaQEAAABUwIoVK7Rx40ZJkq/vnXr66U/LVffjGSA/frK+souV9ughHT9esp037JRt5crfau/eBZIMeXl5WWcJSdLEidLmzSVrJk6suf4Bzs5hYYm3t7c+/fRTPffcc3r77be1c+dO7dy502b7uHHjNGfOHHl7ezvqtAAAAADKKS8vT48++qgkyWIJ0OTJn5e7tngGiD1VWazUvOipI45X3xUWFmrRogG6ePFTSZK7u7tOnDghX19f6z4jR0qdOknffPNDXWSkNGJEDXcWcGIOC0skydfXVwsXLtTcuXO1a9cunTlzRpLUsmVLdevWTT4+Po48HQAAAIAKeOihh3Tjxg1JLnrooX/Iw8OrXHXJydKFC/a3BQVVbbFSe2/YceQrdeuTK1cy9Oc/d1d+ftFUnICAAKWnpysoKMhmPxcXKT5eGjXqh7b4eL6nQEU4NCwp5uPjo9jY2Oo4NAAAAIBKKCws1EcffSRJ8vPrpsjIweWuPXxYunatZLu7uzRpUtVvwqvrlbr1yYEDm/TPf8bJMC5Lkrp27aqdO3fK1dXVuo95YVfDKPr7yc+XmjdnVglQUWSLAAAAQAMwa9as72eVWPTQQ29WqLZHD/vt3bs7ZrZCdb1Stz7Iy8vR668P0j/+cZ81KPnlL3+pL7/80iYokWwXdj1+vCgokaQWLfieAhVV6ZklL7/8cpVOPHPmzCrVAwAAACi/xMRESZKrazOFhnatUK29dUVcXaUBAxzXP0e/Urc+2Lz5La1fP1XSFUmSi4uL3nnnHY0ePdru/qUt7PrCC9XYSaCeshiG+e3b5efi4iKLxaKKlFssFuu/FxYWVua0cKBOnTpJkr4xr/wEAABuKj8/Xx4eHsrLy5O7u3ttdwcoFx8fH2VnZyswsLd++1s7d9Q3sW9fyXVF+vVzYAdhdezYF3r//UeVk5Nmbbv77ruVkpIiDw+PUutu3JA6dy65sOvu3cwsQd3hLPehlZ5ZMmfOnArtf/r0aS1dulTZ2dk2oQkAAABQl5jXfShmsUjjx0vTp9dev6qq+JeVvr7NK1X/43VF+vRxZO9q349fjSwV/b3fdVfNfdarV7/T228/qAsXPpNU9Pfl7e2t//73v7rvvvtuWs/CroDjVDosmTZtWrn2O3funH7/+9/rr3/9q3JycuTn56fJkydX9rQAAABAtSpe9+HH1q1z7rCkeH2LvDw7K7WWQ/G6ImvXSoMG1b8b8F27pKws++3VHZacP39E//rXr3X+/GeS8iQVzcqfOHGiEhISKnQs82uDeV0wUHnV8jYcScrIyNCrr76qJUuWKCcnR76+vpo6daqmTp2qgICA6jotAAAAUCWlrfswcWLN98WRfH19lZ2drUuXDlf6GPV5XRG3Uu6MSmt3hAMHNujDD6fq2rVvVDyTRJJiY2O1YcOGMh+5KY2Li7R4sTR1qjRvXv0LtYCa4vD/9C9evKi5c+dq8eLFunbtmnx9ffXss89q6tSpJd7/DQAAANQ15t/MF6sPv6G///77tXz5cuXkHNOVKxlq3Di4trtUp/TrJ61cWbK9f3/7+1flsZ2NGxdo69Y/KD//lE17VFSU/vOf/+iWW26pYO9txcZKO3ZU6RBAg+ewnDEzM1PPP/+82rZtqz/+8Y+SpN/97nc6evSoZs+eTVACAAAAp1C87oNZfVj34fXXX//+3wr0l7/8pFb7Uhd16iT5+dm2+fkVrdViz+HDUmZm0aM7xV+ZmUXt9uTl5ej9959UfHygkpOftgYlbm5uevTRR5Wbm6vt27dXOSgB4BhVvuRfunRJM2bMUNu2bfXqq6/qxo0bmjp1qo4ePapXX31VTZo0cUQ/AQAAgBpTPLtEqh+zSqSix3AeeOABSdKlSzu1adPrN6loWFxcitZiMRs8uPSQrEcP++09e/7w74WFhdq8ean+8IdumjUrQAcPLpZhZEkq+vt49dVXlZ+fr7///e+VeuQGQPWp9GM4ly9f1vz585WQkKBLly7J29tbv/3tbzVt2jQ1a9bMkX0EAAAAalR9Xffhv//9r3x8fJSXl6dPP31arq5u6tOnni5CUgmdOknr1xfNEgkIKH1WiWT7dqBizZpJt98ubd/+vrZsSdClS3slZdvU3XLLLVq6dKkG/TiZAVCnWAzD/JRd+QUGBury5cvy8vLSr371Kz377LNq3rxyryFD7XCW91sDAFDX5Ofny8PDQ3l5eXJ3d6/t7gAVcuDAAUVGRurGjRuSXNWp01N6+OGKvXGlPjt27Ic3/rRpU/a++/ZJ//rXD3/28Zmu69f/LOm6zX6enp7q16+f3nzzTbVu3drBPQaci7Pch1Y6LHFxcZHFYpHFYpFLBaN2i8Wi3NzcypwWDuQsgxQAgLqGsATObt++ferSpcv3gYnk7d1Bv/rVOjVpUrdv5KuyqKqjFRTkafv297VhQx8VFraVtFdSF0lFnfPw8FDv3r21aNEi3X777TXbOaAOc5b70Cq9DccwDBmGYb3IAgAAAKj7IiMjdfbsWUVGRur8+fPKzk5VQkK4mjaN1WOPLVdgYKva7qJdxYuq2muv7rCksLBQu3at1K5df1dGxlcqKDgnqUBSb0nzJE2Vu7ubevTooYULF+rOO++s3g4BqFaVDksISAAAAADnFRwcrHPnzmncuHF65513JBXowoVP9Kc/tVXTpn3UocN/tH+/X52YxVGsRw/p+PGS7eZFVR2lsLBQu3d/qJ0739X587uUn39OUn6J/dzdt6tr14lKSEhQz+roCIBaUaWZJQAAAACc29tvv60FCxZoyJAh2rx5s4pCk426cOFrSfeU2L8mZnGUpqxFVavq0qVz+uKLfyotbZMyMnYrP/9bSXkl9nNzc1Pr1q01cuRITZ8+Xf7+/lU/OYA6h7AEAAAAaOB8fX312Wef6dKlS3rggQeUkpIiaaGKwhJDksX6z4CATSos7CNXV9ca76eLi9S3r+2iqv36VextRYWFhTpy5HPt2/exTp7coUuX0pSff0E/XpS1mKurq1q1aqWhQ4dq5syZCg4OrtJnAOAcCEsAAAAASJL8/f21ZcsW5eXlac6cuZo9O1X5+R2+32qRtFe7dw/Q7t3ucnNrpsaNQ9WyZTd16nS/br/9vhoJUMyzS0qbVVJQkKeTJ7/WiRNf6uzZA8rI2K9Ll44qL++CDOOqpMJSj+/u7q7mzZvr/vvv1wsvvMDba4AGqtJvw4Hzc5ZViAEAqGt4Gw4aipUrpVGjfvizm9v/U0HBilL2dpHkLVdXP3l5Bcvfv42aNAmTr2+wfH2by8+vuYKCblVg4K3y9Q2qcF9yc6/p6tWLun49UwcOXNJXX4XLz+9t5ed/ouvXzykv75IKC6/KMLJVtLbIzW9zvLy81LJlS/Xo0UOPP/64BgwYUCszZuqL2bOlpUtLvq1o/Hhp+vTa6xfqFme5DyUsacCcZZACAFDXEJagobhxQ+rcWfrmGykyUtq9W/r229OaMWOGtm7dqlOnTun69euq+C2FRZLr919usliKJrwbRqGkGyqa+XHj+y/j+39WjouLizw8PBQcHKxOnTrpvvvu02OPPcbjNNXgnnukzZvttycn13x/UDc5y30oj+EAAAAAsMvFRVq8WJo6VZo3r+jPt9xyi95++22b/S5duqR//etf+vTTT7Vv3z6dOXNGly9fVn5+filBiqGi1+4WSMpVZX996+bmJk9PT/n5+Sk4OFht2rRRx44dFR0drT59+rD4ag2bONF+WDJxYs33BagqZpY0YM6S6AEAUNcwswQoXVmPYjz99FUdOXJE6enpOnXqlE6dOqWMjAxlZGTIw8NDvr6+aty4sRo1aqSAgAAFBAQoKChIQUFBCg4Otn55eHjU3gdEqcwzkYoVz0iqyCK8qN+c5T6UmSUAAAAAHGbtWuno0ZLt69ZJ06f7qnPnzurcuXPNdwzVzsVFio+3XecmPp6gBM6JYQsAAADAYUp75GLixKJZJ2FhUtu2P3yFhRW1o34YOVL6fuKAIiOlESNqtz9AZRGWAAAAAHAY881yseKb5uJZJ8eO/fB19GjRrBNnRQBkq3idm+7dpTfeYFYJnBdDFwAAACgHborLp/hRDLPiRzHKmnXirOpjAFRVsbHSjh1F/wScFWEJAAAAUA7cFJdfaY9ilDXrxFnVxwAIAGEJAAAAUC7cFJdfaY9ilDXrxFnVxwAIAGEJAAAAUC7cFFdMaY9i1LcFQOtjAASAsAQAAAAoF26KHaM+LgBa3wIgAIQlAAAAQLlxU+wY9W0B0PoYAAENHf8ZAwAAAOXETTFKU98CIKChc6vtDgAAAADOpPimGABQf5GFAwAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAAAAmBCWAAAAAPXY7NlSWJjUtu0PX2FhRe0AAPvcarsDAAAAAKrP2rXS0aMl29etk6ZPr/n+AIAzYGYJAAAAUI9NnFixdgAAYQkAAABQr40cKXXqZNsWGSmNGFE7/QEAZ0BYAgAAANRjLi5SfLxtW3x8UTsAwD4ukQAAAEA9Z55dwqwSALg5whIAAACgnnNxkRYvlrp3l954g1klAHAzvA0HAAAAaABiY6UdO2q7FwDgHMiUAQAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATAhLAAAAAAAATBpsWHLt2jW99957mjhxonr06CFPT09ZLBa9+OKLN609deqUxo4dq5YtW8rLy0sRERGKj49XTk5OqTXZ2dmaOXOmIiIi5OXlpZYtW2rcuHE6ffp0medatmyZoqKi5Ovrq6CgIA0ZMkRbt26t6McFAAAAAADl5FbbHagtaWlpGj16dIXrDh8+rOjoaF24cEGRkZGKjY3VF198oZdfflkbN27Uxo0b5enpaVOTk5Oj/v37a9u2bQoJCdGwYcN07NgxvfPOO/roo4+0bds2hYWFlTjX5MmTlZCQIG9vbw0cOFA5OTlav3691q1bp8TERA0fPryyHx8AAAAAAJSiwc4sady4scaPH68lS5Zo165devnll8tVN2bMGF24cEGTJk3S3r17tWLFCqWmpiouLk4pKSmaM2dOiZpZs2Zp27Ztio6O1qFDh7RixQpt375d8+bNU0ZGhsaNG1eiZsOGDUpISFCTJk20e/duffDBB1qzZo0+++wzubq6auzYscrKyqrqtwEAAAAAAPxIgw1LwsPD9de//lW//vWvddddd8nd3f2mNTt27FBKSoqaNWum1157zdru5uamxYsXy93dXQsWLFBBQYF1W15enhYtWiRJev311+Xr62vdNmXKFHXu3FnJycnatWuXzbnmz58vSXrhhRfUvn17a3t0dLSeeOIJZWVlaenSpZX78AAAAAAAoFQNNiypjNWrV0uShg4dWuJRm+bNmys2NlaZmZnasmWLtT0lJUWXLl1SeHi4unbtWuKYDz74oCQpKSnJ2padna1NmzbZbL9ZDQAAAAAAcAzCkgrYvXu3JOmuu+6yu724fc+ePVWqSU1NVW5uroKDg9WqVaty1QAAAAAAAMdosAu8VsaJEyckyW6AYW4/fvx4tdY0atRIAQEByszM1JUrV9S4ceMy+92pUye77enp6QoPDy+zFgAAAACAhoaZJRVw9epVSZKPj4/d7Y0aNZIkXblypVprSqsDAAAAAABV57QzS+Li4nTgwIEK1SxfvlxRUVHV1KO665tvvrHbXtqMEwAAAAAAGjKnDUuOHj2q1NTUCtVcv369SucsfpNNace5du2aJNk8FlMdNaXVAQAAAACAqnPasOTrr7+u8XO2bt1aX331lU6dOmV3e3F7aGioTY15myNqrl27pqysLAUGBhKWAAAAAADgYKxZUgFdunSRJH355Zd2txe3d+7cuUo1HTp0kKenpzIyMnT69Oly1QAAAAAAAMcgLKmABx54QJKUlJSk3Nxcm23nzp3T5s2bFRgYqJiYGGt7TEyM/P39lZ6ebnc2TGJioiRp6NCh1jZvb2/1799fkrRy5cpy1QAAAAAAAMcgLKmAqKgoxcTE6Pz585o2bZq1vaCgQE8++aTy8/M1adIkubu7W7d5eHhowoQJkqSnnnrKutaIJM2fP1979uxRnz591K1bN5tzTZkyRZI0a9YspaWlWds///xzvfnmmwoICND48eOr5XMCAAAAANCQWQzDMGq7E7UlLi5O3377rSTpzJkzOnnypG655Ra1atVKkhQSEqJVq1bZ1KSlpSk6OloXL17UHXfcoY4dO2rnzp06cuSIevXqpU2bNsnT09OmJicnR3379tX27dsVEhKi2NhYHT9+XNu3b1dwcLC2bdumsLCwEv2bPHmyEhIS5OPjo/vuu095eXlav369DMNQYmKihg8fXqXPX/w2nNLelgMAAOzLz8+Xh4eH8vLybH5JAgAAyuYs96ENOixp06aNjh8/Xur20NBQHTt2rET7yZMnNXPmTK1Zs0bfffedWrdurUceeUTPP/+8vLy87B4rOztbc+bM0fvvv6+TJ08qKChIgwcP1iuvvGINZ+xZtmyZFi1apAMHDsjDw0M9e/bUjBkz1KtXrwp/3h9zlkEKAEBdQ1gCAEDlOMt9aIMOSxo6ZxmkAADUNYQlAABUjrPch7JmCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgAlhCQAAAAAAgEmDDUsOHjyouXPnql+/fmratKnc3d3VokULjRgxQps3by6z9tSpUxo7dqxatmwpLy8vRUREKD4+Xjk5OaXWZGdna+bMmYqIiJCXl5datmypcePG6fTp02Wea9myZYqKipKvr6+CgoI0ZMgQbd26tVKfGQAAAAAA3JzFMAyjtjtRG1q1aqXTp0/L19dXPXv2VFBQkPbv3699+/bJYrFo/vz5mjx5com6w4cPKzo6WhcuXFBkZKQ6duyoL774QkeOHFFMTIw2btwoT09Pm5qcnBz169dP27ZtU0hIiGJjY3Xs2DHt2LFDwcHB2rZtm8LCwkqca/LkyUpISJC3t7cGDhyonJwcbdy4UYZhKDExUcOHD6/S96BTp06SpG+++aZKxwEAoKHJz8+Xh4eH8vLy5O7uXtvdAQDAaTjLfWiDnVly2223afny5crIyND69eu1YsUK7d27V0uWLJFhGHrmmWe0f//+EnVjxozRhQsXNGnSJO3du1crVqxQamqq4uLilJKSojlz5pSomTVrlrZt26bo6GgdOnRIK1as0Pbt2zVv3jxlZGRo3LhxJWo2bNighIQENWnSRLt379YHH3ygNWvW6LPPPpOrq6vGjh2rrKys6vjWAAAAAADQoDXYsGTDhg167LHH5OXlZdP+61//WgMHDlRhYaFWrlxps23Hjh1KSUlRs2bN9Nprr1nb3dzctHjxYrm7u2vBggUqKCiwbsvLy9OiRYskSa+//rp8fX2t26ZMmaLOnTsrOTlZu3btsjnX/PnzJUkvvPCC2rdvb22Pjo7WE088oaysLC1durSK3wUAAAAAAPBjDTYsKUuXLl0kSWfOnLFpX716tSRp6NChJR61ad68uWJjY5WZmaktW7ZY21NSUnTp0iWFh4era9euJc714IMPSpKSkpKsbdnZ2dq0aZPN9pvVAAAAAAAAxyAssePIkSOSpBYtWti07969W5J011132a0rbt+zZ0+ValJTU5Wbm6vg4GC1atWqXDUAAAAAAMAxCEt+JD09XR999JEk6ac//anNthMnTkiS3QDD3H78+PFqrWnUqJECAgKUmZmpK1eulP2BAAAAAABAhbjVdgfqkoKCAo0ZM0a5ubl6+OGH1a1bN5vtV69elST5+PjYrW/UqJEk2QQY1VFTXJeVlaUrV66ocePGZX6u4tWGfyw9PV3h4eFl1gIAAAAA0NA4bVgSFxenAwcOVKhm+fLlioqKKnX7pEmTtGXLFoWFhemNN96oahcBAAAAAIATctqw5OjRo0pNTa1QzfXr10vdNnv2bC1evFjNmzfX2rVrFRQUVGKf4jfZlHaca9euSZLNTI/qqCmtrjSlvb+6tBknAAAAAAA0ZE4blnz99dcOO9aSJUv0wgsvyN/fX2vWrFG7du3s7te6dWt99dVXOnXqlN3txe2hoaE2NeZtjqi5du2asrKyFBgYWK6wBAAAAAAAlF+DX+D1n//8p5566in5+Pho9erVuvPOO0vdt/iVwl9++aXd7cXtnTt3rlJNhw4d5OnpqYyMDJ0+fbpcNQAAAAAAwDEadFjy8ccfa/To0XJzc9OqVasUExNT5v4PPPCAJCkpKUm5ubk2286dO6fNmzcrMDDQ5jgxMTHy9/dXenq63dkwiYmJkqShQ4da27y9vdW/f39J0sqVK8tVAwAAAAAAHKPBhiUpKSl68MEHZRiGVqxYoYEDB960JioqSjExMTp//rymTZtmbS8oKNCTTz6p/Px8TZo0Se7u7tZtHh4emjBhgiTpqaeesq41Iknz58/Xnj171KdPnxJv3pkyZYokadasWUpLS7O2f/7553rzzTcVEBCg8ePHV+7DAwAAAACAUlkMwzBquxO1ITAwUFlZWWrbtq3uueceu/v07t1bv/jFL2za0tLSFB0drYsXL+qOO+5Qx44dtXPnTh05ckS9evXSpk2b5OnpaVOTk5Ojvn37avv27QoJCVFsbKyOHz+u7du3Kzg4WNu2bVNYWFiJ80+ePFkJCQny8fHRfffdp7y8PK1fv16GYSgxMVHDhw+v0vegeIHX0haABQAA9uXn58vDw0N5eXk2vyQBAABlc5b70AYbllgslpvu8/jjj2vZsmUl2k+ePKmZM2dqzZo1+u6779S6dWs98sgjev755+Xl5WX3WNnZ2ZozZ47ef/99nTx5UkFBQRo8eLBeeeUVtWrVqtQ+LFu2TIsWLdKBAwfk4eGhnj17asaMGerVq1e5P2tpnGWQAgBQ1xCWAABQOc5yH9pgwxI4zyAFAKCuISwBAKBynOU+tMGuWQIAAAAAAGAPYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIAJYQkAAAAAAIBJgw1L9uzZowkTJqhnz55q2bKlPD095e/vr+joaC1cuFD5+fml1p46dUpjx45Vy5Yt5eXlpYiICMXHxysnJ6fUmuzsbM2cOVMRERHy8vJSy5YtNW7cOJ0+fbrMfi5btkxRUVHy9fVVUFCQhgwZoq1bt1b6cwMAAAAAgLJZDMMwarsTtWHRokWaOHGiQkND1a5dOwUHBysjI0MpKSnKyclRnz59tG7dOnl4eNjUHT58WNHR0bpw4YIiIyPVsWNHffHFFzpy5IhiYmK0ceNGeXp62tTk5OSoX79+2rZtm0JCQhQbG6tjx45px44dCg4O1rZt2xQWFlaij5MnT1ZCQoK8vb01cOBA5eTkaOPGjTIMQ4mJiRo+fHiVvgedOnWSJH3zzTdVOg4AAA1Nfn6+PDw8lJeXJ3d399ruDgAATsNZ7kMb7MySIUOGKD09XceOHdOGDRv0j3/8Qxs2bNCxY8cUGRmp5ORk/eUvfylRN2bMGF24cEGTJk3S3r17tWLFCqWmpiouLk4pKSmaM2dOiZpZs2Zp27Ztio6O1qFDh7RixQpt375d8+bNU0ZGhsaNG1eiZsOGDUpISFCTJk20e/duffDBB1qzZo0+++wzubq6auzYscrKyqqObw0AAAAAAA1agw1LwsLC7M7maN68uaZNmyZJ2rRpk822HTt2KCUlRc2aNdNrr71mbXdzc9PixYvl7u6uBQsWqKCgwLotLy9PixYtkiS9/vrr8vX1tW6bMmWKOnfurOTkZO3atcvmXPPnz5ckvfDCC2rfvr21PTo6Wk888YSysrK0dOnSyn58AAAAAABQigYblpSleDrtjx/BWb16tSRp6NChJR61ad68uWJjY5WZmaktW7ZY21NSUnTp0iWFh4era9euJc714IMPSpKSkpKsbdnZ2dagpnj7zWoAAAAAAIBjEJb8SGZmpubNmydJeuCBB2y27d69W5J011132a0tbt+zZ0+ValJTU5Wbm6vg4GC1atWqXDUAAAAAAMAx3Gq7A7UtLS1Ns2fP1o0bN3Tu3Dlt3bpVV69e1RNPPKGf/exnNvueOHFCkuwGGOb248ePV2tNo0aNFBAQoMzMTF25ckWNGzcu8zMWL6DzYwcPHpS7u3up2wEAgH3F6+N36dJFFoullnsDAIDzSE9Pd4rF0Rt8WHLu3Dm9++67Nm2TJk3SK6+8IhcX24k3V69elST5+PjYPVajRo0kSVeuXKnWmuK6rKyscoUlpblx40aZr0gGHCU9PV2SFB4eXss9QX3HWENNOXLkiDw9PQlKUO24rqGmMNZQU/Lz823W+ayrnDYsiYuL04EDBypUs3z5ckVFRdm09e7dW4ZhqLCwUCdOnNCqVav00ksv6X//+5/WrVunNm3aOLDXtaO0VzI5yyub4PwYa6gpjDXUFMYaagpjDTWFsYaa4ixPNjhtWHL06FGlpqZWqOb69eulbnN1dVXbtm01ZcoUtWnTRiNHjtTEiRNtFlEtfpNNace5du2aJNnM9KiOmtLqAAAAAABA1TltWPL1119X27Hj4uLk6+urNWvWKC8vz/pWnNatW+urr77SqVOn7NYVt4eGhlrbWrdubbPNETXXrl1TVlaWAgMDCUsAAAAAAHAw3oZjh8ViUVBQkAoKCpSZmWlt79KliyTpyy+/tFtX3N65c+cq1XTo0EGenp7KyMjQ6dOny1UDAAAAAAAcg7DEjiNHjujkyZPy8/NT06ZNre3FrxJOSkpSbm6uTc25c+e0efNmBQYGKiYmxtoeExMjf39/paen250Nk5iYKEkaOnSotc3b21v9+/eXJK1cubJcNQAAAAAAwDEabFiycOFCnT17tkR7amqqHn30URmGodGjR8vV1dW6LSoqSjExMTp//rymTZtmbS8oKNCTTz6p/Px8TZo0yeY1SB4eHpowYYIk6amnnrKuNSJJ8+fP1549e9SnTx9169bNph9TpkyRJM2aNUtpaWnW9s8//1xvvvmmAgICNH78+Cp+FwAAAAAAwI9ZDMMwarsTtaFNmzY6efKkunTponbt2skwDB0/fly7du3SjRs3dM8992j16tXWxVaLpaWlKTo6WhcvXtQdd9yhjh07aufOnTpy5Ih69eqlTZs2ydPT06YmJydHffv21fbt2xUSEqLY2FgdP35c27dvV3BwsLZt26awsLASfZw8ebISEhLk4+Oj++67T3l5eVq/fr0Mw1BiYqKGDx9end8iAAAAAAAapAYblvz973/Xxx9/rC+++EJnz55Vdna2goKCdOedd+qRRx7RY489JhcX+xNvTp48qZkzZ2rNmjX67rvv1Lp1az3yyCN6/vnn5eXlZbcmOztbc+bM0fvvv6+TJ08qKChIgwcP1iuvvKJWrVqV2s9ly5Zp0aJFOnDggDw8PNSzZ0/NmDFDvXr1csj3AQAAAAAA2GqwYQkAAAAAAIA9DXbNEgAAAAAAAHsISwAAAAAAAEwISwAAAAAAAEwISwAAAAAAAEwISwAAAAAAAEwIS5zYnj17NGHCBPXs2VMtW7aUp6en/P39FR0drYULFyo/P7/U2lOnTmns2LFq2bKlvLy8FBERofj4eOXk5JRak52drZkzZyoiIkJeXl5q2bKlxo0bp9OnT5fZz2XLlikqKkq+vr4KCgrSkCFDtHXr1kp/btS8gwcPau7cuerXr5+aNm0qd3d3tWjRQiNGjNDmzZvLrGWsoSKuXbum9957TxMnTlSPHj3k6ekpi8WiF1988aa1jDXUhMqOGdRvu3bt0quvvqoRI0aoVatWslgsslgsN62rzLUkJSVFQ4YMUVBQkHx9fRUVFaXly5eXWVOZ6yPqnuvXr+uDDz7Q+PHj1aFDB3l5ealRo0bq0qWLXn75ZV29erXUWsYaKmP+/PkaMWKE2rdvL39/f3l6eio0NFSjR4/W3r17S62rN+PNgNNauHChIckIDQ017r33XuP//b//Z9x7772Gl5eXIcno06ePkZubW6IuLS3NaNq0qSHJiIyMNEaNGmWEhYUZkoyYmBgjJyenRE12drbRs2dPQ5IREhJijBo1yoiKijIkGcHBwUZ6errdPj799NOGJMPb29sYNmyYMWjQIMPNzc1wdXU1Vq1a5ehvCarJLbfcYkgyfH19jQEDBhijRo0yIiMjDUmGxWIx/vSnP9mtY6yhor766itDUomv+Pj4MusYa6gJlR0zqP+GDRtm99pVlspcSxITEw1XV1fDYrEYffr0MUaOHGkEBAQYkoypU6faranM9RF101tvvWUdW7fffrvx0EMPGYMGDTIaN25sSDJuu+0249y5cyXqGGuorCZNmhheXl5GVFSUERcXZ8TFxRkRERGGJMPd3d1ISkoqUVOfxhthiRNLT0+3+4PZ2bNnrTeyCxcuLLE9JibGkGRMmjTJ2pafn2/ExcWVelMyffp0Q5IRHR1tXLlyxdo+b948azDzY+vXrzckGU2aNDEOHTpkbd+6davh4eFhBAQEGJmZmRX70KgV9957r7F8+XIjOzvbpn3JkiWGJMPV1dX45ptvStQx1lBRhw8fNsaPH28sWbLE2LVrl/Hyyy+XKyxhrKEmVGbMoGF49dVXjRkzZhgffvih8e233xqenp5lhiWVuZZcvHjR8PPzMyQZ//73v63tZ8+eNdq1a2dIMj755JMS56rM9RF107Jly4xf/epXxv79+23az5w5Y3Tt2tWQZDzyyCM22xhrqIotW7aU+PnfMAzj9ddfNyQZzZs3N/Lz863t9W28EZbUU++9954hyYiLi7Np3759uyHJaNasWYm07ezZs4a7u7sRGBhoM+hzc3MNf39/Q5Lx5ZdfljhX586dDUnGF198YdN+//33G5LszjqYNGmSIcn44x//WIVPibpg4MCBhiTjxRdftGlnrMER5syZc9P/4THWUBMqO2bQMN0sLKnMtWTu3LmGJGPYsGElav7zn/8Ykoyf/OQnNu2VuT7COW3dutWQZHh6etrMLGesobqEh4cbkozdu3db2+rbeGPNknrK3d1dkuTh4WHTvnr1aknS0KFD5enpabOtefPmio2NVWZmprZs2WJtT0lJ0aVLlxQeHq6uXbuWONeDDz4oSUpKSrK2ZWdna9OmTTbbb1YD59SlSxdJ0pkzZ2zaGWuoKYw11ITKjBnAnspeS4qvdfZqHnjgAXl5eWnDhg02z+pX5voI51T881hubq4uXrwoibGG6vXj+836ON4IS+qhzMxMzZs3T1LRADPbvXu3JOmuu+6yW1vcvmfPnirVpKamKjc3V8HBwWrVqlW5auCcjhw5Iklq0aKFTTtjDTWFsYaaUJkxA9hT2WtJWWPQw8NDkZGRysnJ0aFDh8pVU9a54HyKfx5zd3dXUFCQJMYaqs97772n1NRUtW/fXu3bt5dUP8cbYUk9kJaWpjFjxmj06NEaNGiQWrdurZ07d+qJJ57Qz372M5t9T5w4IUl2B7C5/fjx49Va06hRIwUEBCgzM1NXrly56WdE3ZSenq6PPvpIkvTTn/7UZhtjDTWFsYaaUJkxA9hTmWvJ5cuXdenSpTLrHHWtg3NKSEiQJA0ePNj6m3bGGhzlD3/4g8aMGaOHHnpIkZGRGj16tEJCQvSPf/xDrq6ukurneHOrUjXqhHPnzundd9+1aZs0aZJeeeUVubjY5mHFrxTz8fGxe6xGjRpJks0P+tVRU1yXlZWlK1euqHHjxqXuh7qpoKBAY8aMUW5urh5++GF169bNZjtjDTWFsYaaUJkxA9hTmWuJ+ZWw1X2tg/P5+OOPtXTpUrm7u+uVV16xtjPW4Chr167Vxo0brX8ODQ3V8uXLbX7+r4/jjbCkFsXFxenAgQMVqlm+fLmioqJs2nr37i3DMFRYWKgTJ05o1apVeumll/S///1P69atU5s2bRzYazgjR401s0mTJmnLli0KCwvTG2+8UdUuop6ojrEGAADsO3jwoH7+85/LMAz94Q9/sK5dAjjShg0bJElZWVnau3evXn75ZfXp00ezZs3S9OnTa7l31YewpBYdPXpUqampFaq5fv16qdtcXV3Vtm1bTZkyRW3atNHIkSM1ceJEm0V0fH19yzzOtWvXJMnmN6LVUVNaHaqHo8fa7NmztXjxYjVv3lxr1661PhtrxlhrmBw91sqDsYaaUJkxA9hTmWtJcU1xnZ+f301rynMuxq1zO336tAYPHqzMzExNmTJFTz/9tM12xhocLSAgQLGxsfr4448VHR2tGTNmaODAgerevXu9HG+sWVKLvv76axlFr28u91ffvn3Ldey4uDj5+vpqzZo1ysvLs7a3bt1aknTq1Cm7dcXtoaGh1Vpz7do1ZWVlKTAwkItmDXDkWFuyZIleeOEF+fv7a82aNWrXrp3d/RhrDVN1XtdKw1hDTajMmAHsqcy1xM/PT/7+/mXWOepaB+fw3XffaeDAgTp+/LjGjh2rP/7xjyX2Yayhuri7u+vhhx+WYRjWX8zXx/FGWFJPWSwWBQUFqaCgQJmZmdb24ql5X375pd264vbOnTtXqaZDhw7y9PRURkaGTp8+Xa4a1H3//Oc/9dRTT8nHx0erV6/WnXfeWeq+jDXUFMYaakJlxgxgT2WvJWWNwfz8fO3bt09eXl6KiIgoV01Z50LddvXqVd1///3av3+/RowYobfeeksWi6XEfow1VKemTZtKkjIyMiTVz/FGWFJPHTlyRCdPnpSfn591IEs/vEo4KSlJubm5NjXnzp3T5s2bFRgYqJiYGGt7TEyM/P39lZ6erq+//rrEuRITEyUVvee6mLe3t/r37y9JWrlyZblqULd9/PHHGj16tNzc3LRq1SqbMWIPYw01hbGGmlCZMQPYU9lrSfG1rni72UcffaScnBwNGDBAXl5eJWoqcn1E3Zabm6thw4Zpx44dGjRokM3bSH6MsYbqlJycLEkKDw+XVE/HmwGntWDBAuPbb78t0X7w4EGjR48ehiRjwoQJJbbHxMQYkoynn37a2pafn2+MGDHCkGTEx8eXqJk+fbohyejVq5dx9epVa/u8efMMSUafPn1K1Kxfv96QZDRp0sQ4dOiQtX3r1q2Gp6enERAQYGRmZlboM6N2bNmyxfD29jbc3NyMVatWlbuOsYaqmjNnTqljxYyxhppQmTGDhsnT09Mo68fsylxLLl68aPj5+RmSjH//+9/W9nPnzhnt2rUzJBmffPJJiXNV5vqIuqmgoMCIi4szJBmxsbHGtWvXblrDWENlbdmyxfjf//5nFBYW2rTn5eUZCxYsMFxcXAxvb2/jxIkT1m31bbwRljix0NBQw8XFxejatavx0EMPGQ8++KDRvXt3w8XFxZBk3HPPPcaVK1dK1B06dMho0qSJIcm44447jIcfftgICwuz/gCYk5NToiY7O9sawISEhBijRo2y/jk4ONhIT0+328enn37akGT4+PgYw4YNM+6//37Dzc3NcHV1rdBNN2pXQECAIclo27at8fjjj9v9euutt0rUMdZQGcOHDzd69Ohh9OjRw7j11lsNScYtt9xibRs+fHiJGsYaakJlxwzqv48++sh6jerRo4dhsVgMSTZtH330kU1NZa4liYmJhouLi2GxWIx+/foZDz74oPX/0VOmTLFbU5nrI+qmP//5z4YkQ5IRFxdX6s9kGRkZNnWMNVTGO++8Y0gymjZtagwaNMh49NFHjYEDBxohISGGJMPLy8tYsWJFibr6NN4IS5zY3/72N+PRRx81IiIiDD8/P8Pd3d1o3ry5MWjQIGPZsmUlUkCzEydOGGPGjDFatGhheHh4GO3atTNmzJhhZGdnl1pz/fp1Y8aMGUZ4eLjh4eFhtGjRwhgzZoxx8uTJMvv5zjvvGN26dTN8fHyMgIAAY/DgwUZKSkqlPzdqXvH/mMv6evzxx+3WMtZQUaGhoWWOtdDQULt1jDXUhMqOGdRvxTcVZX298847dusqei3ZsmWLMXjwYCMgIMDw8fEx7r77bmPZsmVl1lTm+oi6Jz4+vlw/kx09erRELWMNFXXkyBHj+eefN2JiYoyQkBDD3d3daNSokdGpUydj4sSJRlpaWqm19WW8WQzDMEp7RAcAAAAAAKChYYFXAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAAAAAAAAE8ISAABQp1gslpt+jRkzpra7WSFZWVlq0qSJHnrooWo9z1dffSWLxaLXXnutWs8DAEB9ZzEMw6jtTgAAABSzWCySpMcff7zUfXr37q1f/OIXNdKfZcuWaezYsYqPj9eLL75YqWP83//9n+bNm6c9e/YoMjLSsR38kWHDhumzzz5Tenq6goKCqvVcAADUV2613QEAAAB7li1bVttdcIhvv/1WCxcu1NChQ6s9KJGk5557Th9++KHmzp2ruXPnVvv5AACoj3gMBwAAoBq9/fbbys3N1ejRo2vkfD179lS7du309ttvKy8vr0bOCQBAfUNYAgAAnN7mzZs1YcIEde7cWYGBgfL29tZtt92mZ599VllZWXZrtm7dquHDhys0NFSenp5q0aKFoqKi9Oyzz+rq1auSpL59+2rs2LGSpJdeeslm3ZTyzHwxDENLly5V48aN9cADD5TY/uKLL1qPtWvXLt1///0KCAhQUFCQRo0apVOnTkmSrl27pt/97ndq06aNvLy8FBkZqcTExFLP+8gjj+jChQtatWrVTfsIAABKIiwBAABO7//+7/+0dOlSeXt7695779W9996ry5cva+7cuerdu7c1/CiWlJSk2NhYffjhhwoJCdGIESPUtWtXfffdd5o7d64uXLggSRo8eLBiYmIkSV26dNHjjz9u/WrXrt1N+7V//34dPXpUPXv2lJeXV6n7bd++XTExMcrIyNCgQYPUpEkTrVy5Uvfee68uXbqkfv366d1331X37t0VHR2t/fv3a9SoUVq7dq3d4/Xt21eStHr16vJ8+wAAwI+wZgkAAHB68fHx6tWrl/z9/a1tubm5mjRpkv7yl79o/vz5mjlzpnXbH//4R924cUOJiYkaOXKkzbF27typJk2aSJKeffZZtWjRQikpKRo+fHiFF3jdvHmzJKl79+5l7rdkyRItXrxYTzzxhCQpPz9fQ4YM0YYNG9SrVy+1aNFCR44cUaNGjSRJS5cu1S9+8Qv9/ve/16BBg0oc7+6775aLi4uSk5Mr1F8AAFCEmSUAAKBOKuvVwR988IHNvvfff79NUCJJnp6e+vOf/yw3Nzf997//tdmWkZEhSRowYECJ83bv3l2NGzd2yGfYs2ePJKlDhw5l7te7d29rUCJJ7u7umjhxoiTp4MGDWrx4sTUokaQxY8aoadOm+vzzz5Wfn1/ieH5+fgoJCdGJEyeUmZnpiI8CAECDwswSAABQJ5X16uDWrVuXaDt9+rSSkpJ08OBBXb58WTdu3JAkeXh4KC0tzWbfbt266cCBA3rsscc0Y8YMdevWTS4ujv8d0vnz5yVJgYGBZe43cODAEm1hYWGSpDZt2igiIsJmm6urq0JDQ7Vr1y5duHBBISEhJeqDgoJ0+vRpZWRk3PT8AADAFmEJAACokyry6uD58+fr2WeftTvLwp7f//732rt3r5KSkpSUlKTAwED17t1bP/3pT/Xzn/+8zPVFKuLSpUuSdNOZKrfcckuJNl9f31K3mbfn5uba3e7n5ydJpS5wCwAASsdjOAAAwKlt27ZNU6dOlY+Pj5YtW6Zjx44pJydHhmHIMAy7sy5uvfVWffHFF1q7dq0mTpyoW2+9VUlJSfrlL3+pzp076+LFiw7pW/GjQVeuXClzv7JmtVR2xktxUBMQEFCpegAAGjLCEgAA4NSKX487e/ZsPf7449ZXAUtSdna2zp49a7fOzc1NAwcO1IIFC7R7924dO3ZM/fv3V1pamubOneuQvjVr1kyS9N133znkeBVRvFZJcHBwjZ8bAABnR1gCAACcWnEo0KpVqxLbVq5cKcMwynWc0NBQTZs2TZK0b98+a7uHh4ckqaCgoMJ969KliyQpNTW1wrVVcfnyZZ05c0atW7dmvRIAACqBsAQAADi14sVPly5darNmyf79+63hx4/96U9/sjvj5OOPP5ZU9JhOsZYtW0qqXOARGxsrqeh1xDVp586dMgxDffr0qdHzAgBQX7DAKwAAqJPGjBlT6rbWrVvr5ZdfliSNHTtW8+bNU1JSkjp06KDu3bvru+++U3JysoYPH64dO3bo+PHjNvUvvfSSnnnmGXXp0kXt27eXYRjavXu3Dh06pKCgID3zzDPWfXv27KlmzZopMTFRffv2VVhYmFxcXDRu3Dj16tWrzM9w++23q23bttq+fbtycnIctnDszXz66aeSpAceeKBGzgcAQH1DWAIAAOqkd999t9RtXbp0sYYlTZo00c6dOzVt2jQlJyfrww8/VNu2bfXKK6/omWeeUXh4eIn6hQsXas2aNdq1a5f+97//SSqaTTJlyhRNmTLF5g00Xl5eWr16tZ5//nnt2LFDn332mQzDUO/evW8allgsFv3iF7/Q9OnTlZSUpIceeqgy34oK+8c//qGmTZsqLi6uRs4HAEB9YzHK+yAvAAAAKuzs2bNq27atBgwYoKSkpGo/3+eff65evXrpd7/7ncMWqgUAoKFhzRIAAIBq1KJFC02cOFGrV6/W3r17q/18r776qgICAkpdrwUAANwcYQkAAEA1e/755xUYGKiXXnqpWs/z1Vdf6cMPP9Rzzz2noKCgaj0XAAD1GY/hAAAAAAAAmDCzBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwISwBAAAAAAAwOT/AwVQurskzFGKAAAAAElFTkSuQmCC",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "test_dispersion.plots.ellipses(xlim=(-200, 3500), ylim=(-200, 3500))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGzCAYAAAA1yP25AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3zElEQVR4nO3deVhU9eLH8c/IJiqgKKAkAqmpuKa2uOSeZlZa3tKyFLXyJoZK15LK3UK9avzymlk3l7JuLmlp5paa3sx9TTNxTa8bboCgIcr5/dHDPI0sztgMw8H363nmqfmeM+d8OAh+/J5zZiyGYRgCAAAwoRLuDgAAAHC7KDIAAMC0KDIAAMC0KDIAAMC0KDIAAMC0KDIAAMC0KDIAAMC0KDIAAMC0KDIAAMC0KDIotiIiIhQdHe3uGMXeP//5T919993y8PBQgwYN3B3H6dLT0/Xiiy+qYsWKslgsGjRoUKHtu1WrVmrVqpX1+bFjx2SxWDRr1qxCy5AXi8WikSNHumTbReVrhHlQZGAKs2bNksVi0bZt2/Jc3qpVK9WpU+cv7+e7775z2S/o4mjlypV6/fXX1axZM82cOVPvvvtuoe37ypUrGjlypH744QeX7ufdd9/VrFmz9Morr+izzz7TCy+84NL9ITd+LlEQT3cHAFzlwIEDKlHCsa7+3XffaerUqfzStNOaNWtUokQJffLJJ/L29i7UfV+5ckWjRo2SJJtZC2dbs2aNHnzwQY0YMcJl+8jPypUrC32f7hYeHq6rV6/Ky8vLOsbPJQrCjAyKLR8fH5tfhmaQkZHh7ggOSU5Olq+vb6GXmMKUnJyssmXL/uXtGIahq1evOvQab2/vYn1s82KxWFSyZEl5eHi4OwpMgiKDYuvma2SysrI0atQoVa9eXSVLllT58uXVvHlzrVq1SpIUHR2tqVOnSvrjl2nOI0dGRoZee+01hYWFycfHRzVq1NDEiRN18wfIX716VbGxsapQoYL8/Pz0xBNP6OTJk7muKxg5cqQsFot++eUXPffccypXrpyaN28uSdqzZ4+io6N19913q2TJkqpYsaL69OmjCxcu2OwrZxtJSUl6/vnnFRAQoKCgIA0bNkyGYejEiRPq3Lmz/P39VbFiRU2aNMmuY3f9+nWNGTNGVatWlY+PjyIiIvTmm28qMzPTuo7FYtHMmTOVkZFhPVa3uq5h/vz5atSokXx9fVWhQgU9//zzOnnypM06N18XkiM6OloRERGS/riOIigoSJI0atQo6/4d+Rd7cnKy+vbtq5CQEJUsWVL169fX7Nmzrct/+OEHWSwWHT16VEuXLrXu49ixY3ZtPyIiQo899phWrFihxo0by9fXV9OnT5ckzZw5U23atFFwcLB8fHwUFRWladOm5dpGfsfCXmfPnpWnp6d15urPDhw4IIvFon/961/WsZSUFA0aNMj6Z7xatWoaP368srOzb7mvnTt3qmPHjvL391eZMmXUtm1bbdq0Kdd6KSkpGjx4sCIiIuTj46PKlSurZ8+eOn/+vKTc18jk93NpGIYiIiLUuXPnXPv4/fffFRAQoH79+tl1nGBunFqCqaSmplp/4f1ZVlbWLV87cuRIJSQk6MUXX9T999+vtLQ0bdu2TTt27NDDDz+sfv366dSpU1q1apU+++wzm9cahqEnnnhCa9euVd++fdWgQQOtWLFCQ4YM0cmTJ/Xee+9Z142Ojta8efP0wgsv6MEHH9S6devUqVOnfHM9/fTTql69ut59911rKVq1apWOHDmi3r17q2LFitq3b58++ugj7du3T5s2bbIpWJLUrVs31apVS+PGjdPSpUs1duxYBQYGavr06WrTpo3Gjx+vzz//XP/4xz903333qUWLFgUeqxdffFGzZ8/W3/72N7322mvavHmzEhIStH//fi1atEiS9Nlnn+mjjz7Sli1b9O9//1uS1LRp03y3OWvWLPXu3Vv33XefEhISdPbsWf3f//2fNmzYoJ07dzo06xEUFKRp06bplVde0ZNPPqmnnnpKklSvXj27Xn/16lW1atVKhw4d0oABAxQZGan58+crOjpaKSkpGjhwoGrVqqXPPvtMgwcPVuXKlfXaa69Z922vAwcO6Nlnn1W/fv300ksvqUaNGpKkadOmqXbt2nriiSfk6empJUuWqH///srOzlZMTIzd27+VkJAQtWzZUvPmzct1amzu3Lny8PDQ008/LemPU3UtW7bUyZMn1a9fP1WpUkU//fST4uPjdfr0aSUmJua7n3379umhhx6Sv7+/Xn/9dXl5eWn69Olq1aqV1q1bpwceeEDSHxdOP/TQQ9q/f7/69Omjhg0b6vz581q8eLH+97//qUKFCrm2nd/PpcVi0fPPP68JEybo4sWLCgwMtC5bsmSJ0tLS9Pzzz/+VwwezMAATmDlzpiGpwEft2rVtXhMeHm706tXL+rx+/fpGp06dCtxPTEyMkdePxddff21IMsaOHWsz/re//c2wWCzGoUOHDMMwjO3btxuSjEGDBtmsFx0dbUgyRowYYR0bMWKEIcl49tlnc+3vypUrucb+85//GJKM9evX59rGyy+/bB27fv26UblyZcNisRjjxo2zjl+6dMnw9fW1OSZ52bVrlyHJePHFF23G//GPfxiSjDVr1ljHevXqZZQuXbrA7RmGYVy7ds0IDg426tSpY1y9etU6/u233xqSjOHDh1vHWrZsabRs2TLXNnr16mWEh4dbn587dy7XMbVXYmKiIcmYM2eOTcYmTZoYZcqUMdLS0qzj4eHht/xzk5fw8HBDkrF8+fJcy/L6/nbo0MG4++67bcZuPhZHjx41JBkzZ860O8f06dMNScbPP/9sMx4VFWW0adPG+nzMmDFG6dKljaSkJJv1hg4danh4eBjHjx+3jt183Lt06WJ4e3sbhw8fto6dOnXK8PPzM1q0aGEdGz58uCHJWLhwYa6c2dnZ+X6N+f1cHjhwwJBkTJs2zWb8iSeeMCIiIqzbRPHGqSWYytSpU7Vq1apcD3v+JV62bFnt27dPBw8edHi/3333nTw8PBQbG2sz/tprr8kwDC1btkyStHz5cklS//79bdZ79dVX89323//+91xjvr6+1v///fffdf78eT344IOSpB07duRa/8UXX7T+v4eHhxo3bizDMNS3b1/reNmyZVWjRg0dOXIk3yzSH1+rJMXFxdmM58xILF26tMDX52Xbtm1KTk5W//79VbJkSet4p06dVLNmzdva5l/x3XffqWLFinr22WetY15eXoqNjVV6errWrVvnlP1ERkaqQ4cOucb//P3NmWVs2bKljhw5otTUVKfsO8dTTz0lT09PzZ071zq2d+9e/fLLL+rWrZt1bP78+XrooYdUrlw5nT9/3vpo166dbty4ofXr1+e5/Rs3bmjlypXq0qWL7r77but4pUqV9Nxzz+nHH39UWlqaJOmrr75S/fr19eSTT+bazs2zjPa455579MADD+jzzz+3jl28eFHLli1Tjx49bmubMB+KDEzl/vvvV7t27XI9ypUrd8vXjh49WikpKbrnnntUt25dDRkyRHv27LFrv7/99ptCQ0Pl5+dnM16rVi3r8pz/lihRQpGRkTbr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R/7+/jYPAABQPBXZIhMZGamKFStq9erV1rG0tDRt3rxZTZo0cWMyAABQVLj1Gpn09HQdOnTI+vzo0aPatWuXAgMDVaVKFQ0aNEhjx45V9erVFRkZqWHDhik0NFRdunRxX2gAAFBkuLXIbNu2Ta1bt7Y+j4uLkyT16tVLs2bN0uuvv66MjAy9/PLLSklJUfPmzbV8+XKVLFnSXZEBAEARYjEMw3B3CFdKS0tTQECAUlNTuV4GAG4Tdy2hsNn793eRvUYGAADgVigyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtCgyAADAtIp0kblx44aGDRumyMhI+fr6qmrVqhozZowMw3B3NAAAUAR4ujtAQcaPH69p06Zp9uzZql27trZt26bevXsrICBAsbGx7o4HAADcrEgXmZ9++kmdO3dWp06dJEkRERH6z3/+oy1btrg5GQAAKAqK9Kmlpk2bavXq1UpKSpIk7d69Wz/++KM6duyY72syMzOVlpZm8wAAAMVTkZ6RGTp0qNLS0lSzZk15eHjoxo0beuedd9SjR498X5OQkKBRo0YVYkoAAOAuRXpGZt68efr888/1xRdfaMeOHZo9e7YmTpyo2bNn5/ua+Ph4paamWh8nTpwoxMQAAKAwFekZmSFDhmjo0KHq3r27JKlu3br67bfflJCQoF69euX5Gh8fH/n4+BRmTAAA4CZFekbmypUrKlHCNqKHh4eys7PdlAgAABQlRXpG5vHHH9c777yjKlWqqHbt2tq5c6cmT56s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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAGzCAYAAAABsTylAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA4O0lEQVR4nO3dd3xUVf7/8fckIYWS0MFIqEGQ3gQpghSpiqCrgEjXRQ1SggiBLyWABhAQC6DuIrDuCi5SdEFK6BZAepcaygqICEkIYAjM+f3hL7MOoeTCJHNJXs/HYx5kzj1z7+eeJMw79557x2GMMQIAALAhH28XAAAAcCsEFQAAYFsEFQAAYFsEFQAAYFsEFQAAYFsEFQAAYFsEFQAAYFsEFQAAYFsEFQAAYFsEFSADlSxZUt27d/d2GVneO++8o9KlS8vX11fVqlXL8O3NmjVLDodDx44dy/BtAdkdQQVIp9Q3py1bttx0+eOPP65KlSrd83a++eYbjRo16p7Xk12sWLFCb775purXr6+ZM2fq7bff9nZJ95Vp06Zp1qxZ3i4DuCU/bxcAZGUHDhyQj4+1vwe++eYbTZ06lbCSTqtXr5aPj49mzJghf3//TNlmly5d1LFjRwUEBGTK9jLStGnTVLBgQY78wbY4ogJkoICAAOXIkcPbZVhy6dIlb5dgydmzZxUUFJRpIUWSfH19FRgYKIfDkWnbBLIrggqQgW6co5KSkqLo6GiVLVtWgYGBKlCggBo0aKDY2FhJUvfu3TV16lRJksPhcD1SXbp0SQMHDlRYWJgCAgJUrlw5TZw4UTd+CPqVK1fUt29fFSxYUHny5FHbtm31888/y+FwuB2pGTVqlBwOh/bt26cXXnhB+fLlU4MGDSRJu3btUvfu3VW6dGkFBgaqaNGi6tmzp3777Te3baWu4+DBg3rxxRcVEhKiQoUKafjw4TLG6OTJk3r66acVHBysokWLatKkSekau2vXrmnMmDEqU6aMAgICVLJkSQ0dOlTJycmuPg6HQzNnztSlS5dcY3Wr0xj79+9XUFCQunbt6tb+3XffydfXV4MHD05XXdLN56iULFlSTz75pNauXatatWopKChIlStX1tq1ayVJCxYsUOXKlRUYGKiaNWtq+/btbuvs3r27cufOraNHj6pFixbKlSuXQkNDNXr06DTf34kTJ6pevXoqUKCAgoKCVLNmTX355Zc3rfWf//ynateurZw5cypfvnxq2LChVqxY4ap57969WrdunWv8Hn/88XSPA5AZOPUDWJSQkKBz586laU9JSbnja0eNGqWYmBi99NJLql27thITE7VlyxZt27ZNTzzxhHr37q1Tp04pNjZWn332mdtrjTFq27at1qxZo169eqlatWpavny5Bg0apJ9//lnvvvuuq2/37t3173//W126dNGjjz6qdevWqU2bNres67nnnlPZsmX19ttvu94UY2NjdfToUfXo0UNFixbV3r179cknn2jv3r3auHFjmqMJHTp00MMPP6xx48ZpyZIlGjt2rPLnz6+PP/5YTZo00fjx4/Wvf/1Lb7zxhh555BE1bNjwtmP10ksvafbs2frLX/6igQMHatOmTYqJidH+/fu1cOFCSdJnn32mTz75RD/++KP+/ve/S5Lq1at30/U9/PDDGjNmjAYNGqS//OUvatu2rS5duqTu3burfPnyGj169G3rSY/Dhw/rhRdeUO/evfXiiy9q4sSJeuqpp/TRRx9p6NCheu211yRJMTExev7559OcGrx+/bpatmypRx99VBMmTNCyZcs0cuRIXbt2za2+9957T23btlXnzp119epVzZ07V88995wWL17s9n2Ojo7WqFGjVK9ePY0ePVr+/v7atGmTVq9erebNm2vKlCl6/fXXlTt3bg0bNkySVKRIkXseB8CjDIB0mTlzppF020fFihXdXlOiRAnTrVs31/OqVauaNm3a3HY7ERER5ma/mosWLTKSzNixY93a//KXvxiHw2EOHz5sjDFm69atRpLp37+/W7/u3bsbSWbkyJGutpEjRxpJplOnTmm2d/ny5TRtc+bMMZLM+vXr06zjr3/9q6vt2rVrplixYsbhcJhx48a52i9cuGCCgoLcxuRmduzYYSSZl156ya39jTfeMJLM6tWrXW3dunUzuXLluu36Ul2/ft00aNDAFClSxJw7d85EREQYPz8/s3nz5nS9PlXqz0JcXJyrrUSJEkaS+eGHH1xty5cvN5JMUFCQOX78uKv9448/NpLMmjVr3PZDknn99dddbU6n07Rp08b4+/ubX3/91dV+4/fm6tWrplKlSqZJkyautkOHDhkfHx/Tvn17c/36dbf+TqfT9XXFihVNo0aNLO0/kJk49QNYNHXqVMXGxqZ5VKlS5Y6vzZs3r/bu3atDhw5Z3u4333wjX19f9e3b16194MCBMsZo6dKlkqRly5ZJkuuv91Svv/76Ldf9yiuvpGkLCgpyff3777/r3LlzevTRRyVJ27ZtS9P/pZdecn3t6+urWrVqyRijXr16udrz5s2rcuXK6ejRo7esRfpjXyUpMjLSrX3gwIGSpCVLltz29bfi4+OjWbNmKSkpSa1atdK0adMUFRWlWrVq3dX6blShQgXVrVvX9bxOnTqSpCZNmqh48eJp2m82Dn369HF97XA41KdPH129elUrV650tf/5e3PhwgUlJCTosccec/u+LFq0SE6nUyNGjEgzoZu5NbifcOoHsKh27do3fWPLly/fTU8J/dno0aP19NNP66GHHlKlSpXUsmVLdenSJV0h5/jx4woNDVWePHnc2h9++GHX8tR/fXx8VKpUKbd+4eHht1z3jX0l6fz584qOjtbcuXN19uxZt2UJCQlp+v/5jViSQkJCFBgYqIIFC6Zpv3Gey41S9+HGmosWLaq8efO69vVulClTRqNGjdKgQYNUqVIlDR8+/K7XdaObjYEkhYWF3bT9woULbu0+Pj4qXbq0W9tDDz0kSW7zYRYvXqyxY8dqx44daebspDpy5Ih8fHxUoUKFu9wbwB44ogJkooYNG+rIkSP69NNPValSJf39739XjRo1XPMrvOXPf6Gnev755/W3v/1Nr7zyihYsWKAVK1a4jtY4nc40/X19fdPVJinN5NBbyai//FMnk546deqOocmKW+3vvY7Dn3377bdq27atAgMDNW3aNH3zzTeKjY3VCy+8cFfrA+yOoAJksvz586tHjx6aM2eOTp48qSpVqrhdiXOrN+cSJUro1KlTunjxolv7Tz/95Fqe+q/T6VRcXJxbv8OHD6e7xgsXLmjVqlUaMmSIoqOj1b59ez3xxBNp/trPKKn7cOMpsl9++UXx8fGufb0bH330kWJjY/XWW2/p6tWr6t27972W6zFOpzPN6aCDBw9K+uMKHUmaP3++AgMDtXz5cvXs2VOtWrVSs2bN0qyrTJkycjqd2rdv3223yWkg2B1BBchEN/71njt3boWHh7sdvs+VK5ckKT4+3q1v69atdf36dX344Ydu7e+++64cDodatWolSWrRooWkP27k9WcffPBBuutMPQJw41/oU6ZMSfc67kXr1q1vur3JkydL0m2vYLqduLg4DRo0SM8++6yGDh2qiRMn6uuvv9Y//vGPe6rXk/78/TXG6MMPP1SOHDnUtGlTSX98bxwOh65fv+7qd+zYMS1atMhtPe3atZOPj49Gjx6d5gjYn7+vuXLlSvOzBtgJc1SATFShQgU9/vjjqlmzpvLnz68tW7boyy+/dJtAWbNmTUlS37591aJFC/n6+qpjx4566qmn1LhxYw0bNkzHjh1T1apVtWLFCn311Vfq37+/ypQp43r9s88+qylTpui3335zXZ6c+pd5ev6CDg4OVsOGDTVhwgSlpKTowQcf1IoVK9IcpckoVatWVbdu3fTJJ58oPj5ejRo10o8//qjZs2erXbt2aty4seV1GmPUs2dPBQUFafr06ZKk3r17a/78+erXr5+aNWum0NBQT++KJYGBgVq2bJm6deumOnXqaOnSpVqyZImGDh2qQoUKSfojpE2ePFktW7bUCy+8oLNnz2rq1KkKDw/Xrl27XOsKDw/XsGHDNGbMGD322GN65plnFBAQoM2bNys0NFQxMTGS/vh5mT59usaOHavw8HAVLlxYTZo08cr+AzflteuNgPtM6iWpt7qUtVGjRne8PHns2LGmdu3aJm/evCYoKMiUL1/evPXWW+bq1auuPteuXTOvv/66KVSokHE4HG6XKl+8eNEMGDDAhIaGmhw5cpiyZcuad955x+1yU2OMuXTpkomIiDD58+c3uXPnNu3atTMHDhwwktwuF069tPjPl76m+u9//2vat29v8ubNa0JCQsxzzz1nTp06dctLnG9cx60uG77ZON1MSkqKiY6ONqVKlTI5cuQwYWFhJioqyvz+++/p2s6N3nvvPSPJzJ8/3639xIkTJjg42LRu3fqO60h1q8uTb3bpuSQTERHh1hYXF2ckmXfeeSfNfhw5csQ0b97c5MyZ0xQpUsSMHDkyzeXFM2bMMGXLljUBAQGmfPnyZubMma7vw40+/fRTU716dRMQEGDy5ctnGjVqZGJjY13Lz5w5Y9q0aWPy5MljJHGpMmzHYQyzr4DsYMeOHapevbr++c9/qnPnzt4uBzfo3r27vvzySyUlJXm7FMBWmKMCZEFXrlxJ0zZlyhT5+Pjc8Y6wAGAnzFEBsqAJEyZo69ataty4sfz8/LR06VItXbpUf/3rX9Pc0wP/k5SUdMcjGoUKFbrl5cYAPI+gAmRB9erVU2xsrMaMGaOkpCQVL15co0aNcn2eC25u4sSJio6Ovm2fuLg416XCADIec1QA4P87evToHW/v36BBAwUGBmZSRQAIKgAAwLaYTAsAAGzrvp6j4nQ6derUKeXJk4fbQAMAcJ8wxujixYsKDQ1N8+neN7qvg8qpU6e4ggEAgPvUyZMnVaxYsdv2ua+DSurH3Z88eVLBwcFergYAAKRHYmKiwsLCXO/jt3NfB5XU0z3BwcEEFQAA7jPpmbbBZFoAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbBBUAAGBbXg0qJUuWlMPhSPOIiIjwZlkAAMAmvPpZP5s3b9b169ddz/fs2aMnnnhCzz33nBerAgAAduHVoFKoUCG35+PGjVOZMmXUqFEjL1UEAADsxDafnnz16lX985//VGRk5C0/TTE5OVnJycmu54mJiZlVHgAA8ALbBJVFixYpPj5e3bt3v2WfmJgYRUdHZ15RAGBRySFLvF2CZcfGtfF2CcAt2eaqnxkzZqhVq1YKDQ29ZZ+oqCglJCS4HidPnszECgEAQGazxRGV48ePa+XKlVqwYMFt+wUEBCggICCTqgIAAN5miyMqM2fOVOHChdWmDYcfAQDA/3g9qDidTs2cOVPdunWTn58tDvAAAACb8HpQWblypU6cOKGePXt6uxQAAGAzXj+E0bx5cxljvF0GAACwIa8fUQEAALgVggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtggoAALAtrweVn3/+WS+++KIKFCigoKAgVa5cWVu2bPF2WQAAwAb8vLnxCxcuqH79+mrcuLGWLl2qQoUK6dChQ8qXL583ywIAADbh1aAyfvx4hYWFaebMma62UqVKebEiAABgJ1499fP111+rVq1aeu6551S4cGFVr15df/vb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oAIAAGyLoGLB9evXNXz4cJUqVUpBQUEqU6aMxowZ4/ahSsYYjRgxQg888ICCgoLUrFkzHTp0yG0958+fV+fOnRUcHKy8efOqV69eSkpKyuzdSbf169frqaeeUmhoqBwOhxYtWuS23FP7vGvXLj322GMKDAxUWFiYJkyYkNG7ZsntxiElJUWDBw9W5cqVlStXLoWGhqpr1646deqU2zru93G408/Cn73yyityOByaMmWKW/v9PgZS+sZh//79atu2rUJCQpQrVy498sgjOnHihGv577//roiICBUoUEC5c+fWs88+m+Yu3SdOnFCbNm2UM2dOFS5cWIMGDdK1a9cyevfS5U5jkJSUpD59+qhYsWIKCgpShQoV9NFHH7n1ud/HICYmRo888ojy5MmjwoULq127djpw4IBbH0/t49q1a1WjRg0FBAQoPDxcs2bNyujdsw+DdHvrrbdMgQIFzOLFi01cXJyZN2+eyZ07t3nvvfdcfcaNG2dCQkLMokWLzM6dO03btm1NqVKlzJUrV1x9WrZsaapWrWo2btxovv32WxMeHm46derkjV1Kl2+++cYMGzbMLFiwwEgyCxcudFvuiX1OSEgwRYoUMZ07dzZ79uwxc+bMMUFBQebjjz/OrN28o9uNQ3x8vGnWrJn54osvzE8//WQ2bNhgateubWrWrOm2jvt9HO70s5BqwYIFpmrVqiY0NNS8++67bsvu9zEw5s7jcPjwYZM/f34zaNAgs23bNnP48GHz1VdfmV9++cXV55VXXjFhYWFm1apVZsuWLebRRx819erVcy2/du2aqVSpkmnWrJnZvn27+eabb0zBggVNVFRUZu3mbd1pDF5++WVTpkwZs2bNGhMXF2c+/vhj4+vra7766itXn/t9DFq0aGFmzpxp9uzZY3bs2GFat25tihcvbpKSklx9PLGPR48eNTlz5jSRkZFm37595oMPPjC+vr5m2bJlmbq/3kJQsaBNmzamZ8+ebm3PPPOM6dy5szHGGKfTaYoWLWreeecd1/L4+HgTEBBg5syZY4wxZt++fUaS2bx5s6vP0qVLjcPhMD///HMm7MW9ufE/JE/t87Rp00y+fPlMcnKyq8/gwYNNuXLlMniP7s7t3qRT/fjjj0aSOX78uDEm643Drcbgv//9r3nwwQfNnj17TIkSJdyCSlYbA2NuPg4dOnQwL7744i1f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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAGzCAYAAAABsTylAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAwEUlEQVR4nO3dd3zT5eL+/ystbSnQFsoUKUPKYQ8BlaGogKCignoEjigUEFGKBeoAVLZaQBlHRT2oDPm4qAgOBGQJiOy9pEzhMAQstCxLae7fH/6a7wlpoe+akDfk9Xw88pDcuZNcyd3KxXskDmOMEQAAgA0F+TsAAABAbigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqwGVUrFhRcXFx/o5x3XvzzTd10003KTg4WPXq1fN3nOuKw+HQ0KFD/R0DyDeKCgLGlClT5HA4tHbt2hxvv+uuu1SrVq2//Tw//PADfzFY8OOPP+qll15S06ZNNXnyZL3xxhv+jnTN4WcO17MC/g4A2NnOnTsVFGStz//www+aMGECf3Hk0aJFixQUFKSPP/5YoaGh/o5zTbrcz9z58+dVoAD/q8e1iy0qwGWEhYUpJCTE3zEsOXv2rL8jWHLs2DGFh4dTUnykYMGCFBVc0ygqwGVceoxKZmamhg0bpipVqqhgwYIqXry4br/9ds2fP1+SFBcXpwkTJkj669iA7Eu2s2fP6vnnn1dMTIzCwsJUtWpVvfXWW7r0S8zPnz+vhIQElShRQhEREXrooYd06NAhj+MNhg4dKofDoe3bt+vxxx9XsWLFdPvtt0uSNm/erLi4ON10000qWLCgypQpo27duumPP/5we67sx0hJSdETTzyhqKgolSxZUoMGDZIxRgcPHlTbtm0VGRmpMmXKaMyYMXl67y5evKgRI0aocuXKCgsLU8WKFfXyyy8rIyPDNcfhcGjy5Mk6e/as672aMmVKro+5bNkyPfbYYypfvrzCwsIUExOjfv366fz5827z4uLiVKRIEe3du1etW7dW4cKFVbZsWQ0fPtzjvfb2mkjSoUOH1K1bN5UuXVphYWGqWbOmJk2a5PF6MjIyNGTIEMXGxrpez0svveT2Hl3JlX7mcvuZ+Tvr7Y3cQF5RsxFw0tLSdOLECY/xzMzMK9536NChSkpK0lNPPaVbb71V6enpWrt2rdavX6977rlHPXv21OHDhzV//nxNmzbN7b7GGD300ENavHixunfvrnr16mnevHl68cUXdejQIY0bN841Ny4uTtOnT9eTTz6pRo0aacmSJWrTpk2uuR577DFVqVJFb7zxhusv2Pnz52vv3r3q2rWrypQpo23btmnixInatm2bVq5c6faXmSR16NBB1atX18iRIzV79my99tprio6O1n/+8x81b95co0aN0qeffqoXXnhBt9xyi5o1a3bZ9+qpp57S1KlT9c9//lPPP/+8Vq1apaSkJO3YsUMzZ86UJE2bNk0TJ07U6tWr9dFHH0mSmjRpkutjJicn69y5c3r22WdVvHhxrV69Wu+8847++9//Kjk52W1uVlaW7r33XjVq1EijR4/W3LlzNWTIEF28eFHDhw/32Zr8/vvvatSokRwOh3r37q2SJUtqzpw56t69u9LT09W3b19JktPp1EMPPaSff/5ZTz/9tKpXr64tW7Zo3LhxSklJ0axZsy77/ma73M/c5eR3vb2VG8gzAwSIyZMnG0mXvdSsWdPtPhUqVDBdunRxXa9bt65p06bNZZ8nPj7e5PSrNWvWLCPJvPbaa27j//znP43D4TC7d+82xhizbt06I8n07dvXbV5cXJyRZIYMGeIaGzJkiJFk/vWvf3k837lz5zzGPv/8cyPJLF261OMxnn76adfYxYsXTbly5YzD4TAjR450jZ88edKEh4e7vSc52bhxo5FknnrqKbfxF154wUgyixYtco116dLFFC5c+LKPd7nXlJSUZBwOh/ntt9/cHlOSee6551xjTqfTtGnTxoSGhprjx48bY3yzJt27dzc33HCDOXHihNvcjh07mqioKNdrmDZtmgkKCjLLli1zm/fBBx8YSWb58uV5ek+Myf1nzhiT689Mftfbm7mBvGDXDwLOhAkTNH/+fI9LnTp1rnjfokWLatu2bdq1a5fl5/3hhx8UHByshIQEt/Hnn39exhjNmTNHkjR37lxJUq9evdzmPffcc7k+9jPPPOMxFh4e7vrzn3/+qRMnTqhRo0aSpPXr13vMf+qpp1x/Dg4OVsOGDWWMUffu3V3jRYsWVdWqVbV3795cs0h/vVZJSkxMdBt//vnnJUmzZ8++7P1z87+v6ezZszpx4oSaNGkiY4w2bNjgMb93796uP2dv4bhw4YIWLFjgyunNNTHGaMaMGXrwwQdljNGJEydcl9atWystLc313icnJ6t69eqqVq2a27zmzZtLkhYvXpyv9yiv8rve/s6NwMOuHwScW2+9VQ0bNvQYL1asWI67hP7X8OHD1bZtW/3jH/9QrVq1dO+99+rJJ5/MU8n57bffVLZsWUVERLiNV69e3XV79n+DgoJUqVIlt3mxsbG5PvalcyUpNTVVw4YN0xdffKFjx4653ZaWluYxv3z58m7Xo6KiVLBgQZUoUcJj/NLjXC6V/RouzVymTBkVLVrU9VqtOnDggAYPHqxvv/1WJ0+edLvt0tcUFBSkm266yW3sH//4hyRp//79rpzeXJPjx4/r1KlTmjhxoiZOnJjja8hei127dmnHjh0qWbLkZef5Sn7X29+5EXgoKoAFzZo10549e/TNN9/oxx9/1EcffaRx48bpgw8+cPsX6tX2v1sasrVv316//PKLXnzxRdWrV09FihSR0+nUvffeK6fT6TE/ODg4T2OSPA40zc2lx8H8HVlZWbrnnnuUmpqq/v37q1q1aipcuLAOHTqkuLi4HF/T1Zad4YknnlCXLl1ynJNdap1Op2rXrq2xY8fmOC8mJsY3If9/+V1vf+dG4KGoABZFR0era9eu6tq1q86cOaNmzZpp6NChrqKS21/OFSpU0IIFC3T69Gm3f8H/+uuvrtuz/+t0OrVv3z5VqVLFNW/37t15znjy5EktXLhQw4YN0+DBg13j+dlllR/Zr2HXrl2urRPSXweanjp1yvVardiyZYtSUlI0depUde7c2TWefcbVpZxOp/bu3evaiiJJKSkpkv46mys7pzfXpGTJkoqIiFBWVpZatmx52ddTuXJlbdq0SS1atPjbhc6bhfBKvJkbyAuOUQEsuHSXR5EiRRQbG+t2WmbhwoUlSadOnXKbe//99ysrK0vvvvuu2/i4cePkcDh03333SZJat24tSXrvvffc5r3zzjt5zpn9L+NLt3yMHz8+z4/xd9x///05Pl/2v8IvdwZTbnJ6TcYY/fvf/871Pv/7Xhtj9O677yokJEQtWrRw5fTmmgQHB+vRRx/VjBkztHXrVo88x48fd/25ffv2OnTokD788EOPeefPn7f0eTi5/cz5gjdzA3nBFhXAgho1auiuu+5SgwYNFB0drbVr1+qrr75yO2izQYMGkqSEhAS1bt1awcHB6tixox588EHdfffdeuWVV7R//37VrVtXP/74o7755hv17dtXlStXdt3/0Ucf1fjx4/XHH3+4ToXN3hqQl3/FRkZGqlmzZho9erQyMzN144036scff9S+fft88K54qlu3rrp06aKJEyfq1KlTuvPOO7V69WpNnTpV7dq109133235MatVq6bKlSvrhRde0KFDhxQZGakZM2Z4HKuSrWDBgpo7d666dOmi2267TXPmzNHs2bP18ssvu46v8MWajBw5UosXL9Ztt92mHj16qEaNGkpNTdX69eu1YMECpaamSpKefPJJTZ8+Xc8884wWL16spk2bKisrS7/++qumT5+uefPm5XgsVU5y+5nzBW/mBvLEL+caAX6QfXrymjVrcrz9zjvvvOLpya+99pq59dZbTdGiRU14eLipVq2aef31182FCxdccy5evGiee+45U7JkSeNwONxOGz19+rTp16+fKVu2rAkJCTFVqlQxb775pnE6nW7Pe/bsWRMfH2+io6NNkSJFTLt27czOnTuNJLfTR7NPNc0+3fZ//fe//zUPP/ywKVq0qImKijKPPfaYOXz4cK6nq176GLmdNpzT+5STzMxMM2zYMFOpUiUTEhJiYmJizMCBA82ff/6Zp+fJyfbt203Lli1NkSJFTIkSJUyPHj3Mpk2bjCQzefJkj8fcs2ePadWqlSlUqJApXbq0GTJkiMnKynJ7TG+viTHG/P777yY+Pt7ExMSYkJAQU6ZMGdOiRQszceJEt3kXLlwwo0aNMjVr1jRhYWGmWLFipkGDBmbYsGEmLS0tT++JMZf/mfPFensrN5AXDmPyeFQcAL/auHGjbr75Zv3f//2fOnXq5O84thYXF6evvvpKZ86c8enzsCaA73GMCmBDl34kvPTX8R5BQUFX/ERY+AZrAvgHx6gANjR69GitW7dOd999twoUKKA5c+Zozpw5evrppzn900/8sSZpaWk5FqT/VaZMGZ88N2AXFBXAhpo0aaL58+drxIgROnPmjMqXL6+hQ4fqlVde8Xe0gOWPNenTp4+mTp162Tnsvcf1jmNUAMCmtm/frsOHD192zpU+rwW41lFUAACAbXEwLQAAsK1r+hgVp9Opw4cPKyIigo9yBgDgGmGM0enTp1W2bFkFBV1+m8k1XVQOHz7MGRAAAFyjDh48qHLlyl12zjVdVLK/ROzgwYOKjIz0cxoAAJAX6enpiomJcfsy0Nxc00Ule3dPZGQkRQUAgGtMXg7b4GBaAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWwX8HQAAgEBRccBsf0ewbP/INn59fraoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA26KoAAAA2/JrUcnKytKgQYNUqVIlhYeHq3LlyhoxYoSMMf6MBQAAbKKAP5981KhRev/99zV16lTVrFlTa9euVdeuXRUVFaWEhAR/RgMAADbg16Lyyy+/qG3btmrTpo0kqWLFivr888+1evXqHOdnZGQoIyPDdT09Pf2q5AQAAP7h110/TZo00cKFC5WSkiJJ2rRpk37++Wfdd999Oc5PSkpSVFSU6xITE3M14wIAgKvMr1tUBgwYoPT0dFWrVk3BwcHKysrS66+/rk6dOuU4f+DAgUpMTHRdT09Pp6wAAHAd82tRmT59uj799FN99tlnqlmzpjZu3Ki+ffuqbNmy6tKli8f8sLAwhYWF+SEpAADwB78WlRdffFEDBgxQx44dJUm1a9fWb7/9pqSkpByLCgAACCx+PUbl3LlzCgpyjxAcHCyn0+mnRAAAwE78ukXlwQcf1Ouvv67y5curZs2a2rBhg8aOHatu3br5MxYAALAJvxaVd955R4MGDVKvXr107NgxlS1bVj179tTgwYP9GQsAANiEX4tKRESExo8fr/Hjx/szBgAAsCm+6wcAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgWRQUAANgW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03799ddeCwcAAAKb5aJStGhRPfLII77IAgAA4MZyUZk8ebIvcgAAAHjg42UBAIBtWd6iUqlSpct+XsrevXv/ViAAAIBslotK37593a5nZmZqw4YNmjt3rl588UVv5QIAALBeVPr06ZPj+IQJE7R27dq/HQgArmUVB8z2dwTL9o9s4+8IQK68dozKfffdpxkzZnjr4QAAALxXVL766itFR0d76+EAAACs7/q5+eab3Q6mNcbo6NGjOn78uN577z2vhgMAAIHNclFp166d2/WgoCCVLFlSd911l6pVq+atXAAAANaLypAhQ3yRAwAAwAMf+AYAAGwrz1tUgoKCLvtBb5LkcDh08eLFvx0KAABAslBUZs6cmettK1as0Ntvvy2n0+mVUAAAAJKFotK2bVuPsZ07d2rAgAH67rvv1KlTJw0fPtyr4QAAQGDL1zEqhw8fVo8ePVS7dm1dvHhRGzdu1NSpU1WhQgVv5wMAAAHMUlFJS0tT//79FRsbq23btmnhwoX67rvvVKtWLV/lAwAAASzPu35Gjx6tUaNGqUyZMvr8889z3BUEAADgTXkuKgMGDFB4eLhiY2M1depUTZ06Ncd5X3/9tdfCAQCAwJbnotK5c+crnp4MAADgTXkuKlOmTPFhDAAAAE98Mi0AALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtigoAALAtvxaVpKQk3XLLLYqIiFCpUqXUrl077dy505+RAACAjfi1qCxZskTx8fFauXKl5s+fr8zMTLVq1Upnz571ZywAAGATBfz55HPnznW7PmXKFJUqVUrr1q1Ts2bN/JQKAADYhV+LyqXS0tIkSdHR0TnenpGRoYyMDNf19PT0q5ILAAD4h22KitPpVN++fdW0aVPVqlUrxzlJSUkaNmzYVU4GANe3igNm+zsCkCvbnPUTHx+vrVu36osvvsh1zsCBA5WWlua6HDx48ComBAAAV5sttqj07t1b33//vZYuXapy5crlOi8sLExhYWFXMRkAAPAnvxYVY4yee+45zZw5Uz/99JMqVarkzzgAAMBm/FpU4uPj9dlnn+mbb75RRESEjh49KkmKiopSeHi4P6MBAAAb8OsxKu+//77S0tJ011136YYbbnBdvvzyS3/GAgAANuH3XT8AAAC5sc1ZPwAAAJeiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANsq4O8AdlZxwGx/RwgI+0e28XeEgMDPM4BrEVtUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbdmiqEyYMEEVK1ZUwYIFddttt2n16tX+jgQAAGzA70Xlyy+/VGJiooYMGaL169erbt26at26tY4dO+bvaAAAwM/8XlTGjh2rHj16qGvXrqpRo4Y++OADFSpUSJMmTfJ3NAAA4GcF/PnkFy5c0Lp16zRw4EDXWFBQkFq2bKkVK1Z4zM/IyFBGRobrelpamiQpPT3dJ/mcGed88rhw56v18yV+NgAECl/8Pzr7MY0xV5zr16Jy4sQJZWVlqXTp0m7jpUuX1q+//uoxPykpScOGDfMYj4mJ8VlG+F7UeH8nAADkxpf/jz59+rSioqIuO8evRcWqgQMHKjEx0XXd6XQqNTVVxYsXl8Ph8GMy70lPT1dMTIwOHjyoyMhIf8cJaKyFfbAW9sFa2MO1vg7GGJ0+fVply5a94ly/FpUSJUooODhYv//+u9v477//rjJlynjMDwsLU1hYmNtY0aJFfRnRbyIjI6/JH77rEWthH6yFfbAW9nAtr8OVtqRk8+vBtKGhoWrQoIEWLlzoGnM6nVq4cKEaN27sx2QAAMAO/L7rJzExUV26dFHDhg116623avz48Tp79qy6du3q72gAAMDP/F5UOnTooOPHj2vw4ME6evSo6tWrp7lz53ocYBsowsLCNGTIEI9dXLj6WAv7YC3sg7Wwh0BaB4fJy7lBAAAAfuD3D3wDAADIDUUFAADYFkUFAADYFkUFAADYFkUFAADYFkXFD5KSknTLLbcoIiJCpUqVUrt27bRz5063OX/++afi4+NVvHhxFSlSRI8++qjHJ/ji77vSWqSmpuq5555T1apVFR4ervLlyyshIcH1hZjwnrz8XmQzxui+++6Tw+HQrFmzrm7QAJDXtVixYoWaN2+uwoULKzIyUs2aNdP58+f9kPj6lZe1OHr0qJ588kmVKVNGhQsXVv369TVjxgw/JfY+ioofLFmyRPHx8Vq5cqXmz5+vzMxMtWrVSmfPnnXN6devn7777jslJydryZIlOnz4sB555BE/pr4+XWktDh8+rMOHD+utt97S1q1bNWXKFM2dO1fdu3f3c/LrT15+L7KNHz/+uvl+LzvKy1qsWLFC9957r1q1aqXVq1drzZo16t27t4KC+GvFm/KyFp07d9bOnTv17bffasuWLXrkkUfUvn17bdiwwY/JvcjA744dO2YkmSVLlhhjjDl16pQJCQkxycnJrjk7duwwksyKFSv8FTMgXLoWOZk+fboJDQ01mZmZVzFZ4MltLTZs2GBuvPFGc+TIESPJzJw50z8BA0hOa3HbbbeZV1991Y+pAlNOa1G4cGHzySefuM2Ljo42H3744dWO5xNUXxvI3o0QHR0tSVq3bp0yMzPVsmVL15xq1aqpfPnyWrFihV8yBopL1yK3OZGRkSpQwO8f7Hxdy2ktzp07p8cff1wTJkzI8YtL4RuXrsWxY8e0atUqlSpVSk2aNFHp0qV155136ueff/ZnzICQ0+9FkyZN9OWXXyo1NVVOp1NffPGF/vzzT911111+SuldFBU/czqd6tu3r5o2bapatWpJ+mt/Y2hoqMc3Q5cuXVpHjx71Q8rAkNNaXOrEiRMaMWKEnn766aucLrDkthb9+vVTkyZN1LZtWz+mCyw5rcXevXslSUOHDlWPHj00d+5c1a9fXy1atNCuXbv8Gfe6ltvvxfTp05WZmanixYsrLCxMPXv21MyZMxUbG+vHtN7DPwn9LD4+Xlu3buVfIjZwpbVIT09XmzZtVKNGDQ0dOvTqhgswOa3Ft99+q0WLFl0/+92vETmthdPplCT17NnT9QWyN998sxYuXKhJkyYpKSnJL1mvd7n9P2rQoEE6deqUFixYoBIlSmjWrFlq3769li1bptq1a/sprRf5e99TIIuPjzflypUze/fudRtfuHChkWROnjzpNl6+fHkzduzYq5gwcOS2FtnS09NN48aNTYsWLcz58+evcrrAktta9OnTxzgcDhMcHOy6SDJBQUHmzjvv9E/Y61xua7F3714jyUybNs1tvH379ubxxx+/mhEDRm5rsXv3biPJbN261W28RYsWpmfPnlczos+w68cPjDHq3bu3Zs6cqUWLFqlSpUputzdo0EAhISFauHCha2znzp06cOCAGjdufLXjXteutBbSX1tSWrVqpdDQUH377bcqWLCgH5Je/660FgMGDNDmzZu1ceNG10WSxo0bp8mTJ/sh8fXrSmtRsWJFlS1b1uM02ZSUFFWoUOFqRr3uXWktzp07J0keZ1sFBwe7tnxd8/xakwLUs88+a6KiosxPP/1kjhw54rqcO3fONeeZZ54x5cuXN4sWLTJr1641jRs3No0bN/Zj6uvTldYiLS3N3HbbbaZ27dpm9+7dbnMuXrzo5/TXl7z8XlxKnPXjE3lZi3HjxpnIyEiTnJxsdu3aZV599VVTsGBBs3v3bj8mv/5caS0uXLhgYmNjzR133GFWrVpldu/ebd566y3jcDjM7Nmz/ZzeOygqfiApx8vkyZNdc86fP2969eplihUrZgoVKmQefvhhc+TIEf+Fvk5daS0WL16c65x9+/b5Nfv1Ji+/Fzndh6LifXldi6SkJFOuXDlTqFAh07hxY7Ns2TL/BL6O5WUtUlJSzCOPPGJKlSplChUqZOrUqeNxuvK1zGGMMb7cYgMAAJBfHKMCAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABs6/8DhagaJnXz3CMAAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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N3v37jW7du0yX3zxhWt7enq6qVGjhmnTpo1JSEgwixcvNpGRkWb48OGuPocOHTIFCxY0gwYNMrt37zZTpkwxgYGBZunSpf4Ykpty5cqZMWPGuL1+KSkpru12fu2uNmDAANOuXTsjySQkJLja7T6+SZMmmQ0bNpjExESzfv1607hxY9O4cWPXdjuPb8mSJaZnz55m2bJl5uDBg2bhwoUmOjraDB482NXHzuMbOXKkmTRpkhk0aJAJDw/32G733y3XmjNnjgkODjYzZ840u3btMn369DERERHm9OnT/i4tV4sXLzYjRoww8+fPN5LMV1995bZ93LhxJjw83CxYsMBs27bNdOzY0VSoUMH8/vvvrj4PPPCAqV27ttm4caP59ttvTWxsrOnSpYulOggz+SgtLc1ERUWZMWPGuNo++OADU7RoUZOamupqGzp0qKlSpYrr/hNPPGE6dOjgtq9GjRqZvn375n3RObhy5YopXbq0+eijj3Lss3jxYhMQEGBOnTrlaps+fboJCwtzjffVV1811atXd3vck08+adq2bZs3hVtQrlw589577+W43a6v3dUWL15sqlatanbt2uURZm6H8V1t4cKFxuFwmLS0NGPM7Te+8ePHmwoVKrju3w7jmzVrVrZhxu6/W67VsGFD069fP9f9jIwMU6pUKRMfH+/Hqqy7NsxkZmaakiVLmnfffdfVdvHiReN0Os3nn39ujDFm9+7dRpLZtGmTq8+SJUuMw+Ewv/zyi9fH5mOmfPR///d/OnfunNtXNWzYsEHNmjVTcHCwq61t27bau3evLly44OrTpk0bt321bdtWGzZsyJ/Cs/HTTz/pl19+UUBAgOrWras77rhD7dq1086dO119NmzYoJo1a7pdzblt27ZKTk7Wrl27XH1utbFdbdy4cSpevLjq1q2rd9991+00tl1fuyynT59Wnz599Mknn6hgwYIe2+0+vqudP39en332mZo0aaKgoCBJt9f4JCkpKUnFihVz3b/dxne12+F3S5a0tDRt2bLFrdaAgAC1adPmlqvVqsOHD+vUqVNuYwsPD1ejRo1cY9uwYYMiIiLUoEEDV582bdooICBAP/zwg9fHIszkoxkzZqht27YqU6aMq+3UqVMeX92Qdf/UqVPX7ZO13R8OHTokSRo9erRef/11ff311ypatKhatGih8+fPS7q5sSUnJ+v333/P62Fc14ABAzRnzhytXr1affv21dixY/Xqq6+6ttv1tZP+/By7Z8+eev75591+iVzNzuPLMnToUBUqVEjFixfX0aNHtXDhQte222F8WQ4cOKApU6aob9++rrbbaXzXsvvvlqudPXtWGRkZtnwdcpNV//XGdurUKUVHR7ttL1CggIoVK2Zp/ISZGzBs2LAcJ/Zm3X7++We3xxw/flzLli1T7969/VS1d7wdW2ZmpiRpxIgReuyxx1S/fn3NmjVLDodDc+fO9fMocmbltRs0aJBatGihWrVq6fnnn9fEiRM1ZcoUpaam+nkUOfN2fFOmTNGlS5c0fPhwf5dsidV/e0OGDFFCQoKWL1+uwMBAde/eXeYW/gaXG/nd8ssvv+iBBx7Q448/rj59+vip8tzdyNgAb/n9iybtaPDgwerZs+d1+1SsWNHt/qxZs1S8eHF17NjRrb1kyZI6ffq0W1vW/ZIlS163T9Z2X/J2bCdPnpQkVatWzdXudDpVsWJFHT16VNKfdV87I9/bsYWFhSk0NPSmxpKdG3ntsjRq1Ejp6elKTExUlSpVbrnXTvJ+fKtWrdKGDRs8vvStQYMG6tq1qz7++GNbjy9LZGSkIiMjdeedd+quu+5STEyMNm7cqMaNG98W4ztx4oRatmypJk2a6B//+Idbv1ttfDfzb+9at+LvlhsVGRmpwMDAfP05yy9Z9Z8+fVp33HGHq/306dOqU6eOq8+ZM2fcHpeenq7z589bG//NTvhB7jIzM02FChXcVhpkyZqklzUp0Rhjhg8f7jFJ78EHH3R7XOPGjf06SS8pKck4nU63CcBpaWkmOjratVoia5Le1TPyP/zwQxMWFmb++OMPY8yfk/Rq1Kjhtu8uXbrckpP0Pv30UxMQEGDOnz9vjLHva2eMMUeOHDE7duxw3ZYtW2YkmXnz5pljx44ZY+w9vuwcOXLESDKrV682xth/fMePHzeVK1c2nTt3Nunp6R7b7T4+Y3KfAHy7/G5p2LCh6d+/v+t+RkaGKV269G0zAXjChAmutqz3jmsnAG/evNnVZ9myZZYnABNm8sE333xjJJk9e/Z4bLt48aIpUaKE6datm9m5c6eZM2eOKViwoMfyyQIFCpgJEyaYPXv2mFGjRt0SyycHDhxoSpcubZYtW2Z+/vln07t3bxMdHe16s89aPnn//febrVu3mqVLl5qoqKhsl08OGTLE7Nmzx0ybNu2WWD75/fffm/fee89s3brVHDx40Hz66acmKirKdO/e3dXHzq/dtQ4fPuyxmsnO49u4caOZMmWKSUhIMImJiWblypWmSZMmplKlSq43OzuP7/jx4yY2Nta0bt3aHD9+3O3yAVnsPL4jR46YhIQEExcXZwoXLmwSEhJMQkKCuXTpkjHG3r9bsjNnzhzjdDrN7Nmzze7du81zzz1nIiIi3FZr3aouXbrken0kmUmTJpmEhARz5MgRY8yfS7MjIiLMwoULzfbt283DDz+c7dLsunXrmh9++MF89913pnLlyizNvhV16dLFNGnSJMft27ZtM02bNjVOp9OULl3ajBs3zqPP//7v/5o777zTBAcHm+rVq5tFixblZcleSUtLM4MHDzbR0dGmSJEipk2bNmbnzp1ufRITE027du1MaGioiYyMNIMHDzZXrlxx67N69WpTp04dExwcbCpWrGhmzZqVj6PI3pYtW0yjRo1MeHi4CQkJMXfddZcZO3as640wi11fu2tlF2aMse/4tm/fblq2bGmKFStmnE6nKV++vHn++efN8ePH3frZdXyzZs0ykrK9Xc2u4+vRo0e2Y8s6q2aMfX+35GTKlCmmbNmyJjg42DRs2NBs3LjR3yV5ZfXq1dm+Vj169DDG/Hl25o033jAlSpQwTqfTtG7d2uzdu9dtH+fOnTNdunQxhQsXNmFhYaZXr16u4OothzG38Gw4AACAXLCaCQAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2BphBgAA2Nr/A9XXdFiRv490AAAAAElFTkSuQmCC",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAGzCAYAAAABsTylAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA0eElEQVR4nO3dd3xUVf7/8fckpAkpRAgRiUko0ouCqKB0RUUF3VVhEUlE5CvRALEAupSAkoCAWRWxElgsuNgVaSLgiigdFJAaBEU6JIRggMz5/bEP5ucwAXLDTOZiXs/HYx4y55459zMnB3nnlhmHMcYIAADAhgL8XQAAAMDZEFQAAIBtEVQAAIBtEVQAAIBtEVQAAIBtEVQAAIBtEVQAAIBtEVQAAIBtEVQAAIBtEVRQriQkJCgpKcnfZfzlPf/886pZs6YCAwPVrFkzf5fjdfn5+XrooYcUGxsrh8OhgQMHltm+27Vrp3bt2rme79ixQw6HQ1OnTvXK+ElJSUpISPDKWIA3EFRw0Zo6daocDodWrFhR7PZ27dqpUaNGF7yfL7/8UiNHjrzgccqLefPm6amnnlLr1q2VnZ2tMWPGlNm+CwoKNHLkSC1atMin+xkzZoymTp2qRx55RNOnT1evXr18uj9v2717t0aOHKk1a9b4uxTgvCr4uwCgLG3atEkBAdby+ZdffqlJkyYRVkro66+/VkBAgN566y0FBweX6b4LCgqUnp4uSW5HHbzt66+/1nXXXacRI0b4bB9nM2/evAseY/fu3UpPT1dCQoLHEa833nhDTqfzgvcBeAtHVFCuhISEKCgoyN9lWHLs2DF/l2DJvn37FBYWVuYhpSzt27dPUVFRFzyOMUbHjx+39Jrg4GCfzm1QUJBCQkJ8Nj5gFUEF5cqZ16icPHlS6enpqlOnjkJDQ3XppZfqhhtu0Pz58yX973z9pEmTJEkOh8P1OO3YsWN6/PHHFRcXp5CQENWtW1fjx4/XmV9Kfvz4caWmpqpKlSoKDw/XnXfeqd9++00Oh8PtSM3IkSPlcDi0YcMG/eMf/1DlypV1ww03SJLWrVunpKQk1axZU6GhoYqNjdWDDz6ogwcPuu3r9BibN2/W/fffr8jISFWtWlXDhg2TMUa7du1S165dFRERodjYWE2YMKFEc3fq1CmNHj1atWrVUkhIiBISEvT000+rsLDQ1cfhcCg7O1vHjh1zzdX5rp2YOXOmmjdvrrCwMFWpUkX333+/fvvtN7c+Z16Xcdqfr6fYsWOHqlatKklKT0937d/KkbB9+/apT58+qlatmkJDQ9W0aVNNmzbNtX3RokVyOBzKycnRrFmzXPvYsWNHicZPSEjQ7bffrrlz56pFixYKCwvTa6+9JknKzs5Whw4dFBMTo5CQEDVo0ECTJ0/2GONsc1FSixYt0jXXXCNJSk5O9vg5nXmNyulrYMaPH69JkyapZs2auuSSS3TzzTdr165dMsZo9OjRqlGjhsLCwtS1a1cdOnTIY7+zZ8/WjTfeqIoVKyo8PFxdunTR+vXrS/0+UH5w6gcXvdzcXB04cMCj/eTJk+d97ciRI5WRkaGHHnpILVu2VF5enlasWKFVq1bppptuUr9+/bR7927Nnz9f06dPd3utMUZ33nmnFi5cqD59+qhZs2aaO3eunnzySf3222964YUXXH2TkpL0n//8R7169dJ1112nxYsXq0uXLmet65577lGdOnU0ZswYV+iZP3++tm/fruTkZMXGxmr9+vV6/fXXtX79en3//fduAUqS7rvvPtWvX1+ZmZmaNWuWnn32WUVHR+u1115Thw4dNHbsWL3zzjt64okndM0116hNmzbnnKuHHnpI06ZN09///nc9/vjj+uGHH5SRkaGNGzfq448/liRNnz5dr7/+upYtW6Y333xTktSqVauzjjl16lQlJyfrmmuuUUZGhvbu3at//etfWrJkiVavXm3pqEXVqlU1efJkPfLII7rrrrt09913S5KaNGlSotcfP35c7dq109atW/Xoo48qMTFRM2fOVFJSko4cOaIBAwaofv36mj59ugYNGqQaNWro8ccfd+27pDZt2qQePXqoX79+6tu3r+rWrStJmjx5sho2bKg777xTFSpU0Oeff67+/fvL6XQqJSWlxOOfT/369TVq1CgNHz5cDz/8sG688UZJ5/45SdI777yjEydO6LHHHtOhQ4c0btw43XvvverQoYMWLVqkwYMHa+vWrXrppZf0xBNPaMqUKa7XTp8+Xb1791bnzp01duxYFRQUaPLkybrhhhu0evVqLt7FuRngIpWdnW0knfPRsGFDt9fEx8eb3r17u543bdrUdOnS5Zz7SUlJMcX9Vfnkk0+MJPPss8+6tf/97383DofDbN261RhjzMqVK40kM3DgQLd+SUlJRpIZMWKEq23EiBFGkunRo4fH/goKCjza3nvvPSPJfPPNNx5jPPzww662U6dOmRo1ahiHw2EyMzNd7YcPHzZhYWFuc1KcNWvWGEnmoYcecmt/4oknjCTz9ddfu9p69+5tKlaseM7xjDHmxIkTJiYmxjRq1MgcP37c1f7FF18YSWb48OGutrZt25q2bdt6jNG7d28THx/ver5//36POS2prKwsI8m8/fbbbjVef/31plKlSiYvL8/VHh8ff951U5z4+HgjycyZM8djW3E/386dO5uaNWu6tZ05Fzk5OUaSyc7OLnEdy5cvP+trzpzT0+NXrVrVHDlyxNU+dOhQI8k0bdrUnDx50tXeo0cPExwcbP744w9jjDFHjx41UVFRpm/fvm772bNnj4mMjPRoB87EqR9c9CZNmqT58+d7PErym3RUVJTWr1+vLVu2WN7vl19+qcDAQKWmprq1P/744zLGaPbs2ZKkOXPmSJL69+/v1u+xxx4769j/93//59EWFhbm+vMff/yhAwcO6LrrrpMkrVq1yqP/Qw895PpzYGCgWrRoIWOM+vTp42qPiopS3bp1tX379rPWIv3vvUpSWlqaW/vpIwqzZs065+uLs2LFCu3bt0/9+/dXaGioq71Lly6qV69eqca8EF9++aViY2PVo0cPV1tQUJBSU1OVn5+vxYsXe2U/iYmJ6ty5s0f7n3++p48Stm3bVtu3b1dubq5X9n0h7rnnHkVGRrqeX3vttZKk+++/XxUqVHBrP3HihOv03fz583XkyBH16NFDBw4ccD0CAwN17bXXauHChWX7RnDR4dQPLnotW7ZUixYtPNorV65c7CmhPxs1apS6du2qK6+8Uo0aNdItt9yiXr16lSjk/PLLL6pevbrCw8Pd2uvXr+/afvq/AQEBSkxMdOtXu3bts459Zl9JOnTokNLT0zVjxgzt27fPbVtx/5BdccUVbs8jIyMVGhqqKlWqeLSfeZ3LmU6/hzNrjo2NVVRUlOu9WnH6NadPffxZvXr19O2331oe80L88ssvqlOnjsddYWf+PC9UcT9bSVqyZIlGjBihpUuXqqCgwG1bbm6uW0jwh+LWkyTFxcUV23748GFJcv0S0KFDh2LHjYiI8Gqd+OshqKBca9OmjbZt26ZPP/1U8+bN05tvvqkXXnhBr776qtsRibL259+uT7v33nv13Xff6cknn1SzZs1UqVIlOZ1O3XLLLcXeThoYGFiiNkkeF/+ezZnXwZQVh8NRbI1FRUV+qObCFPez3bZtmzp27Kh69epp4sSJiouLU3BwsL788ku98MILtrhd+Gxr53xr6nTt06dPV2xsrEe/Px+NAYrDCkG5Fx0dreTkZCUnJys/P19t2rTRyJEjXUHlbP84x8fH66uvvtLRo0fdjqr8/PPPru2n/+t0OpWTk6M6deq4+m3durXENR4+fFgLFixQenq6hg8f7movzSmr0jj9HrZs2eI6wiBJe/fu1ZEjR1zv1eqY0v8uLj3zt+1Nmza5jVm5cuViT0+deZTjQoJUfHy81q1bJ6fT6XZU5cyfpy98/vnnKiws1GeffeZ25MJXp0XKMnDWqlVLkhQTE6NOnTqV2X7x18E1KijXzjzlUalSJdWuXdvtltuKFStKko4cOeLW97bbblNRUZFefvllt/YXXnhBDodDt956qyS5rkd45ZVX3Pq99NJLJa7z9G+tZx5VyMrKKvEYF+K2224rdn8TJ06UpHPewXQ2LVq0UExMjF599VW3+Z49e7Y2btzoNmatWrX0888/a//+/a62tWvXasmSJW5jXnLJJZI8f1Ylcdttt2nPnj16//33XW2nTp3SSy+9pEqVKqlt27aWxyyp4n6+ubm5ys7O9sn+zramfaFz586KiIjQmDFjir0T788/U6A4HFFBudagQQO1a9dOzZs3V3R0tFasWKEPPvhAjz76qKtP8+bNJUmpqanq3LmzAgMD1b17d91xxx1q3769nnnmGe3YsUNNmzbVvHnz9Omnn2rgwIGu3ySbN2+uv/3tb8rKytLBgwddtydv3rxZUsl+u42IiFCbNm00btw4nTx5UpdffrnmzZunnJwcH8yKp6ZNm6p37956/fXXdeTIEbVt21bLli3TtGnT1K1bN7Vv397ymEFBQRo7dqySk5PVtm1b9ejRw3V7ckJCggYNGuTq++CDD2rixInq3Lmz+vTpo3379unVV19Vw4YNlZeX5+oXFhamBg0a6P3339eVV16p6OhoNWrUqERfpfDwww/rtddeU1JSklauXKmEhAR98MEHWrJkibKysjyuRfKmm2++WcHBwbrjjjvUr18/5efn64033lBMTIx+//13r++vVq1aioqK0quvvqrw8HBVrFhR11577Vmvn7kQERERmjx5snr16qWrr75a3bt3V9WqVbVz507NmjVLrVu39gj7gBs/3nEEXJDTtycvX7682O1t27Y97+3Jzz77rGnZsqWJiooyYWFhpl69eua5554zJ06ccPU5deqUeeyxx0zVqlWNw+Fwu1X56NGjZtCgQaZ69eomKCjI1KlTxzz//PPG6XS67ffYsWMmJSXFREdHm0qVKplu3bqZTZs2GUlutwufvrV4//79Hu/n119/NXfddZeJiooykZGR5p577jG7d+8+6y3OZ45xttuGi5un4pw8edKkp6ebxMREExQUZOLi4szQoUNdt6Gebz9n8/7775urrrrKhISEmOjoaNOzZ0/z66+/evR7++23Tc2aNU1wcLBp1qyZmTt3rsettMYY891335nmzZub4OBgy7cq79271yQnJ5sqVaqY4OBg07hx42Jv4b2Q25PP9rrPPvvMNGnSxISGhpqEhAQzduxYM2XKFCPJ5OTkuPp54/ZkY4z59NNPTYMGDUyFChXcXn+225Off/55t9cvXLjQSDIzZ850az/b38uFCxeazp07m8jISBMaGmpq1aplkpKSzIoVKyzVjfLHYUwJr6ID4FVr1qzRVVddpbfffls9e/b0dzkAYEtcowKUgeK+zyUrK0sBAQHn/URYACjPuEYFKAPjxo3TypUr1b59e1WoUEGzZ8/W7Nmz9fDDD3t8DgW868SJE8V+98yfRUZGFnvbcEnt37//nLdKBwcHKzo6utTjl1RZvFegrHHqBygD8+fPV3p6ujZs2KD8/HxdccUV6tWrl5555hk+R8LHFi1adN6LfbOzs92+rNKqhISEc34gXNu2bbVo0aJSj19SZfFegbJGUAHwl3b48GGtXLnynH0aNmyoyy67rNT7WLJkSbGn906rXLmy6+4xXyqL9wqUNYIKAACwLS6mBQAAtnVRnxx3Op3avXu3wsPD/fYdJAAAwBpjjI4eParq1at7fBHomS7qoLJ7927umAAA4CK1a9cu1ahR45x9LuqgcvojrXft2sVXhQMAcJHIy8tTXFxcib6a4qIOKqdP90RERBBUAAC4yJTksg0upgUAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZFUAEAALZVwd8FAAlDZvm7BMt2ZHbxdwkAUC5wRAUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANiWX4NKUVGRhg0bpsTERIWFhalWrVoaPXq0jDH+LAsAANhEBX/ufOzYsZo8ebKmTZumhg0basWKFUpOTlZkZKRSU1P9WRoAALABvwaV7777Tl27dlWXLl0kSQkJCXrvvfe0bNmyYvsXFhaqsLDQ9TwvL69M6gQAAP7h16DSqlUrvf7669q8ebOuvPJKrV27Vt9++60mTpxYbP+MjAylp6eXcZUXl4Qhs/xdAgAAXuPXoDJkyBDl5eWpXr16CgwMVFFRkZ577jn17Nmz2P5Dhw5VWlqa63leXp7i4uLKqlwAAFDG/BpU/vOf/+idd97Ru+++q4YNG2rNmjUaOHCgqlevrt69e3v0DwkJUUhIiB8qBQAA/uDXoPLkk09qyJAh6t69uySpcePG+uWXX5SRkVFsUAEAAOWLX29PLigoUECAewmBgYFyOp1+qggAANiJX4+o3HHHHXruued0xRVXqGHDhlq9erUmTpyoBx980J9lAQAAm/BrUHnppZc0bNgw9e/fX/v27VP16tXVr18/DR8+3J9lAQAAm/BrUAkPD1dWVpaysrL8WQYAALApvusHAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYFkEFAADYluWgsmrVKv3444+u559++qm6deum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0vr161WjRg3WWynnTSr79Wa7oHKhMjMzNWPGDC1atMjtAqDu3bu7/ty4cWM1adJEtWrV0qJFi9SxY0d/lGoL4eHhWrNmjfLz87VgwQKlpaWpZs2aateunb9Ls7XzzRvrzd3Ro0fVq1cvvfHGG6pSpYq/y7lolHTeWG+err/+el1//fWu561atVL9+vX12muvafTo0X6szN5KMm9lvd5sF1SqVKmiwMBA7d2716197969io2NPedrx48fr8zMTH311Vdq0qTJOfvWrFlTVapU0datW/8Sf5FLO28BAQGqXbu2JKlZs2bauHGjMjIy1K5dO9fr9u7dq8suu8xtzGbNmnn/TfiBL+atOOV9vW3btk07duzQHXfc4WpzOp2SpAoVKmjTpk2st1LOW61atTxeV97XW3GCgoJ01VVXaevWrZLEeivlvBXH1+vNdteoBAcHq3nz5lqwYIGrzel0asGCBW4p70zjxo3T6NGjNWfOHLVo0eK8+/n111918OBBtwV6MSvtvJ3J6XSqsLBQkpSYmKjY2Fi3MfPy8vTDDz9YGtPOfDFvxSnv661evXr68ccftWbNGtfjzjvvVPv27bVmzRrFxcWx3ko5b8Up7+utOEVFRfrxxx9dc8J6K928Fcfn663MLtu1YMaMGSYkJMRMnTrVbNiwwTz88MMmKirKdYtUr169zJAhQ1z9MzMzTXBwsPnggw/cbpc6evSoMcaYo0ePmieeeMIsXbrU5OTkmK+++spcffXVpk6dOuaPP/7wy3v0BavzNmbMGDNv3jyzbds2s2HDBjN+/HhToUIF88Ybb7j6ZGZmmqioKPPpp5+adevWma5du/4lb9/z5ryx3oqftzMVd+cA6836vLHeip+39PR0M3fuXLNt2zazcuVK0717dxMaGmrWr1/v6sN6sz5v/lhvtgwqxhjz0ksvmSuuuMIEBwebli1bmu+//961rW3btqZ3796u5/Hx8UaSx2PEiBHGGGMKCgrMzTffbKpWrWqCgoJMfHy86du3r8e94X8FVubtmWeeMbVr1zahoaGmcuXK5vrrrzczZsxwG8/pdJphw4aZatWqmZCQENOxY0ezadOmsno7Zcab88Z6+58z5+1MxQUV1pv1eWO9/c+Z8zZw4EBX32rVqpnbbrvNrFq1ym081pv1efPHenMYY4xvjtUAAABcGNtdowIAAHAaQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANgWQQUAANjW/wPMGYv9WNTfogAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAGzCAYAAAABsTylAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3/UlEQVR4nO3dd3hUZcL+8XuSkEJJQglNIl16R1AwdGERUdwVAVmpAq/EpURRIksJKAFUQBRRVwgsvopL9bcgvYvSQar0AEoXSAhogMzz+4Mr8zokgRycZA7k+7muuXSeeWbmnnMSuDltHMYYIwAAABvy8XYAAACAjFBUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUAACAbVFUYGulSpVSt27dvB3jgffuu++qTJky8vX1Vc2aNe84d+bMmapYsaJy5cql0NDQbMnnaQ6HQyNGjPB2jHTdvHlTb7zxhsLDw+Xj46N27dp5O5LHjRgxQg6Hw/avCXugqCDbTJ8+XQ6HQ1u3bk338SZNmqhq1ap/+n2+/fZb2/4lZEfLli3TG2+8oYYNGyouLk6jR4/OcO5PP/2kbt26qWzZsvrXv/6lzz77LBuT3vLll19q4sSJ2f6+2WXatGl699139fzzz2vGjBkaOHCgtyMBXuXn7QDAnRw4cEA+Ptb69LfffqvJkydTVjJp1apV8vHx0dSpU+Xv73/HuWvWrJHT6dQHH3ygcuXKZVNCd19++aX27NmjAQMGeOX9s9qqVav00EMPacKECd6OkmX++c9/avDgwd6OgfsEW1RgawEBAcqVK5e3Y1hy9epVb0ew5Ny5cwoKCrprSUmdK+muu3yMMfrtt988ES9H+OPyOnfu3H27Sy2z/Pz8FBgY6O0YuE9QVGBrtx+jcuPGDcXExKh8+fIKDAxUwYIF9cQTT2j58uWSpG7dumny5MmSbh2HkHpLdfXqVb322msKDw9XQECAKlSooPfee0+3f4n4b7/9pn79+qlQoULKly+fnnnmGf3yyy9pjm1I3S++b98+vfjii8qfP7+eeOIJSdKuXbvUrVs3lSlTRoGBgSpatKh69OihX3/91e29Ul/j4MGD+vvf/66QkBCFhYVp6NChMsbo5MmTevbZZxUcHKyiRYvq/fffz9Syu3nzpkaNGqWyZcsqICBApUqV0ltvvaXk5GTXHIfDobi4OF29etW1rKZPn57huhg+fLgkKSwszG1ZlCpVSk8//bSWLl2qunXrKigoSJ9++qkk6ejRo2rfvr0KFCig3Llz67HHHtOiRYvcXnvNmjVyOBz6z3/+o3feeUclSpRQYGCgmjdvrsOHD7vmNWnSRIsWLdLx48ddeUuVKiVJun79uoYNG6Y6deooJCREefLkUUREhFavXp2p5XU3s2bNUp06dZQvXz4FBwerWrVq+uCDD1yPZ3SMROouz/j4eNdYRsvL4XBo9erV2rt3r+vzrVmzRpL03nvvqUGDBipYsKCCgoJUp04dzZkzJ92sX3zxherVq6fcuXMrf/78atSokZYtW+Y2Z/HixYqIiFCePHmUL18+tWnTRnv37s308jDGqFChQoqKinKNOZ1OhYaGytfXV5cvX3aNjx07Vn5+fkpKSspwWTkcDr366qtasGCBqlatqoCAAFWpUkVLlixJ897fffedHn30UQUGBqps2bKunzU8mNj1g2yXkJCgCxcupBm/cePGXZ87YsQIxcbG6uWXX1a9evWUmJiorVu3avv27XryySfVp08fnTp1SsuXL9fMmTPdnmuM0TPPPKPVq1erZ8+eqlmzppYuXapBgwbpl19+cdvU3q1bN/3nP//RSy+9pMcee0xr165VmzZtMszVvn17lS9fXqNHj3aVnuXLl+vo0aPq3r27ihYtqr179+qzzz7T3r17tXHjxjR/UHfo0EGVKlXSmDFjtGjRIr399tsqUKCAPv30UzVr1kxjx47V//7v/+r111/Xo48+qkaNGt1xWb388suaMWOGnn/+eb322mvatGmTYmNjtX//fs2fP1/SrQNjP/vsM23evFmff/65JKlBgwbpvt7EiRP173//W/Pnz9eUKVOUN29eVa9e3fX4gQMH1KlTJ/Xp00e9evVShQoVdPbsWTVo0EDXrl1Tv379VLBgQc2YMUPPPPOM5syZo+eee87tPcaMGSMfHx+9/vrrSkhI0Lhx49S5c2dt2rRJkjRkyBAlJCTo559/dq2vvHnzSpISExP1+eefq1OnTurVq5euXLmiqVOnqlWrVtq8efNdDxK+k+XLl6tTp05q3ry5xo4dK0nav3+/NmzYoP79+9/Ta96+vEqUKKGZM2fqnXfeUVJSkmJjYyVJlSpVkiR98MEHeuaZZ9S5c2ddv35ds2bNUvv27bVw4UK3n82YmBiNGDFCDRo00MiRI+Xv769NmzZp1apVatmypaRb671r165q1aqVxo4dq2vXrmnKlCl64okntGPHDlf5uxOHw6GGDRtq3bp1rrFdu3YpISFBPj4+2rBhgyvX+vXrVatWLde6ysh3332nefPmqW/fvsqXL58mTZqkv/3tbzpx4oQKFiwoSdq9e7datmypsLAwjRgxQjdv3tTw4cNVpEiRzC983F8MkE3i4uKMpDveqlSp4vackiVLmq5du7ru16hRw7Rp0+aO7xMZGWnS+9FesGCBkWTefvttt/Hnn3/eOBwOc/jwYWOMMdu2bTOSzIABA9zmdevWzUgyw4cPd40NHz7cSDKdOnVK837Xrl1LM/bVV18ZSWbdunVpXqN3796usZs3b5oSJUoYh8NhxowZ4xq/dOmSCQoKclsm6dm5c6eRZF5++WW38ddff91IMqtWrXKNde3a1eTJk+eOr3d71vPnz7uNlyxZ0kgyS5YscRsfMGCAkWTWr1/vGrty5YopXbq0KVWqlElJSTHGGLN69WojyVSqVMkkJye75n7wwQdGktm9e7drrE2bNqZkyZJpst28edPtucbcWl5FihQxPXr0cBu/fT3eTf/+/U1wcLC5efNmhnNSl83tUn/ujx075hrLaHkZY0zjxo3T/B4Yk/bn6fr166Zq1aqmWbNmrrFDhw4ZHx8f89xzz7mWbSqn02mMubX8Q0NDTa9evdweP3PmjAkJCUkzfifvvvuu8fX1NYmJicYYYyZNmmRKlixp6tWrZ958801jjDEpKSkmNDTUDBw40PW89JaVJOPv7+/6PTTGmB9//NFIMh9++KFrrF27diYwMNAcP37cNbZv3z7j6+ub7vLH/Y9dP8h2kydP1vLly9Pc/viv84yEhoZq7969OnTokOX3/fbbb+Xr66t+/fq5jb/22msyxmjx4sWS5NrU3LdvX7d5//jHPzJ87f/5n/9JMxYUFOT6/99//10XLlzQY489Jknavn17mvkvv/yy6/99fX1Vt25dGWPUs2dP13hoaKgqVKigo0ePZphFuvVZJbltlpdufVZJaXa9eELp0qXVqlWrNDnq1avn2h0m3doC0rt3b8XHx2vfvn1u87t37+52rExERIQk3fXzSreWWepznU6nLl68qJs3b6pu3brpLm8rQkNDdfXqVdcuRk9Ib3ndyR9/ni5duqSEhARFRES4fbYFCxbI6XRq2LBhaQ5CT92Ct3z5cl2+fFmdOnXShQsXXDdfX1/Vr1/f0q6yiIgIpaSk6Pvvv5d0a8tJRESEIiIitH79eknSnj17dPnyZde6vJMWLVqobNmyrvvVq1dXcHCwa/2npKRo6dKlateunR5++GHXvEqVKllalri/UFSQ7erVq6cWLVqkueXPn/+uzx05cqQuX76sRx55RNWqVdOgQYO0a9euTL3v8ePHVbx4ceXLl89tPHXT+vHjx13/9fHxUenSpd3m3eksl9vnStLFixfVv39/FSlSREFBQQoLC3PNS0hISDP/j3/wSlJISIgCAwNVqFChNOOXLl3KMMsfP8PtmYsWLarQ0FDXZ/Wk9JbB8ePHVaFChTTjty/zVLcvg9Sfibt93lQzZsxQ9erVXccvhYWFadGiRekubyv69u2rRx55RK1bt1aJEiXUo0ePdI+dsCK95XUnCxcu1GOPPabAwEAVKFBAYWFhmjJlittnO3LkiHx8fFS5cuUMXye15Ddr1kxhYWFut2XLlrkOmM6M2rVrK3fu3K5SklpUGjVqpK1bt+r33393PfbHspqR29e/dOtnIHX9nz9/Xr/99pvKly+fZl56P2d4MHCMCu4rjRo10pEjR/TNN99o2bJl+vzzzzVhwgR98sknblskstsf/7Wb6oUXXtD333+vQYMGqWbNmsqbN6+cTqf+8pe/yOl0ppnv6+ubqTFJaQ7+zUh2XgArvWVg1Z/5vF988YW6deumdu3aadCgQSpcuLB8fX0VGxurI0eO/KlchQsX1s6dO7V06VItXrxYixcvVlxcnLp06aIZM2ZIynhZp6SkpDtuZXmtX79ezzzzjBo1aqSPP/5YxYoVU65cuRQXF6cvv/zS0mdJ/dmbOXOmihYtmuZxP7/M/7WQK1cu1a9fX+vWrdPhw4d15swZRUREqEiRIrpx44Y2bdqk9evXq2LFigoLC7vr6/3Zn3c8mCgquO8UKFBA3bt3V/fu3ZWUlKRGjRppxIgRrqKS0V8YJUuW1IoVK3TlyhW3rSo//fST6/HU/zqdTh07dsztX25/PPvkbi5duqSVK1cqJiZGw4YNc43fyy6re5H6GQ4dOuTaeiFJZ8+e1eXLl12fNTtyHDhwIM347cvciozW75w5c1SmTBnNmzfPbU7qmUp/lr+/v9q2bau2bdvK6XSqb9+++vTTTzV06FCVK1fOtfXn8uXLbqcXe2Lr1dy5cxUYGKilS5cqICDANR4XF+c2r2zZsnI6ndq3b1+GBw+n7lopXLiwWrRo8aezRUREaOzYsVqxYoUKFSqkihUryuFwqEqVKlq/fr3Wr1+vp59++k+/j3TrbLOgoKB0f4/S+znDg4FdP7iv3H5qb968eVWuXDm3U27z5MkjSW6nR0rSU089pZSUFH300Udu4xMmTJDD4VDr1q0lybWv++OPP3ab9+GHH2Y6Z+q/DG//l2B2XVH1qaeeSvf9xo8fL0l3PIPJ0zk2b96sH374wTV29epVffbZZypVqtQdd1FkJE+ePOnuyklvmW/atMntve/V7T93Pj4+rmOqUn/2UgvAH8+CuXr1qmuLy5/h6+srh8PhtnUmPj5eCxYscJvXrl07+fj4aOTIkWm22qUul1atWik4OFijR49O90y78+fPW8oWERGh5ORkTZw4UU888YSrJEZERGjmzJk6depUpo5PyQxfX1+1atVKCxYs0IkTJ1zj+/fv19KlSz3yHrAftqjgvlK5cmU1adJEderUUYECBbR161bNmTNHr776qmtOnTp1JEn9+vVTq1at5Ovrq44dO6pt27Zq2rSphgwZovj4eNWoUUPLli3TN998owEDBrj+oqlTp47+9re/aeLEifr1119dpycfPHhQUuZ2pwQHB6tRo0YaN26cbty4oYceekjLli3TsWPHsmCppFWjRg117dpVn332mS5fvqzGjRtr8+bNmjFjhtq1a6emTZtmS47Bgwfrq6++UuvWrdWvXz8VKFBAM2bM0LFjxzR37lzLVx2Wbq2fr7/+WlFRUXr00UeVN29etW3bVk8//bTmzZun5557Tm3atNGxY8f0ySefqHLlyq7rd9yrl19+WRcvXlSzZs1UokQJHT9+XB9++KFq1qzp2mLVsmVLPfzww+rZs6cGDRokX19fTZs2TWFhYW5/qd6LNm3aaPz48frLX/6iF198UefOndPkyZNVrlw5t2O0ypUrpyFDhmjUqFGKiIjQX//6VwUEBGjLli0qXry4YmNjFRwcrClTpuill15S7dq11bFjR1fGRYsWqWHDhmnK/J08/vjj8vPz04EDB9S7d2/XeKNGjTRlyhRJ8lhRkW6dfr1kyRJFRESob9++unnzpj788ENVqVIl08er4T7jvROOkNOknqa5ZcuWdB9P77TM209Pfvvtt029evVMaGioCQoKMhUrVjTvvPOOuX79umvOzZs3zT/+8Q8TFhZmHA6H2ymLV65cMQMHDjTFixc3uXLlMuXLlzfvvvuu69TNVFevXjWRkZGmQIECJm/evKZdu3bmwIEDRpLb6cIZna5rjDE///yzee6550xoaKgJCQkx7du3N6dOncrwFOfbXyOj04YzOn31djdu3DAxMTGmdOnSJleuXCY8PNxER0eb33//PVPvk547nZ6c0WnjR44cMc8//7wJDQ01gYGBpl69embhwoVuc1JPT549e7bb+LFjx4wkExcX5xpLSkoyL774ogkNDTWSXKcqO51OM3r0aFOyZEkTEBBgatWqZRYuXGi6du2a5nTm29fB3cyZM8e0bNnSFC5c2Pj7+5uHH37Y9OnTx5w+fdpt3rZt20z9+vVdc8aPH5/h6ckZLa+M1u/UqVNN+fLlTUBAgKlYsaKJi4vL8JToadOmmVq1apmAgACTP39+07hxY7N8+XK3OatXrzatWrUyISEhJjAw0JQtW9Z069bNbN26NdPLJdWjjz5qJJlNmza5xn7++WcjyYSHh6eZn9HpyZGRkWnm3v5ngDHGrF271tSpU8f4+/ubMmXKmE8++STDZYH7n8MYjlICMmPnzp2qVauWvvjiC3Xu3NnbcQAgR+AYFSAd6X1PzcSJE+Xj43PXK8ICADyHY1SAdIwbN07btm1T06ZN5efn5zoltXfv3goPD/d2PHhISkrKXQ8ezZs3710v/f6guX79ui5evHjHOSEhIR45JR24G3b9AOlYvny5YmJitG/fPiUlJenhhx/WSy+9pCFDhli6zgTsLT4+/q4XXhs+fLjbF1HmBGvWrLnrAddxcXFuXxgKZBWKCoAc6/fff9d33313xzllypRRmTJlsimRPVy6dEnbtm2745wqVaqoWLFi2ZQIORlFBQAA2BYH0wIAANu6r3e2O51OnTp1Svny5cvW7zQBAAD3zhijK1euqHjx4ne98ON9XVROnTrFGRgAANynTp48qRIlStxxzn1dVFK/WO7kyZMKDg72choAAJAZiYmJCg8Pd/uC2Izc10UldXdPcHAwRQUAgPtMZg7b4GBaAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgWxQVAABgW14tKqVKlZLD4Uhzi4yM9GYsAABgE179rp8tW7YoJSXFdX/Pnj168skn1b59ey+mAgAAduHVohIWFuZ2f8yYMSpbtqwaN27spUQAAMBObPPtydevX9cXX3yhqKioDL9NMTk5WcnJya77iYmJ2RUPAAB4gW2KyoIFC3T58mV169YtwzmxsbGKiYnJvlAAAHhQqcGLvB3Bsvgxbbz6/rY562fq1Klq3bq1ihcvnuGc6OhoJSQkuG4nT57MxoQAACC72WKLyvHjx7VixQrNmzfvjvMCAgIUEBCQTakAAIC32WKLSlxcnAoXLqw2bby7eQkAANiL14uK0+lUXFycunbtKj8/W2zgAQAANuH1orJixQqdOHFCPXr08HYUAABgM17fhNGyZUsZY7wdAwAA2JDXt6gAAABkhKICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsi6ICAABsy+tF5ZdfftHf//53FSxYUEFBQapWrZq2bt3q7VgAAMAG/Lz55pcuXVLDhg3VtGlTLV68WGFhYTp06JDy58/vzVgAAMAmvFpUxo4dq/DwcMXFxbnGSpcu7cVEAADATry66+f//b//p7p166p9+/YqXLiwatWqpX/9618Zzk9OTlZiYqLbDQAAPLi8ukXl6NGjmjJliqKiovTWW29py5Yt6tevn/z9/dW1a9c082NjYxUTE+OFpIC7UoMXeTuCZfFj2ng7AgBY5tUtKk6nU7Vr19bo0aNVq1Yt9e7dW7169dInn3yS7vzo6GglJCS4bidPnszmxAAAIDt5tagUK1ZMlStXdhurVKmSTpw4ke78gIAABQcHu90AAMCDy6tFpWHDhjpw4IDb2MGDB1WyZEkvJQIAAHbi1aIycOBAbdy4UaNHj9bhw4f15Zdf6rPPPlNkZKQ3YwEAAJvwalF59NFHNX/+fH311VeqWrWqRo0apYkTJ6pz587ejAUAAGzCq2f9SNLTTz+tp59+2tsxAACADXn9EvoAAAAZoagAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADboqgAAADbslxUtm/frt27d7vuf/PNN2rXrp3eeustXb9+3aPhAABAzma5qPTp00cHDx6UJB09elQdO3ZU7ty5NXv2bL3xxhseDwgAAHIuy0Xl4MGDqlmzpiRp9uzZatSokb788ktNnz5dc+fO9XQ+AACQg1kuKsYYOZ1OSdKKFSv01FNPSZLCw8N14cIFz6YDAAA5muWiUrduXb399tuaOXOm1q5dqzZt2kiSjh07piJFing8IAAAyLksF5WJEydq+/btevXVVzVkyBCVK1dOkjRnzhw1aNDA4wEBAEDO5Wf1CdWrV3c76yfVu+++K19fX4+EAgAAkO7xOiqXL1/W559/rujoaF28eFGStG/fPp07d86j4QAAQM5meYvKrl271Lx5c4WGhio+Pl69evVSgQIFNG/ePJ04cUL//ve/syInAADIgSxvUYmKilL37t116NAhBQYGusafeuoprVu3zqPhAABAzma5qGzZskV9+vRJM/7QQw/pzJkzll5rxIgRcjgcbreKFStajQQAAB5Qlnf9BAQEKDExMc34wYMHFRYWZjlAlSpVtGLFiv8L5Gc5EgAAeEBZ3qLyzDPPaOTIkbpx44YkyeFw6MSJE3rzzTf1t7/9zXIAPz8/FS1a1HUrVKiQ5dcAAAAPJstF5f3331dSUpIKFy6s3377TY0bN1a5cuWUL18+vfPOO5YDHDp0SMWLF1eZMmXUuXNnnThxIsO5ycnJSkxMdLsBAIAHl+X9LCEhIVq+fLk2bNigH3/8UUlJSapdu7ZatGhh+c3r16+v6dOnq0KFCjp9+rRiYmIUERGhPXv2KF++fGnmx8bGKiYmxvL7AJBKDV7k7QiWxY9p4+0IALzMYYwx3g6R6vLlyypZsqTGjx+vnj17pnk8OTlZycnJrvuJ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SopSUlK0atUq9e/fXx07dsyKjAAAIIeyvOtn1KhRio+PV/PmzeXnd+vpTqdTXbp04RgVAADgUZaLir+/v77++muNGjVKP/74o4KCglStWjWVLFkyK/IBAIAc7J6uoyJJBQoUUNOmTdM9AwgAAMATLB2jcvnyZUVGRqpQoUIqUqSIihQpokKFCunVV1/V5cuXsygiAADIqTK9ReXixYt6/PHH9csvv6hz586qVKmSJGnfvn2aPn26Vq5cqe+//1758+fPsrAAACBnyXRRGTlypPz9/XXkyBEVKVIkzWMtW7bUyJEjNWHCBI+HBAAAOVOmd/0sWLBA7733XpqSIklFixbVuHHjNH/+fI+GAwAAOVumi8rp06dVpUqVDB+vWrWqzpw545FQAAAAkoWiUqhQIcXHx2f4+LFjx1SgQAFPZAIAAJBkoai0atVKQ4YM0fXr19M8lpycrKFDh+ovf/mLR8MBAICczdLBtHXr1lX58uUVGRmpihUryhij/fv36+OPP1ZycrJmzpyZlVkBAEAOk+miUqJECf3www/q27evoqOjZYyRJDkcDj355JP66KOPFB4enmVBAQBAzmPpyrSlS5fW4sWLdenSJR06dEiSVK5cOY5NAQAAWeKeLqGfP39+1atXz9NZAAAA3Fi6hD4AAEB2oqgAAADboqgAAADbylRRqV27ti5duiTp1mnK165dy9JQAAAAUiaLyv79+3X16lVJUkxMjJKSkrI0FAAAgJTJs35q1qyp7t2764knnpAxRu+9957y5s2b7txhw4Z5NCAAAMi5MlVUpk+fruHDh2vhwoVyOBxavHix/PzSPtXhcFBUAACAx2SqqFSoUEGzZs2SJPn4+GjlypUqXLhwlgYDAACwfME3p9OZFTkAAADSuKcr0x45ckQTJ07U/v37JUmVK1dW//79VbZsWY+GAwAAOZvl66gsXbpUlStX1ubNm1W9enVVr15dmzZtUpUqVbR8+fKsyAgAAHIoy1tUBg8erIEDB2rMmDFpxt988009+eSTHgsHAAByNstbVPbv36+ePXumGe/Ro4f27dvnkVAAAADSPRSVsLAw7dy5M834zp07ORMIAAB4lOVdP7169VLv3r119OhRNWjQQJK0YcMGjR07VlFRUR4PCAAAci7LRWXo0KHKly+f3n//fUVHR0uSihcvrhEjRqhfv34eDwgAAHIu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gPtPpovK9OnTPf7mS5YsSfMehQsX1rZt29SoUSOPvx8AALi/WL6EflZKSEiQpAy/hTk5OVnJycmu+4mJidmSCwAAeIdtiorT6dSAAQPUsGHDDM8iio2NVUxMTDYnA+AtpQYv8naEHCF+TBtvRwAyZJvv+omMjNSePXs0a9asDOdER0crISHBdTt58mQ2JgQAANnNFltUXn31VS1cuFDr1q1TiRIlMpwXEBCggICAbEwGAAC8yatFxRijf/zjH5o/f77WrFmj0qVLezMOAACwGa8WlcjISH355Zf65ptvlC9fPp05c0aSFBISoqCgIG9GAwAANuDVY1SmTJmihIQENWnSRMWKFXPdvv76a2/GAgAANuH1XT8AAAAZsc1ZPwAAALejqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANuiqAAAANvyalFZt26d2rZtq+LFi8vhcGjBggXejAMAAGzGq0Xl6tWrqlGjhiZPnuzNGAAAwKb8vPnmrVu3VuvWrb0ZAQAA2JhXi4pVycnJSk5Odt1PTEz0YhoAAJDV7quiEhsbq5iYmGx7v1KDF2XbewEAgLTuq7N+oqOjlZCQ4LqdPHnS25EAAEAWuq+2qAQEBCggIMDbMQAAQDa5r7aoAACAnMWrW1SSkpJ0+PBh1/1jx45p586dKlCggB5++GEvJgMAAHbg1aKydetWNW3a1HU/KipKktS1a1dNnz7dS6kAAIBdeLWoNGnSRMYYb0YAAAA2xjEqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADAtigqAADA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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAGzCAYAAAABsTylAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA46UlEQVR4nO3dd3hUZd7G8XuSkCGUhBYSggFCkd5ZkSKKgIgswq6rwCIkgOhqlCpCZCkBIYEVZVFEcRFYxYYKrgWQJgjSe5NeIkVASEJAA2Se9w8v5nWcgJk4wxyY7+e6zmXmOc+c8zvPHMyd08ZmjDECAACwoCB/FwAAAHAtBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBXABypUqKCEhAR/l3HL+9e//qWKFSsqODhY9erV83c5AHyAoAL8jpkzZ8pms2nDhg25zr/nnntUq1atP7yeL7/8UqNGjfrDywkUX331lZ577jk1a9ZMM2bM0Lhx4/xdEgAfCPF3AcCtaM+ePQoK8uzvgC+//FJTpkwhrOTR0qVLFRQUpOnTpys0NNTf5QDwEY6oAD5gt9tVoEABf5fhkQsXLvi7BI+cOnVKYWFhhBTgFkdQAXzgt9eoXL58WcnJyapSpYoKFiyokiVLqnnz5lq0aJEkKSEhQVOmTJEk2Ww253TVhQsXNGjQIMXGxsput6tq1ap68cUX9dsvP//pp5/Ut29flSpVSkWLFtWDDz6oY8eOyWazuRypGTVqlGw2m3bt2qW///3vKl68uJo3by5J2rZtmxISElSxYkUVLFhQ0dHR6tWrl3788UeXdV1dxt69e/Xoo48qIiJCkZGRGj58uIwxSktLU8eOHRUeHq7o6GhNnDgxT2N35coVjRkzRpUqVZLdbleFChX0/PPPKzs729nHZrNpxowZunDhgnOsZs6cec1lfvPNN3r44YdVrlw52e12xcbGasCAAfrpp59c+iUkJKhIkSI6ePCg2rZtq8KFCysmJkajR492G2tvfyaSdOzYMfXq1UtRUVGy2+2qWbOm3nrrLbftyc7O1siRI1W5cmXn9jz33HMuY/R7ZsyYIZvNps2bN7vNGzdunIKDg3Xs2LE8Lw/wFU79AHmUkZGhM2fOuLVfvnz5d987atQopaSk6LHHHtMdd9yhzMxMbdiwQZs2bVKbNm30xBNP6Pjx41q0aJHefvttl/caY/Tggw9q2bJl6t27t+rVq6eFCxdq8ODBOnbsmF5++WVn34SEBH344Yfq3r277rzzTi1fvlzt27e/Zl0PP/ywqlSponHjxjl/wS5atEgHDx5Uz549FR0drZ07d2ratGnauXOn1qxZ4xKgJKlz586qXr26UlNT9cUXX+iFF15QiRIl9MYbb+jee+/V+PHjNXv2bD377LP605/+pBYtWlx3rB577DHNmjVLf/vb3zRo0CCtXbtWKSkp2r17t+bOnStJevvttzVt2jStW7dO//nPfyRJTZs2veYy58yZo4sXL+rJJ59UyZIltW7dOr3yyiv6/vvvNWfOHJe+OTk5uv/++3XnnXdqwoQJWrBggUaOHKkrV65o9OjRPvtMfvjhB915552y2Wx6+umnFRkZqfnz56t3797KzMxU//79JUkOh0MPPvigVq5cqccff1zVq1fX9u3b9fLLL2vv3r2aN2/edcf3qr/97W9KTEzU7NmzVb9+fZd5s2fP1j333KOyZcvmaVmATxkA1zVjxgwj6bpTzZo1Xd5Tvnx5Ex8f73xdt25d0759++uuJzEx0eT2T3LevHlGknnhhRdc2v/2t78Zm81m9u/fb4wxZuPGjUaS6d+/v0u/hIQEI8mMHDnS2TZy5EgjyXTt2tVtfRcvXnRre++994wks2LFCrdlPP744862K1eumNtuu83YbDaTmprqbD937pwJCwtzGZPcbNmyxUgyjz32mEv7s88+aySZpUuXOtvi4+NN4cKFr7u8621TSkqKsdls5siRIy7LlGSeeeYZZ5vD4TDt27c3oaGh5vTp08YY33wmvXv3NmXKlDFnzpxx6dulSxcTERHh3Ia3337bBAUFmW+++cal3+uvv24kmVWrVuVpTIwxpmvXriYmJsbk5OQ42zZt2mQkmRkzZuR5OYAvceoHyKMpU6Zo0aJFblOdOnV+973FihXTzp07tW/fPo/X++WXXyo4OFh9+/Z1aR80aJCMMZo/f74kacGCBZKkp556yqXfM888c81l/+Mf/3BrCwsLc/78888/68yZM7rzzjslSZs2bXLr/9hjjzl/Dg4OVqNGjWSMUe/evZ3txYoVU9WqVXXw4MFr1iL9sq2SNHDgQJf2QYMGSZK++OKL677/Wn69TRcuXNCZM2fUtGlTGWNyPfXx9NNPO3++eoTj0qVLWrx4sbNOb34mxhh9/PHH6tChg4wxOnPmjHNq27atMjIynGM/Z84cVa9eXdWqVXPpd++990qSli1bludx6dGjh44fP+7yntmzZyssLEwPPfRQnpcD+BKnfoA8uuOOO9SoUSO39uLFi+d6SujXRo8erY4dO+r2229XrVq1dP/996t79+55CjlHjhxRTEyMihYt6tJevXp15/yr/w0KClJcXJxLv8qVK19z2b/tK0lnz55VcnKy3n//fZ06dcplXkZGhlv/cuXKubyOiIhQwYIFVapUKbf2317n8ltXt+G3NUdHR6tYsWLObfXU0aNHNWLECP3vf//TuXPnXOb9dpuCgoJUsWJFl7bbb79dknT48GFnnd78TE6fPq309HRNmzZN06ZNy3Ubrn4W+/bt0+7duxUZGXndfnnRpk0blSlTRrNnz1arVq3kcDj03nvvqWPHjm7bBvgLQQW4AVq0aKEDBw7o008/1VdffaX//Oc/evnll/X666+7HJG40X59pOGqRx55RN9++60GDx6sevXqqUiRInI4HLr//vvlcDjc+gcHB+epTZLbhabX8tvrYP6InJwctWnTRmfPntWQIUNUrVo1FS5cWMeOHVNCQkKu23SjXa3h0UcfVXx8fK59roZah8Oh2rVr66WXXsq1X2xsbJ7XGxwcrL///e9688039dprr2nVqlU6fvy4Hn30UQ+3APAdggpwg5QoUUI9e/ZUz549lZWVpRYtWmjUqFHOoHKtX87ly5fX4sWLdf78eZe/cr/77jvn/Kv/dTgcOnTokKpUqeLst3///jzXeO7cOS1ZskTJyckaMWKEsz0/p6zy4+o27Nu3z3l0QvrlQtP09HTntnpi+/bt2rt3r2bNmqUePXo426/ecfVbDodDBw8edB5FkaS9e/dK+uVurqt1evMziYyMVNGiRZWTk6PWrVtfd3sqVaqkrVu3qlWrVl4JdD169NDEiRP12Wefaf78+YqMjFTbtm3/8HIBb+EaFeAG+O0pjyJFiqhy5cout5MWLlxYkpSenu7S94EHHlBOTo5effVVl/aXX35ZNptN7dq1kyTnL5fXXnvNpd8rr7yS5zqvHgn57ZGPSZMm5XkZf8QDDzyQ6/quHj243h1M15LbNhlj9O9///ua7/n1WBtj9Oqrr6pAgQJq1aqVs05vfibBwcF66KGH9PHHH2vHjh1u9Zw+fdr58yOPPKJjx47pzTffdOv3008/efw8nDp16qhOnTr6z3/+o48//lhdunRRSAh/w8I62BuBG6BGjRq655571LBhQ5UoUUIbNmzQRx995HLRZsOGDSVJffv2Vdu2bRUcHKwuXbqoQ4cOatmypYYNG6bDhw+rbt26+uqrr/Tpp5+qf//+qlSpkvP9Dz30kCZNmqQff/zReSvs1aMBefnrOzw8XC1atNCECRN0+fJllS1bVl999ZUOHTrkg1FxV7duXcXHx2vatGlKT0/X3XffrXXr1mnWrFnq1KmTWrZs6fEyq1WrpkqVKunZZ5/VsWPHFB4ero8//tjtWpWrChYsqAULFig+Pl6NGzfW/Pnz9cUXX+j55593Xhfii88kNTVVy5YtU+PGjdWnTx/VqFFDZ8+e1aZNm7R48WKdPXtWktS9e3d9+OGH+sc//qFly5apWbNmysnJ0XfffacPP/xQCxcuzPVaquvp0aOHnn32WUnitA+sx093GwE3jau3J69fvz7X+Xfffffv3p78wgsvmDvuuMMUK1bMhIWFmWrVqpmxY8eaS5cuOftcuXLFPPPMMyYyMtLYbDaXW5XPnz9vBgwYYGJiYkyBAgVMlSpVzL/+9S/jcDhc1nvhwgWTmJhoSpQoYYoUKWI6depk9uzZYyS53C589dbiq7fb/tr3339v/vKXv5hixYqZiIgI8/DDD5vjx49f8xbn3y7jWrcN5zZOubl8+bJJTk42cXFxpkCBAiY2NtYkJSWZn3/+OU/ryc2uXbtM69atTZEiRUypUqVMnz59zNatW91uw726zAMHDpj77rvPFCpUyERFRZmRI0e63MJrjPc/E2OM+eGHH0xiYqKJjY01BQoUMNHR0aZVq1Zm2rRpLv0uXbpkxo8fb2rWrGnsdrspXry4adiwoUlOTjYZGRl5GpNfO3HihAkODja33367x+8FfM1mTB6vbgNwU9qyZYvq16+vd955R926dfN3OZaWkJCgjz76SFlZWT5dj9U+kzNnzqhMmTIaMWKEhg8f7u9yABdcowLcQn77SHjpl+s9goKCfveJsPCNm+EzmTlzpnJyctS9e3d/lwK44RoV4BYyYcIEbdy4US1btlRISIjmz5+v+fPn6/HHH/fotlV4jz8+k4yMjFwD0q9FR0dr6dKl2rVrl8aOHatOnTo572oCrISgAtxCmjZtqkWLFmnMmDHKyspSuXLlNGrUKA0bNszfpQUsf3wm/fr106xZs67bxxij0aNH69tvv1WzZs08ujsMuJG4RgUAbjG7du3S8ePHr9vn957XAlgFQQUAAFgWF9MCAADLuqmvUXE4HDp+/LiKFi3q1e8GAQAAvmOM0fnz5xUTE6OgoOsfM7mpg8rx48e5kwEAgJtUWlqabrvttuv2uamDytUvA0tLS1N4eLifqwEAAHmRmZmp2NhYly/1vJabOqhcPd0THh5OUAEA4CaTl8s2uJgWAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYFkEFAABYll+DSk5OjoYPH664uDiFhYWpUqVKGjNmjIwx/iwLAABYhF+/62f8+PGaOnWqZs2apZo1a2rDhg3q2bOnIiIi1LdvX3+WBgAALMCvQeXbb79Vx44d1b59e0lShQoV9N5772ndunX+LAsAAFiEX0/9NG3aVEuWLNHevXslSVu3btXKlSvVrl27XPtnZ2crMzPTZQIAALcuvx5RGTp0qDIzM1WtWjUFBwcrJydHY8eOVbdu3XLtn5KSouTk5BtcJXBrqDD0C3+X4LHDqe39XQIAP/PrEZUPP/xQs2fP1rvvvqtNmzZp1qxZevHFFzVr1qxc+yclJSkjI8M5paWl3eCKAQDAjeTXIyqDBw/W0KFD1aVLF0lS7dq1deTIEaWkpCg+Pt6tv91ul91uv9FlAgAAP/HrEZWLFy8qKMi1hODgYDkcDj9VBAAArMSvR1Q6dOigsWPHqly5cqpZs6Y2b96sl156Sb169fJnWQAAwCL8GlReeeUVDR8+XE899ZROnTqlmJgYPfHEExoxYoQ/ywIAABbh16BStGhRTZo0SZMmTfJnGQAAwKL4rh8AAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZBBUAAGBZfg0qFSpUkM1mc5sSExP9WRYAALCIEH+ufP369crJyXG+3rFjh9q0aaOHH37Yj1UBAACr8GtQiYyMdHmdmpqqSpUq6e677/ZTRQAAwEr8GlR+7dKlS3rnnXc0cOBA2Wy2XPtkZ2crOzvb+TozM/NGlQcAAPzAMhfTzps3T+np6UpISLhmn5SUFEVERDin2NjYG1cgAAC44SwTVKZPn6527dopJibmmn2SkpKUkZHhnNLS0m5ghQAA4EazxKmfI0eOaPHixfrkk0+u289ut8tut9+gqgAAgL9Z4ojKjBkzVLp0abVv397fpQAAAAvxe1BxOByaMWOG4uPjFRJiiQM8AADAIvweVBYvXqyjR4+qV69e/i4FAABYjN8PYdx3330yxvi7DAAAYEF+P6ICAABwLQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWQQVAABgWX4PKseOHdOjjz6qkiVLKiwsTLVr19aGDRv8XRYAALCAEH+u/Ny5c2rWrJlatmyp+fPnKzIyUvv27VPx4sX9WRYAALAIvwaV8ePHKzY2VjNmzHC2xcXF+bEiAABgJR6f+tm0aZO2b9/ufP3pp5+qU6dOev7553Xp0iWPlvW///1PjRo10sMPP6zSpUurfv36evPNN6/ZPzs7W5mZmS4TAAC4dXkcVJ544gnt3btXknTw4EF16dJFhQoV0pw5c/Tcc895tKyDBw9q6tSpqlKlihYuXKgnn3xSffv21axZs3Ltn5KSooiICOcUGxvrafkAAOAmYjPGGE/eEBERoU2bNqlSpUoaP368li5dqoULF2rVqlXq0qWL0tLS8rys0NBQNWrUSN9++62zrW/fvlq/fr1Wr17t1j87O1vZ2dnO15mZmYqNjVVGRobCw8M92Qwg4FQY+oW/S/DY4dT2/i4BgA9kZmYqIiIiT7+/PT6iYoyRw+GQJC1evFgPPPCAJCk2NlZnzpzxaFllypRRjRo1XNqqV6+uo0eP5trfbrcrPDzcZQIAALcuj4NKo0aN9MILL+jtt9/W8uXL1b79L3/xHDp0SFFRUR4tq1mzZtqzZ49L2969e1W+fHlPywIAALcgj4PKpEmTtGnTJj399NMaNmyYKleuLEn66KOP1LRpU4+WNWDAAK1Zs0bjxo3T/v379e6772ratGlKTEz0tCwAAHAL8vgalWv5+eefFRwcrAIFCnj0vs8//1xJSUnat2+f4uLiNHDgQPXp0ydP7/XkHBcQ6LhGBYBVePL7O1/PUUlPT9dHH32kAwcOaPDgwSpRooR27dqlqKgolS1b1qNl/fnPf9af//zn/JQBAABucR4HlW3btqlVq1YqVqyYDh8+rD59+qhEiRL65JNPdPToUf33v//1RZ0AACAAeXyNysCBA9WzZ0/t27dPBQsWdLY/8MADWrFihVeLAwAAgc3joLJ+/Xo98cQTbu1ly5bVyZMnvVIUAACAlI+gYrfbc310/d69exUZGemVogAAAKR8BJUHH3xQo0eP1uXLlyVJNptNR48e1ZAhQ/TQQw95vUAAABC4PA4qEydOVFZWlkqXLq2ffvpJd999typXrqyiRYtq7NixvqgRAAAEKI/v+omIiNCiRYu0atUqbd26VVlZWWrQoIFat27ti/oAAEAAy9dzVKRfHn/frFkzb9YCAADgwuNTP3379tXkyZPd2l999VX179/fGzUBAABIykdQ+fjjj3M9ktK0aVN99NFHXikKAABAykdQ+fHHHxUREeHWHh4erjNnznilKAAAACkfQaVy5cpasGCBW/v8+fNVsWJFrxQFAAAg5eNi2oEDB+rpp5/W6dOnde+990qSlixZookTJ2rSpEnerg8AAAQwj4NKr169lJ2drbFjx2rMmDGSpAoVKmjq1Knq0aOH1wsEAACBK1+3Jz/55JN68skndfr0aYWFhalIkSLergsAACD/z1GRxHf7AAAAn/L4YtoffvhB3bt3V0xMjEJCQhQcHOwyAQAAeIvHR1QSEhJ09OhRDR8+XGXKlJHNZvNFXQAAAJ4HlZUrV+qbb75RvXr1fFAOAADA//P41E9sbKyMMb6oBQAAwIXHQWXSpEkaOnSoDh8+7INyAAAA/p/Hp346d+6sixcvqlKlSipUqJAKFCjgMv/s2bNeKw4AAAQ2j4MKT58FAAA3isdBJT4+3hd1AAAAuPH4GhVJOnDggP75z3+qa9euOnXqlKRfvpRw586dXi0OAAAENo+DyvLly1W7dm2tXbtWn3zyibKysiRJW7du1ciRI71eIAAACFweB5WhQ4fqhRde0KJFixQaGupsv/fee7VmzRqvFgcAAAKbx0Fl+/bt+stf/uLWXrp0aZ05c8YrRQEAAEj5CCrFihXTiRMn3No3b96ssmXLeqUoAAAAKR9BpUuXLhoyZIhOnjwpm80mh8OhVatW6dlnn1WPHj18USMAAAhQHgeVcePGqVq1aoqNjVVWVpZq1KihFi1aqGnTpvrnP//pixoBAECA8ug5KsYYnTx5UpMnT9aIESO0fft2ZWVlqX79+qpSpYqvagQAAAHK46BSuXJl7dy5U1WqVFFsbKyv6gIAAPDs1E9QUJCqVKmiH3/80SsrHzVqlGw2m8tUrVo1rywbAADc/Dy+RiU1NVWDBw/Wjh07vFJAzZo1deLECee0cuVKrywXAADc/Dz+rp8ePXro4sWLqlu3rkJDQxUWFuYy39NvTw4JCVF0dLSnZQAAgADg929P3rdvn2JiYlSwYEE1adJEKSkpKleuXK59s7OzlZ2d7XydmZnp1VoAAIC1eBRULl++rOXLl2v48OGKi4v7wytv3LixZs6cqapVq+rEiRNKTk7WXXfdpR07dqho0aJu/VNSUpScnPyH1wvg5lBh6Bf+LsFjh1Pb+7sEjzHOsDKPrlEpUKCAPv74Y6+tvF27dnr44YdVp04dtW3bVl9++aXS09P14Ycf5to/KSlJGRkZziktLc1rtQAAAOvx+GLaTp06ad68eT4o5ZfH899+++3av39/rvPtdrvCw8NdJgAAcOvy+BqVKlWqaPTo0Vq1apUaNmyowoULu8zv27dvvovJysrSgQMH1L1793wvAwAA3Do8DirTp09XsWLFtHHjRm3cuNFlns1m8yioPPvss+rQoYPKly+v48ePa+TIkQoODlbXrl09LQsAANyCPA4qhw4d8trKv//+e3Xt2lU//vijIiMj1bx5c61Zs0aRkZFeWwcAALh5eRxUvOn999/35+oBAIDFeRxUevXqdd35b731Vr6LAQAA+DWPg8q5c+dcXl++fFk7duxQenq67r33Xq8VBgAA4HFQmTt3rlubw+HQk08+qUqVKnmlKAAAACkfz1HJdSFBQRo4cKBefvllbywOAABAkpeCiiQdOHBAV65c8dbiAAAAPD/1M3DgQJfXxhidOHFCX3zxheLj471WGAAAgMdBZfPmzS6vg4KCFBkZqYkTJ/7uHUEAAACe8DioLFu2zBd1AAAAuPH4GpVDhw5p3759bu379u3T4cOHvVETAACApHwElYSEBH377bdu7WvXrlVCQoI3agIAAJCUj6CyefNmNWvWzK39zjvv1JYtW7xREwAAgKR8BBWbzabz58+7tWdkZCgnJ8crRQEAAEj5CCotWrRQSkqKSyjJyclRSkqKmjdv7tXiAABAYPP4rp/x48erRYsWqlq1qu666y5J0jfffKPMzEwtXbrU6wUCAIDA5fERlRo1amjbtm165JFHdOrUKZ0/f149evTQd999p1q1avmiRgAAEKA8PqIiSTExMRo3bpy3awEAAHDh8RGVGTNmaM6cOW7tc+bM0axZs7xSFAAAgJSPoJKSkqJSpUq5tZcuXZqjLAAAwKs8DipHjx5VXFycW3v58uV19OhRrxQFAAAg5SOolC5dWtu2bXNr37p1q0qWLOmVogAAAKR8BJWuXbuqb9++WrZsmXJycpSTk6OlS5eqX79+6tKliy9qBAAAAcrju37GjBmjw4cPq1WrVgoJ+eXtDodDPXr04BoVAADgVR4HldDQUH3wwQcaM2aMtm7dqrCwMNWuXVvly5f3RX0AACCA5es5KpJUokQJtWzZMtc7gAAAALzBo2tU0tPTlZiYqFKlSikqKkpRUVEqVaqUnn76aaWnp/uoRAAAEKjyfETl7NmzatKkiY4dO6Zu3bqpevXqkqRdu3Zp5syZWrJkib799lsVL17cZ8UCAIDAkuegMnr0aIWGhurAgQOKiopym3ffffdp9OjRevnll71eJAAACEx5PvUzb948vfjii24hRZKio6M1YcIEzZ0716vFAQCAwJbnoHLixAnVrFnzmvNr1aqlkydPeqUoAAAAyYOgUqpUKR0+fPia8w8dOqQSJUp4oyYAAABJHgSVtm3batiwYbp06ZLbvOzsbA0fPlz333+/V4sDAACBzaOLaRs1aqQqVaooMTFR1apVkzFGu3fv1muvvabs7Gy9/fbbvqwVAAAEmDwHldtuu02rV6/WU089paSkJBljJEk2m01t2rTRq6++qtjYWJ8VCgAAAo9HD3yLi4vT/PnzdebMGa1Zs0Zr1qzR6dOntWDBAlWuXPkPFZKamiqbzab+/fv/oeUAAIBbR74eoV+8eHHdcccdXiti/fr1euONN1SnTh2vLRMAANz8PDqi4gtZWVnq1q2b3nzzTZ5qCwAAXPg9qCQmJqp9+/Zq3br17/bNzs5WZmamywQAAG5d+f72ZG94//33tWnTJq1fvz5P/VNSUpScnOzjqgAAgFXk6YhKgwYNdO7cOUm/3KZ88eLFP7zitLQ09evXT7Nnz1bBggXz9J6kpCRlZGQ4p7S0tD9cBwAAsK48BZXdu3frwoULkqTk5GRlZWX94RVv3LhRp06dUoMGDRQSEqKQkBAtX75ckydPVkhIiHJyctzeY7fbFR4e7jIBAIBbV55O/dSrV089e/ZU8+bNZYzRiy++qCJFiuTad8SIEXlacatWrbR9+3aXtp49e6patWoaMmSIgoOD87QcAABw68pTUJk5c6ZGjhypzz//XDabTfPnz1dIiPtbbTZbnoNK0aJFVatWLZe2woULq2TJkm7tAAAgMOUpqFStWlXvv/++JCkoKEhLlixR6dKlfVoYAACAx3f9OBwOX9QhSfr66699tmwAAHDzydftyQcOHNCkSZO0e/duSVKNGjXUr18/VapUyavFAQCAwObxA98WLlyoGjVqaN26dapTp47q1KmjtWvXqmbNmlq0aJEvagQAAAHK4yMqQ4cO1YABA5SamurWPmTIELVp08ZrxQEAgMDm8RGV3bt3q3fv3m7tvXr10q5du7xSFAAAgJSPoBIZGaktW7a4tW/ZsoU7gQAAgFd5fOqnT58+evzxx3Xw4EE1bdpUkrRq1SqNHz9eAwcO9HqBAAAgcHkcVIYPH66iRYtq4sSJSkpKkiTFxMRo1KhR6tu3r9cLBAAAgcvjoGKz2TRgwAANGDBA58+fl/TLU2YBAAC8LV/PUbmKgAIAAHzJ44tpAQAAbhSCCgAAsCyCCgAAsCyPgsrly5fVqlUr7du3z1f1AAAAOHkUVAoUKKBt27b5qhYAAAAXHp/6efTRRzV9+nRf1AIAAODC49uTr1y5orfeekuLFy9Ww4YNVbhwYZf5L730kteKAwAAgc3joLJjxw41aNBAkrR3716XeTabzTtVAQAAKB9BZdmyZb6oAwAAwE2+b0/ev3+/Fi5cqJ9++kmSZIzxWlEAAABSPoLKjz/+qFatWun222/XAw88oBMnTkiSevfurUGDBnm9QAAAELg8DioDBgxQgQIFdPToURUqVMjZ3rlzZy1YsMCrxQEAgMDm8TUqX331lRYuXKjbbrvNpb1KlSo6cuSI1woDAADw+IjKhQsXXI6kXHX27FnZ7XavFAUAACDlI6jcdddd+u9//+t8bbPZ5HA4NGHCBLVs2dKrxQEAgMDm8amfCRMmqFWrVtqwYYMuXbqk5557Tjt37tTZs2e1atUqX9QIAAAClMdHVGrVqqW9e/eqefPm6tixoy5cuKC//vWv2rx5sypVquSLGgEAQIDy+IiKJEVERGjYsGHergUAAMBFvoLKuXPnNH36dO3evVuSVKNGDfXs2VMlSpTwanEAACCweXzqZ8WKFapQoYImT56sc+fO6dy5c5o8ebLi4uK0YsUKX9QIAAAClMdHVBITE9W5c2dNnTpVwcHBkqScnBw99dRTSkxM1Pbt271eJAAACEweH1HZv3+/Bg0a5AwpkhQcHKyBAwdq//79Xi0OAAAENo+DSoMGDZzXpvza7t27VbduXa8UBQAAIOXx1M+2bducP/ft21f9+vXT/v37deedd0qS1qxZoylTpig1NdU3VQIAgICUp6BSr1492Ww2GWOcbc8995xbv7///e/q3Llznlc+depUTZ06VYcPH5Yk1axZUyNGjFC7du3yvAwAAHDrylNQOXTokE9Wfttttyk1NVVVqlSRMUazZs1Sx44dtXnzZtWsWdMn6wQAADePPAWV8uXL+2TlHTp0cHk9duxYTZ06VWvWrCGoAACA/D3w7fjx41q5cqVOnTolh8PhMq9v3775KiQnJ0dz5szRhQsX1KRJk1z7ZGdnKzs72/k6MzMzX+sCAAA3B4+DysyZM/XEE08oNDRUJUuWlM1mc86z2WweB5Xt27erSZMm+vnnn1WkSBHNnTtXNWrUyLVvSkqKkpOTPS0ZFldh6Bf+LsFjh1Pb+7sEWNTNuD8DVubx7cnDhw/XiBEjlJGRocOHD+vQoUPO6eDBgx4XULVqVW3ZskVr167Vk08+qfj4eO3atSvXvklJScrIyHBOaWlpHq8PAADcPDw+onLx4kV16dJFQUEeZ5xchYaGqnLlypKkhg0bav369fr3v/+tN954w62v3W6X3W73ynoBAID1eZw2evfurTlz5viiFkmSw+FwuQ4FAAAELo+PqKSkpOjPf/6zFixYoNq1a6tAgQIu81966aU8LyspKUnt2rVTuXLldP78eb377rv6+uuvtXDhQk/LAgAAt6B8BZWFCxeqatWqkuR2Ma0nTp06pR49eujEiROKiIhQnTp1tHDhQrVp08bTsgAAwC3I46AyceJEvfXWW0pISPjDK58+ffofXgYAALh1eXyNit1uV7NmzXxRCwAAgAuPg0q/fv30yiuv+KIWAAAAFx6f+lm3bp2WLl2qzz//XDVr1nS7mPaTTz7xWnEAACCweRxUihUrpr/+9a++qAUAAMCFx0FlxowZvqgDAADAjXceLwsAAOADHh9RiYuLu+7zUvLzfT8AAAC58Tio9O/f3+X15cuXtXnzZi1YsECDBw/2Vl0AAACeB5V+/frl2j5lyhRt2LDhDxcEAABwldeuUWnXrp0+/vhjby0OAADAe0Hlo48+UokSJby1OAAAAM9P/dSvX9/lYlpjjE6ePKnTp0/rtdde82pxAAAgsHkcVDp16uTyOigoSJGRkbrnnntUrVo1b9UFAADgeVAZOXKkL+oAAABwwwPfAACAZeX5iEpQUNB1H/QmSTabTVeuXPnDRQEAAEgeBJW5c+dec97q1as1efJkORwOrxQFAAAgeRBUOnbs6Na2Z88eDR06VJ999pm6deum0aNHe7U4AAAQ2PJ1jcrx48fVp08f1a5dW1euXNGWLVs0a9YslS9f3tv1AQCAAOZRUMnIyNCQIUNUuXJl7dy5U0uWLNFnn32mWrVq+ao+AAAQwPJ86mfChAkaP368oqOj9d577+V6KggAAMCb8hxUhg4dqrCwMFWuXFmzZs3SrFmzcu33ySefeK04AAAQ2PIcVHr06PG7tycDAAB4U56DysyZM31YBgAAgDueTAsAACyLoAIAACyLoAIAACyLoAIAACyLoAIAACyLoAIAACyLoAIAACyLoAIAACyLoAIAACzLr0ElJSVFf/rTn1S0aFGVLl1anTp10p49e/xZEgAAsBC/BpXly5crMTFRa9as0aJFi3T58mXdd999unDhgj/LAgAAFpHn7/rxhQULFri8njlzpkqXLq2NGzeqRYsWfqoKAABYhV+Dym9lZGRIkkqUKJHr/OzsbGVnZztfZ2Zm3pC6AACAf9iMMcbfRUiSw+HQgw8+qPT0dK1cuTLXPqNGjVJycrJbe0ZGhsLDw31dInykwtAv/F0CAOAaDqe29/oyMzMzFRERkaff35a56ycxMVE7duzQ+++/f80+SUlJysjIcE5paWk3sEIAAHCjWeLUz9NPP63PP/9cK1as0G233XbNfna7XXa7/QZWBgAA/MmvQcUYo2eeeUZz587V119/rbi4OH+WAwAALMavQSUxMVHvvvuuPv30UxUtWlQnT56UJEVERCgsLMyfpQEAAAvw6zUqU6dOVUZGhu655x6VKVPGOX3wwQf+LAsAAFiE30/9AAAAXItl7voBAAD4LYIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLIIKAACwLL8GlRUrVqhDhw6KiYmRzWbTvHnz/FkOAACwGL8GlQsXLqhu3bqaMmWKP8sAAAAWFeLPlbdr107t2rXzZwkAAMDC/BpUPJWdna3s7Gzn68zMTD9WAwAAfO2mCiopKSlKTk6+YeurMPSLG7Yubzmc2t7fJQAA4DU31V0/SUlJysjIcE5paWn+LgkAAPjQTXVExW63y263+7sMAABwg9xUR1QAAEBg8esRlaysLO3fv9/5+tChQ9qyZYtKlCihcuXK+bEyAABgBX4NKhs2bFDLli2drwcOHChJio+P18yZM/1UFQAAsAq/BpV77rlHxhh/lgAAACyMa1QAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlEVQAAIBlWSKoTJkyRRUqVFDBggXVuHFjrVu3zt8lAQAAC/B7UPnggw80cOBAjRw5Ups2bVLdunXVtm1bnTp1yt+lAQAAP/N7UHnppZfUp08f9ezZUzVq1NDrr7+uQoUK6a233vJ3aQAAwM9C/LnyS5cuaePGjUpKSnK2BQUFqXXr1lq9erVb/+zsbGVnZztfZ2RkSJIyMzN9Up8j+6JPlutLvhoLX7oZxxkAAoUvfq9cXaYx5nf7+jWonDlzRjk5OYqKinJpj4qK0nfffefWPyUlRcnJyW7tsbGxPqvxZhMxyd8VAABuJb78vXL+/HlFRERct49fg4qnkpKSNHDgQOdrh8Ohs2fPqmTJkrLZbH6pKTMzU7GxsUpLS1N4eLhfarAixsUdY5I7xsUdY+KOMcndzTouxhidP39eMTExv9vXr0GlVKlSCg4O1g8//ODS/sMPPyg6Otqtv91ul91ud2krVqyYL0vMs/Dw8JtqJ7lRGBd3jEnuGBd3jIk7xiR3N+O4/N6RlKv8ejFtaGioGjZsqCVLljjbHA6HlixZoiZNmvixMgAAYAV+P/UzcOBAxcfHq1GjRrrjjjs0adIkXbhwQT179vR3aQAAwM/8HlQ6d+6s06dPa8SIETp58qTq1aunBQsWuF1ga1V2u10jR450OyUV6BgXd4xJ7hgXd4yJO8Ykd4EwLjaTl3uDAAAA/MDvD3wDAAC4FoIKAACwLIIKAACwLIIKAACwLIIKAACwLIJKHqSmpspms6l///7Otp9//lmJiYkqWbKkihQpooceesjtCbtHjx5V+/btVahQIZUuXVqDBw/WlStXbnD13jNq1CjZbDaXqVq1as75gTgmknTs2DE9+uijKlmypMLCwlS7dm1t2LDBOd8YoxEjRqhMmTIKCwtT69attW/fPpdlnD17Vt26dVN4eLiKFSum3r17Kysr60ZvitdUqFDBbV+x2WxKTEyUFJj7Sk5OjoYPH664uDiFhYWpUqVKGjNmjMuXsgXivnL+/Hn1799f5cuXV1hYmJo2bar169c75wfCmKxYsUIdOnRQTEyMbDab5s2b5zLfW2Owbds23XXXXSpYsKBiY2M1YcIEX2+adxhc17p160yFChVMnTp1TL9+/Zzt//jHP0xsbKxZsmSJ2bBhg7nzzjtN06ZNnfOvXLliatWqZVq3bm02b95svvzyS1OqVCmTlJTkh63wjpEjR5qaNWuaEydOOKfTp0875wfimJw9e9aUL1/eJCQkmLVr15qDBw+ahQsXmv379zv7pKammoiICDNv3jyzdetW8+CDD5q4uDjz008/Ofvcf//9pm7dumbNmjXmm2++MZUrVzZdu3b1xyZ5xalTp1z2k0WLFhlJZtmyZcaYwNxXxo4da0qWLGk+//xzc+jQITNnzhxTpEgR8+9//9vZJxD3lUceecTUqFHDLF++3Ozbt8+MHDnShIeHm++//94YExhj8uWXX5phw4aZTz75xEgyc+fOdZnvjTHIyMgwUVFRplu3bmbHjh3mvffeM2FhYeaNN964UZuZbwSV6zh//rypUqWKWbRokbn77rudQSU9Pd0UKFDAzJkzx9l39+7dRpJZvXq1MeaXHS8oKMicPHnS2Wfq1KkmPDzcZGdn39Dt8JaRI0eaunXr5jovUMdkyJAhpnnz5tec73A4THR0tPnXv/7lbEtPTzd2u9289957xhhjdu3aZSSZ9evXO/vMnz/f2Gw2c+zYMd8VfwP169fPVKpUyTgcjoDdV9q3b2969erl0vbXv/7VdOvWzRgTmPvKxYsXTXBwsPn8889d2hs0aGCGDRsWkGPy26DirTF47bXXTPHixV3+/QwZMsRUrVrVx1v0x3Hq5zoSExPVvn17tW7d2qV948aNunz5skt7tWrVVK5cOa1evVqStHr1atWuXdvlCbtt27ZVZmamdu7ceWM2wAf27dunmJgYVaxYUd26ddPRo0clBe6Y/O9//1OjRo308MMPq3Tp0qpfv77efPNN5/xDhw7p5MmTLuMSERGhxo0bu4xLsWLF1KhRI2ef1q1bKygoSGvXrr1xG+Mjly5d0jvvvKNevXrJZrMF7L7StGlTLVmyRHv37pUkbd26VStXrlS7du0kBea+cuXKFeXk5KhgwYIu7WFhYVq5cmVAjslveWsMVq9erRYtWig0NNTZp23bttqzZ4/OnTt3g7Ymf/z+CH2rev/997Vp0yaXc6VXnTx5UqGhoW7f3BwVFaWTJ086+/z2awCuvr7a52bTuHFjzZw5U1WrVtWJEyeUnJysu+66Szt27AjYMTl48KCmTp2qgQMH6vnnn9f69evVt29fhYaGKj4+3rlduW33r8eldOnSLvNDQkJUokSJm3Zcfm3evHlKT09XQkKCpMD99zN06FBlZmaqWrVqCg4OVk5OjsaOHatu3bpJUkDuK0WLFlWTJk00ZswYVa9eXVFRUXrvvfe0evVqVa5cOSDH5Le8NQYnT55UXFyc2zKuzitevLhP6vcGgkou0tLS1K9fPy1atMgt6Qeyq3/5SVKdOnXUuHFjlS9fXh9++KHCwsL8WJn/OBwONWrUSOPGjZMk1a9fXzt27NDrr7+u+Ph4P1dnDdOnT1e7du0UExPj71L86sMPP9Ts2bP17rvvqmbNmtqyZYv69++vmJiYgN5X3n77bfXq1Utly5ZVcHCwGjRooK5du2rjxo3+Lg0WwamfXGzcuFGnTp1SgwYNFBISopCQEC1fvlyTJ09WSEiIoqKidOnSJaWnp7u874cfflB0dLQkKTo62u0uhquvr/a52RUrVky333679u/fr+jo6IAckzJlyqhGjRoubdWrV3eeEru6Xblt96/H5dSpUy7zr1y5orNnz96043LVkSNHtHjxYj322GPOtkDdVwYPHqyhQ4eqS5cuql27trp3764BAwYoJSVFUuDuK5UqVdLy5cuVlZWltLQ0rVu3TpcvX1bFihUDdkx+zVtjcDP/myKo5KJVq1bavn27tmzZ4pwaNWqkbt26OX8uUKCAlixZ4nzPnj17dPToUTVp0kSS1KRJE23fvt1l51m0aJHCw8PdfrHdrLKysnTgwAGVKVNGDRs2DMgxadasmfbs2ePStnfvXpUvX16SFBcXp+joaJdxyczM1Nq1a13GJT093eUvyKVLl8rhcKhx48Y3YCt8Z8aMGSpdurTat2/vbAvUfeXixYsKCnL9X25wcLAcDock9pXChQurTJkyOnfunBYuXKiOHTsG/JhI3tsvmjRpohUrVujy5cvOPosWLVLVqlUtfdpHErcn59Wv7/ox5pfbK8uVK2eWLl1qNmzYYJo0aWKaNGninH/19sr77rvPbNmyxSxYsMBERkbe1LdXDho0yHz99dfm0KFDZtWqVaZ169amVKlS5tSpU8aYwByTdevWmZCQEDN27Fizb98+M3v2bFOoUCHzzjvvOPukpqaaYsWKmU8//dRs27bNdOzYMddbC+vXr2/Wrl1rVq5caapUqXJT3V6Zm5ycHFOuXDkzZMgQt3mBuK/Ex8ebsmXLOm9P/uSTT0ypUqXMc8895+wTiPvKggULzPz5883BgwfNV199ZerWrWsaN25sLl26ZIwJjDE5f/682bx5s9m8ebORZF566SWzefNmc+TIEWOMd8YgPT3dREVFme7du5sdO3aY999/3xQqVIjbk28lvw0qP/30k3nqqadM8eLFTaFChcxf/vIXc+LECZf3HD582LRr186EhYWZUqVKmUGDBpnLly/f4Mq9p3PnzqZMmTImNDTUlC1b1nTu3NnleSGBOCbGGPPZZ5+ZWrVqGbvdbqpVq2amTZvmMt/hcJjhw4ebqKgoY7fbTatWrcyePXtc+vz444+ma9eupkiRIiY8PNz07NnTnD9//kZuhtctXLjQSHLbVmMCc1/JzMw0/fr1M+XKlTMFCxY0FStWNMOGDXO5XTQQ95UPPvjAVKxY0YSGhpro6GiTmJho0tPTnfMDYUyWLVtmJLlN8fHxxhjvjcHWrVtN8+bNjd1uN2XLljWpqak3ahP/EJsxv3osIgAAgIVwjQoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALAsggoAALCs/wMaSYTu41RsdAAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGzCAYAAAA1yP25AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAyiklEQVR4nO3dd3hUZcL+8XsSSAglgQABkUAQsii9KVJEKYrIq6DuCi4qIAoqGCCIkpWOGkBKXhSxA7qLIGCQFWkGKSLSI0WkI7xKQEoSaoDk+f3hlfk5pM3BGWZO+H6uay6d55yZc+chM9ycMuMwxhgBAADYUICvAwAAAFwrigwAALAtigwAALAtigwAALAtigwAALAtigwAALAtigwAALAtigwAALAtigwAALAtigxgM1FRUerRo4evYxR6b775pm655RYFBgaqQYMG13U71+PPuEePHoqKivLqNoDrgSID+NCMGTPkcDi0adOmXJffc889qlOnzl/eztdff62RI0f+5ee5USxbtkwvv/yyWrRooenTp+uNN97Ic91Zs2YpISHB69sBkLsivg4AwJrdu3crIMDav0G+/vprTZ06lTLjphUrViggIEAfffSRgoKC8l131qxZ2rFjhwYMGOCx7VzLnzFwo+KVAthMcHCwihYt6usYlpw7d87XESw5fvy4QkJCCiwx3tqOHf+MAV+hyAA2c/X5E5cvX9aoUaMUHR2tYsWKqWzZsmrZsqWWL18u6Y9zIaZOnSpJcjgczlu2c+fOadCgQYqMjFRwcLBq1qypCRMmyBjjst0LFy4oJiZG5cqVU6lSpfTQQw/p119/lcPhcNnTM3LkSDkcDv3000/65z//qTJlyqhly5aSpG3btqlHjx665ZZbVKxYMVWsWFFPP/20Tp486bKt7OfYs2ePnnjiCYWFhal8+fIaNmyYjDE6cuSIOnXqpNDQUFWsWFETJ050a+6uXLmiMWPGqHr16goODlZUVJT+9a9/KSMjw7mOw+HQ9OnTde7cOedczZgxI9fnu+eee7Ro0SL98ssvznXdPe8kv+1c/WecfQhy7dq1io2NVfny5VWiRAk9/PDD+v33312e98svv1THjh1VqVIlBQcHq3r16hozZowyMzPdygXYDYeWAD+QlpamEydO5Bi/fPlygY8dOXKk4uPj9cwzz+iOO+5Qenq6Nm3apC1btujee+9Vnz599Ntvv2n58uX69NNPXR5rjNFDDz2kb7/9Vr169VKDBg20dOlSDR48WL/++qsmT57sXLdHjx76/PPP9eSTT+rOO+/UqlWr1LFjxzxz/eMf/1B0dLTeeOMNZylavny5Dhw4oJ49e6pixYrauXOn3n//fe3cuVM//PCDS8GSpC5duui2227T2LFjtWjRIr322msKDw/Xe++9pzZt2mjcuHH6z3/+o5deekm33367WrVqle9cPfPMM5o5c6b+/ve/a9CgQVq/fr3i4+O1a9cuJSYmSpI+/fRTvf/++9qwYYM+/PBDSVLz5s1zfb5XX31VaWlp+r//+z/nXJUsWTLfDNmsbCfbiy++qDJlymjEiBE6dOiQEhIS1K9fP82ZM8e5zowZM1SyZEnFxsaqZMmSWrFihYYPH6709HS9+eabbmUDbMUA8Jnp06cbSfneateu7fKYqlWrmu7duzvv169f33Ts2DHf7fTt29fk9nJfsGCBkWRee+01l/G///3vxuFwmH379hljjNm8ebORZAYMGOCyXo8ePYwkM2LECOfYiBEjjCTz+OOP59je+fPnc4x99tlnRpJZvXp1jufo3bu3c+zKlSumcuXKxuFwmLFjxzrHT58+bUJCQlzmJDfJyclGknnmmWdcxl966SUjyaxYscI51r17d1OiRIl8ny9bx44dTdWqVd1a92p5befqP+Ps35N27dqZrKws5/jAgQNNYGCgSU1NdY7lNsd9+vQxxYsXNxcvXnTZ9rXmBvwJh5YAPzB16lQtX748x61evXoFPrZ06dLauXOn9u7da3m7X3/9tQIDAxUTE+MyPmjQIBljtHjxYknSkiVLJEkvvPCCy3ovvvhins/93HPP5RgLCQlx/v/Fixd14sQJ3XnnnZKkLVu25Fj/mWeecf5/YGCgmjRpImOMevXq5RwvXbq0atasqQMHDuSZRfrjZ5Wk2NhYl/FBgwZJkhYtWpTv4/1B7969XfZa3XXXXcrMzNQvv/ziHPvzHJ85c0YnTpzQXXfdpfPnz+vnn3++rnmB64FDS4AfuOOOO9SkSZMc42XKlMn1kNOfjR49Wp06ddLf/vY31alTR/fff7+efPJJt0rQL7/8okqVKqlUqVIu47fddptzefZ/AwICVK1aNZf1atSokedzX72uJJ06dUqjRo3S7Nmzdfz4cZdlaWlpOdavUqWKy/2wsDAVK1ZM5cqVyzF+9Xk2V8v+Ga7OXLFiRZUuXdqlDPirq+ejTJkykqTTp087x3bu3KmhQ4dqxYoVSk9Pd1k/tzkG7I4iA9hcq1attH//fn355ZdatmyZPvzwQ02ePFnvvvuuyx6N6+3PewayPfbYY/r+++81ePBgNWjQQCVLllRWVpbuv/9+ZWVl5Vg/MDDQrTFJOU5OzsvV5+HYSUE/e2pqqu6++26FhoZq9OjRql69uooVK6YtW7bolVdeyXWOAbujyACFQHh4uHr27KmePXvq7NmzatWqlUaOHOksMnn95V21alV98803OnPmjMtemexDEFWrVnX+NysrSwcPHlR0dLRzvX379rmd8fTp00pKStKoUaM0fPhw5/i1HBK7Ftk/w969e517nCTp2LFjSk1Ndf6sVvlTMVq5cqVOnjypL774wuXE54MHD/owFeBdnCMD2NzVh1RKliypGjVquFxSXKJECUl//Iv9zx544AFlZmbq7bffdhmfPHmyHA6HOnToIElq3769JOmdd95xWe+tt95yO2f23oSr95xc66fiWvXAAw/kur1JkyZJUr5XYOWnRIkSfnPIJrc5vnTpUo4/N6AwYY8MYHO1atXSPffco8aNGys8PFybNm3SvHnz1K9fP+c6jRs3liTFxMSoffv2CgwMVNeuXfXggw+qdevWevXVV3Xo0CHVr19fy5Yt05dffqkBAwaoevXqzsc/+uijSkhI0MmTJ52XX+/Zs0eSe3slQkND1apVK40fP16XL1/WzTffrGXLll23vQX169dX9+7d9f777zsPwWzYsEEzZ85U586d1bp162t63saNG2vOnDmKjY3V7bffrpIlS+rBBx/0cHr3NG/eXGXKlFH37t0VExMjh8OhTz/91O3DboAdUWQAm4uJidHChQu1bNkyZWRkqGrVqnrttdc0ePBg5zqPPPKIXnzxRc2ePVv//ve/ZYxR165dFRAQoIULF2r48OGaM2eOpk+frqioKL355pvOq3myffLJJ6pYsaI+++wzJSYmql27dpozZ45q1qypYsWKuZV11qxZevHFFzV16lQZY3Tfffdp8eLFqlSpkkfnJC8ffvihbrnlFs2YMUOJiYmqWLGi4uLiNGLEiGt+zhdeeEHJycmaPn26Jk+erKpVq/qsyJQtW1ZfffWVBg0apKFDh6pMmTJ64okn1LZt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cZlhYZ6DyZMnm9DQUDN37lyzd+9eM3ToUFOsWDGzb98+5zr333+/adiwoVm/fr357rvvTHR0tG0uOzam4Hm4dOmSqVGjhrnrrrvM+vXrzb59+8yECROMw+EwixYtcj6PnedhyJAhZtWqVebgwYNm27ZtZsiQIcbhcJhly5YZY/64/LpKlSpmxYoVZtOmTaZZs2amWbNmzsfb/bVgTP5zcCO8J2Yr6HfhaoXtfTE3FBk/JCnX2/Tp040xxnz77bd5rnPw4EHn8xw6dMh06NDBhISEmHLlyplBgwY5L0X0dwXNQV6P+fML1pgbYw7i4+NN5cqVTfHixU2zZs3MmjVrXJafPHnSPP7446ZkyZImNDTU9OzZ05w5c+Y6/iR/jTvzsGfPHvPII4+YiIgIU7x4cVOvXr0cl2PbeR6efvppU7VqVRMUFGTKly9v2rZt6/IX14ULF8wLL7xgypQpY4oXL24efvhhc/ToUZfnsPNrwZj85+BGeE/MVtDvwtUK2/tibhzGGOO9/T0AAADewzkyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtigyAADAtv4f282T47hfAA8AAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGzCAYAAAAMr0ziAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3o0lEQVR4nO3dd3RUdeL//9ckIZMAKZRQAjFAgChd4AtSpAiKgIofd4UoJSCCq4EAAYGIlAASQCmCiOsuJDbEQ1NXOkhZBSwU6dKCsEiRGooEyNzfH/4yh3GC5IZJ5gaej3PmyLznzr2vvDOYF7fFZhiGIQAAAAvz8XYAAACA26GwAAAAy6OwAAAAy6OwAAAAy6OwAAAAy6OwAAAAy6OwAAAAy6OwAAAAy6OwAAAAy6OwoECpUKGCunfv7u0Yd70333xTlSpVkq+vr+rUqePtOHet7t27q2jRot6OkWdGjRolm82m06dPezsK7gIUFnhNamqqbDabfvzxx2xfb9GihWrUqHHH21myZIlGjRp1x+u5V6xYsUKDBw9WkyZNlJKSonHjxnk7EgDIz9sBADN+/vln+fiY69lLlizRjBkzKC059PXXX8vHx0ezZs2Sv7+/t+MAgCT2sKCAsdvtKlSokLdjmHL58mVvRzDl1KlTCgwMpKygwLhy5Yq3IyAfUFhQoPz5HJbr168rKSlJVapUUUBAgEqUKKGmTZtq5cqVkv44R2DGjBmSJJvN5nxkuXz5sgYOHKiIiAjZ7XZFR0frrbfe0p9/ifnvv/+u+Ph4lSxZUkFBQXrqqad07Ngx2Ww2lz03Wcfsd+/ereeff17FihVT06ZNJUnbt29X9+7dValSJQUEBKhMmTJ64YUXdObMGZdtZa1j37596tKli0JCQhQWFqbhw4fLMAwdPXpUHTp0UHBwsMqUKaNJkyblaO5u3LihMWPGKCoqSna7XRUqVNBrr72mjIwM5zI2m00pKSm6fPmyc65SU1Nvuc6sw3bbt29X8+bNVbhwYVWuXFnz58+XJK1bt04NGzZUYGCgoqOjtWrVKpf3//LLL3rllVcUHR2twMBAlShRQs8++6wOHz7sXMYwDLVs2VJhYWE6deqUc/zatWuqWbOmoqKiclwKDx8+LJvNprfeekszZsxQpUqVVLhwYT322GM6evSoDMPQmDFjVL58eQUGBqpDhw46e/asyzq++OILtW/fXuHh4bLb7YqKitKYMWOUmZnptr3vvvtO7dq1U7FixVSkSBHVqlVLb7/9tttyx44d09NPP62iRYsqLCxMgwYNynZ9fyXre7F79261bNlShQsXVrly5TRx4kSX5bIOxd48x5K0du1a2Ww2rV271m2duf3+Zjl9+rQ6duyo4OBglShRQv369dPVq1fdlvv4449Vr149BQYGqnjx4oqJidHRo0ez/To3b96sZs2aqXDhwnrttddMzRUKJgoLvO7ChQs6ffq02+P69eu3fe+oUaOUlJSkli1b6p133tGwYcN03333acuWLZKkl156SY8++qgk6aOPPnI+pD9+ED711FOaMmWKHn/8cU2ePFnR0dF69dVXlZCQ4LKd7t27a/r06WrXrp0mTJigwMBAtW/f/pa5nn32WV25ckXjxo1Tr169JEkrV67UoUOH1KNHD02fPl0xMTGaO3eu2rVr51aQJKlTp05yOBwaP368GjZsqLFjx2rq1Kl69NFHVa5cOU2YMEGVK1fWoEGDtH79+tvO1YsvvqgRI0aobt26mjJlipo3b67k5GTFxMQ4l/noo4/08MMPy263O+eqWbNmf7nec+fO6YknnlDDhg01ceJE2e12xcTE6LPPPlNMTIzatWun8ePH6/Lly/r73/+uixcvOt/7ww8/aMOGDYqJidG0adP0j3/8Q6tXr1aLFi2c/2q22WyaPXu2rl69qn/84x/O944cOVK7du1SSkqKihQpctuv/2affPKJ3n33XfXt21cDBw7UunXr1LFjR73++utatmyZhgwZot69e+s///mPBg0a5PLe1NRUFS1aVAkJCXr77bdVr149jRgxQkOHDnVZbuXKlWrWrJl2796tfv36adKkSWrZsqW++uorl+UyMzPVpk0blShRQm+99ZaaN2+uSZMm6f333zf1NUl/fC8ef/xx1a5dW5MmTdL999+vIUOGaOnSpabXdfM6c/v9zdKxY0ddvXpVycnJateunaZNm6bevXu7LPPGG2+oW7duqlKliiZPnqz+/ftr9erVatasmc6fP++y7JkzZ9S2bVvVqVNHU6dOVcuWLXP99aEAMQAvSUlJMST95aN69eou74mMjDRiY2Odz2vXrm20b9/+L7cTFxdnZPdR//zzzw1JxtixY13G//73vxs2m804cOCAYRiGsXnzZkOS0b9/f5flunfv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/fv3d/6PvV69evrb3/6mqVOn6syZM3rooYe0bt067du3T1LODrMEBwerWbNmmjhxoq5fv65y5cppxYoVbv8yzyu1a9dWbGys3n//fedhje+//14ffPCBnn76aa9dFvrEE0/oo48+UkhIiKpVq6aNGzdq1apVKlGihMtyKSkpWrx4sVJTU1W+fHlJf/zQ69Kli2bOnOl2QnReady4sYoVK6bY2FjFx8fLZrPpo48+cvsh6+Pjo5kzZ+rJJ59UnTp11KNHD5UtW1Z79+7Vrl27tHz58nzJm53q1avroYceUmJios6ePavixYtr7ty5unHjRp5tMy0tTU899ZQef/xxbdy4UR9//LGef/551a5dW9IfJWrs2LFKTEzU4cOH9fTTTysoKEhpaWlatGiRevfu7XZ5Oe49FBYUaPHx8fryyy+1YsUKZWRkKDIyUmPHjtWrr77qXOaZZ55R3759NXfuXH388ccyDEMxMTHy8fHRl19+qREjRuizzz5TSkqKKlSooDfffNN59UyWDz/8UGXKlNGnn36qRYsWqXXr1vrss88UHR2tgICAHGWdM2eO+vbtqxkzZsgwDD322GNaunSpwsPDPTont/Lvf/9blSpVUmpqqhYtWqQyZcooMTFRI0eOzJftZ+ftt9+Wr6+vPvnkE129elVNmjTRqlWrnHu1JOl///ufBgwYoCeffFKxsbHO8c6dO2vBggUaPHiw2rZtm+2Jzp5WokQJffXVVxo4cKBef/11FStWTF26dFGrVq1cMkt/7Jlbs2aNkpKSNGnSJDkcDkVFRTnvy+NNn3zyiV566SWNHz9eoaGh6tmzp1q2bOm8Z5GnffbZZ8571fj5+alPnz568803XZYZOnSoqlatqilTpigpKUnSHydBP/bYY3rqqafyJBcKFpvh7f2TQAG1bds2Pfjgg/r444/VuXNnb8cBgLsa57AAOfD777+7jU2dOlU+Pj63vRMsAODOcUgIyIGJEydq8+bNatmypfz8/LR06VItXbpUvXv3drsfBfJfZmamfvvtt79cpmjRom6XxxYEZ8+e1bVr1275uq+vr9t9XIC7EYeEgBxYuXKlkpKStHv3bl26dEn33XefunbtqmHDhrncGRXecfjw4duewzJy5EiXX1RZULRo0ULr1q275euRkZFuv8gQuBtRWAAUeFevXtU333zzl8tUqlRJlSpV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AHAz03tYYmJiNGTIEM2bN082m00Oh0PffvutBg0apG7dut1RmLVr197R+wEAwN3J9B6WcePG6f7771dERIQuXbqkatWqqVmzZmrcuLFef/31vMgIAADucab2sBiGoRMnTmjatGkaMWKEduzYoUuXLunBBx9UlSpV8iojAAC4x5kuLJUrV9auXbtUpUoVRURE5FUuAAAAJ1OHhHx8fFSlShWdOXMmr/IAAAC4MX0Oy/jx4/Xqq69q586deZEHAADAjemrhLp166YrV66odu3a8vf3V2BgoMvrZ8+e9Vg4AAAAyQK/rRkAAOB2TBWW69eva926dRo+fLgqVqyYV5kAAABcmDqHpVChQlqwYEFeZQEAAMiW6ZNun376aX3++ed5EAUAACB7ps9hqVKlikaPHq1vv/1W9erVU5EiRVxej4+P91g4AAAAKReFZdasWQoNDdXmzZu1efNml9dsNhuFBQAAeJzpwpKWlpYXOQAAAG7J9DksAAAA+c30HpYXXnjhL1+fPXt2rsMAAABkx3RhOXfunMvz69eva+fOnTp//rweeeQRjwUDAADIYrqwLFq0yG3M4XDo5ZdfVlRUlEdCAQAA3Mwj57D4+PgoISFBU6ZM8cTqAAAAXHjspNuDBw/qxo0bnlodAACAk+lDQgkJCS7PDcPQ8ePHtXjxYsXGxnosGAAAQBbThWXr1q0uz318fBQWFqZJkybd9goiAACA3DBdWNasWZMXOQAAAG7J9DksaWlp2r9/v9v4/v37dfjwYU9kAgAAcGG6sHTv3l0bNmxwG//uu+/UvXt3T2QCAABwYbqwbN26VU2aNHEbf+ihh7Rt2zZPZAIAAHBhurDYbDZdvHjRbfzChQvKzMz0SCgAAICbmS4szZo1U3Jysks5yczMVHJyspo2berRcAAAAFIurhKaMGGCmjVrpujoaD388MOSpP/+979KT0/X119/7fGAAAAApvewVKtWTdu3b1fHjh116tQpXbx4Ud26ddPevXtVo0aNvMgIAADucab3sEhSeHi4xo0b5+ksAAAA2TK9hyUlJUXz5s1zG583b54++OADj4QCAAC4menCkpycrJIlS7qNlypVir0uAAAgT5guLEeOHFHFihXdxiMjI3XkyBGPhAIAALiZ6cJSqlQpbd++3W38p59+UokSJTwSCgAA4GamC8tzzz2n+Ph4rVmzRpmZ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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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y3379qly5cpu7atVq1basWOHS9vOnTtVrVo1d8sCAABFkNtBZcKECVq3bp0GDBigl156STVr1pQkzZo1Sy1btnRrX4MHD9aKFSv06quvavfu3frkk080ZcoUxcXFuVsWAAAogtxeo3ItFy9elL+/v0qWLOnW677++mslJiZq165dioqKUkJCgvr161eg17pzjgvWxRoVAChe3Pn7Xaj7qKSnp2vWrFnas2ePhg4dqtDQUG3btk2VK1fW7bff7ta+/vSnP+lPf/pTYcoAAABFnNtBZdOmTWrbtq1CQkK0f/9+9evXT6Ghofryyy918OBB/fvf//ZGnQAAoBhye41KQkKCevfurV27dqlUqVLO9kceeURLly71aHEAAKB4czuorF69Wk8//XSe9ttvv11Hjx71SFEAAABSIYKK3W7P99b1O3fuVFhYmEeKAgAAkAoRVB599FGNHj1aOTk5kiSbzaaDBw/qxRdf1GOPPebxAgEAQPHldlAZP368zp07p0qVKunChQu67777VLNmTZUrV05jxozxRo0AAKCYcvuqn+DgYKWmpmrZsmXauHGjzp07p8aNG6tdu3beqA8AABRjhbqPivTr7e9btWrlyVoAAABcuH3qJz4+XhMnTszT/s4772jQoEGeqAkAAEBSIYLKF198ke9MSsuWLTVr1iyPFAUAACAVIqicOnVKwcHBedqDgoJ08uRJjxQFAAAgFSKo1KxZU/PmzcvTPnfuXN1xxx0eKQoAAEAqxGLahIQEDRgwQCdOnNADDzwgSVq4cKHGjx+vCRMmeLo+AABQjLkdVPr06aPs7GyNGTNGL7/8siSpevXqmjx5snr16uXxAgEAQPFVqMuT+/fvr/79++vEiRMKDAxU2bJlPV0XAABA4e+jIonP9gEAAF7l9mLaY8eO6YknnlBERIRKlCghf39/lwcAAICnuD2jEhsbq4MHD2r48OG67bbbZLPZvFEXAACA+0Hlxx9/1A8//KBGjRp5oRwAAID/4/apn8jISBljvFELAACAC7eDyoQJEzRs2DDt37/fC+UAAAD8H7dP/XTr1k3nz59XjRo1VLp0aZUsWdJl++nTpz1WHAAAKN7cDircfRYAANwsbgeVmJgYb9QBAACQh9trVCRpz549+sc//qEePXro+PHjkn79UMKtW7d6tDgAAFC8uR1UlixZovr162vlypX6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tLS0m1ghAAC42SwxozJgwAB9/fXXWrp0qapUqXLNfna7XXa7/SZWBgAAfMmnQcUYo+eee06zZ8/W999/r6ioKF+WAwAALManQSUuLk6ffPKJvvrqK5UrV05Hjx6VJAUHByswMNCXpQEAAAvw6RqVyZMnKyMjQ/fff79uu+025+Ozzz7zZVkAAMAifH7qBwAA4Fosc9UPAADA1QgqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsggqAADAsnwaVJYuXapOnTopIiJCNptNc+bM8WU5AADAYnwaVLKystSwYUNNmjTJl2UAAACLKuHLg3fo0EEdOnTwZQkAAMDCfBpU3JWdna3s7Gzn88zMTB9WAwAAvO2WWkybnJys4OBg5yMyMtLXJQEAAC+6pYJKYmKiMjIynI+0tDRflwQAALzoljr1Y7fbZbfbfV0GAAC4SW6pGRUAAFC8+HRG5dy5c9q9e7fz+b59+7RhwwaFhoaqatWqPqwMAABYgU+Dypo1a9SmTRvn84SEBElSTEyMpk2b5qOqAACAVfg0qNx///0yxviyBAAAYGGsUQEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZFUAEAAJZliaAyadIkVa9eXaVKlVLz5s21atUqX5cEAAAswOdB5bPPPlNCQoJGjhypdevWqWHDhmrfvr2OHz/u69IAAICP+TyovPHGG+rXr5969+6tOnXq6N1331Xp0qX14Ycf+ro0AADgYyV8efBLly5p7dq1SkxMdLb5+fmp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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi8AAAGzCAYAAADnmPfhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA+y0lEQVR4nO3deZyN9f//8eeZYY6xzIxhxpDJHg0yIkRGoiItWiVlTdtoiKSpDxpkpEgKpYRvm8rW51PZKdrssu8mym7MjCEzxrx/f/SbkzMLc83izMXjfrudW5339T7X9bre53I8Xdf7OsdhjDECAACwCS9PFwAAAGAF4QUAANgK4QUAANgK4QUAANgK4QUAANgK4QUAANgK4QUAANgK4QUAANgK4QUAANgK4QVFWtWqVdW9e3dPl3HFe/PNN1W9enV5e3srPDw8x37du3dX1apVL1tdBS0uLk4Oh0PTpk3zdCnZSk5O1pNPPqmQkBA5HA7169fP0yUVuMI4hux+XMI6wgsum2nTpsnhcGjNmjXZLr/11ltVr169fG/n+++/12uvvZbv9VwtFi5cqJdeekktWrTQ1KlTNXLkyELZzsiRIzV37txCWfeVYuTIkZo2bZqeffZZffLJJ3riiSc8XRJQJBXzdAHAxezYsUNeXtYy9vfff68JEyYQYHJp6dKl8vLy0pQpU+Tj41No2xk5cqQeeughdezYsdC2YXdLly5Vs2bNNHToUE+XUmg+/PBDpaene7oM2BxnXlCkOZ1OFS9e3NNlWHL69GlPl2DJ0aNH5evrW6jBpbCcPXvW9n8Rpqen6+zZs5L+eS8CAgI8W1AhK168uJxOp6fLgM0RXlCkZZ7zcu7cOcXExKhWrVoqUaKEypUrp1tuuUWLFi2S9M+17wkTJkiSHA6H65Hh9OnTGjBggEJDQ+V0OlW7dm299dZbyvzj6n///beioqJUvnx5lSlTRvfee6/++usvORwOtzM6r732mhwOh7Zu3arHHntMZcuW1S233CJJ2rhxo7p3767q1aurRIkSCgkJUc+ePXXixAm3bWWsY+fOnXr88cfl7++voKAgDR48WMYYHThwQPfdd5/8/PwUEhKiMWPG5Grs0tLSNHz4cNWoUUNOp1NVq1bVK6+8opSUFFcfh8OhqVOn6vTp066xsjof5K233lLz5s1Vrlw5+fr6qlGjRpo5c6ZbH4fDodOnT2v69Omu7Vz4vv7111/q2bOnKlSoIKfTqbp16+rjjz92W8cPP/wgh8OhGTNm6D//+Y+uueYalSxZUklJSYqPj9eLL76o+vXrq3Tp0vLz81P79u31+++/W9qXnLz77ruqW7euSpYsqbJly6px48b6/PPPXctzmnOR8d5mHos+ffros88+U926deV0OjV//nw5HA7t27dP3333nWuM4uLilJqaqiFDhqhRo0by9/dXqVKl1LJlSy1btizL9tLT0/XOO++ofv36KlGihIKCgtSuXbssl2o//fRTNWrUSL6+vgoMDNSjjz6qAwcO5Ho8EhIS5O3trfHjx7vajh8/Li8vL5UrV87tz9Ozzz6rkJCQHMcqYx7SW2+9pcmTJ7uO15tuukmrV6/Osu25c+eqXr16KlGihOrVq6c5c+bkum5cObhshMsuMTFRx48fz9J+7ty5S772tddeU2xsrJ588kk1adJESUlJWrNmjdatW6fbb79dTz/9tA4ePKhFixbpk08+cXutMUb33nuvli1bpl69eik8PFwLFizQwIED9ddff+ntt9929e3evbu++uorPfHEE2rWrJl+/PFHdejQIce6Hn74YdWqVUsjR450fXAvWrRIe/fuVY8ePRQSEqItW7Zo8uTJ2rJli3777bcsf6l16tRJ119/vUaNGqXvvvtOI0aMUGBgoD744APddttteuONN/TZZ5/pxRdf1E033aSIiIiLjtWTTz6p6dOn66GHHtKAAQO0cuVKxcbGatu2ba4P/E8++USTJ0/WqlWr9NFHH0mSmjdvfsn34ULvvPOO7r33XnXp0kWpqamaMWOGHn74YX377beuMfvkk09c79lTTz0lSapRo4Yk6ciRI2rWrJnrL/WgoCDNmzdPvXr1UlJSUpZJq8OHD5ePj49efPFFpaSkyMfHR1u3btXcuXP18MMPq1q1ajpy5Ig++OADtWrVSlu3blWlSpUs7dOFPvzwQ0VFRemhhx5S3759dfbsWW3cuFErV67UY489lqd1Ll26VF999ZX69Omj8uXLq2LFivrkk0/0wgsvqHLlyhowYIAkKSgoSElJSfroo4/UuXNn9e7dW6dOndKUKVN05513atWqVW4TrHv16qVp06apffv2evLJJ5WWlqYVK1bot99+U+PGjSVJr7/+ugYPHqxHHnlETz75pI4dO6Z3331X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Lbfcop49eyo+Pt71HTwXjgWuApf79iZcvTJulV69enW2y1u1anXJW6VHjBhhmjRpYgICAoyvr6+pU6eOef31101qaqqrT1pamnn++edNUFCQcTgcbreqnjp1yrzwwgumUqVKpnjx4qZWrVrmzTffdN1KmuH06dMmMjLSBAYGmtKlS5uOHTuaHTt2GEluty5n3Ap77NixLPvz559/mvvvv98EBAQYf39/8/DDD5uDBw/meLt15nXkdAtzduOUnXPnzpmYmBhTrVo1U7x4cRMaGmqio6PN2bNnc7Wd7GR3S/CUKVNMrVq1jNPpNHXq1DFTp07N9hbh7du3m4iICOPr62skub2vR44cMZGRkSY0NNQUL17chISEmDZt2pjJkye7+mTcKv31119nqevs2bNmwIABpmLFisbX19e0aNHC/Prrr6ZVq1amVatWrn55uVX6gw8+MBEREaZcuXLG6XSaGjVqmIEDB5rExES3fgsXLjT16tUzPj4+pnbt2ubTTz/N8VbpyMjIbLeV3a3S6enpZuTIkaZKlSrG6XSahg0bmm+//Tbb9yItLc28+eabpk6dOsbHx8cEBQWZ9u3bm7Vr17r1mzVrlrnllltMqVKlTKlSpUydOnVMZGSk2bFjR67HJUNwcLCRZI4cOeJq++mnn4wk07Jlyyz9c7pV+s0338zSN/OflYzar7/+euN0Ok1YWJiZPXt2jreq48rlMIbZUEBubNiwQQ0bNtSnn36qLl26eLocALhqMecFyMbff/+dpW3cuHHy8vK65DfbAgAKF3NegGyMHj1aa9euVevWrVWsWDHNmzdP8+bN01NPPaXQ0FBPl4cCkJqaesn5NP7+/pZua74S/P3339l+D9GFAgMDbflDnrhycNkIyMaiRYsUExOjrVu3Kjk5Wddee62eeOIJvfrqqypWjMx/Jfjhhx8uOXF56tSpbj8geTWYNm2aevTocdE+y5Yt06233np5CgKyQXgBcFU6efKk1q5de9E+devWVcWKFS9TRUXDoUOHtGXLlov2adSokdtX+QOXG+EFAADYChN2AQCArdj64n16eroOHjyoMmXKFPpvuAAAgIJhjNGpU6dUqVKlXP32VWa2Di8HDx7kzg8AAGzqwIEDqly5suXX2Tq8ZHw194EDB+Tn5+fhagAAQG4kJSUpNDTU7UdyrbB1eMm4VOTn50d4AQDA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rRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRBeAACArRSJ8DJhwgRVrVpVJUqUUNOmTbVq1SpPlwQAAIooj4eXL7/8Uv3799fQoUO1bt06NWjQQHfeeaeOHj3q6dIAAEAR5PHwMnbsWPXu3Vs9evRQWFiY3n//fZUsWVIff/yxp0sDAABFUDFPbjw1NVVr165VdHS0q83Ly0tt27bVr7/+mqV/SkqKUlJSXM8TExMlSUlJSYVSX3rKmUJZLwAgfwrrc7+w2fHvlcIY64x1GmPy9HqPhpfjx4/r/PnzqlChglt7hQoVtH379iz9Y2NjFRMTk6U9NDS00GoEABQ9/uM8XcHVozDH+tSpU/L397f8Oo+GF6uio6PVv39/1/P09HTFx8erXLlycjgcWfonJSUpNDRUBw4ckJ+f3+UstchhLNwxHv9iLNwxHv9iLNwxHv/K71gYY3Tq1ClVqlQpT9v3aHgpX768vL29deTIEbf2I0eOKCQkJEt/p9Mpp9Pp1hYQEHDJ7fj5+V31B1oGxsId4/EvxsId4/EvxsId4/Gv/IxFXs64ZPDohF0fHx81atRIS5YscbWlp6dryZIluvnmmz1YGQAAKKo8ftmof//+6tatmxo3bqwmTZpo3LhxOn36tHr06OHp0gAAQBHk8fDSqVMnHTt2TEOGDNHhw4cVHh6u+fPnZ5nEmxdOp1NDhw7NcqnpasRYuGM8/sVYuGM8/sVYuGM8/uXpsXCYvN6nBAAA4AEe/5I6AAAAKwgvAADAVggvAADAVggvAADAVggvAADAVmwfXr777js1bdpUvr6+Klu2rDp27Jhj33PnzmnQoEGqX7++SpUqpUqVKqlr1646ePCgW7+qVavK4XC4PUaNGlXIe1IwrIyH9M9XNA8ZMkQVK1aUr6+v2rZtq127drn1iY+PV5cuXeTn56eAgAD16tVLycnJhbgX+Wf1PYyLi8vSP+Px9ddfu/pl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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGzCAYAAAA1yP25AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAxkklEQVR4nO3dd3RUZeLG8WcSkhBKAqEE0ACBRJAuoFJcFEERUMF1FRSFAIIlGCBKiUoVDaAoiyIuFkB/VqoFKREQG0oNXUIVFoGAQAIBAyTv7489meOQwlycyczF7+ecOTLvvTPzzDtXebxlxmGMMQIAALChAF8HAAAAuFwUGQAAYFsUGQAAYFsUGQAAYFsUGQAAYFsUGQAAYFsUGQAAYFsUGQAAYFsUGQAAYFsUGcCP1axZU3Fxcb6OccV76aWXVKtWLQUGBqpJkya+jgPAAooMUExmzpwph8OhtWvXFrj8lltuUYMGDf7y63z11VcaPXr0X36ev4ulS5dq6NChat26tWbMmKEXX3zR15EAWFDC1wEAFG7Hjh0KCLD2/xtfffWVpk6dSplx0/LlyxUQEKB33nlHwcHBvo4DwCL2yAB+LCQkREFBQb6OYUlWVpavI1iSnp6u0NBQSgxgUxQZwI9dfI7M+fPnNWbMGMXGxqpkyZKqUKGCbrrpJqWkpEiS4uLiNHXqVEmSw+Fw3vJkZWXpqaeeUlRUlEJCQlSnTh29/PLLMsa4vO7Zs2eVkJCgihUrqmzZsrr77rt18OBBORwOlz09o0ePlsPh0LZt2/Tggw+qfPnyuummmyRJmzZtUlxcnGrVqqWSJUuqSpUq6tOnj37//XeX18p7jrS0ND300EMKDw9XpUqVNGLECBljdODAAXXp0kVhYWGqUqWKJk2a5NbcXbhwQc8//7xq166tkJAQ1axZU88884yys7Od6zgcDs2YMUNZWVnOuZo5c2ahz/ndd9/pvvvuU/Xq1RUSEqKoqCgNHjxYZ8+edVkvLi5OZcqU0Z49e9ShQweVLl1a1apV09ixY/PNtac/E0k6ePCg+vTpo8jISIWEhKh+/fp69913872f7OxsjRo1SjExMc73M3ToUJc5Avwdh5aAYpaRkaFjx47lGz9//vwlHzt69GglJyfrkUce0Q033KDMzEytXbtW69ev12233aZHH31Uv/32m1JSUvT++++7PNYYo7vvvlsrVqxQ37591aRJEy1ZskRDhgzRwYMH9eqrrzrXjYuL06effqqHH35YLVq00MqVK9W5c+dCc913332KjY3Viy++6PwLOCUlRXv27FHv3r1VpUoVbd26VdOnT9fWrVv1008/uRQsSerWrZuuvfZajR8/XgsXLtS4ceMUERGh//znP7r11ls1YcIEffDBB3r66ad1/fXXq02bNkXO1SOPPKJZs2bpX//6l5566in9/PPPSk5O1vbt2zV//nxJ0vvvv6/p06dr9erVevvttyVJrVq1KvQ5Z8+erTNnzujxxx9XhQoVtHr1ar322mv673//q9mzZ7usm5OTozvuuEMtWrTQxIkTtXjxYo0aNUoXLlzQ2LFjvfaZHDlyRC1atJDD4dCAAQNUqVIlLVq0SH379lVmZqYGDRokScrNzdXdd9+t77//Xv3799e1116rzZs369VXX1VaWpoWLFhQ5PwCfsMAKBYzZswwkoq81a9f3+UxNWrUML169XLeb9y4sencuXORrxMfH28K+ld7wYIFRpIZN26cy/i//vUv43A4zK5du4wxxqxbt85IMoMGDXJZLy4uzkgyo0aNco6NGjXKSDIPPPBAvtc7c+ZMvrGPPvrISDLffvttvufo37+/c+zChQvm6quvNg6Hw4wfP945fuLECRMaGuoyJwVJTU01kswjjzziMv70008bSWb58uXOsV69epnSpUsX+XxFvafk5GTjcDjMr7/+6vKcksyTTz7pHMvNzTWdO3c2wcHB5ujRo8YY73wmffv2NVWrVjXHjh1zWbd79+4mPDzc+R7ef/99ExAQYL777juX9d58800jyfzwww9uzQngaxxaAorZ1KlTlZKSku/WqFGjSz62XLly2rp1q3bu3Gn5db/66isFBgYqISHBZfypp56SMUaLFi2SJC1evFiS9MQTT7is9+STTxb63I899li+sdDQUOef//jjDx07dkwtWrSQJK1fvz7f+o888ojzz4GBgWrevLmMMerbt69zvFy5cqpTp4727NlTaBbpf+9VkhITE13Gn3rqKUnSwoULi3x8Yf78nrKysnTs2DG1atVKxhht2LAh3/oDBgxw/jlvD8m5c+f09ddfO3N68jMxxmju3Lm66667ZIzRsWPHnLcOHTooIyPDOfezZ8/Wtddeq7p167qsd+utt0qSVqxYcVlzBBQ3Di0BxeyGG25Q8+bN842XL1++wENOfzZ27Fh16dJF11xzjRo0aKA77rhDDz/8sFsl6Ndff1W1atVUtmxZl/Frr73WuTzvnwEBAYqOjnZZLyYmptDnvnhdSTp+/LjGjBmjjz/+WOnp6S7LMjIy8q1fvXp1l/vh4eEqWbKkKlasmG/84vNsLpb3Hi7OXKVKFZUrV875Xq3av3+/Ro4cqc8//1wnTpxwWXbxewoICFCtWrVcxq655hpJ0r59+5w5PfmZHD16VCdPntT06dM1ffr0At9D3mexc+dObd++XZUqVSpyPcDfUWQAG2nTpo12796tzz77TEuXLtXbb7+tV199VW+++abLHo3i9uc9FXnuv/9+/fjjjxoyZIiaNGmiMmXKKDc3V3fccYdyc3PzrR8YGOjWmKR8J8IW5uLzcP6KnJwc3XbbbTp+/LiGDRumunXrqnTp0jp48KDi4uIKfE/FLS/DQw89pF69ehW4Tl7pzc3NVcOGDfXKK68UuF5UVJR3QgIeRpEBbCYiIkK9e/dW7969dfr0abVp00ajR492FpnC/vKuUaOGvv76a506dcplD8Avv/ziXJ73z9zcXO3du1exsbHO9Xbt2uV2xhMnTmjZsmUaM2aMRo4c6Ry/nENilyPvPezcudO5d0P634mwJ0+edL5XKzZv3qy0tDTNmjVLPXv2dI7nXTF2sdzcXO3Zs8e5F0aS0tLSJP3varS8nJ78TCpVqqSyZcsqJydH7du3L/L91K5dWxs3blS7du08WviA4sY5MoCNXHxIpUyZMoqJiXG5XLZ06dKSpJMnT7qs26lTJ+Xk5Oj11193GX/11VflcDjUsWNHSVKHDh0kSW+88YbLeq+99prbOfP2pFy852Ty5MluP8df0alTpwJfL2/vQ1FXYBWmoPdkjNG///3vQh/z57k2xuj1119XUFCQ2rVr58zpyc8kMDBQ9957r+bOnastW7bky3P06FHnn++//34dPHhQb731Vr71zp49a7vvA8LfF3tkABupV6+ebrnlFjVr1kwRERFau3at5syZ43JSabNmzSRJCQkJ6tChgwIDA9W9e3fdddddatu2rZ599lnt27dPjRs31tKlS/XZZ59p0KBBql27tvPx9957ryZPnqzff//dealv3t4Ed/7vPSwsTG3atNHEiRN1/vx5XXXVVVq6dKn27t3rhVnJr3HjxurVq5em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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "test_dispersion.plots.all()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, one may also export the ellipses to a ``.kml`` file so it can be easily visualized in Google Earth\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "test_dispersion.export_ellipses_to_kml(\n",
+ " filename=\"monte_carlo_analysis_outputs/monte_carlo_class_example.kml\",\n",
+ " origin_lat=env.latitude,\n",
+ " origin_lon=env.longitude,\n",
+ " type=\"impact\",\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "hide_input": false,
+ "kernelspec": {
+ "display_name": "Python 3.10.5 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.0"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "26de051ba29f2982a8de78e945f0abaf191376122a1563185a90213a26c5da77"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/notebooks/dispersion_analysis/parachute_drop_from_helicopter.ipynb b/docs/notebooks/monte_carlo_analysis/parachute_drop_from_helicopter.ipynb
similarity index 98%
rename from docs/notebooks/dispersion_analysis/parachute_drop_from_helicopter.ipynb
rename to docs/notebooks/monte_carlo_analysis/parachute_drop_from_helicopter.ipynb
index 873cd6301..b0a510b91 100644
--- a/docs/notebooks/dispersion_analysis/parachute_drop_from_helicopter.ipynb
+++ b/docs/notebooks/monte_carlo_analysis/parachute_drop_from_helicopter.ipynb
@@ -14,6 +14,13 @@
"This is an advanced use of RocketPy. This notebook wraps RocketPy's methods to run a Monte Carlo analysis and predict probability distributions of the rocket's landing point if realeased from a helicopter. This is a common test used to validate the parachute system before a rocket launch."
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "TODO: Use the new MonteCarlo class in this notebook"
+ ]
+ },
{
"attachments": {},
"cell_type": "markdown",
@@ -391,7 +398,7 @@
"outputs": [],
"source": [
"# Basic analysis info\n",
- "filename = \"dispersion_analysis_outputs/parachute_drop_from_helicopter\"\n",
+ "filename = \"monte_carlo_analysis_outputs/parachute_drop_from_helicopter\"\n",
"number_of_simulations = 4000\n",
"\n",
"# Create data files for inputs, outputs and error logging\n",
@@ -411,7 +418,7 @@
"Env.maxExpectedHeight = 1500\n",
"Env.setAtmosphericModel(\n",
" type=\"Ensemble\",\n",
- " file=\"dispersion_analysis_inputs/LASC2019_reanalysis.nc\",\n",
+ " file=\"monte_carlo_analysis_inputs/LASC2019_reanalysis.nc\",\n",
" dictionary=\"ECMWF\",\n",
")\n",
"\n",
@@ -435,7 +442,7 @@
"\n",
" # Create motor\n",
" Keron = SolidMotor(\n",
- " thrustSource=\"dispersion_analysis_inputs/thrustCurve.csv\",\n",
+ " thrustSource=\"monte_carlo_analysis_inputs/thrustCurve.csv\",\n",
" burn_time=5.274,\n",
" reshapeThrustCurve=(setting[\"burn_time\"], setting[\"impulse\"]),\n",
" nozzle_radius=setting[\"nozzle_radius\"],\n",
@@ -458,8 +465,8 @@
" mass=setting[\"rocketMass\"],\n",
" inertiaI=setting[\"inertiaI\"],\n",
" inertiaZ=setting[\"inertiaZ\"],\n",
- " powerOffDrag=\"dispersion_analysis_inputs/Cd_PowerOff.csv\",\n",
- " powerOnDrag=\"dispersion_analysis_inputs/Cd_PowerOn.csv\",\n",
+ " powerOffDrag=\"monte_carlo_analysis_inputs/Cd_PowerOff.csv\",\n",
+ " powerOnDrag=\"monte_carlo_analysis_inputs/Cd_PowerOn.csv\",\n",
" centerOfDryMassPosition=0,\n",
" coordinateSystemOrientation=\"tailToNose\",\n",
" )\n",
@@ -580,7 +587,7 @@
},
"outputs": [],
"source": [
- "filename = \"dispersion_analysis_outputs/parachute_drop_from_helicopter\"\n",
+ "filename = \"monte_carlo_analysis_outputs/parachute_drop_from_helicopter\"\n",
"\n",
"# Initialize variable to store all results\n",
"dispersion_general_results = []\n",
@@ -1164,7 +1171,7 @@
"from matplotlib.patches import Ellipse\n",
"\n",
"# Import background map\n",
- "img = imread(\"dispersion_analysis_inputs/Valetudo_basemap_final.jpg\")\n",
+ "img = imread(\"monte_carlo_analysis_inputs/Valetudo_basemap_final.jpg\")\n",
"\n",
"# Retrieve dispersion data por apogee and impact XY position\n",
"apogeeX = np.array(dispersion_results[\"apogeeX\"])\n",
diff --git a/docs/reference/classes/monte_carlo/index.rst b/docs/reference/classes/monte_carlo/index.rst
new file mode 100644
index 000000000..0f4630696
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/index.rst
@@ -0,0 +1,9 @@
+Monte Carlo Analysis
+====================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Contents:
+
+ monte_carlo
+ Stochastic models
diff --git a/docs/reference/classes/monte_carlo/monte_carlo.rst b/docs/reference/classes/monte_carlo/monte_carlo.rst
new file mode 100644
index 000000000..8c127855b
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/monte_carlo.rst
@@ -0,0 +1,5 @@
+Monte Carlo Class
+-----------------
+
+.. autoclass:: rocketpy.simulation.MonteCarlo
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/index.rst b/docs/reference/classes/monte_carlo/stochastic_models/index.rst
new file mode 100644
index 000000000..fd31647f7
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/index.rst
@@ -0,0 +1,20 @@
+Stochastic Models
+=================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Contents:
+
+ stochastic_model
+ stochastic_environment
+ stochastic_motor_model
+ stochastic_solid_motor
+ stochastic_generic_motor
+ stochastic_nose_cone
+ stochastic_trapezoidal_fins
+ stochastic_elliptical_fins
+ stochastic_tail
+ stochastic_rail_buttons
+ stochastic_rocket
+ stochastic_parachute
+ stochastic_flight
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_elliptical_fins.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_elliptical_fins.rst
new file mode 100644
index 000000000..f661b6115
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_elliptical_fins.rst
@@ -0,0 +1,5 @@
+Stochastic Elliptical Fins
+--------------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticEllipticalFins
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_environment.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_environment.rst
new file mode 100644
index 000000000..41e12dbd7
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_environment.rst
@@ -0,0 +1,5 @@
+Stochastic Environment
+----------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticEnvironment
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_flight.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_flight.rst
new file mode 100644
index 000000000..c3e7ba85d
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_flight.rst
@@ -0,0 +1,5 @@
+Stochastic Flight
+-----------------
+
+.. autoclass:: rocketpy.stochastic.StochasticFlight
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_generic_motor.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_generic_motor.rst
new file mode 100644
index 000000000..617bfd06e
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_generic_motor.rst
@@ -0,0 +1,5 @@
+Stochastic Generic Motor
+------------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticGenericMotor
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_model.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_model.rst
new file mode 100644
index 000000000..619ca848e
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_model.rst
@@ -0,0 +1,7 @@
+.. _stochastic_model:
+
+Stochastic Model
+-----------------
+
+.. autoclass:: rocketpy.stochastic.StochasticModel
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_motor_model.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_motor_model.rst
new file mode 100644
index 000000000..3f96b4a23
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_motor_model.rst
@@ -0,0 +1,5 @@
+Stochastic Motor Model
+----------------------
+
+.. autoclass:: rocketpy.stochastic.stochastic_motor_model.StochasticMotorModel
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_nose_cone.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_nose_cone.rst
new file mode 100644
index 000000000..cf471219b
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_nose_cone.rst
@@ -0,0 +1,5 @@
+Stochastic Nose Cone
+--------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticNoseCone
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_parachute.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_parachute.rst
new file mode 100644
index 000000000..ffd851dc1
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_parachute.rst
@@ -0,0 +1,5 @@
+Stochastic Parachute
+--------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticParachute
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rail_buttons.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rail_buttons.rst
new file mode 100644
index 000000000..7036486aa
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rail_buttons.rst
@@ -0,0 +1,5 @@
+Stochastic Rail Buttons
+-----------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticRailButtons
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rocket.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rocket.rst
new file mode 100644
index 000000000..af262b55b
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_rocket.rst
@@ -0,0 +1,5 @@
+Stochastic Rocket
+-----------------
+
+.. autoclass:: rocketpy.stochastic.StochasticRocket
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_solid_motor.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_solid_motor.rst
new file mode 100644
index 000000000..8135af752
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_solid_motor.rst
@@ -0,0 +1,5 @@
+Stochastic Solid Motor
+----------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticSolidMotor
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_tail.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_tail.rst
new file mode 100644
index 000000000..27c8c321e
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_tail.rst
@@ -0,0 +1,5 @@
+Stochastic Tail
+---------------
+
+.. autoclass:: rocketpy.stochastic.StochasticTail
+ :members:
\ No newline at end of file
diff --git a/docs/reference/classes/monte_carlo/stochastic_models/stochastic_trapezoidal_fins.rst b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_trapezoidal_fins.rst
new file mode 100644
index 000000000..d172a441a
--- /dev/null
+++ b/docs/reference/classes/monte_carlo/stochastic_models/stochastic_trapezoidal_fins.rst
@@ -0,0 +1,5 @@
+Stochastic Trapezoidal Fins
+---------------------------
+
+.. autoclass:: rocketpy.stochastic.StochasticTrapezoidalFins
+ :members:
\ No newline at end of file
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index 9b7295281..08f99447c 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -17,6 +17,7 @@ This reference manual details functions, modules, methods and attributes include
classes/Flight
Utilities
classes/EnvironmentAnalysis
+ Monte Carlo Analysis
.. toctree::
:maxdepth: 2
diff --git a/docs/user/first_simulation.rst b/docs/user/first_simulation.rst
index 6fab61238..93f328922 100644
--- a/docs/user/first_simulation.rst
+++ b/docs/user/first_simulation.rst
@@ -663,7 +663,7 @@ analysis. Here we will show some examples, but much more can be done!
.. seealso::
*RocketPy* can be used to perform a Monte Carlo Dispersion Analysis.
See
- `Monte Carlo Simulations `_
+ `Monte Carlo Simulations `_
for more information.
Apogee as a Function of Mass
diff --git a/docs/user/index.rst b/docs/user/index.rst
index 6896f9d4e..e2dc271fd 100644
--- a/docs/user/index.rst
+++ b/docs/user/index.rst
@@ -30,8 +30,8 @@ RocketPy's User Guide
:maxdepth: 2
:caption: Dispersion Analysis
- ../notebooks/dispersion_analysis/dispersion_analysis.ipynb
- ../notebooks/dispersion_analysis/parachute_drop_from_helicopter.ipynb
+ ../notebooks/monte_carlo_analysis/monte_carlo_analysis.ipynb
+ ../notebooks/monte_carlo_analysis/parachute_drop_from_helicopter.ipynb
.. toctree::
:maxdepth: 2
diff --git a/pyproject.toml b/pyproject.toml
index 350f7ae37..df56a6fd9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -51,7 +51,11 @@ env-analysis = [
"ipywidgets>=7.6.3"
]
-all = ["rocketpy[env-analysis]"]
+monte-carlo = [
+ "imageio",
+]
+
+all = ["rocketpy[env-analysis]", "rocketpy[monte-carlo]"]
[tool.black]
line-length = 88
diff --git a/requirements-optional.txt b/requirements-optional.txt
index 699bbde14..0cf42683d 100644
--- a/requirements-optional.txt
+++ b/requirements-optional.txt
@@ -2,4 +2,5 @@ windrose>=1.6.8
ipython
ipywidgets>=7.6.3
jsonpickle
-timezonefinder
\ No newline at end of file
+timezonefinder
+imageio
\ No newline at end of file
diff --git a/rocketpy/__init__.py b/rocketpy/__init__.py
index 10404b619..400d2124a 100644
--- a/rocketpy/__init__.py
+++ b/rocketpy/__init__.py
@@ -37,4 +37,15 @@
Tail,
TrapezoidalFins,
)
-from .simulation import Flight
+from .simulation import Flight, MonteCarlo
+from .stochastic import (
+ StochasticEllipticalFins,
+ StochasticEnvironment,
+ StochasticFlight,
+ StochasticNoseCone,
+ StochasticParachute,
+ StochasticRocket,
+ StochasticSolidMotor,
+ StochasticTail,
+ StochasticTrapezoidalFins,
+)
diff --git a/rocketpy/_encoders.py b/rocketpy/_encoders.py
new file mode 100644
index 000000000..3fb5202a3
--- /dev/null
+++ b/rocketpy/_encoders.py
@@ -0,0 +1,43 @@
+"""Defines a custom JSON encoder for RocketPy objects."""
+
+import json
+import types
+
+import numpy as np
+
+from rocketpy.mathutils.function import Function
+
+
+class RocketPyEncoder(json.JSONEncoder):
+ """NOTE: This is still under construction, please don't use it yet."""
+
+ def default(self, o):
+ if isinstance(
+ o,
+ (
+ np.int_,
+ np.intc,
+ np.intp,
+ np.int8,
+ np.int16,
+ np.int32,
+ np.int64,
+ np.uint8,
+ np.uint16,
+ np.uint32,
+ np.uint64,
+ ),
+ ):
+ return int(o)
+ elif isinstance(o, (np.float_, np.float16, np.float32, np.float64)):
+ return float(o)
+ elif isinstance(o, np.ndarray):
+ return o.tolist()
+ elif hasattr(o, "to_dict"):
+ return o.to_dict()
+ # elif isinstance(o, Function):
+ # return o.__dict__()
+ elif isinstance(o, (Function, types.FunctionType)):
+ return repr(o)
+ else:
+ return json.JSONEncoder.default(self, o)
diff --git a/rocketpy/plots/monte_carlo_plots.py b/rocketpy/plots/monte_carlo_plots.py
new file mode 100644
index 000000000..e03a3f4f3
--- /dev/null
+++ b/rocketpy/plots/monte_carlo_plots.py
@@ -0,0 +1,188 @@
+import matplotlib.pyplot as plt
+
+from ..tools import generate_monte_carlo_ellipses
+
+
+class _MonteCarloPlots:
+ """Class to plot the monte carlo analysis results."""
+
+ def __init__(self, monte_carlo):
+ self.monte_carlo = monte_carlo
+
+ def ellipses(
+ self,
+ image=None,
+ actual_landing_point=None,
+ perimeter_size=3000,
+ xlim=(-3000, 3000),
+ ylim=(-3000, 3000),
+ save=False,
+ ):
+ """A function to plot the error ellipses for the apogee and impact
+ points of the rocket. The function also plots the real landing point, if
+ given
+
+ Parameters
+ ----------
+ image : str, optional
+ The path to the image to be used as the background
+ actual_landing_point : tuple, optional
+ A tuple containing the actual landing point of the rocket, if known.
+ Useful when comparing the Monte Carlo results with the actual landing.
+ Must be given in tuple format, such as (x, y) in meters.
+ By default None.
+ perimeter_size : int, optional
+ The size of the perimeter to be plotted. The default is 3000.
+ xlim : tuple, optional
+ The limits of the x axis. The default is (-3000, 3000).
+ ylim : tuple, optional
+ The limits of the y axis. The default is (-3000, 3000).
+ save : bool
+ Whether save the output into a file or not. The default is False.
+ If True, the image will not be displayed, and the .savefig() method
+ will be called. If False, the image will be displayed, and the
+ .show() method will be called.
+
+ Returns
+ -------
+ None
+ """
+ # Import background map
+ if image is not None:
+ # TODO: use the optional import function
+ try:
+ from imageio import imread
+
+ img = imread(image)
+ except ImportError:
+ raise ImportError(
+ "The 'imageio' package could not be. Please install it to add background images."
+ )
+ except FileNotFoundError:
+ raise FileNotFoundError(
+ "The image file was not found. Please check the path."
+ )
+
+ (
+ impact_ellipses,
+ apogee_ellipses,
+ apogee_x,
+ apogee_y,
+ impact_x,
+ impact_y,
+ ) = generate_monte_carlo_ellipses(self.monte_carlo.results)
+
+ # Create plot figure
+ plt.figure(num=None, figsize=(8, 6), dpi=150, facecolor="w", edgecolor="k")
+ ax = plt.subplot(111)
+
+ for ell in impact_ellipses:
+ ax.add_artist(ell)
+ for ell in apogee_ellipses:
+ ax.add_artist(ell)
+
+ # Draw launch point
+ plt.scatter(0, 0, s=30, marker="*", color="black", label="Launch Point")
+ # Draw apogee points
+ plt.scatter(
+ apogee_x, apogee_y, s=5, marker="^", color="green", label="Simulated Apogee"
+ )
+ # Draw impact points
+ plt.scatter(
+ impact_x,
+ impact_y,
+ s=5,
+ marker="v",
+ color="blue",
+ label="Simulated Landing Point",
+ )
+ # Draw real landing point
+ if actual_landing_point != None:
+ plt.scatter(
+ actual_landing_point[0],
+ actual_landing_point[1],
+ s=20,
+ marker="X",
+ color="red",
+ label="Measured Landing Point",
+ )
+
+ plt.legend()
+
+ # Add title and labels to plot
+ ax.set_title(
+ "1$\\sigma$, 2$\\sigma$ and 3$\\sigma$ "
+ + "Monte Carlo Ellipses: Apogee and Landing Points"
+ )
+ ax.set_ylabel("North (m)")
+ ax.set_xlabel("East (m)")
+
+ # Add background image to plot
+ # TODO: In the future, integrate with other libraries to plot the map (e.g. cartopy, ee, etc.)
+ # You can translate the basemap by changing dx and dy (in meters)
+ dx = 0
+ dy = 0
+ if image is not None:
+ plt.imshow(
+ img,
+ zorder=0,
+ extent=[
+ -perimeter_size - dx,
+ perimeter_size - dx,
+ -perimeter_size - dy,
+ perimeter_size - dy,
+ ],
+ )
+ plt.axhline(0, color="black", linewidth=0.5)
+ plt.axvline(0, color="black", linewidth=0.5)
+ plt.xlim(*xlim)
+ plt.ylim(*ylim)
+
+ # Save plot and show result
+ if save:
+ plt.savefig(
+ str(self.monte_carlo.filename) + ".png",
+ bbox_inches="tight",
+ pad_inches=0,
+ )
+ else:
+ plt.show()
+
+ def all(self, keys=None):
+ """Plot the results of the Monte Carlo analysis.
+
+ Parameters
+ ----------
+ keys : str, list or tuple, optional
+ The keys of the results to be plotted. If None, all results will be
+ plotted. The default is None.
+
+ Returns
+ -------
+ None
+ """
+
+ if keys is None:
+ keys = self.monte_carlo.results.keys()
+ elif isinstance(keys, str):
+ keys = [keys]
+ elif isinstance(keys, (list, tuple)):
+ keys = list(set(keys).intersection(self.monte_carlo.results.keys()))
+ if len(keys) == 0:
+ raise ValueError(
+ "The selected 'keys' are not available in the results. "
+ "Please check the documentation."
+ )
+ else:
+ raise ValueError(
+ "The 'keys' argument must be a string, list or tuple. "
+ "Please check the documentation."
+ )
+ for key in keys:
+ plt.figure()
+ plt.hist(
+ self.monte_carlo.results[key],
+ )
+ plt.title(f"Histogram of {key}")
+ plt.ylabel("Number of Occurrences")
+ plt.show()
diff --git a/rocketpy/prints/monte_carlo_prints.py b/rocketpy/prints/monte_carlo_prints.py
new file mode 100644
index 000000000..6249626ce
--- /dev/null
+++ b/rocketpy/prints/monte_carlo_prints.py
@@ -0,0 +1,27 @@
+class _MonteCarloPrints:
+ """Class to print the monte carlo analysis results."""
+
+ def __init__(self, monte_carlo):
+ self.monte_carlo = monte_carlo
+
+ def all(self):
+ """Print the mean and standard deviation of each parameter in the results
+ dictionary or of the variables passed as argument.
+
+ Parameters
+ ----------
+ None
+
+ Returns
+ -------
+ None
+
+ """
+ print("Monte Carlo Simulation by RocketPy")
+ print("Data Source: ", self.monte_carlo.filename)
+ print("Number of simulations: ", self.monte_carlo.num_of_loaded_sims)
+ print("Results: \n")
+ print(f"{'Parameter':>25} {'Mean':>15} {'Std. Dev.':>15}")
+ print("-" * 60)
+ for key, value in self.monte_carlo.processed_results.items():
+ print(f"{key:>25} {value[0]:>15.3f} {value[1]:>15.3f}")
diff --git a/rocketpy/rocket/components.py b/rocketpy/rocket/components.py
index 1d1d33e56..3197db687 100644
--- a/rocketpy/rocket/components.py
+++ b/rocketpy/rocket/components.py
@@ -27,7 +27,7 @@ def __repr__(self):
"""Return a string representation of the Components instance."""
components_str = "\n".join(
[
- f"\tComponent: {str(c.component):80} Position: {c.position:>6.3f}"
+ f"\tComponent: {str(c.component):80} Position: {c.position}"
for c in self._components
]
)
@@ -103,6 +103,16 @@ def get_tuple_by_type(self, component_type):
]
return component_type_list
+ def get_components(self):
+ """Return a list of all the components in the list of components.
+
+ Returns
+ -------
+ list
+ A list of all the components in the list of components.
+ """
+ return [c.component for c in self._components]
+
def get_positions(self):
"""Return a list of all the positions of the components in the list of
components.
diff --git a/rocketpy/rocket/parachute.py b/rocketpy/rocket/parachute.py
index 31f9252ed..f96e2a024 100644
--- a/rocketpy/rocket/parachute.py
+++ b/rocketpy/rocket/parachute.py
@@ -65,6 +65,11 @@ class Parachute:
Parachute.lag : float
Time, in seconds, between the parachute ejection system is triggered
and the parachute is fully opened.
+ Parachute.noise : tuple, list
+ List in the format (mean, standard deviation, time-correlation).
+ The values are used to add noise to the pressure signal which is passed
+ to the trigger function. Default value is (0, 0, 0). Units are in
+ pascal.
Parachute.noise_bias : float
Mean value of the noise added to the pressure signal, which is
passed to the trigger function. Unit is in pascal.
@@ -154,6 +159,7 @@ def __init__(
self.trigger = trigger
self.sampling_rate = sampling_rate
self.lag = lag
+ self.noise = noise
self.noise_signal = [[-1e-6, np.random.normal(noise[0], noise[1])]]
self.noisy_pressure_signal = []
self.clean_pressure_signal = []
diff --git a/rocketpy/simulation/__init__.py b/rocketpy/simulation/__init__.py
index 46c3b40ed..b1aecdd99 100644
--- a/rocketpy/simulation/__init__.py
+++ b/rocketpy/simulation/__init__.py
@@ -1,2 +1,3 @@
from .flight import Flight
from .flight_data_importer import FlightDataImporter
+from .monte_carlo import MonteCarlo
diff --git a/rocketpy/simulation/monte_carlo.py b/rocketpy/simulation/monte_carlo.py
new file mode 100644
index 000000000..2ea28eaa9
--- /dev/null
+++ b/rocketpy/simulation/monte_carlo.py
@@ -0,0 +1,669 @@
+"""Defines the MonteCarlo class."""
+
+import json
+import warnings
+from time import process_time, time
+
+import numpy as np
+import simplekml
+
+from rocketpy._encoders import RocketPyEncoder
+from rocketpy.plots.monte_carlo_plots import _MonteCarloPlots
+from rocketpy.prints.monte_carlo_prints import _MonteCarloPrints
+from rocketpy.simulation.flight import Flight
+from rocketpy.tools import (
+ generate_monte_carlo_ellipses,
+ generate_monte_carlo_ellipses_coordinates,
+)
+
+# TODO: Let Functions and Flights be json serializable
+# TODO: Create evolution plots to analyze convergence
+
+
+class MonteCarlo:
+ """Class to run a Monte Carlo simulation of a rocket flight.
+
+ Attributes
+ ----------
+ filename : str
+ When running a new simulation, this parameter represents the
+ initial part of the export filenames. For example, if the value
+ is 'filename', the exported output files will be named
+ 'filename.outputs.txt'. When analyzing the results of a
+ previous simulation, this parameter should be set to the .txt
+ file containing the outputs of the previous monte carlo analysis.
+ environment : StochasticEnvironment
+ The stochastic environment object to be iterated over.
+ rocket : StochasticRocket
+ The stochastic rocket object to be iterated over.
+ flight : StochasticFlight
+ The stochastic flight object to be iterated over.
+ export_list : list
+ The list of variables to export. If None, the default list will
+ be used. Default is None. # TODO: improve docs to explain the
+ default list, and what can be exported.
+ inputs_log : list
+ List of dictionaries with the inputs used in each simulation.
+ outputs_log : list
+ List of dictionaries with the outputs of each simulation.
+ errors_log : list
+ List of dictionaries with the errors of each simulation.
+ num_of_loaded_sims : int
+ Number of simulations loaded from output_file being currently used.
+ results : dict
+ Monte carlo analysis results organized in a dictionary where the keys
+ are the names of the saved attributes, and the values are a list with
+ all the result number of the respective attribute
+ processed_results : dict
+ Creates a dictionary with the mean and standard deviation of each
+ parameter available in the results
+ prints : _MonteCarloPrints
+ Object with methods to print information about the monte carlo
+ simulation.
+ plots : _MonteCarloPlots
+ Object with methods to plot information about the monte carlo
+ simulation.
+ """
+
+ def __init__(self, filename, environment, rocket, flight, export_list=None):
+ """
+ Initialize a MonteCarlo object.
+
+ Parameters
+ ----------
+ filename : str
+ When running a new simulation, this parameter represents the
+ initial part of the export filenames. For example, if the value
+ is 'filename', the exported output files will be named
+ 'filename.outputs.txt'. When analyzing the results of a
+ previous simulation, this parameter should be set to the .txt
+ file containing the outputs of the previous monte carlo
+ analysis.
+ environment : StochasticEnvironment
+ The stochastic environment object to be iterated over.
+ rocket : StochasticRocket
+ The stochastic rocket object to be iterated over.
+ flight : StochasticFlight
+ The stochastic flight object to be iterated over.
+ export_list : list, optional
+ The list of variables to export. If None, the default list will
+ be used. Default is None. # TODO: improve docs to explain the
+ default list, and what can be exported.
+
+ Returns
+ -------
+ None
+ """
+ warnings.warn(
+ "This class is still under testing and some attributes may be "
+ "changed in next versions",
+ UserWarning,
+ )
+
+ # Save and initialize parameters
+ self.filename = filename
+ self.environment = environment
+ self.rocket = rocket
+ self.flight = flight
+ self.export_list = []
+ self.inputs_log = []
+ self.outputs_log = []
+ self.errors_log = []
+ self.num_of_loaded_sims = 0
+ self.results = {}
+ self.processed_results = {}
+ self.prints = _MonteCarloPrints(self)
+ self.plots = _MonteCarloPlots(self)
+ self._inputs_dict = {}
+ self._last_print_len = 0 # used to print on the same line
+
+ # Checks export_list
+ self.export_list = self.__check_export_list(export_list)
+
+ try:
+ self.import_inputs()
+ except FileNotFoundError:
+ self._input_file = f"{filename}.inputs.txt"
+
+ try:
+ self.import_outputs()
+ except FileNotFoundError:
+ self._output_file = f"{filename}.outputs.txt"
+
+ try:
+ self.import_errors()
+ except FileNotFoundError:
+ self._error_file = f"{filename}.errors.txt"
+
+ def simulate(self, number_of_simulations, append=False):
+ """
+ Runs the monte carlo simulation and saves all data.
+
+ Parameters
+ ----------
+ number_of_simulations : int
+ Number of simulations to be run, must be non-negative.
+ append : bool, optional
+ If True, the results will be appended to the existing files. If
+ False, the files will be overwritten. Default is False.
+
+ Returns
+ -------
+ None
+ """
+ # Create data files for inputs, outputs and error logging
+ open_mode = "a" if append else "w"
+ input_file = open(self._input_file, open_mode, encoding="utf-8")
+ output_file = open(self._output_file, open_mode, encoding="utf-8")
+ error_file = open(self._error_file, open_mode, encoding="utf-8")
+
+ # initialize counters
+ self.number_of_simulations = number_of_simulations
+ self.iteration_count = self.num_of_loaded_sims if append else 0
+ self.start_time = time()
+ self.start_cpu_time = process_time()
+
+ # Begin display
+ print("Starting monte carlo analysis", end="\r")
+
+ try:
+ while self.iteration_count < self.number_of_simulations:
+ self.__run_single_simulation(input_file, output_file)
+ except KeyboardInterrupt:
+ print("Keyboard Interrupt, files saved.")
+ error_file.write(json.dumps(self._inputs_dict, cls=RocketPyEncoder) + "\n")
+ self.__close_files(input_file, output_file, error_file)
+ except Exception as error:
+ print(f"Error on iteration {self.iteration_count}: {error}")
+ error_file.write(json.dumps(self._inputs_dict, cls=RocketPyEncoder) + "\n")
+ self.__close_files(input_file, output_file, error_file)
+ raise error
+
+ self.__finalize_simulation(input_file, output_file, error_file)
+
+ def __run_single_simulation(self, input_file, output_file):
+ """Runs a single simulation and saves the inputs and outputs to the
+ respective files."""
+ # Update iteration count
+ self.iteration_count += 1
+ # Run trajectory simulation
+ monte_carlo_flight = Flight(
+ rocket=self.rocket.create_object(),
+ environment=self.environment.create_object(),
+ rail_length=self.flight._randomize_rail_length(),
+ inclination=self.flight._randomize_inclination(),
+ heading=self.flight._randomize_heading(),
+ initial_solution=self.flight.initial_solution,
+ terminate_on_apogee=self.flight.terminate_on_apogee,
+ )
+
+ self._inputs_dict = dict(
+ item
+ for d in [
+ self.environment.last_rnd_dict,
+ self.rocket.last_rnd_dict,
+ self.flight.last_rnd_dict,
+ ]
+ for item in d.items()
+ )
+
+ # Export inputs and outputs to file
+ self.__export_flight_data(
+ flight=monte_carlo_flight,
+ inputs_dict=self._inputs_dict,
+ input_file=input_file,
+ output_file=output_file,
+ )
+
+ average_time = (process_time() - self.start_cpu_time) / self.iteration_count
+ estimated_time = int(
+ (self.number_of_simulations - self.iteration_count) * average_time
+ )
+ self.__reprint(
+ f"Current iteration: {self.iteration_count:06d} | "
+ f"Average Time per Iteration: {average_time:.3f} s | "
+ f"Estimated time left: {estimated_time} s",
+ end="\r",
+ flush=True,
+ )
+
+ def __close_files(self, input_file, output_file, error_file):
+ """Closes all the files."""
+ input_file.close()
+ output_file.close()
+ error_file.close()
+
+ def __finalize_simulation(self, input_file, output_file, error_file):
+ """Finalizes the simulation, closes the files and prints the results."""
+ final_string = (
+ f"Completed {self.iteration_count} iterations. Total CPU time: "
+ f"{process_time() - self.start_cpu_time:.1f} s. Total wall time: "
+ f"{time() - self.start_time:.1f} s\n"
+ )
+
+ self.__reprint(final_string + "Saving results.", flush=True)
+
+ # close files to guarantee saving
+ self.__close_files(input_file, output_file, error_file)
+
+ # resave the files on self and calculate post simulation attributes
+ self.input_file = f"{self.filename}.inputs.txt"
+ self.output_file = f"{self.filename}.outputs.txt"
+ self.error_file = f"{self.filename}.errors.txt"
+
+ print(f"Results saved to {self._output_file}")
+
+ def __export_flight_data(
+ self,
+ flight,
+ inputs_dict,
+ input_file,
+ output_file,
+ ):
+ """Exports the flight data to the respective files."""
+ # Construct the dict with the results from the flight
+ results = {
+ export_item: getattr(flight, export_item)
+ for export_item in self.export_list
+ }
+
+ # Write flight setting and results to file
+ input_file.write(json.dumps(inputs_dict, cls=RocketPyEncoder) + "\n")
+ output_file.write(json.dumps(results, cls=RocketPyEncoder) + "\n")
+
+ def __check_export_list(self, export_list):
+ """Checks if the export_list is valid and returns a valid list. If no
+ export_list is provided, the default list is used."""
+ standard_output = set(
+ {
+ "apogee",
+ "apogee_time",
+ "apogee_x",
+ "apogee_y",
+ "t_final",
+ "x_impact",
+ "y_impact",
+ "impact_velocity",
+ "initial_stability_margin",
+ "out_of_rail_stability_margin",
+ "out_of_rail_time",
+ "out_of_rail_velocity",
+ "max_mach_number",
+ "frontal_surface_wind",
+ "lateral_surface_wind",
+ }
+ )
+ exportables = set(
+ {
+ "inclination",
+ "heading",
+ "effective1rl",
+ "effective2rl",
+ "out_of_rail_time",
+ "out_of_rail_time_index",
+ "out_of_rail_state",
+ "out_of_rail_velocity",
+ "rail_button1_normal_force",
+ "max_rail_button1_normal_force",
+ "rail_button1_shear_force",
+ "max_rail_button1_shear_force",
+ "rail_button2_normal_force",
+ "max_rail_button2_normal_force",
+ "rail_button2_shear_force",
+ "max_rail_button2_shear_force",
+ "out_of_rail_static_margin",
+ "apogee_state",
+ "apogee_time",
+ "apogee_x",
+ "apogee_y",
+ "apogee",
+ "x_impact",
+ "y_impact",
+ "z_impact",
+ "impact_velocity",
+ "impact_state",
+ "parachute_events",
+ "apogee_freestream_speed",
+ "final_static_margin",
+ "frontal_surface_wind",
+ "initial_static_margin",
+ "lateral_surface_wind",
+ "max_acceleration",
+ "max_acceleration_time",
+ "max_dynamic_pressure_time",
+ "max_dynamic_pressure",
+ "max_mach_number_time",
+ "max_mach_number",
+ "max_reynolds_number_time",
+ "max_reynolds_number",
+ "max_speed_time",
+ "max_speed",
+ "max_total_pressure_time",
+ "max_total_pressure",
+ "t_final",
+ }
+ )
+ if export_list:
+ for attr in set(export_list):
+ if not isinstance(attr, str):
+ raise TypeError("Variables in export_list must be strings.")
+
+ # Checks if attribute is not valid
+ if attr not in exportables:
+ raise ValueError(
+ f"Attribute '{attr}' can not be exported. Check export_list."
+ )
+ else:
+ # No export list provided, using default list instead.
+ export_list = standard_output
+
+ return export_list
+
+ def __reprint(self, msg, end="\n", flush=False):
+ """Prints a message on the same line as the previous one and replaces
+ the previous message with the new one, deleting the extra characters
+ from the previous message.
+
+ Parameters
+ ----------
+ msg : str
+ Message to be printed.
+ end : str, optional
+ String appended after the message. Default is a new line.
+ flush : bool, optional
+ If True, the output is flushed. Default is False.
+
+ Returns
+ -------
+ None
+ """
+
+ len_msg = len(msg)
+ if len_msg < self._last_print_len:
+ msg += " " * (self._last_print_len - len_msg)
+ else:
+ self._last_print_len = len_msg
+
+ print(msg, end=end, flush=flush)
+
+ @property
+ def input_file(self):
+ """String containing the filepath of the input file"""
+ return self._input_file
+
+ @input_file.setter
+ def input_file(self, value):
+ """Setter for input_file. Sets/updates inputs_log."""
+ self._input_file = value
+ self.set_inputs_log()
+
+ @property
+ def output_file(self):
+ """String containing the filepath of the output file"""
+ return self._output_file
+
+ @output_file.setter
+ def output_file(self, value):
+ """Setter for input_file. Sets/updates outputs_log, num_of_loaded_sims,
+ results, and processed_results."""
+ self._output_file = value
+ self.set_outputs_log()
+ self.set_num_of_loaded_sims()
+ self.set_results()
+ self.set_processed_results()
+
+ @property
+ def error_file(self):
+ """String containing the filepath of the error file"""
+ return self._error_file
+
+ @error_file.setter
+ def error_file(self, value):
+ """Setter for input_file. Sets/updates inputs_log."""
+ self._error_file = value
+ self.set_errors_log()
+
+ # setters for post simulation attributes
+ def set_inputs_log(self):
+ """Sets inputs_log from a file into an attribute for easy access"""
+ self.inputs_log = []
+ with open(self.input_file, mode="r", encoding="utf-8") as rows:
+ for line in rows:
+ self.inputs_log.append(json.loads(line))
+
+ def set_outputs_log(self):
+ """Sets outputs_log from a file into an attribute for easy access"""
+ self.outputs_log = []
+ with open(self.output_file, mode="r", encoding="utf-8") as rows:
+ for line in rows:
+ self.outputs_log.append(json.loads(line))
+
+ def set_errors_log(self):
+ """Sets errors_log log from a file into an attribute for easy access"""
+ self.errors_log = []
+ with open(self.error_file, mode="r", encoding="utf-8") as errors:
+ for line in errors:
+ self.errors_log.append(json.loads(line))
+
+ def set_num_of_loaded_sims(self):
+ """Number of simulations loaded from output_file being currently used."""
+ with open(self.output_file, mode="r", encoding="utf-8") as outputs:
+ self.num_of_loaded_sims = sum(1 for _ in outputs)
+
+ def set_results(self):
+ """Monte carlo results organized in a dictionary where the keys are the
+ names of the saved attributes, and the values are a list with all the
+ result number of the respective attribute"""
+ self.results = {}
+ for result in self.outputs_log:
+ for key, value in result.items():
+ if key in self.results:
+ self.results[key].append(value)
+ else:
+ self.results[key] = [value]
+
+ def set_processed_results(self):
+ """Creates a dictionary with the mean and standard deviation of each
+ parameter available in the results"""
+ self.processed_results = {}
+ for result, values in self.results.items():
+ mean = np.mean(values)
+ stdev = np.std(values)
+ self.processed_results[result] = (mean, stdev)
+
+ def import_outputs(self, filename=None):
+ """Import monte carlo results from .txt file and save it into a
+ dictionary.
+
+ Parameters
+ ----------
+ filename : str
+ Name or directory path to the file to be imported. If none,
+ self.filename will be used.
+
+ Returns
+ -------
+ None
+ """
+ filepath = filename if filename else self.filename
+
+ try:
+ with open(f"{filepath}.outputs.txt", "r+", encoding="utf-8"):
+ self.output_file = f"{filepath}.outputs.txt"
+ except FileNotFoundError:
+ with open(filepath, "r+", encoding="utf-8"):
+ self.output_file = filepath
+
+ print(
+ f"A total of {self.num_of_loaded_sims} simulations results were "
+ f"loaded from the following output file: {self.output_file}\n"
+ )
+
+ def import_inputs(self, filename=None):
+ """Import monte carlo results from .txt file and save it into a
+ dictionary.
+
+ Parameters
+ ----------
+ filename : str
+ Name or directory path to the file to be imported. If none,
+ self.filename will be used.
+
+ Returns
+ -------
+ None
+ """
+ filepath = filename if filename else self.filename
+
+ try:
+ with open(f"{filepath}.inputs.txt", "r+", encoding="utf-8"):
+ self.input_file = f"{filepath}.inputs.txt"
+ except FileNotFoundError:
+ with open(filepath, "r+", encoding="utf-8"):
+ self.input_file = filepath
+
+ print(f"The following input file was imported: {self.input_file}")
+
+ def import_errors(self, filename=None):
+ """Import monte carlo results from .txt file and save it into a
+ dictionary.
+
+ Parameters
+ ----------
+ filename : str
+ Name or directory path to the file to be imported. If none,
+ self.filename will be used.
+
+ Returns
+ -------
+ None
+ """
+ filepath = filename if filename else self.filename
+
+ try:
+ with open(f"{filepath}.errors.txt", "r+", encoding="utf-8"):
+ self.error_file = f"{filepath}.errors.txt"
+ except FileNotFoundError:
+ with open(filepath, "r+", encoding="utf-8"):
+ self.error_file = filepath
+ print(f"The following error file was imported: {self.error_file}")
+
+ def import_results(self, filename=None):
+ """Import monte carlo results from .txt file and save it into a
+ dictionary.
+
+ Parameters
+ ----------
+ filename : str
+ Name or directory path to the file to be imported. If none,
+ self.filename will be used.
+
+ Returns
+ -------
+ None
+ """
+ # select file to use
+ filepath = filename if filename else self.filename
+
+ self.import_outputs(filename=filepath)
+ self.import_inputs(filename=filepath)
+ self.import_errors(filename=filepath)
+
+ def export_ellipses_to_kml(
+ self,
+ filename,
+ origin_lat,
+ origin_lon,
+ type="all",
+ resolution=100,
+ color="ff0000ff",
+ ):
+ """Generates a KML file with the ellipses on the impact point.
+
+ Parameters
+ ----------
+ results : dict
+ Contains results from the Monte Carlo simulation.
+ filename : String
+ Name to the KML exported file.
+ origin_lat : float
+ Latitude coordinate of Ellipses' geometric center, in degrees.
+ origin_lon : float
+ Latitude coordinate of Ellipses' geometric center, in degrees.
+ type : String
+ Type of ellipses to be exported. Options are: 'all', 'impact' and
+ 'apogee'. Default is 'all', it exports both apogee and impact
+ ellipses.
+ resolution : int
+ Number of points to be used to draw the ellipse. Default is 100.
+ color : String
+ Color of the ellipse. Default is 'ff0000ff', which is red.
+ Kml files use an 8 digit HEX color format, see its docs.
+
+ Returns
+ -------
+ None
+ """
+
+ (
+ impact_ellipses,
+ apogee_ellipses,
+ *_,
+ ) = generate_monte_carlo_ellipses(self.results)
+ outputs = []
+
+ if type == "all" or type == "impact":
+ outputs = outputs + generate_monte_carlo_ellipses_coordinates(
+ impact_ellipses, origin_lat, origin_lon, resolution=resolution
+ )
+
+ if type == "all" or type == "apogee":
+ outputs = outputs + generate_monte_carlo_ellipses_coordinates(
+ apogee_ellipses, origin_lat, origin_lon, resolution=resolution
+ )
+
+ # Prepare data to KML file
+ kml_data = [[(coord[1], coord[0]) for coord in output] for output in outputs]
+
+ # Export to KML
+ kml = simplekml.Kml()
+
+ for i in range(len(outputs)):
+ if (type == "all" and i < 3) or (type == "impact"):
+ ellipse_name = "Impact σ" + str(i + 1)
+ elif type == "all" and i >= 3:
+ ellipse_name = "Apogee σ" + str(i - 2)
+ else:
+ ellipse_name = "Apogee σ" + str(i + 1)
+
+ mult_ell = kml.newmultigeometry(name=ellipse_name)
+ mult_ell.newpolygon(
+ outerboundaryis=kml_data[i],
+ name="Ellipse " + str(i),
+ )
+ # Setting ellipse style
+ mult_ell.tessellate = 1
+ mult_ell.visibility = 1
+ mult_ell.style.linestyle.color = color
+ mult_ell.style.linestyle.width = 3
+ mult_ell.style.polystyle.color = simplekml.Color.changealphaint(
+ 100, simplekml.Color.blue
+ )
+
+ kml.save(filename)
+
+ def info(self):
+ """Print information about the monte carlo simulation."""
+ self.prints.all()
+
+ def all_info(self):
+ """Print and plot information about the monte carlo simulation
+ and its results.
+
+ Returns
+ -------
+ None
+ """
+ self.info()
+ self.plots.ellipses()
+ self.plots.all()
diff --git a/rocketpy/stochastic/__init__.py b/rocketpy/stochastic/__init__.py
new file mode 100644
index 000000000..74364e8ef
--- /dev/null
+++ b/rocketpy/stochastic/__init__.py
@@ -0,0 +1,18 @@
+"""The rocketpy.stochastic module contains classes that are used to generate
+randomized objects based on the provided information. Each of the classes
+defined here represent one different rocketpy class."""
+
+from .stochastic_aero_surfaces import (
+ StochasticEllipticalFins,
+ StochasticNoseCone,
+ StochasticRailButtons,
+ StochasticTail,
+ StochasticTrapezoidalFins,
+)
+from .stochastic_environment import StochasticEnvironment
+from .stochastic_flight import StochasticFlight
+from .stochastic_generic_motor import StochasticGenericMotor
+from .stochastic_model import StochasticModel
+from .stochastic_parachute import StochasticParachute
+from .stochastic_rocket import StochasticRocket
+from .stochastic_solid_motor import StochasticSolidMotor
diff --git a/rocketpy/stochastic/stochastic_aero_surfaces.py b/rocketpy/stochastic/stochastic_aero_surfaces.py
new file mode 100644
index 000000000..5d933204a
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_aero_surfaces.py
@@ -0,0 +1,487 @@
+"""Defines the StochasticNoseCone, StochasticTrapezoidalFins,
+StochasticEllipticalFins, StochasticTail and StochasticRailButtons classes."""
+
+from rocketpy.rocket.aero_surface import (
+ EllipticalFins,
+ NoseCone,
+ RailButtons,
+ Tail,
+ TrapezoidalFins,
+)
+
+from .stochastic_model import StochasticModel
+
+
+class StochasticNoseCone(StochasticModel):
+ """A Stochastic Nose Cone class that inherits from StochasticModel. This
+ class is used to receive a NoseCone object and information about the
+ dispersion of its parameters and generate a random nose cone object based
+ on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : NoseCone
+ NoseCone object to be used for validation.
+ length : tuple, list, int, float
+ Length of the nose cone in meters. Follows the standard input format of
+ Stochastic Models.
+ kind : list
+ List of strings representing the kind of nose cone. Follows the standard
+ input format of Stochastic Models.
+ base_radius : tuple, list, int, float
+ Base radius of the nose cone in meters. Follows the standard input
+ format of Stochastic Models.
+ bluffness : tuple, list, int, float
+ Bluffness of the nose cone. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the nose cone in meters. Follows the standard input
+ format of Stochastic Models.
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ nosecone,
+ length=None,
+ kind=None,
+ base_radius=None,
+ bluffness=None,
+ rocket_radius=None,
+ ):
+ """Initializes the Stochastic Nose Cone class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ nosecone : NoseCone
+ NoseCone object to be used for validation.
+ length : tuple, list, int, float
+ Length of the nose cone in meters. Follows the standard input format
+ of Stochastic Models.
+ kind : list
+ List of strings representing the kind of nose cone. Follows the
+ standard input format of Stochastic Models.
+ base_radius : tuple, list, int, float
+ Base radius of the nose cone in meters. Follows the standard input
+ format of Stochastic Models.
+ bluffness : tuple, list, int, float
+ Bluffness of the nose cone. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the nose cone in meters. Follows the standard input
+ format of Stochastic Models.
+ """
+ self._validate_kind(kind)
+ super().__init__(
+ nosecone,
+ length=length,
+ kind=kind,
+ base_radius=base_radius,
+ bluffness=bluffness,
+ rocket_radius=rocket_radius,
+ name=None,
+ )
+
+ def _validate_kind(self, kind):
+ """Validates the kind input. If the kind input argument is not None, it
+ must be a list of strings."""
+ if kind is not None:
+ assert isinstance(kind, list) and all(
+ isinstance(member, str) for member in kind
+ ), "`kind` must be a list of strings"
+
+ def create_object(self):
+ """Creates and returns a NoseCone object from the randomly generated
+ input arguments.
+
+ Returns
+ -------
+ nosecone : NoseCone
+ NoseCone object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return NoseCone(**generated_dict)
+
+
+class StochasticTrapezoidalFins(StochasticModel):
+ """A Stochastic Trapezoidal Fins class that inherits from StochasticModel.
+ This class is used to receive a TrapezoidalFins object and information about
+ the dispersion of its parameters and generate a random trapezoidal fins
+ object based on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : TrapezoidalFins
+ TrapezoidalFins object to be used for validation.
+ n : list of ints
+ List of integers representing the number of fins. Follows the standard
+ input format of Stochastic Models.
+ root_chord : tuple, list, int, float
+ Root chord of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ tip_chord : tuple, list, int, float
+ Tip chord of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ span : tuple, list, int, float
+ Span of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the fins in meters. Follows the standard input format
+ of Stochastic Models.
+ cant_angle : tuple, list, int, float
+ Cant angle of the fins in degrees. Follows the standard input format of
+ Stochastic Models.
+ sweep_length : tuple, list, int, float
+ Sweep length of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ sweep_angle : tuple, list, int, float
+ Sweep angle of the fins in degrees. Follows the standard input format of
+ Stochastic Models.
+ airfoil : list
+ List of tuples in the form of (airfoil file path, airfoil name).
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ trapezoidal_fins,
+ n=None,
+ root_chord=None,
+ tip_chord=None,
+ span=None,
+ rocket_radius=None,
+ cant_angle=None,
+ sweep_length=None,
+ sweep_angle=None,
+ airfoil=None,
+ ):
+ """Initializes the Stochastic Trapezoidal Fins class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ trapezoidal_fins : TrapezoidalFins
+ TrapezoidalFins object to be used for validation.
+ n : list of ints
+ List of integers representing the number of fins. Follows the
+ standard input format of Stochastic Models.
+ root_chord : tuple, list, int, float
+ Root chord of the fins in meters. Follows the standard input format
+ of Stochastic Models.
+ tip_chord : tuple, list, int, float
+ Tip chord of the fins in meters. Follows the standard input format
+ of Stochastic Models.
+ span : tuple, list, int, float
+ Span of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the fins in meters. Follows the standard input
+ format of Stochastic Models.
+ cant_angle : tuple, list, int, float
+ Cant angle of the fins in degrees. Follows the standard input format
+ of Stochastic Models.
+ sweep_length : tuple, list, int, float
+ Sweep length of the fins in meters. Follows the standard input
+ format of Stochastic Models.
+ sweep_angle : tuple, list, int, float
+ Sweep angle of the fins in degrees. Follows the standard input
+ format of Stochastic Models.
+ airfoil : list
+ List of tuples in the form of (airfoil file path, airfoil name).
+ """
+ self._validate_positive_int_list("n", n)
+ self._validate_airfoil(airfoil)
+ super().__init__(
+ trapezoidal_fins,
+ n=n,
+ root_chord=root_chord,
+ tip_chord=tip_chord,
+ span=span,
+ rocket_radius=rocket_radius,
+ cant_angle=cant_angle,
+ sweep_length=sweep_length,
+ sweep_angle=sweep_angle,
+ airfoil=airfoil,
+ name=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a TrapezoidalFins object from the randomly
+ generated input arguments.
+
+ Returns
+ -------
+ fins : TrapezoidalFins
+ TrapezoidalFins object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return TrapezoidalFins(**generated_dict)
+
+
+class StochasticEllipticalFins(StochasticModel):
+ """A Stochastic Elliptical Fins class that inherits from StochasticModel.
+ This class is used to receive a EllipticalFins object and information about
+ the dispersion of its parameters and generate a random elliptical fins
+ object based on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : EllipticalFins
+ EllipticalFins object to be used for validation.
+ n : list of ints
+ List of integers representing the number of fins. Follows the standard
+ input format of Stochastic Models.
+ root_chord : tuple, list, int, float
+ Root chord of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ span : tuple, list, int, float
+ Span of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the fins in meters. Follows the standard input format
+ of Stochastic Models.
+ cant_angle : tuple, list, int, float
+ Cant angle of the fins in degrees. Follows the standard input format of
+ Stochastic Models.
+ airfoil : list
+ List of tuples in the form of (airfoil file path, airfoil name).
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ elliptical_fins=None,
+ n=None,
+ root_chord=None,
+ span=None,
+ rocket_radius=None,
+ cant_angle=None,
+ airfoil=None,
+ ):
+ """Initializes the Stochastic Elliptical Fins class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ elliptical_fins : EllipticalFins
+ EllipticalFins object to be used for validation.
+ n : list of ints
+ List of integers representing the number of fins. Follows the
+ standard input format of Stochastic Models.
+ root_chord : tuple, list, int, float
+ Root chord of the fins in meters. Follows the standard input format
+ of Stochastic Models.
+ span : tuple, list, int, float
+ Span of the fins in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the fins in meters. Follows the standard input
+ format of Stochastic Models.
+ cant_angle : tuple, list, int, float
+ Cant angle of the fins in degrees. Follows the standard input format
+ of Stochastic Models.
+ airfoil : list
+ List of tuples in the form of (airfoil file path, airfoil name).
+ """
+ self._validate_positive_int_list("n", n)
+ self._validate_airfoil(airfoil)
+ super().__init__(
+ elliptical_fins,
+ n=n,
+ root_chord=root_chord,
+ span=span,
+ rocket_radius=rocket_radius,
+ cant_angle=cant_angle,
+ airfoil=airfoil,
+ name=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a EllipticalFins object from the randomly
+ generated input arguments.
+
+ Returns
+ -------
+ fins : EllipticalFins
+ EllipticalFins object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return EllipticalFins(**generated_dict)
+
+
+class StochasticTail(StochasticModel):
+ """A Stochastic Tail class that inherits from StochasticModel. This class
+ is used to receive a Tail object and information about the dispersion of its
+ parameters and generate a random tail object based on the provided
+ information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : Tail
+ Tail object to be used for validation.
+ top_radius : tuple, list, int, float
+ Top radius of the tail in meters. Follows the standard input format of
+ Stochastic Models.
+ bottom_radius : tuple, list, int, float
+ Bottom radius of the tail in meters. Follows the standard input format
+ of Stochastic Models.
+ length : tuple, list, int, float
+ Length of the tail in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the tail in meters. Follows the standard input format
+ of Stochastic Models.
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ tail,
+ top_radius=None,
+ bottom_radius=None,
+ length=None,
+ rocket_radius=None,
+ ):
+ """Initializes the Stochastic Tail class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ tail : Tail
+ Tail object to be used for validation.
+ top_radius : tuple, list, int, float
+ Top radius of the tail in meters. Follows the standard input format
+ of Stochastic Models.
+ bottom_radius : tuple, list, int, float
+ Bottom radius of the tail in meters. Follows the standard input
+ format of Stochastic Models.
+ length : tuple, list, int, float
+ Length of the tail in meters. Follows the standard input format of
+ Stochastic Models.
+ rocket_radius : tuple, list, int, float
+ Rocket radius of the tail in meters. Follows the standard input
+ format of Stochastic Models.
+ """
+ super().__init__(
+ tail,
+ top_radius=top_radius,
+ bottom_radius=bottom_radius,
+ length=length,
+ rocket_radius=rocket_radius,
+ name=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a Tail object from the randomly generated input
+ arguments.
+
+ Returns
+ -------
+ tail : Tail
+ Tail object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return Tail(**generated_dict)
+
+
+class StochasticRailButtons(StochasticModel):
+ """A Stochastic RailButtons class that inherits from StochasticModel. This
+ class is used to receive a RailButtons object and information about the
+ dispersion of its parameters and generate a random rail buttons object based
+ on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : RailButtons
+ RailButtons object to be used for validation.
+ rail_buttons : list
+ List of RailButton objects. Follows the standard input format of
+ Stochastic Models.
+ buttons_distance : tuple, list, int, float
+ Distance between the buttons in meters. Follows the standard input
+ format of Stochastic Models.
+ angular_position : tuple, list, int, float
+ Angular position of the buttons in degrees. Follows the standard input
+ format of Stochastic Models.
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ rail_buttons=None,
+ buttons_distance=None,
+ angular_position=None,
+ ):
+ """Initializes the Stochastic RailButtons class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ rail_buttons : RailButtons
+ RailButtons object to be used for validation.
+ buttons_distance : tuple, list, int, float
+ Distance between the buttons in meters. Follows the standard input
+ format of Stochastic Models.
+ angular_position : tuple, list, int, float
+ Angular position of the buttons in degrees. Follows the standard
+ input format of Stochastic Models.
+ """
+ super().__init__(
+ rail_buttons,
+ buttons_distance=buttons_distance,
+ angular_position=angular_position,
+ name=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a RailButtons object from the randomly generated
+ input arguments.
+
+ Returns
+ -------
+ rail_buttons : RailButtons
+ RailButtons object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return RailButtons(**generated_dict)
diff --git a/rocketpy/stochastic/stochastic_environment.py b/rocketpy/stochastic/stochastic_environment.py
new file mode 100644
index 000000000..27c55aab5
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_environment.py
@@ -0,0 +1,211 @@
+"""Defines the StochasticEnvironment class."""
+
+from .stochastic_model import StochasticModel
+
+
+class StochasticEnvironment(StochasticModel):
+ """A Stochastic Environment class that inherits from StochasticModel. This
+ class is used to receive a Environment object and information about the
+ dispersion of its parameters and generate a random environment object based
+ on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : Environment
+ Environment object to be used for validation.
+ elevation : tuple, list, int, float
+ Elevation of the launch site in meters. Follows the standard input
+ format of Stochastic Models.
+ gravity : tuple, list, int, float
+ Gravitational acceleration in meters per second squared. Follows the
+ standard input format of Stochastic Models.
+ latitude : tuple, list, int, float
+ Latitude of the launch site in degrees. Follows the standard input
+ format of Stochastic Models.
+ longitude : tuple, list, int, float
+ Longitude of the launch site in degrees. Follows the standard input
+ format of Stochastic Models.
+ ensemble_member : list
+ List of integers representing the ensemble member to be selected.
+ wind_velocity_x_factor : tuple, list, int, float
+ Factor to be multiplied by the wind velocity in the x direction.
+ wind_velocity_y_factor : tuple, list, int, float
+ Factor to be multiplied by the wind velocity in the y direction.
+ date : list
+ List of dates, which are tuples of four elements
+ (year, month, day, hour). This attribute can not be randomized.
+ datum : list
+ List of datum. This attribute can not be randomized.
+ timezone : list
+ List of timezones. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ environment,
+ elevation=None,
+ gravity=None,
+ latitude=None,
+ longitude=None,
+ ensemble_member=None,
+ wind_velocity_x_factor=(1, 0),
+ wind_velocity_y_factor=(1, 0),
+ ):
+ """Initializes the Stochastic Environment class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ environment : Environment
+ Environment object to be used for validation.
+ date : list, optional
+ List of dates, which are tuples of four elements
+ (year, month, day, hour).
+ elevation : int, float, tuple, list, optional
+ Elevation of the launch site in meters. Follows the standard
+ input format of Stochastic Models.
+ gravity : int, float, tuple, list, optional
+ Gravitational acceleration in meters per second squared. Follows
+ the standard input format of Stochastic Models.
+ latitude : int, float, tuple, list, optional
+ Latitude of the launch site in degrees. Follows the standard
+ input format of Stochastic Models.
+ longitude : int, float, tuple, list, optional
+ Longitude of the launch site in degrees. Follows the standard
+ input format of Stochastic Models.
+ ensemble_member : list, optional
+ List of integers representing the ensemble member to be selected.
+ wind_velocity_x_factor : int, float, tuple, list, optional
+ Factor to be multiplied by the wind velocity in the x direction.
+ Follows the factor input format of Stochastic Models.
+ wind_velocity_y_factor : int, float, tuple, list, optional
+ Factor to be multiplied by the wind velocity in the y direction.
+ Follows the factor input format of Stochastic Models.
+ """
+ # Validate in StochasticModel
+ super().__init__(
+ environment,
+ date=None,
+ elevation=elevation,
+ gravity=gravity,
+ latitude=latitude,
+ longitude=longitude,
+ ensemble_member=ensemble_member,
+ wind_velocity_x_factor=wind_velocity_x_factor,
+ wind_velocity_y_factor=wind_velocity_y_factor,
+ datum=None,
+ timezone=None,
+ )
+ self._validate_ensemble(ensemble_member, environment)
+
+ def __str__(self):
+ # special str for environment because of datetime
+ s = ""
+ for key, value in self.__dict__.items():
+ if key.startswith("_"):
+ continue # Skip attributes starting with underscore
+ if isinstance(value, tuple):
+ try:
+ # Format the tuple as a string with the mean and standard deviation.
+ value_str = (
+ f"{value[0]:.5f} ± {value[1]:.5f} "
+ f"(numpy.random.{value[2].__name__})"
+ )
+ except AttributeError:
+ # treats date attribute
+ value_str = str(value)
+ else:
+ # Otherwise, just use the default string representation of the value.
+ value_str = str(value)
+ s += f"{key}: {value_str}\n"
+ return s.strip()
+
+ def _validate_ensemble(self, ensemble_member, environment):
+ """Validates the ensemble member input argument. If the environment
+ does not have ensemble members, the ensemble member input argument
+ must be None. If the environment has ensemble members, the ensemble
+ member input argument must be a list of positive integers, and the
+ integers must be in the range from 0 to the number of ensemble members
+ minus one.
+
+ Parameters
+ ----------
+ ensemble_member : list
+ List of integers representing the ensemble member to be selected.
+ environment : Environment
+ Environment object to be used for validation.
+
+ Returns
+ -------
+ None
+
+ Raises
+ ------
+ AssertionError
+ If the environment does not have ensemble members and the
+ ensemble_member input argument is not None.
+ """
+ valid_atmospheric_types = ["Ensemble", "Reanalysis"]
+
+ if environment.atmospheric_model_type not in valid_atmospheric_types:
+ if ensemble_member is not None:
+ raise AssertionError(
+ f"Environment with {environment.atmospheric_model_type} "
+ "does not have ensemble members"
+ )
+ return
+
+ if ensemble_member is not None:
+ assert isinstance(ensemble_member, list), "`ensemble_member` must be a list"
+ assert all(
+ isinstance(member, int) and member >= 0 for member in ensemble_member
+ ), "`ensemble_member` must be a list of positive integers"
+ assert (
+ 0
+ <= min(ensemble_member)
+ <= max(ensemble_member)
+ < environment.num_ensemble_members
+ ), (
+ "`ensemble_member` must be in the range from 0 to "
+ + f"{environment.num_ensemble_members - 1}"
+ )
+ setattr(self, "ensemble_member", ensemble_member)
+ else:
+ # if no ensemble member is provided, get it from the environment
+ setattr(self, "ensemble_member", environment.ensemble_member)
+
+ def create_object(self):
+ """Creates a Environment object from the randomly generated input
+ arguments.The environment object is not recreated to avoid having to
+ reestablish the atmospheric model. Instead, attributes are changed
+ directly.
+
+ Parameters
+ ----------
+ None
+
+ Returns
+ -------
+ obj : Environment
+ Environment object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ for key, value in generated_dict.items():
+ # special case for ensemble member
+ # TODO: Generalize create_object() with a env.ensemble_member setter
+ if key == "ensemble_member":
+ self.object.select_ensemble_member(value)
+ else:
+ if "factor" in key:
+ # get original attribute value and multiply by factor
+ attribute_name = f"_{key.replace('_factor', '')}"
+ value = getattr(self, attribute_name) * value
+ setattr(self.object, key, value)
+ return self.object
diff --git a/rocketpy/stochastic/stochastic_flight.py b/rocketpy/stochastic/stochastic_flight.py
new file mode 100644
index 000000000..78ed65774
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_flight.py
@@ -0,0 +1,146 @@
+"""Defines the StochasticFlight class."""
+
+from rocketpy.simulation import Flight
+
+from .stochastic_model import StochasticModel
+
+
+class StochasticFlight(StochasticModel):
+ """A Stochastic Flight class that inherits from StochasticModel. This
+ class is used to receive a Flight object and information about the
+ dispersion of its parameters and generate a random flight object based on
+ the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ flight : Flight
+ The Flight object to be used as a base for the Stochastic flight.
+ rail_length : int, float, tuple, list, optional
+ The rail length of the flight. Follows the standard input format of
+ Stochastic Models.
+ inclination : int, float, tuple, list, optional
+ The inclination of the flight. Follows the standard input format of
+ Stochastic Models.
+ heading : int, float, tuple, list, optional
+ The heading of the flight. Follows the standard input format of
+ Stochastic Models.
+ initial_solution : tuple, list, optional
+ The initial solution of the flight. This is a tuple of 14 elements that
+ represent the initial conditions of the flight. This attribute can not
+ be randomized.
+ terminate_on_apogee : bool, optional
+ Whether or not the flight should terminate on apogee. This attribute
+ can not be randomized.
+ """
+
+ def __init__(
+ self,
+ flight,
+ rail_length=None,
+ inclination=None,
+ heading=None,
+ initial_solution=None,
+ terminate_on_apogee=None,
+ ):
+ """Initializes the Stochastic Flight class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ flight : Flight
+ The Flight object to be used as a base for the Stochastic flight.
+ rail_length : int, float, tuple, list, optional
+ The rail length of the flight. Follows the standard input format of
+ Stochastic Models.
+ inclination : int, float, tuple, list, optional
+ The inclination of the flight. Follows the standard input format of
+ Stochastic Models.
+ heading : int, float, tuple, list, optional
+ The heading of the flight. Follows the standard input format of
+ Stochastic Models.
+ initial_solution : tuple, list, optional
+ The initial solution of the flight. This is a tuple of 14 elements
+ that represent the initial conditions of the flight. This attribute
+ can not be randomized.
+ terminate_on_apogee : bool, optional
+ Whether or not the flight should terminate on apogee. This attribute
+ can not be randomized.
+ """
+ if terminate_on_apogee is not None:
+ assert isinstance(
+ terminate_on_apogee, bool
+ ), "`terminate_on_apogee` must be a boolean"
+ super().__init__(
+ flight,
+ rail_length=rail_length,
+ inclination=inclination,
+ heading=heading,
+ )
+
+ self.initial_solution = initial_solution
+ self.terminate_on_apogee = terminate_on_apogee
+
+ def _validate_initial_solution(self, initial_solution):
+ if initial_solution is not None:
+ if isinstance(initial_solution, (tuple, list)):
+ assert len(initial_solution) == 14, (
+ "`initial_solution` must be a 14 element tuple, the "
+ "elements are:\n t_initial, x_init, y_init, z_init, "
+ "vx_init, vy_init, vz_init, e0_init, e1_init, e2_init, "
+ "e3_init, w1Init, w2Init, w3Init"
+ )
+ assert all(
+ isinstance(i, (int, float)) for i in initial_solution
+ ), "`initial_solution` must be a tuple of numbers"
+ else:
+ raise TypeError("`initial_solution` must be a tuple of numbers")
+
+ # TODO: these call dict_generator a lot of times unnecessarily
+ def _randomize_rail_length(self):
+ """Randomizes the rail length of the flight. Follows the standard input
+ format of Stochastic Models.
+ """
+ generated_dict = next(self.dict_generator())
+ return generated_dict["rail_length"]
+
+ def _randomize_inclination(self):
+ """Randomizes the inclination of the flight. Follows the standard input
+ format of Stochastic Models.
+ """
+ generated_dict = next(self.dict_generator())
+ return generated_dict["inclination"]
+
+ def _randomize_heading(self):
+ """Randomizes the heading of the flight. Follows the standard input
+ format of Stochastic Models.
+ """
+ generated_dict = next(self.dict_generator())
+ return generated_dict["heading"]
+
+ def create_object(self):
+ """Creates and returns a Flight object from the randomly generated input
+ arguments.
+
+ Returns
+ -------
+ flight : Flight
+ Flight object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ # TODO: maybe we should use generated_dict["rail_length"] instead
+ return Flight(
+ environment=self.object.env,
+ rail_length=self._randomize_rail_length(),
+ rocket=self.object.rocket,
+ inclination=generated_dict["inclination"],
+ heading=generated_dict["heading"],
+ initial_solution=self.initial_solution,
+ terminate_on_apogee=self.terminate_on_apogee,
+ )
diff --git a/rocketpy/stochastic/stochastic_generic_motor.py b/rocketpy/stochastic/stochastic_generic_motor.py
new file mode 100644
index 000000000..e4220e68a
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_generic_motor.py
@@ -0,0 +1,228 @@
+"""Defines the StochasticGenericMotor class."""
+
+from rocketpy.motors import GenericMotor
+
+from .stochastic_motor_model import StochasticMotorModel
+
+
+class StochasticGenericMotor(StochasticMotorModel):
+ """A Stochastic Generic Motor class that inherits from StochasticModel.
+ This class is used to receive a GenericMotor object and information about
+ the dispersion of its parameters and generate a random generic motor object
+ based on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : GenericMotor
+ GenericMotor object to be used for validation.
+ thrust_source : list
+ List of strings representing the thrust source to be selected.
+ total_impulse : int, float, tuple, list
+ Total impulse of the motor in newton seconds. Follows the standard
+ input format of Stochastic Models.
+ burn_start_time : int, float, tuple, list
+ Burn start time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ burn_out_time : int, float, tuple, list
+ Burn out time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ dry_mass : int, float, tuple, list
+ Dry mass of the motor in kilograms. Follows the standard input
+ format of Stochastic Models.
+ dry_I_11 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ dry_I_22 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ dry_I_33 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ dry_I_12 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ dry_I_13 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ dry_I_23 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows the
+ standard input format of Stochastic Models.
+ chamber_radius : int, float, tuple, list
+ Chamber radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ chamber_height : int, float, tuple, list
+ Chamber height of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ chamber_position : int, float, tuple, list
+ Chamber position of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ nozzle_radius : int, float, tuple, list
+ Nozzle radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ nozzle_position : int, float, tuple, list
+ Nozzle position of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ center_of_dry_mass_position : int, float, tuple, list
+ Center of dry mass position of the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ interpolation_method : str, optional
+ Interpolation method to be used. This attribute can not be randomized.
+ coordinate_system_orientation : str, optional
+ Coordinate system orientation to be used. This attribute can not be
+ randomized.
+ """
+
+ def __init__(
+ self,
+ generic_motor,
+ thrust_source=None,
+ total_impulse=None,
+ burn_start_time=None,
+ burn_out_time=None,
+ propellant_initial_mass=None,
+ dry_mass=None,
+ dry_inertia_11=None,
+ dry_inertia_22=None,
+ dry_inertia_33=None,
+ dry_inertia_12=None,
+ dry_inertia_13=None,
+ dry_inertia_23=None,
+ chamber_radius=None,
+ chamber_height=None,
+ chamber_position=None,
+ nozzle_radius=None,
+ nozzle_position=None,
+ center_of_dry_mass_position=None,
+ ):
+ """Initializes the Stochastic Generic Motor class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ generic_motor : GenericMotor
+ GenericMotor object to be used for validation.
+ thrust_source : list, optional
+ List of strings representing the thrust source to be selected.
+ Follows the 1d array like input format of Stochastic Models.
+ total_impulse : int, float, tuple, list, optional
+ Total impulse of the motor in newton seconds. Follows the standard
+ input format of Stochastic Models.
+ burn_start_time : int, float, tuple, list, optional
+ Burn start time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ burn_out_time : int, float, tuple, list, optional
+ Burn out time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ dry_mass : int, float, tuple, list, optional
+ Dry mass of the motor in kilograms. Follows the standard input
+ format of Stochastic Models.
+ dry_I_11 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_22 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_33 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_12 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_13 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_23 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ chamber_radius : int, float, tuple, list, optional
+ Chamber radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ chamber_height : int, float, tuple, list, optional
+ Chamber height of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ chamber_position : int, float, tuple, list, optional
+ Chamber position of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ nozzle_radius : int, float, tuple, list, optional
+ Nozzle radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ nozzle_position : int, float, tuple, list, optional
+ Nozzle position of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ center_of_dry_mass_position : int, float, tuple, list, optional
+ Center of dry mass position of the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ """
+ super().__init__(
+ generic_motor,
+ thrust_source=thrust_source,
+ total_impulse=total_impulse,
+ burn_start_time=burn_start_time,
+ burn_out_time=burn_out_time,
+ propellant_initial_mass=propellant_initial_mass,
+ dry_mass=dry_mass,
+ dry_I_11=dry_inertia_11,
+ dry_I_22=dry_inertia_22,
+ dry_I_33=dry_inertia_33,
+ dry_I_12=dry_inertia_12,
+ dry_I_13=dry_inertia_13,
+ dry_I_23=dry_inertia_23,
+ chamber_radius=chamber_radius,
+ chamber_height=chamber_height,
+ chamber_position=chamber_position,
+ nozzle_radius=nozzle_radius,
+ nozzle_position=nozzle_position,
+ center_of_dry_mass_position=center_of_dry_mass_position,
+ interpolate=None,
+ coordinate_system_orientation=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a GenericMotor object from the randomly generated
+ input arguments.
+
+ Returns
+ -------
+ generic_motor : GenericMotor
+ GenericMotor object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ generic_motor = GenericMotor(
+ thrust_source=generated_dict["thrust_source"],
+ burn_time=(
+ generated_dict["burn_start_time"],
+ generated_dict["burn_out_time"],
+ ),
+ propellant_initial_mass=generated_dict["propellant_initial_mass"],
+ dry_mass=generated_dict["dry_mass"],
+ dry_inertia=(
+ generated_dict["dry_I_11"],
+ generated_dict["dry_I_22"],
+ generated_dict["dry_I_33"],
+ generated_dict["dry_I_12"],
+ generated_dict["dry_I_13"],
+ generated_dict["dry_I_23"],
+ ),
+ chamber_radius=generated_dict["chamber_radius"],
+ chamber_height=generated_dict["chamber_height"],
+ chamber_position=generated_dict["chamber_position"],
+ nozzle_radius=generated_dict["nozzle_radius"],
+ nozzle_position=generated_dict["nozzle_position"],
+ center_of_dry_mass_position=generated_dict["center_of_dry_mass_position"],
+ reshape_thrust_curve=(
+ (generated_dict["burn_start_time"], generated_dict["burn_out_time"]),
+ generated_dict["total_impulse"],
+ ),
+ coordinate_system_orientation=generated_dict[
+ "coordinate_system_orientation"
+ ],
+ interpolation_method=generated_dict["interpolate"],
+ )
+ return generic_motor
diff --git a/rocketpy/stochastic/stochastic_model.py b/rocketpy/stochastic/stochastic_model.py
new file mode 100644
index 000000000..c60d712f6
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_model.py
@@ -0,0 +1,536 @@
+"""Defines the StochasticModel class, which will be used as a base class for all
+other Stochastic classes."""
+
+from random import choice
+
+import numpy as np
+
+from rocketpy.mathutils.function import Function
+
+from ..tools import get_distribution
+
+# TODO: Stop using assert in production code. Use exceptions instead.
+
+
+class StochasticModel:
+ """Base class for all Stochastic classes. This class is used to validate
+ the input arguments of the child classes. The input arguments are validated
+ and saved as attributes of the class in the correct format. The attributes
+ are then used to generate a dictionary with the randomly generated input
+ arguments. The dictionary is saved as an attribute of the class.
+ """
+
+ # List of arguments that are validated in child classes
+ exception_list = [
+ "initial_solution",
+ "terminate_on_apogee",
+ "date",
+ "ensemble_member",
+ ]
+
+ def __init__(self, object, **kwargs):
+ """Initialize the StochasticModel class with validated input arguments.
+
+ Parameters
+ ----------
+ object : object
+ The main object of the class.
+ **kwargs : dict
+ Dictionary with input arguments for the class. Arguments should be
+ provided as keyword arguments, where the key is the argument name,
+ and the value is the argument value. Valid argument types include
+ tuples, lists, ints, floats, or None. The arguments will then be
+ validated and saved as attributes of the class in the correct
+ format. See each validation method for more information. None values
+ are allowed and will be replaced by the value of the attribute in
+ the main object. When saved as an attribute, the value will be saved
+ as a list with one item. If in the child class constructor an
+ argument of the original class is not allowed, then it has to be
+ passed as None in the super().__init__ call.
+
+ Raises
+ ------
+ AssertionError
+ If the input arguments do not conform to the specified formats.
+ """
+ self.object = object
+ self.last_rnd_dict = {}
+
+ for input_name, input_value in kwargs.items():
+ if input_name not in self.exception_list:
+ if input_value is not None:
+ if "factor" in input_name:
+ attr_value = self._validate_factors(input_name, input_value)
+ elif input_name not in self.exception_list:
+ if isinstance(input_value, tuple):
+ attr_value = self._validate_tuple(input_name, input_value)
+ elif isinstance(input_value, list):
+ attr_value = self._validate_list(input_name, input_value)
+ elif isinstance(input_value, (int, float)):
+ attr_value = self._validate_scalar(input_name, input_value)
+ else:
+ raise AssertionError(
+ f"'{input_name}' must be a tuple, list, int, or float"
+ )
+ else:
+ # if input_value is None, then the value will be taken from
+ # the main object and saved as a one item list.
+ attr_value = [getattr(self.object, input_name)]
+ setattr(self, input_name, attr_value)
+
+ def __str__(self):
+ # TODO: This method with a StochasticRocket with added motor, aero surfaces,
+ # and/or parachutes is a mess right now
+ s = ""
+ for key, value in self.__dict__.items():
+ if key.startswith("_"):
+ continue # Skip attributes starting with underscore
+ if isinstance(value, tuple):
+ # Format the tuple as a string with the mean and standard deviation.
+ value_str = (
+ f"{value[0]:.5f} ± {value[1]:.5f} "
+ f"(numpy.random.{value[2].__name__})"
+ )
+ else:
+ # Otherwise, just use the default string representation of the value.
+ value_str = str(value)
+ s += f"{key}: {value_str}\n"
+ return s.strip()
+
+ # TODO: elaborate a short, concise version of the __str__ method
+ # def __repr__(self):
+ # return f"{self.__class__.__name__}(object={self.object}, **kwargs)"
+
+ def _validate_tuple(self, input_name, input_value, getattr=getattr):
+ """Validator for tuple arguments. Checks if input is in a valid format.
+ Tuples are validated as follows:
+ - Must have length 2 or 3;
+ - First item must be either an int or float;
+ - If length is two, then the type of the second item must be either
+ an int, float or str:
+ - If the second item is an int or float, then it is assumed that
+ the first item is the nominal value and the second item is the
+ standard deviation;
+ - If the second item is a string, then it is assumed that the
+ first item is the standard deviation, and the second item is
+ the distribution function string. In this case, the nominal
+ value will be taken from the main object;
+ - If length is three, then it is assumed that the first item is the
+ nominal value, the second item is the standard deviation and the
+ third item is the distribution function string.
+
+ Tuples are always saved as a tuple with length 3, where the first item
+ is the nominal value, the second item is the standard deviation and the
+ third item is the numpy distribution function.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : tuple
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple
+ Tuple with length 3, where the first item is the nominal value, the
+ second item is the standard deviation and the third item is the
+ numpy distribution function.
+
+ Raises
+ ------
+ AssertionError
+ If the input is not in a valid format.
+ """
+ assert len(input_value) in [
+ 2,
+ 3,
+ ], f"'{input_name}': tuple must have length 2 or 3"
+ assert isinstance(
+ input_value[0], (int, float)
+ ), f"'{input_name}': First item of tuple must be either an int or float"
+
+ if len(input_value) == 2:
+ return self._validate_tuple_length_two(input_name, input_value, getattr)
+ if len(input_value) == 3:
+ return self._validate_tuple_length_three(input_name, input_value, getattr)
+
+ def _validate_tuple_length_two(self, input_name, input_value, getattr=getattr):
+ """Validator for tuples with length 2. Checks if input is in a valid
+ format. If length is two, then the type of the second item must be
+ either an int, float or str:
+
+ - If the second item is an int or float, then it is assumed that the
+ first item is the nominal value and the second item is the standard
+ deviation;
+ - If the second item is a string, then it is assumed that the first
+ item is the standard deviation, and the second item is the
+ distribution function string. In this case, the nominal value will
+ be taken from the main object;
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : tuple
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple
+ Tuple with length 3, where the first item is the nominal value, the
+ second item is the standard deviation and the third item is the
+ numpy distribution function.
+
+ Raises
+ ------
+ AssertionError
+ If the input is not in a valid format.
+ """
+ assert isinstance(
+ input_value[1], (int, float, str)
+ ), f"'{input_name}': second item of tuple must be an int, float, or string."
+
+ if isinstance(input_value[1], str):
+ # if second item is a string, then it is assumed that the first item
+ # is the standard deviation, and the second item is the distribution
+ # function. In this case, the nominal value will be taken from the
+ # object passed.
+ dist_func = get_distribution(input_value[1])
+ return (getattr(self.object, input_name), input_value[0], dist_func)
+ else:
+ # if second item is an int or float, then it is assumed that the
+ # first item is the nominal value and the second item is the
+ # standard deviation. The distribution function will be set to
+ # "normal".
+ return (input_value[0], input_value[1], get_distribution("normal"))
+
+ def _validate_tuple_length_three(self, input_name, input_value, getattr=getattr):
+ """Validator for tuples with length 3. Checks if input is in a valid
+ format. If length is three, then it is assumed that the first item is
+ the nominal value, the second item is the standard deviation and the
+ third item is the distribution function string.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : tuple
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple
+ Tuple with length 3, where the first item is the nominal value, the
+ second item is the standard deviation and the third item is the
+ numpy distribution function.
+
+ Raises
+ ------
+ AssertionError
+ If the input is not in a valid format.
+ """
+ assert isinstance(input_value[1], (int, float)), (
+ f"'{input_name}': Second item of a tuple with length 3 must be "
+ "an int or float."
+ )
+ assert isinstance(input_value[2], str), (
+ f"'{input_name}': Third item of tuple must be a "
+ "string containing the name of a valid numpy.random "
+ "distribution function."
+ )
+ dist_func = get_distribution(input_value[2])
+ return (input_value[0], input_value[1], dist_func)
+
+ def _validate_list(self, input_name, input_value, getattr=getattr):
+ """Validator for list arguments. Checks if input is in a valid format.
+ Lists are validated as follows:
+ - If the list is empty, then the value will be taken from the object
+ passed and returned as a list with one item.
+ - Else, the list is returned as is.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : list
+ Value of the input argument.
+
+ Returns
+ -------
+ list
+ List with the input value.
+
+ Raises
+ ------
+ AssertionError
+ If the input is not in a valid format.
+ """
+ if not input_value:
+ # if list is empty, then the value will be taken from the object
+ # passed and saved as a list with one item.
+ return [getattr(self.object, input_name)]
+ else:
+ # else, the list is saved as is.
+ return input_value
+
+ def _validate_scalar(self, input_name, input_value, getattr=getattr):
+ """Validator for scalar arguments. Checks if input is in a valid format.
+ Scalars are validated as follows:
+ - The value is assumed to be the standard deviation, the nominal
+ value will be taken from the object passed and the distribution
+ function will be set to "normal".
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : float
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple
+ Tuple with length 3, where the first item is the nominal value, the
+ second item is the standard deviation and the third item is the
+ numpy distribution function.
+
+ Raises
+ ------
+ AssertionError
+ If the input is not in a valid format.
+ """
+ return (
+ getattr(self.object, input_name),
+ input_value,
+ get_distribution("normal"),
+ )
+
+ def _validate_factors(self, input_name, input_value):
+ """Validator for factor arguments. Checks if input is in a valid format.
+ Factors can only be tuples of two or three items, or lists. Currently,
+ the supported factors are: wind_velocity_x_factor,
+ wind_velocity_y_factor, power_off_drag_factor, power_on_drag_factor.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : tuple or list
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple or list
+ Tuple or list in the correct format.
+
+ Raises
+ ------
+ AssertionError
+ If input is not a tuple, list, int, or float
+ """
+ # Save original value of attribute that factor is applied to as an
+ # private attribute
+ attribute_name = input_name.replace("_factor", "")
+ setattr(self, f"_{attribute_name}", getattr(self.object, attribute_name))
+
+ if isinstance(input_value, tuple):
+ return self._validate_tuple_factor(input_name, input_value)
+ elif isinstance(input_value, list):
+ return self._validate_list_factor(input_name, input_value)
+ else:
+ raise AssertionError(f"`{input_name}`: must be either a tuple or list")
+
+ def _validate_tuple_factor(self, input_name, factor_tuple):
+ """Validator for tuple factors. Checks if input is in a valid format.
+ Tuple factors can only have length 2 or 3. If length is two, then the
+ type of the second item must be either an int, float or str. If length
+ is three, then it is assumed that the first item is the nominal value,
+ the second item is the standard deviation and the third item is the
+ distribution function string.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ factor_tuple : tuple
+ Value of the input argument.
+
+ Returns
+ -------
+ tuple
+ Tuple in the correct format.
+
+ Raises
+ ------
+ AssertionError
+ If input is not in a valid format.
+ """
+ assert len(factor_tuple) in [
+ 2,
+ 3,
+ ], f"'{input_name}`: Factors tuple must have length 2 or 3"
+ assert all(isinstance(item, (int, float)) for item in factor_tuple[:2]), (
+ f"'{input_name}`: First and second items of Factors tuple must be "
+ "either an int or float"
+ )
+
+ if len(factor_tuple) == 2:
+ return (factor_tuple[0], factor_tuple[1], get_distribution("normal"))
+ elif len(factor_tuple) == 3:
+ assert isinstance(factor_tuple[2], str), (
+ f"'{input_name}`: Third item of tuple must be a string containing "
+ "the name of a valid numpy.random distribution function"
+ )
+ dist_func = get_distribution(factor_tuple[2])
+ return (factor_tuple[0], factor_tuple[1], dist_func)
+
+ def _validate_list_factor(self, input_name, factor_list):
+ """Validator for list factors. Checks if input is in a valid format.
+ List factors can only be lists of ints or floats.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ factor_list : list
+ Value of the input argument.
+
+ Returns
+ -------
+ list
+ List in the correct format.
+
+ Raises
+ ------
+ AssertionError
+ If input is not in a valid format.
+ """
+ assert all(
+ isinstance(item, (int, float)) for item in factor_list
+ ), f"'{input_name}`: Items in list must be either ints or floats"
+ return factor_list
+
+ def _validate_1d_array_like(self, input_name, input_value):
+ """Validator for 1D array like arguments. Checks if input is in a valid
+ format. 1D array like arguments can only be lists of strings, lists of
+ Functions, or lists of lists with shape (n,2).
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : list
+ Value of the input argument.
+
+ Returns
+ -------
+ None
+
+ Raises
+ ------
+ AssertionError
+ If input is not in a valid format.
+ """
+ if input_value is not None:
+ error_msg = (
+ f"`{input_name}` must be a list of path strings, "
+ + "lists with shape (n,2), or Functions."
+ )
+
+ # Inputs must always be a list
+ if not isinstance(input_value, list):
+ raise AssertionError(error_msg)
+
+ for member in input_value:
+ # if item is a list, then it must have shape (n,2)
+ if isinstance(member, list):
+ if len(np.shape(member)) != 2 and np.shape(member)[1] != 2:
+ raise AssertionError(error_msg)
+
+ # If item is not a string or Function, then raise error
+ elif not isinstance(member, (str, Function)):
+ raise AssertionError(error_msg)
+
+ def _validate_positive_int_list(self, input_name, input_value):
+ """Validates the input argument: if it is not None, it must be a list
+ of positive integers.
+
+ Parameters
+ ----------
+ input_name : str
+ Name of the input argument.
+ input_value : list
+ Value of the input argument.
+
+ Raises
+ ------
+ AssertionError
+ If input is not in a valid format.
+ """
+ if input_value is not None:
+ assert isinstance(input_value, list) and all(
+ isinstance(member, int) and member >= 0 for member in input_value
+ ), f"`{input_name}` must be a list of positive integers"
+
+ def _validate_airfoil(self, airfoil):
+ """Validates the input argument: if it is not None, it must be a list
+ of tuples with two items, where the first can be a 1D array like or
+ a string, and the second item must be a string.
+
+ Parameters
+ ----------
+ airfoil : list
+ List of tuples with two items.
+
+ Raises
+ ------
+ AssertionError
+ If input is not in a valid format.
+ """
+ if airfoil is not None:
+ assert isinstance(airfoil, list) and all(
+ isinstance(member, tuple) for member in airfoil
+ ), "`airfoil` must be a list of tuples"
+ for member in airfoil:
+ assert len(member) == 2, "`airfoil` tuples must have length 2"
+ assert isinstance(
+ member[1], str
+ ), "`airfoil` tuples must have a string as second item"
+ # if item is a list, then it must have shape (n,2)
+ if isinstance(member[0], list):
+ if len(np.shape(member[0])) != 2 and np.shape(member[0])[1] != 2:
+ raise AssertionError("`airfoil` tuples must have shape (n,2)")
+
+ # If item is not a string or Function, then raise error
+ elif not isinstance(member[0], (str, Function)):
+ raise AssertionError(
+ "`airfoil` tuples must have a string as first item"
+ )
+
+ def dict_generator(self):
+ """Generator that yields a dictionary with the randomly generated input
+ arguments. The dictionary is saved as an attribute of the class.
+ The dictionary is generated by looping through all attributes of the
+ class and generating a random value for each attribute. The random
+ values are generated according to the format of each attribute. Tuples
+ are generated using the distribution function specified in the tuple.
+ Lists are generated using the random.choice function.
+
+ Parameters
+ ----------
+ None
+
+ Yields
+ -------
+ dict
+ Dictionary with the randomly generated input arguments.
+ """
+ generated_dict = {}
+ for arg, value in self.__dict__.items():
+ if isinstance(value, tuple):
+ generated_dict[arg] = value[-1](value[0], value[1])
+ elif isinstance(value, list):
+ generated_dict[arg] = choice(value) if value else value
+ self.last_rnd_dict = generated_dict
+ yield generated_dict
diff --git a/rocketpy/stochastic/stochastic_motor_model.py b/rocketpy/stochastic/stochastic_motor_model.py
new file mode 100644
index 000000000..cc7764a15
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_motor_model.py
@@ -0,0 +1,18 @@
+"""Defines the StochasticMotorModel class."""
+
+from .stochastic_model import StochasticModel
+
+
+class StochasticMotorModel(StochasticModel):
+ """Stochastic Motor Model class that inherits from StochasticModel. This
+ class is used to standardize the input of the motor stochastic model.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+ """
+
+ def __init__(self, object, **kwargs):
+ self._validate_1d_array_like("thrust_source", kwargs.get("thrust_source"))
+ self._validate_positive_int_list("grain_number", kwargs.get("grain_number"))
+ super().__init__(object, **kwargs)
diff --git a/rocketpy/stochastic/stochastic_parachute.py b/rocketpy/stochastic/stochastic_parachute.py
new file mode 100644
index 000000000..03dae2f28
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_parachute.py
@@ -0,0 +1,143 @@
+"""Defines the StochasticParachute class."""
+
+from rocketpy.rocket import Parachute
+
+from .stochastic_model import StochasticModel
+
+
+class StochasticParachute(StochasticModel):
+ """A Stochastic Parachute class that inherits from StochasticModel. This
+ class is used to receive a Parachute object and information about the
+ dispersion of its parameters and generate a random parachute object based
+ on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : Parachute
+ Parachute object to be used for validation.
+ cd_s : tuple, list, int, float
+ Drag coefficient of the parachute. Follows the standard input format of
+ Stochastic Models.
+ trigger : list
+ List of callables, string "apogee" or ints/floats. Follows the standard
+ input format of Stochastic Models.
+ sampling_rate : tuple, list, int, float
+ Sampling rate of the parachute in seconds. Follows the standard input
+ format of Stochastic Models.
+ lag : tuple, list, int, float
+ Lag of the parachute in seconds. Follows the standard input format of
+ Stochastic Models.
+ noise : list
+ List of tuples in the form of (mean, standard deviation,
+ time-correlation). Follows the standard input format of Stochastic
+ Models.
+ name : list
+ List of names. This attribute can not be randomized.
+ """
+
+ def __init__(
+ self,
+ parachute,
+ cd_s=None,
+ trigger=None,
+ sampling_rate=None,
+ lag=None,
+ noise=None,
+ ):
+ """Initializes the Stochastic Parachute class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ parachute : Parachute
+ Parachute object to be used for validation.
+ cd_s : tuple, list, int, float
+ Drag coefficient of the parachute. Follows the standard input
+ format of Stochastic Models.
+ trigger : list
+ List of callables, string "apogee" or ints/floats. Follows the
+ standard input format of Stochastic Models.
+ sampling_rate : tuple, list, int, float
+ Sampling rate of the parachute in seconds. Follows the standard
+ input format of Stochastic Models.
+ lag : tuple, list, int, float
+ Lag of the parachute in seconds. Follows the standard input format
+ of Stochastic Models.
+ noise : list
+ List of tuples in the form of (mean, standard deviation,
+ time-correlation). Follows the standard input format of Stochastic
+ Models.
+ """
+ self.parachute = parachute
+ self.cd_s = cd_s
+ self.trigger = trigger
+ self.sampling_rate = sampling_rate
+ self.lag = lag
+ self.noise = noise
+
+ self._validate_trigger(trigger)
+ self._validate_noise(noise)
+ super().__init__(
+ parachute,
+ cd_s=cd_s,
+ trigger=trigger,
+ sampling_rate=sampling_rate,
+ lag=lag,
+ noise=noise,
+ name=None,
+ )
+
+ def __repr__(self):
+ return (
+ f"StochasticParachute("
+ f"parachute={self.object}, "
+ f"cd_s={self.cd_s}, "
+ f"trigger={self.trigger}, "
+ f"sampling_rate={self.sampling_rate}, "
+ f"lag={self.lag}, "
+ f"noise={self.noise})"
+ )
+
+ def _validate_trigger(self, trigger):
+ """Validates the trigger input. If the trigger input argument is not
+ None, it must be:
+ - a list of callables, string "apogee" or ints/floats
+ - a tuple that will be further validated in the StochasticModel class
+ """
+ if trigger is not None:
+ assert isinstance(trigger, list) and all(
+ isinstance(member, (str, int, float) or callable(member))
+ for member in trigger
+ ), "`trigger` must be a list of callables, string 'apogee' or ints/floats"
+
+ def _validate_noise(self, noise):
+ """Validates the noise input. If the noise input argument is not
+ None, it must be a list of tuples in the form of
+ (mean, standard deviation, time-correlation)
+ """
+ if noise is not None:
+ assert isinstance(noise, list) and all(
+ isinstance(member, tuple) for member in noise
+ ), (
+ "`noise` must be a list of tuples in the form of "
+ "(mean, standard deviation, time-correlation)"
+ )
+
+ def create_object(self):
+ """Creates and returns a Parachute object from the randomly generated
+ input arguments.
+
+ Returns
+ -------
+ parachute : Parachute
+ Parachute object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ return Parachute(**generated_dict)
diff --git a/rocketpy/stochastic/stochastic_rocket.py b/rocketpy/stochastic/stochastic_rocket.py
new file mode 100644
index 000000000..f629280d7
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_rocket.py
@@ -0,0 +1,660 @@
+"""Defines the StochasticRocket class."""
+
+import warnings
+from random import choice
+
+from rocketpy.motors.motor import EmptyMotor, GenericMotor, Motor
+from rocketpy.motors.solid_motor import SolidMotor
+from rocketpy.rocket.aero_surface import (
+ EllipticalFins,
+ NoseCone,
+ RailButtons,
+ Tail,
+ TrapezoidalFins,
+)
+from rocketpy.rocket.components import Components
+from rocketpy.rocket.parachute import Parachute
+from rocketpy.rocket.rocket import Rocket
+from rocketpy.stochastic.stochastic_generic_motor import StochasticGenericMotor
+from rocketpy.stochastic.stochastic_motor_model import StochasticMotorModel
+
+from .stochastic_aero_surfaces import (
+ StochasticEllipticalFins,
+ StochasticNoseCone,
+ StochasticRailButtons,
+ StochasticTail,
+ StochasticTrapezoidalFins,
+)
+from .stochastic_model import StochasticModel
+from .stochastic_parachute import StochasticParachute
+from .stochastic_solid_motor import StochasticSolidMotor
+
+
+class StochasticRocket(StochasticModel):
+ """A Stochastic Rocket class that inherits from StochasticModel. This
+ class is used to receive a Rocket object and information about the
+ dispersion of its parameters and generate a random rocket object based on
+ the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : Rocket
+ The Rocket object to be used as a base for the Stochastic rocket.
+ motors : Components
+ A Components instance containing all the motors of the rocket.
+ aerodynamic_surfaces : Components
+ A Components instance containing all the aerodynamic surfaces of the
+ rocket.
+ rail_buttons : Components
+ A Components instance containing all the rail buttons of the rocket.
+ parachutes : list of StochasticParachute
+ A list of StochasticParachute instances containing all the parachutes of
+ the rocket.
+ radius : tuple, list, int, float
+ The radius of the rocket. Follows the standard input format of
+ Stochastic Models.
+ mass : tuple, list, int, float
+ The mass of the rocket. Follows the standard input format of
+ Stochastic Models.
+ inertia_11 : tuple, list, int, float
+ The inertia of the rocket around the x axis. Follows the standard input
+ format of Stochastic Models.
+ inertia_22 : tuple, list, int, float
+ The inertia of the rocket around the y axis. Follows the standard input
+ format of Stochastic Models.
+ inertia_33 : tuple, list, int, float
+ The inertia of the rocket around the z axis. Follows the standard input
+ format of Stochastic Models.
+ inertia_12 : tuple, list, int, float
+ The inertia of the rocket around the xy axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_13 : tuple, list, int, float
+ The inertia of the rocket around the xz axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_23 : tuple, list, int, float
+ The inertia of the rocket around the yz axis. Follows the standard
+ input format of Stochastic Models.
+ power_off_drag : list
+ The power off drag of the rocket. Follows the 1d array like input format
+ of Stochastic Models.
+ power_on_drag : list
+ The power on drag of the rocket. Follows the 1d array like input format
+ of Stochastic Models.
+ power_off_drag_factor : tuple, list, int, float
+ The power off drag factor of the rocket. Follows the factor input
+ format of Stochastic Models.
+ power_on_drag_factor : tuple, list, int, float
+ The power on drag factor of the rocket. Follows the standard input
+ format of Stochastic Models.
+ center_of_mass_without_motor : tuple, list, int, float
+ The center of mass of the rocket without the motor. Follows the
+ standard input format of Stochastic Models.
+ coordinate_system_orientation : list
+ The orientation of the coordinate system of the rocket. This attribute
+ can not be a randomized.
+ """
+
+ def __init__(
+ self,
+ rocket,
+ radius=None,
+ mass=None,
+ inertia_11=None,
+ inertia_22=None,
+ inertia_33=None,
+ inertia_12=None,
+ inertia_13=None,
+ inertia_23=None,
+ power_off_drag=None,
+ power_on_drag=None,
+ power_off_drag_factor=(1, 0),
+ power_on_drag_factor=(1, 0),
+ center_of_mass_without_motor=None,
+ ):
+ """Initializes the Stochastic Rocket class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ rocket : Rocket
+ The Rocket object to be used as a base for the Stochastic rocket.
+ radius : int, float, tuple, list, optional
+ The radius of the rocket. Follows the standard input format of
+ Stochastic Models.
+ mass : int, float, tuple, list, optional
+ The mass of the rocket. Follows the standard input format of
+ Stochastic Models.
+ inertia_11 : int, float, tuple, list, optional
+ The inertia of the rocket around the x axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_22 : int, float, tuple, list, optional
+ The inertia of the rocket around the y axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_33 : int, float, tuple, list, optional
+ The inertia of the rocket around the z axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_12 : int, float, tuple, list, optional
+ The inertia of the rocket around the xy axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_13 : int, float, tuple, list, optional
+ The inertia of the rocket around the xz axis. Follows the standard
+ input format of Stochastic Models.
+ inertia_23 : int, float, tuple, list, optional
+ The inertia of the rocket around the yz axis. Follows the standard
+ input format of Stochastic Models.
+ power_off_drag : list, optional
+ The power off drag of the rocket. Follows the 1d array like input
+ format of Stochastic Models.
+ power_on_drag : list, optional
+ The power on drag of the rocket. Follows the 1d array like input
+ format of Stochastic Models.
+ power_off_drag_factor : int, float, tuple, list, optional
+ The power off drag factor of the rocket. Follows the factor input
+ format of Stochastic Models.
+ power_on_drag_factor : int, float, tuple, list, optional
+ The power on drag factor of the rocket. Follows the standard input
+ format of Stochastic Models.
+ center_of_mass_without_motor : int, float, tuple, list, optional
+ The center of mass of the rocket without the motor. Follows the
+ standard input format of Stochastic Models.
+ """
+ self._validate_1d_array_like("power_off_drag", power_off_drag)
+ self._validate_1d_array_like("power_on_drag", power_on_drag)
+ super().__init__(
+ object=rocket,
+ radius=radius,
+ mass=mass,
+ I_11_without_motor=inertia_11,
+ I_22_without_motor=inertia_22,
+ I_33_without_motor=inertia_33,
+ I_12_without_motor=inertia_12,
+ I_13_without_motor=inertia_13,
+ I_23_without_motor=inertia_23,
+ power_off_drag=power_off_drag,
+ power_on_drag=power_on_drag,
+ power_off_drag_factor=power_off_drag_factor,
+ power_on_drag_factor=power_on_drag_factor,
+ center_of_mass_without_motor=center_of_mass_without_motor,
+ coordinate_system_orientation=None,
+ )
+ self.motors = Components()
+ self.aerodynamic_surfaces = Components()
+ self.rail_buttons = Components()
+ self.parachutes = []
+
+ def __str__(self):
+ # special str for rocket because of the components and parachutes
+ s = ""
+ for key, value in self.__dict__.items():
+ if key.startswith("_"):
+ continue # Skip attributes starting with underscore
+ if isinstance(value, tuple):
+ # Format the tuple as a string with the mean and standard deviation.
+ value_str = (
+ f"{value[0]:.5f} ± {value[1]:.5f} "
+ f"(numpy.random.{value[2].__name__})"
+ )
+ s += f"{key}: {value_str}\n"
+ elif isinstance(value, Components):
+ # Format Components as string with the mean and std deviation
+ s += f"{key}:\n"
+ if len(value) == 0:
+ s += "\tNone\n"
+ for component in value:
+ s += f"\t{component.component.__class__.__name__} "
+ if isinstance(component.position, tuple):
+ s += f"at position: {component.position[0]:.5f} ± "
+ s += f"{component.position[1]:.5f} "
+ s += f"(numpy.random.{component.position[2].__name__})\n"
+ elif isinstance(component.position, list):
+ s += f"at position: {component.position}\n"
+ else:
+ s += f"at position: {component.position:.5f}\n"
+ else:
+ # Otherwise, just use the default string representation of the value.
+ value_str = str(value)
+ if isinstance(value, list) and len(value) > 0:
+ if isinstance(value[0], (StochasticParachute)):
+ value_str = ""
+ for parachute in value:
+ value_str += f"\n\t{parachute.name[0]} "
+ s += f"{key}: {value_str}\n"
+ return s.strip()
+
+ def add_motor(self, motor, position=None):
+ """Adds a stochastic motor to the stochastic rocket. If a motor is
+ already present, it will be replaced.
+
+ Parameters
+ ----------
+ motor : StochasticMotor or Motor
+ The motor to be added to the stochastic rocket.
+ position : tuple, list, int, float, optional
+ The position of the motor. Follows the standard input format of
+ Stochastic Models.
+ """
+ # checks if there is a motor already
+ if len(self.motors) > 0:
+ warnings.warn(
+ "Only one motor can be added to the stochastic rocket. "
+ "The previous motor will be replaced."
+ )
+ self.motors = Components()
+
+ # checks if input is a Motor
+ if not isinstance(motor, (Motor, StochasticMotorModel)):
+ raise TypeError("`motor` must be a StochasticMotor or Motor type")
+ if isinstance(motor, Motor):
+ # create StochasticMotor
+ # TODO implement HybridMotor and LiquidMotor stochastic models
+ if isinstance(motor, SolidMotor):
+ motor = StochasticSolidMotor(solid_motor=motor)
+ elif isinstance(motor, GenericMotor):
+ motor = StochasticGenericMotor(generic_motor=motor)
+ self.motors.add(motor, self._validate_position(motor, position))
+
+ def _add_surfaces(self, surfaces, positions, type, stochastic_type, error_message):
+ """Adds a stochastic aerodynamic surface to the stochastic rocket. If
+ an aerodynamic surface is already present, it will be replaced.
+
+ Parameters
+ ----------
+ surfaces : StochasticAeroSurface or AeroSurface
+ The aerodynamic surface to be added to the stochastic rocket.
+ positions : tuple, list, int, float, optional
+ The position of the aerodynamic surface. Follows the standard input
+ format of Stochastic Models.
+ type : type
+ The type of the aerodynamic surface to be added to the stochastic
+ rocket.
+ stochastic_type : type
+ The type of the stochastic aerodynamic surface to be added to the
+ stochastic rocket.
+ error_message : str
+ The error message to be raised if the input is not of the correct
+ type.
+ """
+ if not isinstance(surfaces, (type, stochastic_type)):
+ raise AssertionError(error_message)
+ if isinstance(surfaces, type):
+ # create StochasticSurfaces
+ surfaces = stochastic_type(component=surfaces)
+ self.aerodynamic_surfaces.add(
+ surfaces, self._validate_position(surfaces, positions)
+ )
+
+ def add_nose(self, nose, position=None):
+ """Adds a stochastic nose cone to the stochastic rocket.
+
+ Parameters
+ ----------
+ nose : StochasticNoseCone or NoseCone
+ The nose cone to be added to the stochastic rocket.
+ position : tuple, list, int, float, optional
+ The position of the nose cone. Follows the standard input format of
+ Stochastic Models.
+ """
+ self._add_surfaces(
+ surfaces=nose,
+ positions=position,
+ type=NoseCone,
+ stochastic_type=StochasticNoseCone,
+ error_message="`nose` must be of NoseCone or StochasticNoseCone type",
+ )
+
+ def add_trapezoidal_fins(self, fins, position=None):
+ """Adds a stochastic trapezoidal fins to the stochastic rocket.
+
+ Parameters
+ ----------
+ fins : StochasticTrapezoidalFins or TrapezoidalFins
+ The trapezoidal fins to be added to the stochastic rocket.
+ position : tuple, list, int, float, optional
+ The position of the trapezoidal fins. Follows the standard input
+ format of Stochastic Models.
+ """
+ self._add_surfaces(
+ fins,
+ position,
+ TrapezoidalFins,
+ StochasticTrapezoidalFins,
+ "`fins` must be of TrapezoidalFins or StochasticTrapezoidalFins type",
+ )
+
+ def add_elliptical_fins(self, fins, position=None):
+ """Adds a stochastic elliptical fins to the stochastic rocket.
+
+ Parameters
+ ----------
+ fins : StochasticEllipticalFins or EllipticalFins
+ The elliptical fins to be added to the stochastic rocket.
+ position : tuple, list, int, float, optional
+ The position of the elliptical fins. Follows the standard input
+ format of Stochastic Models.
+ """
+ self._add_surfaces(
+ fins,
+ position,
+ EllipticalFins,
+ StochasticEllipticalFins,
+ "`fins` must be of EllipticalFins or StochasticEllipticalFins type",
+ )
+
+ def add_tail(self, tail, position=None):
+ """Adds a stochastic tail to the stochastic rocket.
+
+ Parameters
+ ----------
+ tail : StochasticTail or Tail
+ The tail to be added to the stochastic rocket.
+ position : tuple, list, int, float, optional
+ The position of the tail. Follows the standard input format of
+ Stochastic Models.
+ """
+ self._add_surfaces(
+ tail,
+ position,
+ Tail,
+ StochasticTail,
+ "`tail` must be of Tail or StochasticTail type",
+ )
+
+ def add_parachute(self, parachute):
+ """Adds a stochastic parachute to the stochastic rocket.
+
+ Parameters
+ ----------
+ parachute : StochasticParachute or Parachute
+ The parachute to be added to the stochastic rocket.
+ """
+ # checks if input is a StochasticParachute type
+ if not isinstance(parachute, (Parachute, StochasticParachute)):
+ raise TypeError(
+ "`parachute` must be of Parachute or StochasticParachute type"
+ )
+ if isinstance(parachute, Parachute):
+ # create StochasticParachute
+ parachute = StochasticParachute(parachute=parachute)
+ self.parachutes.append(parachute)
+
+ def set_rail_buttons(
+ self,
+ rail_buttons,
+ lower_button_position=None,
+ ):
+ """Sets the rail buttons of the stochastic rocket.
+
+ Parameters
+ ----------
+ rail_buttons : StochasticRailButtons or RailButtons
+ The rail buttons to be added to the stochastic rocket.
+ lower_button_position : tuple, list, int, float, optional
+ The position of the lower button. Follows the standard input format
+ of Stochastic Models.
+ """
+ if not isinstance(rail_buttons, (StochasticRailButtons, RailButtons)):
+ raise AssertionError(
+ "`rail_buttons` must be of RailButtons or StochasticRailButtons type"
+ )
+ if isinstance(rail_buttons, RailButtons):
+ # create StochasticRailButtons
+ rail_buttons = StochasticRailButtons(rail_buttons=rail_buttons)
+ self.rail_buttons.add(
+ rail_buttons, self._validate_position(rail_buttons, lower_button_position)
+ )
+
+ def _validate_position(self, validated_object, position):
+ """Validate the position argument.
+
+ Parameters
+ ----------
+ validated_object : object
+ The object to which the position argument refers to.
+ position : tuple, list, int, float
+ The position argument to be validated.
+
+ Returns
+ -------
+ tuple or list
+ Validated position argument.
+
+ Raises
+ ------
+ ValueError
+ If the position argument does not conform to the specified formats.
+ """
+
+ if isinstance(position, tuple):
+ return self._validate_tuple(
+ "position",
+ position,
+ getattr=self._create_get_position(validated_object),
+ )
+ elif isinstance(position, (int, float)):
+ return self._validate_scalar(
+ "position",
+ position,
+ getattr=self._create_get_position(validated_object),
+ )
+ elif isinstance(position, list):
+ return self._validate_list(
+ "position",
+ position,
+ getattr=self._create_get_position(validated_object),
+ )
+ elif position is None:
+ position = []
+ return self._validate_list(
+ "position",
+ position,
+ getattr=self._create_get_position(validated_object),
+ )
+ else:
+ raise AssertionError("`position` must be a tuple, list, int, or float")
+
+ def _create_get_position(self, validated_object):
+ """Create a function to get the nominal position from an object.
+
+ Parameters
+ ----------
+ validated_object : object
+ The object to which the position argument refers to.
+
+ Returns
+ -------
+ function
+ Function to get the nominal position from an object. The function
+ must receive two arguments.
+ """
+
+ # try to get position from object
+ error_msg = (
+ "`position` standard deviation was provided but the rocket does "
+ f"not have the same {validated_object.object.__class__.__name__} "
+ "to get the nominal position value from."
+ )
+ # special case for motor stochastic model
+ if isinstance(validated_object, (StochasticMotorModel)):
+ if isinstance(self.object.motor, EmptyMotor):
+ raise AssertionError(error_msg)
+
+ def get_motor_position(self_object, _):
+ return self_object.motor_position
+
+ return get_motor_position
+ else:
+ if isinstance(validated_object, StochasticRailButtons):
+
+ def get_surface_position(self_object, _):
+ surfaces = self_object.rail_buttons.get_tuple_by_type(
+ validated_object.object.__class__
+ )
+ if len(surfaces) == 0:
+ raise AssertionError(error_msg)
+ for surface in surfaces:
+ if surface.component == validated_object.object:
+ return surface.position
+ else:
+ raise AssertionError(error_msg)
+
+ else:
+
+ def get_surface_position(self_object, _):
+ surfaces = self_object.aerodynamic_surfaces.get_tuple_by_type(
+ validated_object.object.__class__
+ )
+ if len(surfaces) == 0:
+ raise AssertionError(error_msg)
+ for surface in surfaces:
+ if surface.component == validated_object.object:
+ return surface.position
+ else:
+ raise AssertionError(error_msg)
+
+ return get_surface_position
+
+ def _randomize_position(self, position):
+ """Randomize a position provided as a tuple or list."""
+ if isinstance(position, tuple):
+ return position[-1](position[0], position[1])
+ elif isinstance(position, list):
+ return choice(position) if position else position
+
+ def dict_generator(self):
+ """Special generator for the rocket class that yields a dictionary with
+ the randomly generated input arguments. The dictionary is saved as an
+ attribute of the class. The dictionary is generated by looping through
+ all attributes of the class and generating a random value for each
+ attribute. The random values are generated according to the format of
+ each attribute. Tuples are generated using the distribution function
+ specified in the tuple. Lists are generated using the random.choice
+ function.
+
+ Parameters
+ ----------
+ None
+
+ Yields
+ -------
+ dict
+ Dictionary with the randomly generated input arguments.
+ """
+ generated_dict = next(super().dict_generator())
+ generated_dict["motors"] = []
+ generated_dict["aerodynamic_surfaces"] = []
+ generated_dict["rail_buttons"] = []
+ generated_dict["parachutes"] = []
+ self.last_rnd_dict = generated_dict
+ yield generated_dict
+
+ def _create_motor(self, component_stochastic_motor):
+ stochastic_motor = component_stochastic_motor.component
+ motor = stochastic_motor.create_object()
+ position_rnd = self._randomize_position(component_stochastic_motor.position)
+ self.last_rnd_dict["motors"].append(stochastic_motor.last_rnd_dict)
+ self.last_rnd_dict["motors"][-1]["position"] = position_rnd
+ return motor, position_rnd
+
+ def _create_surface(self, component_stochastic_surface):
+ stochastic_surface = component_stochastic_surface.component
+ surface = stochastic_surface.create_object()
+ position_rnd = self._randomize_position(component_stochastic_surface.position)
+ self.last_rnd_dict["aerodynamic_surfaces"].append(
+ stochastic_surface.last_rnd_dict
+ )
+ self.last_rnd_dict["aerodynamic_surfaces"][-1]["position"] = position_rnd
+ return surface, position_rnd
+
+ def _create_rail_buttons(self, component_stochastic_rail_buttons):
+ stochastic_rail_buttons = component_stochastic_rail_buttons.component
+ rail_buttons = stochastic_rail_buttons.create_object()
+ lower_button_position_rnd = self._randomize_position(
+ component_stochastic_rail_buttons.position
+ )
+ upper_button_position_rnd = (
+ rail_buttons.buttons_distance + lower_button_position_rnd
+ )
+ self.last_rnd_dict["rail_buttons"].append(stochastic_rail_buttons.last_rnd_dict)
+ self.last_rnd_dict["rail_buttons"][-1][
+ "lower_button_position"
+ ] = lower_button_position_rnd
+ self.last_rnd_dict["rail_buttons"][-1][
+ "upper_button_position"
+ ] = upper_button_position_rnd
+ return rail_buttons, lower_button_position_rnd, upper_button_position_rnd
+
+ def _create_parachute(self, stochastic_parachute):
+ parachute = stochastic_parachute.create_object()
+ self.last_rnd_dict["parachutes"].append(stochastic_parachute.last_rnd_dict)
+ return parachute
+
+ def create_object(self):
+ """Creates and returns a Rocket object from the randomly generated input
+ arguments.
+
+ Returns
+ -------
+ rocket : Rocket
+ Rocket object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ rocket = Rocket(
+ radius=generated_dict["radius"],
+ mass=generated_dict["mass"],
+ inertia=(
+ generated_dict["I_11_without_motor"],
+ generated_dict["I_22_without_motor"],
+ generated_dict["I_33_without_motor"],
+ generated_dict["I_12_without_motor"],
+ generated_dict["I_13_without_motor"],
+ generated_dict["I_23_without_motor"],
+ ),
+ power_off_drag=generated_dict["power_off_drag"],
+ power_on_drag=generated_dict["power_on_drag"],
+ center_of_mass_without_motor=generated_dict["center_of_mass_without_motor"],
+ coordinate_system_orientation=generated_dict[
+ "coordinate_system_orientation"
+ ],
+ )
+ rocket.power_off_drag *= generated_dict["power_off_drag_factor"]
+ rocket.power_on_drag *= generated_dict["power_on_drag_factor"]
+
+ for component_motor in self.motors:
+ motor, position_rnd = self._create_motor(component_motor)
+ rocket.add_motor(motor, position_rnd)
+
+ for component_surface in self.aerodynamic_surfaces:
+ surface, position_rnd = self._create_surface(component_surface)
+ rocket.add_surfaces(surface, position_rnd)
+
+ for component_rail_buttons in self.rail_buttons:
+ (
+ rail_buttons,
+ lower_button_position_rnd,
+ upper_button_position_rnd,
+ ) = self._create_rail_buttons(component_rail_buttons)
+ rocket.set_rail_buttons(
+ upper_button_position=upper_button_position_rnd,
+ lower_button_position=lower_button_position_rnd,
+ angular_position=rail_buttons.angular_position,
+ )
+
+ for parachute in self.parachutes:
+ parachute = self._create_parachute(parachute)
+ rocket.add_parachute(
+ name=parachute.name,
+ cd_s=parachute.cd_s,
+ trigger=parachute.trigger,
+ sampling_rate=parachute.sampling_rate,
+ lag=parachute.lag,
+ noise=parachute.noise,
+ )
+
+ return rocket
diff --git a/rocketpy/stochastic/stochastic_solid_motor.py b/rocketpy/stochastic/stochastic_solid_motor.py
new file mode 100644
index 000000000..482973840
--- /dev/null
+++ b/rocketpy/stochastic/stochastic_solid_motor.py
@@ -0,0 +1,267 @@
+"""Defines the StochasticSolidMotor class."""
+
+from rocketpy.motors import SolidMotor
+
+from .stochastic_motor_model import StochasticMotorModel
+
+
+class StochasticSolidMotor(StochasticMotorModel):
+ """A Stochastic Solid Motor class that inherits from StochasticModel. This
+ class is used to receive a SolidMotor object and information about the
+ dispersion of its parameters and generate a random solid motor object based
+ on the provided information.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Attributes
+ ----------
+ object : SolidMotor
+ SolidMotor object to be used for validation.
+ thrust_source : list
+ List of strings representing the thrust source to be selected.
+ total_impulse : int, float, tuple, list
+ Total impulse of the motor in newton seconds. Follows the standard
+ input format of Stochastic Models.
+ burn_start_time : int, float, tuple, list
+ Burn start time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ burn_out_time : int, float, tuple, list
+ Burn out time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ dry_mass : int, float, tuple, list
+ Dry mass of the motor in kilograms. Follows the standard input
+ format of Stochastic Models.
+ dry_I_11 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_22 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_33 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_12 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_13 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_23 : int, float, tuple, list
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ nozzle_radius : int, float, tuple, list
+ Nozzle radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ grain_number : int, float, tuple, list
+ Number of grains in the motor. Follows the standard input format of
+ Stochastic Models.
+ grain_density : int, float, tuple, list
+ Density of the grains in the motor in kilograms per meters cubed.
+ Follows the standard input format of Stochastic Models.
+ grain_outer_radius : int, float, tuple, list
+ Outer radius of the grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grain_initial_inner_radius : int, float, tuple, list
+ Initial inner radius of the grains in the motor in meters. Follows
+ the standard input format of Stochastic Models.
+ grain_initial_height : int, float, tuple, list
+ Initial height of the grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grain_separation : int, float, tuple, list
+ Separation between grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grains_center_of_mass_position : int, float, tuple, list
+ Position of the center of mass of the grains in the motor in
+ meters. Follows the standard input format of Stochastic Models.
+ center_of_dry_mass_position : int, float, tuple, list
+ Position of the center of mass of the dry mass in the motor in
+ meters. Follows the standard input format of Stochastic Models.
+ nozzle_position : int, float, tuple, list
+ Position of the nozzle in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ throat_radius : int, float, tuple, list
+ Radius of the throat in the motor in meters. Follows the standard
+ input format of Stochastic Models.
+ """
+
+ def __init__(
+ self,
+ solid_motor,
+ thrust_source=None,
+ total_impulse=None,
+ burn_start_time=None,
+ burn_out_time=None,
+ dry_mass=None,
+ dry_inertia_11=None,
+ dry_inertia_22=None,
+ dry_inertia_33=None,
+ dry_inertia_12=None,
+ dry_inertia_13=None,
+ dry_inertia_23=None,
+ nozzle_radius=None,
+ grain_number=None,
+ grain_density=None,
+ grain_outer_radius=None,
+ grain_initial_inner_radius=None,
+ grain_initial_height=None,
+ grain_separation=None,
+ grains_center_of_mass_position=None,
+ center_of_dry_mass_position=None,
+ nozzle_position=None,
+ throat_radius=None,
+ ):
+ """Initializes the Stochastic Solid Motor class.
+
+ See Also
+ --------
+ :ref:`stochastic_model`
+
+ Parameters
+ ----------
+ solid_motor : SolidMotor
+ SolidMotor object to be used for validation.
+ thrust_source : list, optional
+ List of strings representing the thrust source to be selected.
+ Follows the 1d array like input format of Stochastic Models.
+ total_impulse : int, float, tuple, list, optional
+ Total impulse of the motor in newton seconds. Follows the standard
+ input format of Stochastic Models.
+ burn_start_time : int, float, tuple, list, optional
+ Burn start time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ burn_out_time : int, float, tuple, list, optional
+ Burn out time of the motor in seconds. Follows the standard input
+ format of Stochastic Models.
+ dry_mass : int, float, tuple, list, optional
+ Dry mass of the motor in kilograms. Follows the standard input
+ format of Stochastic Models.
+ dry_I_11 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_22 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_33 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_12 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_13 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ dry_I_23 : int, float, tuple, list, optional
+ Dry inertia of the motor in kilograms times meters squared. Follows
+ the standard input format of Stochastic Models.
+ nozzle_radius : int, float, tuple, list, optional
+ Nozzle radius of the motor in meters. Follows the standard input
+ format of Stochastic Models.
+ grain_number : int, float, tuple, list, optional
+ Number of grains in the motor. Follows the standard input format of
+ Stochastic Models.
+ grain_density : int, float, tuple, list, optional
+ Density of the grains in the motor in kilograms per meters cubed.
+ Follows the standard input format of Stochastic Models.
+ grain_outer_radius : int, float, tuple, list, optional
+ Outer radius of the grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grain_initial_inner_radius : int, float, tuple, list, optional
+ Initial inner radius of the grains in the motor in meters. Follows
+ the standard input format of Stochastic Models.
+ grain_initial_height : int, float, tuple, list, optional
+ Initial height of the grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grain_separation : int, float, tuple, list, optional
+ Separation between grains in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ grains_center_of_mass_position : int, float, tuple, list, optional
+ Position of the center of mass of the grains in the motor in
+ meters. Follows the standard input format of Stochastic Models.
+ center_of_dry_mass_position : int, float, tuple, list, optional
+ Position of the center of mass of the dry mass in the motor in
+ meters. Follows the standard input format of Stochastic Models.
+ nozzle_position : int, float, tuple, list, optional
+ Position of the nozzle in the motor in meters. Follows the
+ standard input format of Stochastic Models.
+ throat_radius : int, float, tuple, list, optional
+ Radius of the throat in the motor in meters. Follows the standard
+ input format of Stochastic Models.
+ """
+ super().__init__(
+ solid_motor,
+ thrust_source=thrust_source,
+ total_impulse=total_impulse,
+ burn_start_time=burn_start_time,
+ burn_out_time=burn_out_time,
+ dry_mass=dry_mass,
+ dry_I_11=dry_inertia_11,
+ dry_I_22=dry_inertia_22,
+ dry_I_33=dry_inertia_33,
+ dry_I_12=dry_inertia_12,
+ dry_I_13=dry_inertia_13,
+ dry_I_23=dry_inertia_23,
+ nozzle_radius=nozzle_radius,
+ grain_number=grain_number,
+ grain_density=grain_density,
+ grain_outer_radius=grain_outer_radius,
+ grain_initial_inner_radius=grain_initial_inner_radius,
+ grain_initial_height=grain_initial_height,
+ grain_separation=grain_separation,
+ grains_center_of_mass_position=grains_center_of_mass_position,
+ center_of_dry_mass_position=center_of_dry_mass_position,
+ nozzle_position=nozzle_position,
+ throat_radius=throat_radius,
+ interpolate=None,
+ coordinate_system_orientation=None,
+ )
+
+ def create_object(self):
+ """Creates and returns a SolidMotor object from the randomly generated
+ input arguments.
+
+ Returns
+ -------
+ solid_motor : SolidMotor
+ SolidMotor object with the randomly generated input arguments.
+ """
+ generated_dict = next(self.dict_generator())
+ solid_motor = SolidMotor(
+ thrust_source=generated_dict["thrust_source"],
+ dry_mass=generated_dict["dry_mass"],
+ dry_inertia=(
+ generated_dict["dry_I_11"],
+ generated_dict["dry_I_22"],
+ generated_dict["dry_I_33"],
+ generated_dict["dry_I_12"],
+ generated_dict["dry_I_13"],
+ generated_dict["dry_I_23"],
+ ),
+ nozzle_radius=generated_dict["nozzle_radius"],
+ grain_number=generated_dict["grain_number"],
+ grain_density=generated_dict["grain_density"],
+ grain_outer_radius=generated_dict["grain_outer_radius"],
+ grain_initial_inner_radius=generated_dict["grain_initial_inner_radius"],
+ grain_initial_height=generated_dict["grain_initial_height"],
+ grain_separation=generated_dict["grain_separation"],
+ grains_center_of_mass_position=generated_dict[
+ "grains_center_of_mass_position"
+ ],
+ center_of_dry_mass_position=generated_dict["center_of_dry_mass_position"],
+ nozzle_position=generated_dict["nozzle_position"],
+ burn_time=(
+ generated_dict["burn_start_time"],
+ generated_dict["burn_out_time"],
+ ),
+ throat_radius=generated_dict["throat_radius"],
+ reshape_thrust_curve=(
+ (generated_dict["burn_start_time"], generated_dict["burn_out_time"]),
+ generated_dict["total_impulse"],
+ ),
+ coordinate_system_orientation=generated_dict[
+ "coordinate_system_orientation"
+ ],
+ interpolation_method=generated_dict["interpolate"],
+ )
+ return solid_motor
diff --git a/rocketpy/tools.py b/rocketpy/tools.py
index 86ad7f17e..730067cfd 100644
--- a/rocketpy/tools.py
+++ b/rocketpy/tools.py
@@ -9,6 +9,7 @@
import functools
import importlib
import importlib.metadata
+import math
import re
import time
from bisect import bisect_left
@@ -16,6 +17,7 @@
import numpy as np
import pytz
from cftime import num2pydate
+from matplotlib.patches import Ellipse
from packaging import version as packaging_version
# Mapping of module name and the name of the package that should be installed
@@ -230,6 +232,323 @@ def bilinear_interpolation(x, y, x1, x2, y1, y2, z11, z12, z21, z22):
) / ((x2 - x1) * (y2 - y1))
+def get_distribution(distribution_function_name):
+ """Sets the distribution function to be used in the monte carlo analysis.
+
+ Parameters
+ ----------
+ distribution_function_name : string
+ The type of distribution to be used in the analysis. It can be
+ 'uniform', 'normal', 'lognormal', etc.
+
+ Returns
+ -------
+ np.random distribution function
+ The distribution function to be used in the analysis.
+ """
+ distributions = {
+ "normal": np.random.normal,
+ "binomial": np.random.binomial,
+ "chisquare": np.random.chisquare,
+ "exponential": np.random.exponential,
+ "gamma": np.random.gamma,
+ "gumbel": np.random.gumbel,
+ "laplace": np.random.laplace,
+ "logistic": np.random.logistic,
+ "poisson": np.random.poisson,
+ "uniform": np.random.uniform,
+ "wald": np.random.wald,
+ }
+ try:
+ return distributions[distribution_function_name]
+ except KeyError as e:
+ raise ValueError(
+ f"Distribution function '{distribution_function_name}' not found, "
+ + "please use one of the following np.random distribution function:"
+ + '\n\t"normal"'
+ + '\n\t"binomial"'
+ + '\n\t"chisquare"'
+ + '\n\t"exponential"'
+ + '\n\t"geometric"'
+ + '\n\t"gamma"'
+ + '\n\t"gumbel"'
+ + '\n\t"laplace"'
+ + '\n\t"logistic"'
+ + '\n\t"poisson"'
+ + '\n\t"uniform"'
+ + '\n\t"wald"\n'
+ ) from e
+
+
+def haversine(lat0, lon0, lat1, lon1, earth_radius=6.3781e6):
+ """Returns the distance between two points in meters.
+ The points are defined by their latitude and longitude coordinates.
+
+ Parameters
+ ----------
+ lat0 : float
+ Latitude of the first point, in degrees.
+ lon0 : float
+ Longitude of the first point, in degrees.
+ lat1 : float
+ Latitude of the second point, in degrees.
+ lon1 : float
+ Longitude of the second point, in degrees.
+ earth_radius : float, optional
+ Earth's radius in meters. Default value is 6.3781e6.
+
+ Returns
+ -------
+ float
+ Distance between the two points in meters.
+
+ """
+ lat0_rad = math.radians(lat0)
+ lat1_rad = math.radians(lat1)
+ delta_lat_rad = math.radians(lat1 - lat0)
+ delta_lon_rad = math.radians(lon1 - lon0)
+
+ a = (
+ math.sin(delta_lat_rad / 2) ** 2
+ + math.cos(lat0_rad) * math.cos(lat1_rad) * math.sin(delta_lon_rad / 2) ** 2
+ )
+ c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
+
+ return earth_radius * c
+
+
+def inverted_haversine(lat0, lon0, distance, bearing, earth_radius=6.3781e6):
+ """Returns a tuple with new latitude and longitude coordinates considering
+ a displacement of a given distance in a given direction (bearing compass)
+ starting from a point defined by (lat0, lon0). This is the opposite of
+ Haversine function.
+
+ Parameters
+ ----------
+ lat0 : float
+ Origin latitude coordinate, in degrees.
+ lon0 : float
+ Origin longitude coordinate, in degrees.
+ distance : float
+ Distance from the origin point, in meters.
+ bearing : float
+ Azimuth (or bearing compass) from the origin point, in degrees.
+ earth_radius : float, optional
+ Earth radius, in meters. Default value is 6.3781e6.
+ See the Environment.calculateEarthRadius() function for more accuracy.
+
+ Returns
+ -------
+ lat1 : float
+ New latitude coordinate, in degrees.
+ lon1 : float
+ New longitude coordinate, in degrees.
+
+ """
+
+ # Convert coordinates to radians
+ lat0_rad = np.deg2rad(lat0)
+ lon0_rad = np.deg2rad(lon0)
+
+ # Apply inverted Haversine formula
+ lat1_rad = math.asin(
+ math.sin(lat0_rad) * math.cos(distance / earth_radius)
+ + math.cos(lat0_rad) * math.sin(distance / earth_radius) * math.cos(bearing)
+ )
+
+ lon1_rad = lon0_rad + math.atan2(
+ math.sin(bearing) * math.sin(distance / earth_radius) * math.cos(lat0_rad),
+ math.cos(distance / earth_radius) - math.sin(lat0_rad) * math.sin(lat1_rad),
+ )
+
+ # Convert back to degrees and then return
+ lat1_deg = np.rad2deg(lat1_rad)
+ lon1_deg = np.rad2deg(lon1_rad)
+
+ return lat1_deg, lon1_deg
+
+
+# Functions for monte carlo analysis
+def generate_monte_carlo_ellipses(results):
+ """A function to create apogee and impact ellipses from the monte carlo
+ analysis results.
+
+ Parameters
+ ----------
+ results : dict
+ A dictionary containing the results of the monte carlo analysis. It
+ should contain the following keys:
+ - apogeeX: an array containing the x coordinates of the apogee
+ - apogeeY: an array containing the y coordinates of the apogee
+ - xImpact: an array containing the x coordinates of the impact
+ - yImpact: an array containing the y coordinates of the impact
+
+ Returns
+ -------
+ apogee_ellipse : list[Ellipse]
+ A list of ellipse objects representing the apogee ellipses.
+ impact_ellipse : list[Ellipse]
+ A list of ellipse objects representing the impact ellipses.
+ apogeeX : np.array
+ An array containing the x coordinates of the apogee ellipse.
+ apogeeY : np.array
+ An array containing the y coordinates of the apogee ellipse.
+ impactX : np.array
+ An array containing the x coordinates of the impact ellipse.
+ impactY : np.array
+ An array containing the y coordinates of the impact ellipse.
+ """
+
+ # Retrieve monte carlo data por apogee and impact XY position
+ try:
+ apogee_x = np.array(results["apogee_x"])
+ apogee_y = np.array(results["apogee_y"])
+ except KeyError:
+ print("No apogee data found. Skipping apogee ellipses.")
+ apogee_x = np.array([])
+ apogee_y = np.array([])
+ try:
+ impact_x = np.array(results["x_impact"])
+ impact_y = np.array(results["y_impact"])
+ except KeyError:
+ print("No impact data found. Skipping impact ellipses.")
+ impact_x = np.array([])
+ impact_y = np.array([])
+
+ # Define function to calculate Eigenvalues
+ def eigsorted(cov):
+ # Calculate eigenvalues and eigenvectors
+ vals, vecs = np.linalg.eigh(cov)
+ # Order eigenvalues and eigenvectors in descending order
+ order = vals.argsort()[::-1]
+ return vals[order], vecs[:, order]
+
+ def calculate_ellipses(list_x, list_y):
+ # Calculate covariance matrix
+ cov = np.cov(list_x, list_y)
+ # Calculate eigenvalues and eigenvectors
+ vals, vecs = eigsorted(cov)
+ # Calculate ellipse angle and width/height
+ theta = np.degrees(np.arctan2(*vecs[:, 0][::-1]))
+ w, h = 2 * np.sqrt(vals)
+ return theta, w, h
+
+ def create_ellipse_objects(x, y, n, w, h, theta, rgb):
+ """Create a list of matplotlib.patches.Ellipse objects.
+
+ Parameters
+ ----------
+ x : list or np.array
+ List of x coordinates.
+ y : list or np.array
+ List of y coordinates.
+ n : int
+ Number of ellipses to create. It represents the number of confidence
+ intervals to be used. For example, n=3 will create 3 ellipses with
+ 1, 2 and 3 standard deviations.
+ w : float
+ Width of the ellipse.
+ h : float
+ Height of the ellipse.
+ theta : float
+ Angle of the ellipse.
+ rgb : tuple
+ Tuple containing the color of the ellipse in RGB format. For example,
+ (0, 0, 1) will create a blue ellipse.
+
+ Returns
+ -------
+ list
+ List of matplotlib.patches.Ellipse objects.
+ """
+ ell_list = [None] * n
+ for j in range(n):
+ ell = Ellipse(
+ xy=(np.mean(x), np.mean(y)),
+ width=w,
+ height=h,
+ angle=theta,
+ color="black",
+ )
+ ell.set_facecolor(rgb)
+ ell_list[j] = ell
+ return ell_list
+
+ # Calculate error ellipses for impact and apogee
+ impactTheta, impactW, impactH = calculate_ellipses(impact_x, impact_y)
+ apogeeTheta, apogeeW, apogeeH = calculate_ellipses(apogee_x, apogee_y)
+
+ # Draw error ellipses for impact
+ impact_ellipses = create_ellipse_objects(
+ impact_x, impact_y, 3, impactW, impactH, impactTheta, (0, 0, 1, 0.2)
+ )
+
+ apogee_ellipses = create_ellipse_objects(
+ apogee_x, apogee_y, 3, apogeeW, apogeeH, apogeeTheta, (0, 1, 0, 0.2)
+ )
+
+ return impact_ellipses, apogee_ellipses, apogee_x, apogee_y, impact_x, impact_y
+
+
+def generate_monte_carlo_ellipses_coordinates(
+ ellipses, origin_lat, origin_lon, resolution=100
+):
+ """Generate a list of latitude and longitude points for each ellipse in
+ ellipses.
+
+ Parameters
+ ----------
+ ellipses : list
+ List of matplotlib.patches.Ellipse objects.
+ origin_lat : float
+ Latitude of the origin of the coordinate system.
+ origin_lon : float
+ Longitude of the origin of the coordinate system.
+ resolution : int, optional
+ Number of points to generate for each ellipse, by default 100
+
+ Returns
+ -------
+ list
+ List of lists of tuples containing the latitude and longitude of each
+ point in each ellipse.
+ """
+ outputs = [None] * len(ellipses)
+
+ for index, ell in enumerate(ellipses):
+ # Get ellipse path points
+ center = ell.get_center()
+ width = ell.get_width()
+ height = ell.get_height()
+ angle = np.deg2rad(ell.get_angle())
+ points = lat_lon_points = [None] * resolution
+
+ # Generate ellipse path points (in a Cartesian coordinate system)
+ for i in range(resolution):
+ x = width / 2 * math.cos(2 * np.pi * i / resolution)
+ y = height / 2 * math.sin(2 * np.pi * i / resolution)
+ x_rot = center[0] + x * math.cos(angle) - y * math.sin(angle)
+ y_rot = center[1] + x * math.sin(angle) + y * math.cos(angle)
+ points[i] = (x_rot, y_rot)
+ points = np.array(points)
+
+ # Convert path points to lat/lon
+ for point in points:
+ x, y = point
+ # Convert to distance and bearing
+ d = math.sqrt((x**2 + y**2))
+ bearing = math.atan2(
+ x, y
+ ) # math.atan2 returns the angle in the range [-pi, pi]
+
+ lat_lon_points[i] = inverted_haversine(
+ origin_lat, origin_lon, d, bearing, earth_radius=6.3781e6
+ )
+
+ outputs[index] = lat_lon_points
+ return outputs
+
+
def find_two_closest_integers(number):
"""Find the two closest integer factors of a number.
diff --git a/tests/conftest.py b/tests/conftest.py
index 4766b570a..a1e4b7f99 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,5 +1,6 @@
import pytest
+# Pytest configuration
pytest_plugins = [
"tests.fixtures.environment.environment_fixtures",
"tests.fixtures.flight.flight_fixtures",
@@ -13,6 +14,9 @@
"tests.fixtures.rockets.rocket_fixtures",
"tests.fixtures.surfaces.surface_fixtures",
"tests.fixtures.units.numerical_fixtures",
+ "tests.fixtures.monte_carlo.monte_carlo_fixtures",
+ "tests.fixtures.monte_carlo.stochastic_fixtures",
+ "tests.fixtures.monte_carlo.stochastic_motors_fixtures",
]
diff --git a/tests/fixtures/dispersion/Valetudo_inputs.csv b/tests/fixtures/monte_carlo/Valetudo_inputs.csv
similarity index 100%
rename from tests/fixtures/dispersion/Valetudo_inputs.csv
rename to tests/fixtures/monte_carlo/Valetudo_inputs.csv
diff --git a/tests/fixtures/monte_carlo/__init__.py b/tests/fixtures/monte_carlo/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/fixtures/monte_carlo/example.inputs.txt b/tests/fixtures/monte_carlo/example.inputs.txt
new file mode 100644
index 000000000..d82cae696
--- /dev/null
+++ b/tests/fixtures/monte_carlo/example.inputs.txt
@@ -0,0 +1,10 @@
+{"elevation": 1401.4956352929128, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9450816780482028, "wind_velocity_y_factor": 0.9781441848266635, "datum": "WGS84", "timezone": "UTC", "radius": 0.0635062964327075, "mass": 15.908580991806707, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322114874292384, "I_33_without_motor": 0.012957242330574877, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.116998067339784, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.6280833219672366, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 1.0177025917838693, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.0967003213742696, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "'Function from R1 to R1 : (Scalar) \u2192 (Scalar)'", "total_impulse": 8008.347921291322, "burn_start_time": 0, "burn_out_time": 3.906214754528265, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03293120513502925, "grain_number": 5, "grain_density": 1854.2340720665204, "grain_outer_radius": 0.032985640020247765, "grain_initial_inner_radius": 0.015310123275236702, "grain_initial_height": 0.11811825300572186, "grain_separation": 0.006711096958736968, "grains_center_of_mass_position": 0.39647964588403434, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0013349636505807958, "throat_radius": 0.010921423639193314, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3720479424144372}], "aerodynamic_surfaces": [{"length": 0.5578974370049176, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1358373309953151}, {"n": 4, "root_chord": 0.11974359643195065, "tip_chord": 0.03940879564813866, "span": 0.10000563733372181, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1674848464453782}, {"top_radius": 0.0629442823276734, "bottom_radius": 0.044000809597868056, "length": 0.060919598903432425, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6979653598166442, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6191976129185146, "upper_button_position": 0.0787677468981296}], "rail_length": 5.2, "inclination": 85.41806990321825, "heading": 54.18109302296489}
+{"elevation": 1406.5350756913592, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9516662861966597, "wind_velocity_y_factor": 1.0064048593297057, "datum": "WGS84", "timezone": "UTC", "radius": 0.06350349167738431, "mass": 15.768610173003173, "I_11_without_motor": 6.321, "I_22_without_motor": 6.315825792646666, "I_33_without_motor": 0.028629613565978755, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.89730766328184, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4899191353962622, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9607265553248231, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.4523711630490321, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "'Function from R1 to R1 : (Scalar) \u2192 (Scalar)'", "total_impulse": 6446.57135198394, "burn_start_time": 0, "burn_out_time": 3.9894949335022, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03320688298961293, "grain_number": 5, "grain_density": 1909.5604610821972, "grain_outer_radius": 0.0324705584521942, "grain_initial_inner_radius": 0.014811951142584205, "grain_initial_height": 0.11731380337585026, "grain_separation": 0.00491393364215582, "grains_center_of_mass_position": 0.39628551738684287, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0007868629707592146, "throat_radius": 0.01060574995942289, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3735008381135014}], "aerodynamic_surfaces": [{"length": 0.5585570098911449, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.132236295583569}, {"n": 4, "root_chord": 0.11988524950598159, "tip_chord": 0.039971120565612084, "span": 0.09991375118669615, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.168340642420532}, {"top_radius": 0.06366749282692026, "bottom_radius": 0.04247035278896944, "length": 0.05982474727356781, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6981342606544769, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6165145493073986, "upper_button_position": 0.08161971134707835}], "rail_length": 5.2, "inclination": 86.94780910509066, "heading": 53.98156443958248}
+{"elevation": 1397.5103755289601, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9963390772837555, "wind_velocity_y_factor": 0.9310545880995709, "datum": "WGS84", "timezone": "UTC", "radius": 0.06349982790733924, "mass": 16.113964741354632, "I_11_without_motor": 6.321, "I_22_without_motor": 6.332851244792044, "I_33_without_motor": 0.030021814198234187, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.779220764010605, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4845247961789623, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9682134611200442, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.585599474971143, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "data/motors/Cesaroni_M1670.eng", "total_impulse": 7487.827034238503, "burn_start_time": 0, "burn_out_time": 3.914765014376584, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032744147927549344, "grain_number": 5, "grain_density": 1867.9086875282821, "grain_outer_radius": 0.03294126549026792, "grain_initial_inner_radius": 0.015080085662914838, "grain_initial_height": 0.11988311114017533, "grain_separation": 0.005305032186539184, "grains_center_of_mass_position": 0.3983717635734512, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00037263633999194966, "throat_radius": 0.011059633377750937, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3738508519821517}], "aerodynamic_surfaces": [{"length": 0.5578912976208477, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1350183318601563}, {"n": 4, "root_chord": 0.12017400986558589, "tip_chord": 0.03962943164232406, "span": 0.09981633200128909, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1688641229895451}, {"top_radius": 0.06373223012294663, "bottom_radius": 0.04232126759707431, "length": 0.060581689919426356, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.7008512596941494, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171911772790206, "upper_button_position": 0.08366008241512879}], "rail_length": 5.2, "inclination": 84.38246649324918, "heading": 57.68102782665487}
+{"elevation": 1391.4643973320065, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.994774900128261, "wind_velocity_y_factor": 1.0273174134096499, "datum": "WGS84", "timezone": "UTC", "radius": 0.06350873600135983, "mass": 15.916394040973515, "I_11_without_motor": 6.321, "I_22_without_motor": 6.308143425967061, "I_33_without_motor": 0.01802192268136874, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.962077401196566, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4441736202776219, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.893598158549614, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.8260068764932076, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "'Function from R1 to R1 : (Scalar) \u2192 (Scalar)'", "total_impulse": 7665.613115626527, "burn_start_time": 0, "burn_out_time": 3.940913002019911, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033695677239588384, "grain_number": 5, "grain_density": 1819.143680494988, "grain_outer_radius": 0.032291825881788055, "grain_initial_inner_radius": 0.015534286519013498, "grain_initial_height": 0.12111389087171241, "grain_separation": 0.00518858578159403, "grains_center_of_mass_position": 0.3958892234962095, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.000841381739081922, "throat_radius": 0.010545258737885452, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.372609521542472}], "aerodynamic_surfaces": [{"length": 0.5582963193527628, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1340975925429957}, {"n": 4, "root_chord": 0.11995055756311049, "tip_chord": 0.03911287548791437, "span": 0.0999837256839886, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.168546806795111}, {"top_radius": 0.06238999721506463, "bottom_radius": 0.04232254608023388, "length": 0.06127586518492881, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6998568516921738, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6169186688752775, "upper_button_position": 0.08293818281689636}], "rail_length": 5.2, "inclination": 85.5600719639608, "heading": 54.55110563306921}
+{"elevation": 1393.8209804460496, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 1.000560647640797, "wind_velocity_y_factor": 1.022342992550456, "datum": "WGS84", "timezone": "UTC", "radius": 0.06349155639173172, "mass": 15.738934754709508, "I_11_without_motor": 6.321, "I_22_without_motor": 6.319864104451785, "I_33_without_motor": 0.02545348425633203, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.028901279392143, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.6235052375811327, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9507391354824055, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.771359370747443, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "data/motors/Cesaroni_M1670.eng", "total_impulse": 7177.104378492918, "burn_start_time": 0, "burn_out_time": 4.027061395012405, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03321825858808873, "grain_number": 5, "grain_density": 1928.250127701342, "grain_outer_radius": 0.0326772635525661, "grain_initial_inner_radius": 0.014434444632840328, "grain_initial_height": 0.11915759110557982, "grain_separation": 0.003435521791718822, "grains_center_of_mass_position": 0.3981852218515913, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0011190287234854237, "throat_radius": 0.01095718616985679, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3718019413845894}], "aerodynamic_surfaces": [{"length": 0.5577890154392657, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1338320467616545}, {"n": 4, "root_chord": 0.11997673771622025, "tip_chord": 0.03961950834152785, "span": 0.09987516565794868, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1677474523375928}, {"top_radius": 0.06268560633721164, "bottom_radius": 0.044510867340116785, "length": 0.06075235914452975, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6988166137446366, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6166577593632545, "upper_button_position": 0.08215885438138204}], "rail_length": 5.2, "inclination": 84.3544821309231, "heading": 50.72164249193685}
+{"elevation": 1400.4245658042064, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9934430357253621, "wind_velocity_y_factor": 0.9995090755329425, "datum": "WGS84", "timezone": "UTC", "radius": 0.06350584375449667, "mass": 16.296803998687906, "I_11_without_motor": 6.321, "I_22_without_motor": 6.319261987424873, "I_33_without_motor": 0.03630373525141324, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.002039291361488, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.521968760387734, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9020101884044889, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.1765277521869204, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]], "total_impulse": 7217.188111138403, "burn_start_time": 0, "burn_out_time": 3.953528968797261, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03284513500057279, "grain_number": 5, "grain_density": 1800.639910024485, "grain_outer_radius": 0.03301656874049487, "grain_initial_inner_radius": 0.014555186055323372, "grain_initial_height": 0.1206707133239914, "grain_separation": 0.004454433148147433, "grains_center_of_mass_position": 0.39627775359288614, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0005563722488752347, "throat_radius": 0.010933800510542133, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3728443371458632}], "aerodynamic_surfaces": [{"length": 0.558850056530137, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1337806099233774}, {"n": 4, "root_chord": 0.12022514479101613, "tip_chord": 0.03977488143313973, "span": 0.0994325007551205, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1664648740494952}, {"top_radius": 0.06479268414162065, "bottom_radius": 0.04152271271281226, "length": 0.05909910459243895, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6986745614799809, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6200750499897003, "upper_button_position": 0.07859951149028055}], "rail_length": 5.2, "inclination": 85.05093618827794, "heading": 53.60886223539351}
+{"elevation": 1415.056657477282, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 1.0312596248131305, "wind_velocity_y_factor": 0.9782064047459161, "datum": "WGS84", "timezone": "UTC", "radius": 0.06350611017605608, "mass": 16.022551859182254, "I_11_without_motor": 6.321, "I_22_without_motor": 6.327756636233426, "I_33_without_motor": 0.02557444953196947, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.980848801873547, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.508699434351987, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9515739039961527, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.5321962395547486, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]], "total_impulse": 6812.795180685129, "burn_start_time": 0, "burn_out_time": 4.049618335869951, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03319383745172945, "grain_number": 5, "grain_density": 1906.7678709629558, "grain_outer_radius": 0.03340103180630861, "grain_initial_inner_radius": 0.014551079041229029, "grain_initial_height": 0.12005768142411836, "grain_separation": 0.00657049931137661, "grains_center_of_mass_position": 0.3981008886145341, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0006893392436535004, "throat_radius": 0.012024640120421601, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3712329054659291}], "aerodynamic_surfaces": [{"length": 0.5594118729079444, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1335349426174457}, {"n": 4, "root_chord": 0.12009642855415019, "tip_chord": 0.04001264775075921, "span": 0.10078751689454832, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1677588565290395}, {"top_radius": 0.06427069561590722, "bottom_radius": 0.04397816658676053, "length": 0.0593018307726965, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6994742704183982, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6179749167952617, "upper_button_position": 0.08149935362313643}], "rail_length": 5.2, "inclination": 85.27775446168337, "heading": 52.07473124199783}
+{"elevation": 1407.8607034367462, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9243120897907832, "wind_velocity_y_factor": 1.0025238660743678, "datum": "WGS84", "timezone": "UTC", "radius": 0.06349969087635444, "mass": 15.890306082322684, "I_11_without_motor": 6.321, "I_22_without_motor": 6.318894753828044, "I_33_without_motor": 0.022625913266197582, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.015807670191228, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4770955482649448, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.909871981719692, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.2298197853504698, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]], "total_impulse": 6290.904709483322, "burn_start_time": 0, "burn_out_time": 4.0264151892663715, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033694339637079185, "grain_number": 5, "grain_density": 1808.8899716051212, "grain_outer_radius": 0.03265337873317285, "grain_initial_inner_radius": 0.015369739745945339, "grain_initial_height": 0.12082242511279105, "grain_separation": 0.00581455836021638, "grains_center_of_mass_position": 0.397321775713535, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0008404742853902787, "throat_radius": 0.011003804698621191, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.372796006115578}], "aerodynamic_surfaces": [{"length": 0.5559534534598283, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.1353044227867581}, {"n": 4, "root_chord": 0.12003997954303475, "tip_chord": 0.040562591675552394, "span": 0.1001969641064779, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1671994512705786}, {"top_radius": 0.06535000693622554, "bottom_radius": 0.04350279638873781, "length": 0.058974725448361943, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.701347285230197, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6181432349663547, "upper_button_position": 0.08320405026384226}], "rail_length": 5.2, "inclination": 84.97776656660177, "heading": 52.580896737469814}
+{"elevation": 1386.2658290054742, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 1.0118150053505988, "wind_velocity_y_factor": 0.9571284969912979, "datum": "WGS84", "timezone": "UTC", "radius": 0.06349006343504872, "mass": 15.42094541890885, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3356695712837094, "I_33_without_motor": 0.006705760681207741, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.066449429645994, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4779869817042537, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.8973690466734414, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.7041267766602894, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "'Function from R1 to R1 : (Scalar) \u2192 (Scalar)'", "total_impulse": 6381.219851440446, "burn_start_time": 0, "burn_out_time": 4.054255258168555, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03222852327072895, "grain_number": 5, "grain_density": 1815.8174750986202, "grain_outer_radius": 0.03275386125470833, "grain_initial_inner_radius": 0.015021358564266188, "grain_initial_height": 0.11894549555735523, "grain_separation": 0.005129849003987609, "grains_center_of_mass_position": 0.3963108881310866, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00015441772326065553, "throat_radius": 0.011378587756155079, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.3725029856828037}], "aerodynamic_surfaces": [{"length": 0.5577981332870249, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.134456731296994}, {"n": 4, "root_chord": 0.12000296575078867, "tip_chord": 0.03907415657688916, "span": 0.10001130751688864, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1678017879176694}, {"top_radius": 0.06376703301251549, "bottom_radius": 0.044211136643289226, "length": 0.06054053098519092, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.6997142332882197, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6196474863730008, "upper_button_position": 0.08006674691521887}], "rail_length": 5.2, "inclination": 85.88443199907574, "heading": 54.81131149740836}
+{"elevation": 1403.7325602045448, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 32.990254, "longitude": -106.974998, "wind_velocity_x_factor": 0.9804329129220021, "wind_velocity_y_factor": 0.988332671080639, "datum": "WGS84", "timezone": "UTC", "radius": 0.0634997822583417, "mass": 15.200469661823616, "I_11_without_motor": 6.321, "I_22_without_motor": 6.335914970817965, "I_33_without_motor": 0.045148017264811394, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.063947984376528, "trigger": ".main_trigger at 0x7814fd01cfe0>", "sampling_rate": 105, "lag": 1.4609886041307245, "noise": [0, 8.3, 0.5], "name": "calisto_main_chute"}, {"cd_s": 0.9010741447720559, "trigger": ".drogue_trigger at 0x7814fd01c540>", "sampling_rate": 105, "lag": 1.0441960102548469, "noise": [0, 8.3, 0.5], "name": "calisto_drogue_chute"}], "motors": [{"thrust_source": "'Function from R1 to R1 : (Scalar) \u2192 (Scalar)'", "total_impulse": 4377.734925575618, "burn_start_time": 0, "burn_out_time": 4.011186754001263, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03305502881850419, "grain_number": 5, "grain_density": 1785.487368974391, "grain_outer_radius": 0.03206110002556264, "grain_initial_inner_radius": 0.015876272475096095, "grain_initial_height": 0.1200659797847355, "grain_separation": 0.006612189921193928, "grains_center_of_mass_position": 0.3977976410061983, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0011342800834796306, "throat_radius": 0.009963047423146689, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.372285899045296}], "aerodynamic_surfaces": [{"length": 0.5594889434620973, "kind": "vonkarman", "base_radius": 0.0635, "bluffness": null, "rocket_radius": 0.0635, "name": "calisto_nose_cone", "position": 1.135362678737609}, {"n": 4, "root_chord": 0.12045943903706133, "tip_chord": 0.040893613797167924, "span": 0.10022691137098828, "rocket_radius": 0.0635, "cant_angle": 0, "sweep_length": 0.07999999999999999, "sweep_angle": null, "airfoil": null, "name": "calisto_trapezoidal_fins", "position": -1.1681386229540538}, {"top_radius": 0.06395950267498926, "bottom_radius": 0.04495193258314121, "length": 0.060736166658098174, "rocket_radius": 0.0635, "name": "calisto_tail", "position": -1.313}], "rail_buttons": [{"buttons_distance": 0.7023822176360356, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6166788769292593, "upper_button_position": 0.08570334070677632}], "rail_length": 5.2, "inclination": 85.49506843878025, "heading": 52.680314874463875}
diff --git a/tests/fixtures/monte_carlo/example.outputs.txt b/tests/fixtures/monte_carlo/example.outputs.txt
new file mode 100644
index 000000000..ffc0f5548
--- /dev/null
+++ b/tests/fixtures/monte_carlo/example.outputs.txt
@@ -0,0 +1,10 @@
+{"lateral_surface_wind": 0.0, "apogee_x": 418.0900192341263, "apogee_time": 29.227877417373804, "max_mach_number": 1.0597636981635778, "apogee": 5690.287437226489, "x_impact": 480.48559284729896, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.28886753090850337, "out_of_rail_velocity": 25.983654528478493, "y_impact": 346.7826493888511, "apogee_y": 301.74630214056145, "impact_velocity": -5.371608743357084, "t_final": 353.87686346458946}
+{"lateral_surface_wind": 0.0, "apogee_x": 664.8205729246815, "apogee_time": 26.40800619077295, "max_mach_number": 0.8577562337266057, "apogee": 4715.816960792063, "x_impact": 774.0891149671631, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.3285641180798137, "out_of_rail_velocity": 22.82061718874699, "y_impact": 562.7937790273377, "apogee_y": 483.3484727242321, "impact_velocity": -5.408315380727355, "t_final": 299.60847406715055}
+{"lateral_surface_wind": 0.0, "apogee_x": 766.3125531509313, "apogee_time": 27.926605808862806, "max_mach_number": 0.9775271452143771, "apogee": 5333.672919610753, "x_impact": 884.994696596615, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.3436250275216524, "out_of_rail_velocity": 27.626343866105426, "y_impact": 559.8829519991676, "apogee_y": 484.798733226189, "impact_velocity": -5.497690913213444, "t_final": 327.7157423960461}
+{"lateral_surface_wind": 0.0, "apogee_x": 587.5317254837414, "apogee_time": 28.782471451734626, "max_mach_number": 1.0199401850539194, "apogee": 5506.343181861931, "x_impact": 686.5316364540121, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.29597291668803427, "out_of_rail_velocity": 25.323284778536475, "y_impact": 488.7776245777793, "apogee_y": 418.2923812342386, "impact_velocity": -5.411864875130086, "t_final": 333.08817486926347}
+{"lateral_surface_wind": 0.0, "apogee_x": 574.3435227488437, "apogee_time": 27.657740448471746, "max_mach_number": 0.9499674698056779, "apogee": 5222.770164417492, "x_impact": 669.7873944157898, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.35454649267427035, "out_of_rail_velocity": 26.79571219168167, "y_impact": 547.7994529511036, "apogee_y": 469.7336805974083, "impact_velocity": -5.3642688614023, "t_final": 325.6947684429422}
+{"lateral_surface_wind": 0.0, "apogee_x": 617.4055133432199, "apogee_time": 27.860776577624453, "max_mach_number": 0.9391624608249222, "apogee": 5165.427839134199, "x_impact": 715.9015528056536, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.31178728761821195, "out_of_rail_velocity": 24.067906801593168, "y_impact": 527.6424058896348, "apogee_y": 455.044172305862, "impact_velocity": -5.467639886548914, "t_final": 314.140756080289}
+{"lateral_surface_wind": 0.0, "apogee_x": 463.7203499996117, "apogee_time": 27.173024195105338, "max_mach_number": 0.8879882772048172, "apogee": 4936.646625623801, "x_impact": 543.9667463996028, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.3262013366369224, "out_of_rail_velocity": 22.993879265630007, "y_impact": 423.8593982789621, "apogee_y": 361.32615557055516, "impact_velocity": -5.431124330631135, "t_final": 307.92373590017286}
+{"lateral_surface_wind": 0.0, "apogee_x": 415.0946170176034, "apogee_time": 26.158939945211348, "max_mach_number": 0.8302455031820458, "apogee": 4621.646237220374, "x_impact": 489.5625692055425, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.3353263159726264, "out_of_rail_velocity": 22.35481535832323, "y_impact": 374.56318197644185, "apogee_y": 317.5838766916845, "impact_velocity": -5.3972844384921, "t_final": 291.01036623249445}
+{"lateral_surface_wind": 0.0, "apogee_x": 466.8917957287704, "apogee_time": 26.612259607079338, "max_mach_number": 0.862939429135814, "apogee": 4750.199442755109, "x_impact": 552.5208903404148, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.3298597000284287, "out_of_rail_velocity": 22.740120701870772, "y_impact": 389.6042530941056, "apogee_y": 329.218827701524, "impact_velocity": -5.2978952420899, "t_final": 302.0154671206384}
+{"lateral_surface_wind": 0.0, "apogee_x": 230.54329163654137, "apogee_time": 21.045450434487567, "max_mach_number": 0.5800585300053369, "apogee": 3303.1748009382363, "x_impact": 284.76193579684883, "frontal_surface_wind": 0.0, "out_of_rail_time": 0.4028036449544367, "out_of_rail_velocity": 18.60552705484144, "y_impact": 217.08948166662054, "apogee_y": 175.75266710831295, "impact_velocity": -5.2650912092579425, "t_final": 226.12896807596684}
diff --git a/tests/fixtures/monte_carlo/monte_carlo_fixtures.py b/tests/fixtures/monte_carlo/monte_carlo_fixtures.py
new file mode 100644
index 000000000..c25a95188
--- /dev/null
+++ b/tests/fixtures/monte_carlo/monte_carlo_fixtures.py
@@ -0,0 +1,34 @@
+"""Defines the fixtures for the Monte Carlo tests. The fixtures should be
+instances of the MonteCarlo class, ideally."""
+
+import pytest
+
+from rocketpy.simulation import MonteCarlo
+
+
+@pytest.fixture
+def monte_carlo_calisto(stochastic_environment, stochastic_calisto, stochastic_flight):
+ """Creates a MonteCarlo object with the stochastic environment, stochastic
+ calisto and stochastic flight.
+
+ Parameters
+ ----------
+ stochastic_environment : StochasticEnvironment
+ The stochastic environment object, this is a pytest fixture.
+ stochastic_calisto : StochasticRocket
+ The stochastic rocket object, this is a pytest fixture.
+ stochastic_flight : StochasticFlight
+ The stochastic flight object, this is a pytest fixture.
+
+ Returns
+ -------
+ MonteCarlo
+ The MonteCarlo object with the stochastic environment, stochastic
+ calisto and stochastic flight.
+ """
+ return MonteCarlo(
+ filename="monte_carlo_test",
+ environment=stochastic_environment,
+ rocket=stochastic_calisto,
+ flight=stochastic_flight,
+ )
diff --git a/tests/fixtures/monte_carlo/stochastic_fixtures.py b/tests/fixtures/monte_carlo/stochastic_fixtures.py
new file mode 100644
index 000000000..bf576e5ed
--- /dev/null
+++ b/tests/fixtures/monte_carlo/stochastic_fixtures.py
@@ -0,0 +1,236 @@
+"""This module contains fixtures for the stochastic module. The fixtures are
+used to test the stochastic objects that will be used in the Monte Carlo
+simulations. It is a team effort to keep it as documented as possible."""
+
+import pytest
+
+from rocketpy.stochastic import (
+ StochasticEnvironment,
+ StochasticFlight,
+ StochasticNoseCone,
+ StochasticParachute,
+ StochasticRailButtons,
+ StochasticRocket,
+ StochasticTail,
+ StochasticTrapezoidalFins,
+)
+
+
+@pytest.fixture
+def stochastic_environment(example_spaceport_env):
+ """This fixture is used to create a stochastic environment object for the
+ Calisto flight.
+
+ Parameters
+ ----------
+ example_spaceport_env : Environment
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticEnvironment
+ The stochastic environment object
+ """
+ return StochasticEnvironment(
+ environment=example_spaceport_env,
+ elevation=(1400, 10, "normal"),
+ gravity=None,
+ latitude=None,
+ longitude=None,
+ ensemble_member=None,
+ wind_velocity_x_factor=(1.0, 0.033, "normal"),
+ wind_velocity_y_factor=(1.0, 0.033, "normal"),
+ )
+
+
+@pytest.fixture
+def stochastic_nose_cone(calisto_nose_cone):
+ """This fixture is used to create a StochasticNoseCone object for the
+ Calisto rocket.
+
+ Parameters
+ ----------
+ calisto_nose_cone : NoseCone
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticNoseCone
+ The stochastic nose cone object
+ """
+ return StochasticNoseCone(
+ nosecone=calisto_nose_cone,
+ length=0.001,
+ )
+
+
+@pytest.fixture
+def stochastic_trapezoidal_fins(calisto_trapezoidal_fins):
+ """This fixture is used to create a StochasticTrapezoidalFins object for the
+ Calisto rocket.
+
+ Parameters
+ ----------
+ calisto_trapezoidal_fins : TrapezoidalFins
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticTrapezoidalFins
+ The stochastic trapezoidal fins object
+ """
+ return StochasticTrapezoidalFins(
+ trapezoidal_fins=calisto_trapezoidal_fins,
+ root_chord=0.0005,
+ tip_chord=0.0005,
+ span=0.0005,
+ )
+
+
+@pytest.fixture
+def stochastic_tail(calisto_tail):
+ """This fixture is used to create a StochasticTail object for the
+ Calisto rocket.
+
+ Parameters
+ ----------
+ calisto_tail : Tail
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticTail
+ The stochastic tail object
+ """
+ return StochasticTail(
+ tail=calisto_tail,
+ top_radius=0.001,
+ bottom_radius=0.001,
+ length=0.001,
+ )
+
+
+@pytest.fixture
+def stochastic_rail_buttons(calisto_rail_buttons):
+ """This fixture is used to create a StochasticRailButtons object for the
+ Calisto rocket.
+
+ Parameters
+ ----------
+ calisto_rail_buttons : RailButtons
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticRailButtons
+ The stochastic rail buttons object
+ """
+ return StochasticRailButtons(
+ rail_buttons=calisto_rail_buttons, buttons_distance=0.001
+ )
+
+
+@pytest.fixture
+def stochastic_main_parachute(calisto_main_chute):
+ """This fixture is used to create a StochasticParachute object for the
+ Calisto rocket.
+
+ Parameters
+ ----------
+ calisto_main_chute : Parachute
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticParachute
+ The stochastic parachute object
+ """
+ return StochasticParachute(
+ parachute=calisto_main_chute,
+ cd_s=0.1,
+ lag=0.1,
+ )
+
+
+@pytest.fixture
+def stochastic_drogue_parachute(calisto_drogue_chute):
+ """This fixture is used to create a StochasticParachute object for the
+ Calisto rocket. This time, the drogue parachute is created.
+
+ Parameters
+ ----------
+ calisto_drogue_chute : Parachute
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticParachute
+ The stochastic parachute object
+ """
+ return StochasticParachute(
+ parachute=calisto_drogue_chute,
+ cd_s=0.07,
+ lag=0.2,
+ )
+
+
+@pytest.fixture
+def stochastic_calisto(
+ calisto_robust,
+ stochastic_nose_cone,
+ stochastic_trapezoidal_fins,
+ stochastic_tail,
+ stochastic_solid_motor,
+ stochastic_rail_buttons,
+ stochastic_main_parachute,
+ stochastic_drogue_parachute,
+):
+ """This fixture creates a StochasticRocket object for the Calisto rocket.
+ The fixture will already have the stochastic nose cone, trapezoidal fins,
+ tail, solid motor, rail buttons, main parachute, and drogue parachute.
+
+ Returns
+ -------
+ StochasticRocket
+ The stochastic rocket object
+ """
+ rocket = StochasticRocket(
+ rocket=calisto_robust,
+ radius=0.0127 / 2000,
+ mass=(15.426, 0.5, "normal"),
+ inertia_11=(6.321, 0),
+ inertia_22=0.01,
+ inertia_33=0.01,
+ center_of_mass_without_motor=0,
+ )
+ rocket.add_motor(stochastic_solid_motor, position=0.001)
+ rocket.add_nose(stochastic_nose_cone, position=(1.134, 0.001))
+ rocket.add_trapezoidal_fins(stochastic_trapezoidal_fins, position=(0.001, "normal"))
+ rocket.add_tail(stochastic_tail)
+ rocket.set_rail_buttons(
+ stochastic_rail_buttons, lower_button_position=(-0.618, 0.001, "normal")
+ )
+ rocket.add_parachute(stochastic_main_parachute)
+ rocket.add_parachute(stochastic_drogue_parachute)
+ return rocket
+
+
+@pytest.fixture
+def stochastic_flight(flight_calisto_robust):
+ """This fixture creates a StochasticFlight object for the Calisto flight.
+
+ Parameters
+ ----------
+ flight_calisto_robust : Flight
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticFlight
+ The stochastic flight object
+ """
+ return StochasticFlight(
+ flight=flight_calisto_robust,
+ inclination=(84.7, 1),
+ heading=(53, 2),
+ )
diff --git a/tests/fixtures/monte_carlo/stochastic_motors_fixtures.py b/tests/fixtures/monte_carlo/stochastic_motors_fixtures.py
new file mode 100644
index 000000000..9bc46de16
--- /dev/null
+++ b/tests/fixtures/monte_carlo/stochastic_motors_fixtures.py
@@ -0,0 +1,78 @@
+"""This module contains fixtures for the stochastic motors tests."""
+
+import pytest
+
+from rocketpy.mathutils.function import Function
+from rocketpy.stochastic import StochasticGenericMotor, StochasticSolidMotor
+
+
+@pytest.fixture
+def stochastic_solid_motor(cesaroni_m1670):
+ """A Stochastic Solid Motor fixture for the Cesaroni M1670 motor.
+
+ Parameters
+ ----------
+ cesaroni_m1670 : SolidMotor
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticSolidMotor
+ The stochastic solid motor object.
+ """
+ return StochasticSolidMotor(
+ solid_motor=cesaroni_m1670,
+ thrust_source=[
+ "data/motors/Cesaroni_M1670.eng",
+ [[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]],
+ Function([[0, 6000], [1, 6000], [2, 6000], [3, 6000], [4, 6000]]),
+ ],
+ burn_out_time=(4, 0.1),
+ grains_center_of_mass_position=0.001,
+ grain_density=50,
+ grain_separation=1 / 1000,
+ grain_initial_height=1 / 1000,
+ grain_initial_inner_radius=0.375 / 1000,
+ grain_outer_radius=0.375 / 1000,
+ total_impulse=(6500, 1000),
+ throat_radius=0.5 / 1000,
+ nozzle_radius=0.5 / 1000,
+ nozzle_position=0.001,
+ )
+
+
+@pytest.fixture
+def stochastic_generic_motor(generic_motor):
+ """A Stochastic Generic Motor fixture
+
+ Parameters
+ ----------
+ generic_motor : GenericMotor
+ This is another fixture.
+
+ Returns
+ -------
+ StochasticGenericMotor
+ The stochastic generic motor object.
+ """
+ return StochasticGenericMotor(
+ generic_motor,
+ thrust_source=None,
+ total_impulse=None,
+ burn_start_time=None,
+ burn_out_time=None,
+ propellant_initial_mass=None,
+ dry_mass=None,
+ dry_inertia_11=None,
+ dry_inertia_22=None,
+ dry_inertia_33=None,
+ dry_inertia_12=None,
+ dry_inertia_13=None,
+ dry_inertia_23=None,
+ chamber_radius=None,
+ chamber_height=(0.5, 0.005),
+ chamber_position=None,
+ nozzle_radius=None,
+ nozzle_position=None,
+ center_of_dry_mass_position=None,
+ )
diff --git a/tests/test_monte_carlo.py b/tests/test_monte_carlo.py
new file mode 100644
index 000000000..8142f91dd
--- /dev/null
+++ b/tests/test_monte_carlo.py
@@ -0,0 +1,171 @@
+import os
+from unittest.mock import patch
+
+import matplotlib as plt
+import numpy as np
+import pytest
+
+plt.rcParams.update({"figure.max_open_warning": 0})
+
+
+def test_stochastic_environment_create_object_with_wind_x(stochastic_environment):
+ """Tests the stochastic environment object by checking if the wind velocity
+ can be generated properly. The goal is to check if the create_object()
+ method is being called without any problems.
+
+ Parameters
+ ----------
+ stochastic_environment : StochasticEnvironment
+ The stochastic environment object, this is a pytest fixture.
+ """
+ wind_x_at_1000m = []
+ for _ in range(10):
+ random_env = stochastic_environment.create_object()
+ wind_x_at_1000m.append(random_env.wind_velocity_x(1000))
+
+ assert np.isclose(np.mean(wind_x_at_1000m), 0, atol=0.1)
+ assert np.isclose(np.std(wind_x_at_1000m), 0, atol=0.1)
+ # TODO: add a new test for the special case of ensemble member
+
+
+def test_stochastic_solid_motor_create_object_with_impulse(stochastic_solid_motor):
+ """Tests the stochastic solid motor object by checking if the total impulse
+ can be generated properly. The goal is to check if the create_object()
+ method is being called without any problems.
+
+ Parameters
+ ----------
+ stochastic_solid_motor : StochasticSolidMotor
+ The stochastic solid motor object, this is a pytest fixture.
+ """
+ total_impulse = []
+ for _ in range(20):
+ random_motor = stochastic_solid_motor.create_object()
+ total_impulse.append(random_motor.total_impulse)
+
+ assert np.isclose(np.mean(total_impulse), 6500, rtol=0.3)
+ assert np.isclose(np.std(total_impulse), 1000, rtol=0.3)
+
+
+def test_stochastic_calisto_create_object_with_static_margin(stochastic_calisto):
+ """Tests the stochastic calisto object by checking if the static margin
+ can be generated properly. The goal is to check if the create_object()
+ method is being called without any problems.
+
+ Parameters
+ ----------
+ stochastic_calisto : StochasticCalisto
+ The stochastic calisto object, this is a pytest fixture.
+ """
+
+ all_margins = []
+ for _ in range(10):
+ random_rocket = stochastic_calisto.create_object()
+ all_margins.append(random_rocket.static_margin(0))
+
+ assert np.isclose(np.mean(all_margins), 2.2625350013000434, rtol=0.15)
+ assert np.isclose(np.std(all_margins), 0.1, atol=0.2)
+
+
+@pytest.mark.slow
+def test_monte_carlo_simulate(monte_carlo_calisto):
+ """Tests the simulate method of the MonteCarlo class.
+
+ Parameters
+ ----------
+ monte_carlo_calisto : MonteCarlo
+ The MonteCarlo object, this is a pytest fixture.
+ """
+ # NOTE: this is really slow, it runs 10 flight simulations
+ monte_carlo_calisto.simulate(number_of_simulations=10, append=False)
+
+ assert monte_carlo_calisto.num_of_loaded_sims == 10
+ assert monte_carlo_calisto.number_of_simulations == 10
+ assert monte_carlo_calisto.filename == "monte_carlo_test"
+ assert monte_carlo_calisto.error_file == "monte_carlo_test.errors.txt"
+ assert monte_carlo_calisto.output_file == "monte_carlo_test.outputs.txt"
+ assert np.isclose(
+ monte_carlo_calisto.processed_results["apogee"][0], 4711, rtol=0.15
+ )
+ assert np.isclose(
+ monte_carlo_calisto.processed_results["impact_velocity"][0],
+ -5.234,
+ rtol=0.15,
+ )
+ os.remove("monte_carlo_test.errors.txt")
+ os.remove("monte_carlo_test.outputs.txt")
+ os.remove("monte_carlo_test.inputs.txt")
+
+
+def test_monte_carlo_set_inputs_log(monte_carlo_calisto):
+ """Tests the set_inputs_log method of the MonteCarlo class.
+
+ Parameters
+ ----------
+ monte_carlo_calisto : MonteCarlo
+ The MonteCarlo object, this is a pytest fixture.
+ """
+ monte_carlo_calisto.input_file = "tests/fixtures/monte_carlo/example.inputs.txt"
+ monte_carlo_calisto.set_inputs_log()
+ assert len(monte_carlo_calisto.inputs_log) == 10
+ assert all(isinstance(item, dict) for item in monte_carlo_calisto.inputs_log)
+ assert all(
+ "gravity" in item and "elevation" in item
+ for item in monte_carlo_calisto.inputs_log
+ )
+
+
+def test_monte_carlo_set_outputs_log(monte_carlo_calisto):
+ """Tests the set_outputs_log method of the MonteCarlo class.
+
+ Parameters
+ ----------
+ monte_carlo_calisto : MonteCarlo
+ The MonteCarlo object, this is a pytest fixture.
+ """
+ monte_carlo_calisto.output_file = "tests/fixtures/monte_carlo/example.outputs.txt"
+ monte_carlo_calisto.set_outputs_log()
+ assert len(monte_carlo_calisto.outputs_log) == 10
+ assert all(isinstance(item, dict) for item in monte_carlo_calisto.outputs_log)
+ assert all(
+ "apogee" in item and "impact_velocity" in item
+ for item in monte_carlo_calisto.outputs_log
+ )
+
+
+# def test_monte_carlo_set_errors_log(monte_carlo_calisto):
+# monte_carlo_calisto.error_file = "tests/fixtures/monte_carlo/example.errors.txt"
+# monte_carlo_calisto.set_errors_log()
+# assert
+
+
+def test_monte_carlo_prints(monte_carlo_calisto):
+ """Tests the prints methods of the MonteCarlo class."""
+ monte_carlo_calisto.info()
+
+
+@patch("matplotlib.pyplot.show")
+def test_monte_carlo_plots(mock_show, monte_carlo_calisto):
+ """Tests the plots methods of the MonteCarlo class."""
+ assert monte_carlo_calisto.all_info() is None
+
+
+def test_monte_carlo_export_ellipses_to_kml(monte_carlo_calisto):
+ """Tests the export_ellipses_to_kml method of the MonteCarlo class.
+
+ Parameters
+ ----------
+ monte_carlo_calisto : MonteCarlo
+ The MonteCarlo object, this is a pytest fixture.
+ """
+ assert (
+ monte_carlo_calisto.export_ellipses_to_kml(
+ filename="monte_carlo_class_example.kml",
+ origin_lat=32,
+ origin_lon=-104,
+ type="impact",
+ )
+ is None
+ )
+
+ os.remove("monte_carlo_class_example.kml")
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/unit/stochastic/__init__.py b/tests/unit/stochastic/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/unit/stochastic/test_stochastic_aero_surfaces.py b/tests/unit/stochastic/test_stochastic_aero_surfaces.py
new file mode 100644
index 000000000..d63feb76c
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_aero_surfaces.py
@@ -0,0 +1,92 @@
+from rocketpy.rocket.aero_surface import NoseCone, RailButtons, Tail, TrapezoidalFins
+
+## NOSE CONE
+
+
+def test_stochastic_nose_cone_create_object(stochastic_nose_cone):
+ """Test create object method of StochasticNoseCone class.
+
+ This test checks if the create_object method of the StochasticNoseCone
+ class creates a StochasticNoseCone object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_nose_cone : StochasticNoseCone
+ StochasticNoseCone object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_nose_cone.create_object()
+ assert isinstance(obj, NoseCone)
+
+
+## TRAPEZOIDAL FINS
+
+
+def test_stochastic_trapezoidal_fins_create_object(stochastic_trapezoidal_fins):
+ """Test create object method of StochasticTrapezoidalFins class.
+
+ This test checks if the create_object method of the StochasticTrapezoidalFins
+ class creates a StochasticTrapezoidalFins object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_trapezoidal_fins : StochasticTrapezoidalFins
+ StochasticTrapezoidalFins object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_trapezoidal_fins.create_object()
+ assert isinstance(obj, TrapezoidalFins)
+
+
+## TAIL
+
+
+def test_stochastic_tail_create_object(stochastic_tail):
+ """Test create object method of StochasticTail class.
+
+ This test checks if the create_object method of the StochasticTail
+ class creates a StochasticTail object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_tail : StochasticTail
+ StochasticTail object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_tail.create_object()
+ assert isinstance(obj, Tail)
+
+
+## RAIL BUTTONS
+
+
+def test_stochastic_rail_buttons_create_object(stochastic_rail_buttons):
+ """Test create object method of StochasticRailButtons class.
+
+ This test checks if the create_object method of the StochasticRailButtons
+ class creates a StochasticRailButtons object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_rail_buttons : StochasticRailButtons
+ StochasticRailButtons object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_rail_buttons.create_object()
+ assert isinstance(obj, RailButtons)
diff --git a/tests/unit/stochastic/test_stochastic_environment.py b/tests/unit/stochastic/test_stochastic_environment.py
new file mode 100644
index 000000000..ce115fe05
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_environment.py
@@ -0,0 +1,43 @@
+from rocketpy.environment.environment import Environment
+
+
+def test_str(stochastic_environment):
+ """Test __str__ method of StochasticEnvironment class.
+
+ This test checks if the __str__ method of the StochasticEnvironment class
+ returns a string without raising any exceptions.
+
+ Parameters
+ ----------
+ stochastic_environment : StochasticEnvironment
+ StochasticEnvironment object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ assert isinstance(str(stochastic_environment), str)
+
+
+# def test_validate_ensemble(stochastic_environment):
+# print("Implement this later")
+
+
+def test_create_object(stochastic_environment):
+ """Test create object method of StochasticEnvironment class.
+
+ This test checks if the create_object method of the StochasticEnvironment
+ class creates a StochasticEnvironment object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_environment : StochasticEnvironment
+ StochasticEnvironment object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_environment.create_object()
+ assert isinstance(obj, Environment)
diff --git a/tests/unit/stochastic/test_stochastic_flight.py b/tests/unit/stochastic/test_stochastic_flight.py
new file mode 100644
index 000000000..aeb71b906
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_flight.py
@@ -0,0 +1,6 @@
+from rocketpy.simulation.flight import Flight
+
+
+def test_stochastic_flight_create_object(stochastic_flight):
+ obj = stochastic_flight.create_object()
+ assert isinstance(obj, Flight)
diff --git a/tests/unit/stochastic/test_stochastic_motors.py b/tests/unit/stochastic/test_stochastic_motors.py
new file mode 100644
index 000000000..214772743
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_motors.py
@@ -0,0 +1,6 @@
+from rocketpy.motors import GenericMotor
+
+
+def test_stochastic_generic_motor_create_object(stochastic_generic_motor):
+ obj = stochastic_generic_motor.create_object()
+ assert isinstance(obj, GenericMotor)
diff --git a/tests/unit/stochastic/test_stochastic_parachute.py b/tests/unit/stochastic/test_stochastic_parachute.py
new file mode 100644
index 000000000..09a1497f7
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_parachute.py
@@ -0,0 +1,21 @@
+from rocketpy.rocket.parachute import Parachute
+
+
+def test_stochastic_parachute_create_object(stochastic_main_parachute):
+ """Test create object method of StochasticParachute class.
+
+ This test checks if the create_object method of the StochasticParachute
+ class creates a StochasticParachute object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_main_parachute : StochasticParachute
+ StochasticParachute object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_main_parachute.create_object()
+ assert isinstance(obj, Parachute)
diff --git a/tests/unit/stochastic/test_stochastic_rocket.py b/tests/unit/stochastic/test_stochastic_rocket.py
new file mode 100644
index 000000000..8306b6039
--- /dev/null
+++ b/tests/unit/stochastic/test_stochastic_rocket.py
@@ -0,0 +1,25 @@
+from rocketpy.rocket.rocket import Rocket
+
+
+def test_str(stochastic_calisto):
+ assert isinstance(str(stochastic_calisto), str)
+
+
+def test_create_object(stochastic_calisto):
+ """Test create object method of StochasticRocket class.
+
+ This test checks if the create_object method of the StochasticCalisto
+ class creates a StochasticCalisto object from the randomly generated
+ input arguments.
+
+ Parameters
+ ----------
+ stochastic_calisto : StochasticCalisto
+ StochasticCalisto object to be tested.
+
+ Returns
+ -------
+ None
+ """
+ obj = stochastic_calisto.create_object()
+ assert isinstance(obj, Rocket)
diff --git a/tests/unit/test_utilities.py b/tests/unit/test_utilities.py
index 33942b445..43df536dd 100644
--- a/tests/unit/test_utilities.py
+++ b/tests/unit/test_utilities.py
@@ -48,7 +48,7 @@ def test_create_dispersion_dictionary():
"""Test if the function returns a dictionary with the correct keys.
It reads the keys from the dictionary generated by the utilities function
and compares them to the expected.
- Be careful if you change the "fixtures/dispersion/Valetudo_inputs.csv" file.
+ Be careful if you change the "fixtures/monte_carlo/Valetudo_inputs.csv" file.
Parameters
----------
@@ -60,11 +60,11 @@ def test_create_dispersion_dictionary():
"""
returned_dict = utilities.create_dispersion_dictionary(
- "tests/fixtures/dispersion/Valetudo_inputs.csv"
+ "tests/fixtures/monte_carlo/Valetudo_inputs.csv"
)
test_array = np.genfromtxt(
- "tests/fixtures/dispersion/Valetudo_inputs.csv",
+ "tests/fixtures/monte_carlo/Valetudo_inputs.csv",
usecols=(1, 2, 3),
skip_header=1,
delimiter=";",