From 0fe7b4538c2c20352374991909eb0cad847d4eee Mon Sep 17 00:00:00 2001 From: Bruno Beltran Date: Thu, 3 Sep 2020 13:04:46 -0700 Subject: [PATCH 01/15] API: separate epigenetic marks into own module --- chromo/{Polymer.py => components.py} | 46 ++++++++++++--------------- chromo/{Field.py => fields.py} | 0 chromo/marks.py | 47 ++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 26 deletions(-) rename chromo/{Polymer.py => components.py} (91%) rename chromo/{Field.py => fields.py} (100%) create mode 100644 chromo/marks.py diff --git a/chromo/Polymer.py b/chromo/components.py similarity index 91% rename from chromo/Polymer.py rename to chromo/components.py index a75c112..d8c3c51 100644 --- a/chromo/Polymer.py +++ b/chromo/components.py @@ -1,7 +1,8 @@ """ -Polymer class. +Components that will make up our simulation. -Creates a polymer with a defined length and discretization. +Various types of polymers, solvents, and other simulation components should be +defined here. """ from pathlib import Path from enum import Enum @@ -10,28 +11,18 @@ import numpy as np import pandas as pd -from .util import dss_params, combine_repeat - -@dataclasses.dataclass -class Epigenmark: - """Information about the chemical properties of an epigenetic mark.""" - - name: str - bind_energy: float - interaction_energy: float - chemical_potential: float +from . import marks +from .util import dss_params, combine_repeat -class State: +class State(Enum): """Defines the epigenetic state of a given bead for a single mark.""" - pass -class HP1_State(State, Enum): +class HP1_State(State): """HP1 can be bound to none, either, or both nucleosome tails.""" - NONE = 0 LBOUND = 1 RBOUND = 2 @@ -44,7 +35,7 @@ def make_epi_collection(epigenmarks): Parameters ---------- - epigenmarks : Sequence[Epigenmark] + epigenmarks : Sequence[Epigenmark] or Sequence[str] The epigenetic marks to be summarized. Returns @@ -54,7 +45,11 @@ def make_epi_collection(epigenmarks): """ df = pd.DataFrame(columns=['name', 'bind_energy', 'interaction_energy', 'chemical_potential']) + if type(epigenmarks) is str: + epigenmarks = [epigenmarks] # allow the "one mark" case for mark in epigenmarks: + if type(mark) is str: + mark = marks.get_by_name(mark) df = df.append(dataclasses.asdict(mark), ignore_index=True) return df @@ -77,7 +72,7 @@ class Polymer: objects. """ - def __init__(self, name, r, t_3, t_2, epigenmarks, states, + def __init__(self, name, r, *, t_3, t_2, states, epigenmarks, length_per_bead): """ Parameters @@ -90,12 +85,12 @@ def __init__(self, name, r, t_3, t_2, epigenmarks, states, The tangent vector to each bead in global coordinates. t_2 : (N, 3) array_like of float A material normal to each bead in global coordinates. - epigenmarks : (M, ) Sequence[Epigenmark] - Information about the chemical properties of each of the epigenetic - marks being tracked. - states : (N, M) array_like of State + states : (N, M) array_like of int State of each of the M epigenetic marks being tracked for each bead. + epigenmarks : (M, ) Sequence[Epigenmark] or Sequence[str] + Information about the chemical properties of each of the epigenetic + marks being tracked, or the name of the mark to be looked up. length_per_bead : float How many Kuhn lengths of polymer are simulated by each bead. """ @@ -127,8 +122,8 @@ def from_files(cls, *, r=None, t_3=None, t_2=None, marks=None, states=None, return cls(r, t_3, t_2, marks, states, lengths) @classmethod - def straight_line_in_x(cls, name, marks, states, num_beads, - length_per_bead): + def straight_line_in_x(cls, name, *, length_per_bead, marks=None, + states=None): r = np.zeros((num_beads, 3)) r[:, 0] = length_per_bead * np.arange(num_beads) t_3 = np.zeros((num_beads, 3)) @@ -147,8 +142,7 @@ def __repr__(self): def write_repr(self, path): np.savez(path, r=self.r, t_2=self.t_2, t_3=self.t_3, - states=self.states, marks=self.epigenmarks.values, - length_per_bead=self.length_per_bead) + states=self.states, length_per_bead=self.length_per_bead) @classmethod def from_repr(cls, path): diff --git a/chromo/Field.py b/chromo/fields.py similarity index 100% rename from chromo/Field.py rename to chromo/fields.py diff --git a/chromo/marks.py b/chromo/marks.py new file mode 100644 index 0000000..08c47d1 --- /dev/null +++ b/chromo/marks.py @@ -0,0 +1,47 @@ +""" +Modifications to the polymer's chemical state that affect the energy. + +Each simulation type will typically require a particular type of Mark, for +which there will be a class defined here. In addition, for common, physically +derived marks, such as known epigenetic modifications to DNA or +well-characterized modifications to other real polymers, the best-known +parameters for that mark should be documented here, as instances of the +appropriate `.Mark` subclass. +""" + +from dataclasses import dataclass +import inspect +import sys + +@dataclass +class Mark: + """ + In order for our code to work, all marks need a string name. + """ + name: str + +@dataclass +class Epigenmark(Mark): + """Information about the chemical properties of an epigenetic mark.""" + bind_energy: float + interaction_energy: float + chemical_potential: float + +hp1 = Epigenmark('HP1', bind_energy=1, interaction_energy=1, chemical_potential=1) +""" +Heterochromatin Protein 1, binds H3K9me marks. + +For now, we just use filler values for the energies. In the future, this +documentation string should go through the process of explaining exactly how we +arrive at the values that we actually use. +""" + +def get_by_name(name): + all_marks = [obj for name, obj in inspect.getmembers(sys.modules[__name__]) + if isinstance(obj, Mark)] + matching_marks = [mark for mark in all_marks if mark.name == name] + if not matching_marks: + raise ValueError(f"No marks found in {__name__} with name: {name}") + if len(matching_marks) > 1: + raise ValueError(f"More than one mark has the name requested: {name}") + return matching_marks[0] From 2466bbd10f37641720e08136b4332d6ea538a7d9 Mon Sep 17 00:00:00 2001 From: Bruno Beltran Date: Sun, 13 Sep 2020 11:19:48 -0700 Subject: [PATCH 02/15] CODE/REORG: Implement discussion w/. Andy/Joe --- chromo/components.py | 315 +++++++++++++++++++-------------- chromo/fields.py | 211 ++++++++++++++++++---- chromo/marks.py | 50 +++++- chromo/mc/__init__.py | 24 +-- chromo/mc/mc_sim.py | 4 +- chromo/mc/moves.py | 4 +- chromo/util/reproducibility.py | 78 ++++++-- tests/test_components.py | 14 ++ tests/test_fields.py | 49 +++++ 9 files changed, 545 insertions(+), 204 deletions(-) create mode 100644 tests/test_components.py create mode 100644 tests/test_fields.py diff --git a/chromo/components.py b/chromo/components.py index d8c3c51..05161ce 100644 --- a/chromo/components.py +++ b/chromo/components.py @@ -4,56 +4,29 @@ Various types of polymers, solvents, and other simulation components should be defined here. """ -from pathlib import Path from enum import Enum -import dataclasses -import io import numpy as np import pandas as pd -from . import marks -from .util import dss_params, combine_repeat +from .util import dss_params class State(Enum): - """Defines the epigenetic state of a given bead for a single mark.""" + """Defines the chemical state of a given bead for a single mark.""" + pass class HP1_State(State): """HP1 can be bound to none, either, or both nucleosome tails.""" + NONE = 0 LBOUND = 1 RBOUND = 2 BOTH = 3 -def make_epi_collection(epigenmarks): - """ - Takes a sequence of epigenetic marks and returns a summary DataFrame. - - Parameters - ---------- - epigenmarks : Sequence[Epigenmark] or Sequence[str] - The epigenetic marks to be summarized. - - Returns - ------- - pd.DataFrame - Columns are the properties of Epigenmark. - """ - df = pd.DataFrame(columns=['name', 'bind_energy', 'interaction_energy', - 'chemical_potential']) - if type(epigenmarks) is str: - epigenmarks = [epigenmarks] # allow the "one mark" case - for mark in epigenmarks: - if type(mark) is str: - mark = marks.get_by_name(mark) - df = df.append(dataclasses.asdict(mark), ignore_index=True) - return df - - class Polymer: """ The positions and chemical state of a discrete polymer. @@ -72,166 +45,242 @@ class Polymer: objects. """ - def __init__(self, name, r, *, t_3, t_2, states, epigenmarks, - length_per_bead): + _arrays = 'r', 't3', 't2', 'states', 'bead_length' + """Track which arrays will be saved to file.""" + _3d_arrays = 'r', 't3', 't2' + """Track which arrays need to have multi-indexed values (x, y, z).""" + + def __init__(self, name, r, *, bead_length, t3=None, t2=None, + states=None, mark_names=None): """ + Construct a polymer. + Parameters ---------- name : str A name for convenient repr. Should be a valid filename. r : (N, 3) array_like of float The positions of each bead. - t_3 : (N, 3) array_like of float + t3 : (N, 3) array_like of float The tangent vector to each bead in global coordinates. - t_2 : (N, 3) array_like of float + t2 : (N, 3) array_like of float A material normal to each bead in global coordinates. states : (N, M) array_like of int State of each of the M epigenetic marks being tracked for each bead. - epigenmarks : (M, ) Sequence[Epigenmark] or Sequence[str] - Information about the chemical properties of each of the epigenetic - marks being tracked, or the name of the mark to be looked up. - length_per_bead : float - How many Kuhn lengths of polymer are simulated by each bead. + mark_names : (M, ) str or Sequence[str] + The name of each chemical modification tracked in `states`, for + each of tracking which mark is which. + bead_length : float or (N,) array_like of float + The amount of polymer path length between this bead and the next + bead. For now, a constant value is assumed (the first value if an + array is passed). """ self.name = name self.r = r - self.t_3 = t_3 - self.t_2 = t_2 - self.epigenmarks = make_epi_collection(epigenmarks) + self.t3 = t3 + self.t2 = t2 self.states = states - self.length_per_bead = length_per_bead + self.mark_names = mark_names + if states is not None: + # does what atleast_2d(axis=1) should do (but doesn't) + self.states = self.states.reshape(states.shape[0], -1) + num_beads, num_marks = self.states.shape + if num_marks != len(mark_names): + raise ValueError("Each chemical state must be given a name.") + if num_beads != len(self.r): + raise ValueError("Initial epigenetic state of wrong length.") + # first if makes sure len will work in second if + if not issubclass(type(bead_length), np.ndarray): + bead_length = np.atleast_1d(bead_length) + if len(bead_length) == 1: + bead_length = np.broadcast_to(bead_length, (self.num_beads, 1)) + self.bead_length = bead_length # Load the polymer parameters for the conformational energy - self.sim_type, self.eps_bend, self.eps_par, self.eps_perp, \ - self.gamma, self.eta = self._find_parameters(length_per_bead) + # for now, the array-values of bead_length are ignored + self.eps_bend, self.eps_par, self.eps_perp, self.gamma, self.eta \ + = self._find_parameters(self.bead_length[0]) @classmethod - def from_files(cls, *, r=None, t_3=None, t_2=None, marks=None, states=None, - lengths=None): - """ - Instantiate a Polymer from input files. - - Each of the r, t_3, t_2, epigenmarks, states, and length_per_bead - arrays requires a separate input file. - """ - r = pd.read_csv(r, header=None) if r is not None else None - t_3 = pd.read_csv(t_3, header=None) if t_3 is not None else None - t_2 = pd.read_csv(t_2, header=None) if t_2 is not None else None - states = pd.read_csv(states) if states is not None else None - marks = pd.read_csv(r, header=None) if r is not None else None - return cls(r, t_3, t_2, marks, states, lengths) + def from_csv(cls, csv_file): + """Construct Polymer from CSV file.""" + df = pd.read_csv(csv_file) + return cls.from_dataframe(df) @classmethod - def straight_line_in_x(cls, name, *, length_per_bead, marks=None, - states=None): + def straight_line_in_x(cls, name, num_beads, bead_length, **kwargs): + """Construct polymer initialized uniformly along the positve x-axis.""" r = np.zeros((num_beads, 3)) - r[:, 0] = length_per_bead * np.arange(num_beads) - t_3 = np.zeros((num_beads, 3)) - t_3[:, 0] = 1 - t_2 = np.zeros((num_beads, 3)) - t_2[:, 1] = 1 - return cls(name, r, t_3, t_2, marks, states, length_per_bead) - - def write_marks(self, marks_file, **kwargs): - self.epigenmarks.to_csv(marks_file, **kwargs) + r[:, 0] = bead_length * np.arange(num_beads) + t3 = np.zeros((num_beads, 3)) + t3[:, 0] = 1 + t2 = np.zeros((num_beads, 3)) + t2[:, 1] = 1 + return cls(name, r, t3=t3, t2=t2, bead_length=bead_length, **kwargs) + + def to_dataframe(self): + """ + Write canonical CSV representation of the Polymer to file. - def __repr__(self): - s = io.Bytes() - self.write_repr(s) - return s.decode() + The top-level multiindex values for the columns should correspond to + the kwargs, to simplify unpacking the structure (and to make for easy + accessing of the dataframe. + """ + arrays = {name: self.__dict__[name] for name in self._arrays + if self.__dict__[name] is not None} + vector_arrs = {} + regular_arrs = {} + for name, arr in arrays.items(): + if name in self._3d_arrays: + vector_arrs[name] = arr + # special-cased below to get correct epigenmark names + elif name != 'states': + regular_arrs[name] = arr + # first construct the parts of the DataFrame that need a multi-index + # TODO: remove "list" after numpy fixes + # https://github.com/numpy/numpy/issues/17305 + vector_arr = np.concatenate(list(vector_arrs.values()), axis=1) + # vector_arr = np.concatenate(vector_arrs.values(), axis=1) + vector_index = pd.MultiIndex.from_product([vector_arrs.keys(), + ('x', 'y', 'z')]) + vector_df = pd.DataFrame(vector_arr, columns=vector_index) + states_index = pd.MultiIndex.from_tuples( + [('states', name) for name in self.mark_names]) + states_df = pd.DataFrame(self.states, columns=states_index) + df = pd.concat([vector_df, states_df], axis=1) + # now throw in the remaining columns one-by-one + for name, arr in regular_arrs.items(): + df[name] = arr + return df - def write_repr(self, path): - np.savez(path, r=self.r, t_2=self.t_2, t_3=self.t_3, - states=self.states, length_per_bead=self.length_per_bead) + @classmethod + def from_dataframe(cls, df, name=None): + """Construct Polymer object from DataFrame. Inverts `.to_dataframe`.""" + # top-level multiindex values correspond to kwargs + kwnames = np.unique(df.columns.get_level_values(0)) + kwargs = {name: df[name].to_numpy() for name in kwnames} + # extract names of each epigenetic state from multi-index + if 'states' in df: + mark_names = df['states'].columns.to_numpy() + kwargs['mark_names'] = mark_names + return cls(name, **kwargs) @classmethod - def from_repr(cls, path): - npz = np.load(path) - mark_info_arr = npz['marks'] - marks = [Epigenmark(*info) for info in mark_info_arr] - return cls(r=npz['r'], t_3=npz['t_3'], t_2=npz['t_2'], - states=npz['states'], marks=marks, - length_per_bead=npz['length_per_bead']) + def from_file(cls, path, name=None): + """Construct Polymer object from string representation.""" + if name is None: + name = path.name + return cls.from_dataframe( + pd.read_csv(path, header=[0, 1], index_col=0), + name + ) + + def to_csv(self, path): + """Save Polymer object to CSV file as DataFrame.""" + return self.to_dataframe().to_csv(path) + + def to_file(self, path): + """Synonym for *to_csv* to conform to `make_reproducible` spec.""" + return self.to_csv(path) @property def num_marks(self): - return len(self.epigenmarks) + """Return number of states tracked per bead.""" + return self.states.shape[1] @property def num_beads(self): + """Return number of beads in the polymer.""" return self.r.shape[0] def __str__(self): + """Return string representation of the Polymer.""" return f"Polymer<{self.name}, nbeads={self.num_beads}, " \ f"nmarks={self.num_marks}>" @staticmethod def _find_parameters(length_bead): - """Determine the parameters for the elastic forces based on ssWLC with twist.""" - sim_type = "sswlc" + """Look up elastic parameters of ssWLC for each bead_length.""" lp_dna = 53 # Persistence length of DNA in nm - length_dim = length_bead * 0.34 / lp_dna # Non-dimensionalized length per bead - - # Determine the parameter values using linear interpolation of the parameter table - eps_bend = np.interp(length_dim, dss_params[:, 0], dss_params[:, 1]) / length_dim - gamma = np.interp(length_dim, dss_params[:, 0], dss_params[:, 2]) * length_dim * lp_dna - eps_par = np.interp(length_dim, dss_params[:, 0], dss_params[:, 3]) / (length_dim * lp_dna**2) - eps_perp = np.interp(length_dim, dss_params[:, 0], dss_params[:, 4]) / (length_dim * lp_dna**2) - eta = np.interp(length_dim, dss_params[:, 0], dss_params[:, 5]) / lp_dna - - return sim_type, eps_bend, eps_par, eps_perp, gamma, eta - - def compute_dE(self, ind0, indf, r_poly_trial, t3_poly_trial, t2_poly_trial, - states_trial): - """ - Compute change in energy of polymer state from proposed new state. - """ + # Non-dimensionalized length per bead + length_dim = length_bead * 0.34 / lp_dna + + # Determine the parameter values using linear interpolation of the + # parameter table + eps_bend = np.interp(length_dim, dss_params[:, 0], dss_params[:, 1]) \ + / length_dim + gamma = np.interp(length_dim, dss_params[:, 0], dss_params[:, 2]) \ + * length_dim * lp_dna + eps_par = np.interp(length_dim, dss_params[:, 0], dss_params[:, 3]) \ + / (length_dim * lp_dna**2) + eps_perp = np.interp(length_dim, dss_params[:, 0], dss_params[:, 4]) \ + / (length_dim * lp_dna**2) + eta = np.interp(length_dim, dss_params[:, 0], dss_params[:, 5]) \ + / lp_dna + + return eps_bend, eps_par, eps_perp, gamma, eta + + def compute_dE(self, ind0, indf, r_poly_trial, t3_poly_trial, + t2_poly_trial, states_trial): + """Compute change in polymer energy moving to proposed new state.""" delta_energy_poly = 0 # Calculate contribution to polymer energy at the ind0 position if ind0 != 0: delta_r_trial = r_poly_trial[0, :] - self.r[ind0 - 1, :] - delta_r_par_trial = np.dot(delta_r_trial, self.t_3[ind0 - 1, :]) - delta_r_perp_trial = delta_r_trial - delta_r_par_trial * self.t_3[ind0 - 1, :] + delta_r_par_trial = np.dot(delta_r_trial, self.t3[ind0 - 1, :]) + delta_r_perp_trial = delta_r_trial \ + - delta_r_par_trial * self.t3[ind0 - 1, :] delta_r = self.r[ind0, :] - self.r[ind0 - 1, :] - delta_r_par = np.dot(delta_r, self.t_3[ind0 - 1, :]) - delta_r_perp = delta_r - delta_r_par * self.t_3[ind0 - 1, :] + delta_r_par = np.dot(delta_r, self.t3[ind0 - 1, :]) + delta_r_perp = delta_r - delta_r_par * self.t3[ind0 - 1, :] - bend_vec_trial = (t3_poly_trial[0, :] - self.t_3[ind0 - 1, :] - - self.eta * delta_r_perp_trial) - bend_vec = (self.t_3[ind0, :] - self.t_3[ind0 - 1, :] - - self.eta * delta_r_perp) + bend_vec_trial = (t3_poly_trial[0, :] - self.t3[ind0 - 1, :] + - self.eta * delta_r_perp_trial) + bend_vec = (self.t3[ind0, :] - self.t3[ind0 - 1, :] + - self.eta * delta_r_perp) - delta_energy_poly += (0.5 * self.eps_bend * np.dot(bend_vec_trial, bend_vec_trial) - + 0.5 * self.eps_par * (delta_r_par_trial - self.gamma) ** 2 - + 0.5 * self.eps_perp * np.dot(delta_r_perp_trial, delta_r_perp_trial)) - delta_energy_poly -= (0.5 * self.eps_bend * np.dot(bend_vec, bend_vec) - + 0.5 * self.eps_par * (delta_r_par - self.gamma) ** 2 - + 0.5 * self.eps_perp * np.dot(delta_r_perp, delta_r_perp)) + delta_energy_poly += ( + 0.5 * self.eps_bend * np.dot(bend_vec_trial, bend_vec_trial) + + 0.5 * self.eps_par * (delta_r_par_trial - self.gamma) ** 2 + + 0.5 * self.eps_perp * np.dot(delta_r_perp_trial, + delta_r_perp_trial) + ) + delta_energy_poly -= ( + 0.5 * self.eps_bend * np.dot(bend_vec, bend_vec) + + 0.5 * self.eps_par * (delta_r_par - self.gamma) ** 2 + + 0.5 * self.eps_perp * np.dot(delta_r_perp, delta_r_perp) + ) # Calculate contribution to polymer energy at the indf position if indf != self.num_beads: delta_r_trial = self.r[indf, :] - r_poly_trial[indf - ind0 - 1, :] - delta_r_par_trial = np.dot(delta_r_trial, t3_poly_trial[indf - ind0 - 1, :]) - delta_r_perp_trial = delta_r_trial - delta_r_par_trial * t3_poly_trial[indf - ind0 - 1, :] + delta_r_par_trial = np.dot(delta_r_trial, + t3_poly_trial[indf - ind0 - 1, :]) + delta_r_perp_trial = delta_r_trial \ + - delta_r_par_trial * t3_poly_trial[indf - ind0 - 1, :] delta_r = self.r[indf, :] - self.r[indf - 1, :] - delta_r_par = np.dot(delta_r, self.t_3[indf - 1, :]) - delta_r_perp = delta_r - delta_r_par * self.t_3[indf - 1, :] + delta_r_par = np.dot(delta_r, self.t3[indf - 1, :]) + delta_r_perp = delta_r - delta_r_par * self.t3[indf - 1, :] - bend_vec_trial = (self.t_3[indf, :] - t3_poly_trial[indf - ind0 - 1, :] - - self.eta * delta_r_perp_trial) - bend_vec = (self.t_3[indf, :] - self.t_3[indf - 1, :] + bend_vec_trial = (self.t3[indf, :] + - t3_poly_trial[indf - ind0 - 1, :] + - self.eta * delta_r_perp_trial) + bend_vec = (self.t3[indf, :] - self.t3[indf - 1, :] - self.eta * delta_r_perp) - delta_energy_poly += (0.5 * self.eps_bend * np.dot(bend_vec_trial, bend_vec_trial) - + 0.5 * self.eps_par * (delta_r_par_trial - self.gamma) ** 2 - + 0.5 * self.eps_perp * np.dot(delta_r_perp_trial, delta_r_perp_trial)) - delta_energy_poly -= (0.5 * self.eps_bend * np.dot(bend_vec, bend_vec) - + 0.5 * self.eps_par * (delta_r_par - self.gamma) ** 2 - + 0.5 * self.eps_perp * np.dot(delta_r_perp, delta_r_perp)) + delta_energy_poly += ( + 0.5 * self.eps_bend * np.dot(bend_vec_trial, bend_vec_trial) + + 0.5 * self.eps_par * (delta_r_par_trial - self.gamma) ** 2 + + 0.5 * self.eps_perp * np.dot(delta_r_perp_trial, + delta_r_perp_trial) + ) + delta_energy_poly -= ( + 0.5 * self.eps_bend * np.dot(bend_vec, bend_vec) + + 0.5 * self.eps_par * (delta_r_par - self.gamma) ** 2 + + 0.5 * self.eps_perp * np.dot(delta_r_perp, delta_r_perp) + ) return delta_energy_poly - - diff --git a/chromo/fields.py b/chromo/fields.py index d027e0e..1ddaa12 100644 --- a/chromo/fields.py +++ b/chromo/fields.py @@ -1,12 +1,12 @@ """ -Field class +Fields discretize space to efficiently track changes in Mark energy. Creates a field object that contains parameters for the field calculations and functions to generate the densities - """ - import numpy as np +import pandas as pd + from .util import combine_repeat @@ -16,10 +16,21 @@ class FieldBase: Must be subclassed to be useful. """ + + _field_descriptors = [] + + @property + def name(self): + """For now, there's only one field per sim, so classname works.""" + return self.__class__.__name__ + def __init__(self): + """Construct a field holding no Polymers, tracking no Marks.""" self.polymers = [] + self.marks = pd.DataFrame() def __str__(self): + """Print representation of empty field.""" return "Field<>" def __contains__(self, poly): @@ -62,9 +73,80 @@ def compute_dE(self, poly, ind0, indf, r, t3, t2, states): pass +class Reconstructor: + """ + Defer construction of `Field` until after `Polymer`/`Mark` instances. + + Constructs a kwargs object that can be re-passed to the appropriate `Field` + constructor when they become available. + """ + + def __init__(self, cls, **kwargs): + """Construct our Reconstructor.""" + self.field_constructor = cls + self.kwargs = kwargs + + def finalize(self, polymers, marks): + """Finish construction of appropriate `Field` object.""" + return self.field_constructor(polymers=polymers, marks=marks, + **self.kwargs) + + @classmethod + def from_file(cls, path): + """Assume class name is encoded in file name.""" + constructor = globals()[path.name] + # read info as a series + kwargs = pd.read_csv(path).iloc[0].to_dict() + return cls(constructor, **kwargs) + + def __call__(self, polymers, marks): + """Synonym for `Reconstructor.finalize`.""" + return self.finalize(polymers, marks) + + class UniformDensityField(FieldBase): - def __init__(self, polymers, x_width, nx, y_width, ny, z_width, nz): + """ + Rectilinear discretization of a rectangular box. + + Computes field energies at the corners of each box. The bead in each box + contributes "mass" to each vertex linearly based on its position in the + box. This is much more stable numerically than just using the boxes as + "bins" as would be done in a e.g. finite-differences discretization. + """ + + _field_descriptors = ['x_width', 'nx', 'y_width', 'ny', 'z_width', 'nz'] + + def __init__(self, polymers, marks, x_width, nx, y_width, ny, z_width, + nz): + """ + Construct a UniformDensityField. + + Parameters + ---------- + polymers : Sequence[Polymer] + Name of (or object representing) each polymer in the field. + marks : pd.DataFrame + Output of `chromo.marks.make_mark_collection` for the `Mark`s to be + used. + x_width : float + Width of the box containing the field in the x-direction. + nx : int + Number of bins in the x-direction. + y_width : float + Width of the box containing the field in the y-direction. + ny : int + Number of bins in the y-direction. + z_width : float + Width of the box containing the field in the z-direction. + nz : int + Number of bins in the z-direction. + """ self.polymers = polymers + self.marks = marks + for poly in polymers: + if poly.num_marks != len(marks): + raise NotImplementedError("For now, all polymers must use all" + " of the same marks.") self.x_width = x_width self.y_width = y_width self.z_width = z_width @@ -78,18 +160,58 @@ def __init__(self, polymers, x_width, nx, y_width, ny, z_width, nz): self.vol_bin = x_width * y_width * z_width / self.n_bins self.bin_index = UniformDensityField._get_corner_bin_index( self.nx, self.ny, self.nz) - num_epigenmarks = np.array([len(p.epigenmarks) for p in polymers]) - if np.any(num_epigenmarks != num_epigenmarks[0]): - raise ValueError("All Polymers must have the same number of " - "epigenetic marks for now.") # one column of density for each state and one for the actual bead # density of the polymer - self.density = np.zeros((self.n_bins, num_epigenmarks[0] + 1), 'd') + self.num_marks = len(marks) + self.density = np.zeros((self.n_bins, self.num_marks + 1), 'd') self._recompute_field() # initialize the density field + def to_file(self, path): + """Save Field description and Polymer/Mark names to CSV as Series.""" + rows = {name: self.__dict__[name] for name in self._field_descriptors} + for i, polymer in enumerate(self.polymers): + rows[polymer.name] = 'polymer' + for i, mark in self.marks.iterrows(): + # careful! mark.name is the Series.name attribute + rows[mark['name']] = 'mark' + # prints just key,value for each key in rows + return pd.Series(rows).to_csv(path, header=None) + + @classmethod + def from_file(cls, path, polymers, marks): + """Recover field saved with `.to_file`. Requires Poly/Mark inputs.""" + # the 0th column will be the index, the 1th column holds the data... + field_series = pd.read_csv(path, header=None, index_col=0)[1] + kwargs = pd.to_numeric(field_series[cls._field_descriptors]).to_dict() + polymer_names = field_series[field_series == 'polymer'].index.values + mark_names = field_series[field_series == 'mark'].index.values + + err_prefix = f"Tried to instantiate class:{cls} from file:{path} with " + if len(polymers) != len(polymer_names): + raise ValueError(err_prefix + f"{len(polymers)} polymers, but " + f" there are {len(polymer_names)} listed.") + for polymer in polymers: + if polymer.name not in polymer_names: + raise ValueError(err_prefix + f"polymer:{polymer.name}, but " + " this polymer was not present in file.") + if len(marks) != len(mark_names): + raise ValueError(err_prefix + f"{len(marks)} marks, but " + f" there are {len(mark_names)} listed.") + for i, mark in marks.iterrows(): + if mark['name'] not in mark_names: + raise ValueError(err_prefix + f"mark:{mark}, but " + " this mark was not present in file.") + + return cls(polymers=polymers, marks=marks, **kwargs) + @staticmethod def _get_corner_bin_index(nx, ny, nz): - """Setup the index array for density bins corners.""" + """ + Set up the index array for density bins corners. + + TODO: this should just be a higher-dimensional array to avoid having to + do any of this math. + """ bin_index = np.zeros((nx * ny * nz, 8), 'd') count = 0 for index_z in range(nz): @@ -121,9 +243,10 @@ def _get_corner_bin_index(nx, ny, nz): return bin_index def __str__(self): + """Print summary of the UniformDensityField.""" n_poly = len(self.polymers) - return "UniformRectField" + return f"UniformDensityField" def _recompute_field(self, check_consistency=False): new_density = self.density.copy() @@ -138,49 +261,63 @@ def _recompute_field(self, check_consistency=False): " bug in this code.") def compute_dE(self, poly, ind0, indf, r, t3, t2, states): + """ + Compute change in energy based on proposed new polymer location. + + Requires the polymer to be moved in order to compare to old state. + """ # even if the move does not change the states, we cannot ignore them # because they're needed to compute the energy at any point along the # polymer if states is None: states = poly.states density_poly, index_xyz = self._calc_density( - poly.r[ind0:indf, :], poly.states, ind0, indf) - density_poly_trial, index_xyz_trial = self._calc_density(r, states, ind0, indf) - delta_density_poly_total = np.concatenate((density_poly_trial, -density_poly)) - delta_index_xyz_total = np.concatenate((index_xyz_trial, index_xyz)).astype(int) - delta_density, delta_index_xyz = combine_repeat(delta_density_poly_total, delta_index_xyz_total) - - delta_energy_epigen = 0 - for i, (_, epi_info) in enumerate(poly.epigenmarks.iterrows()): - delta_energy_epigen += 0.5 * epi_info.interaction_energy * np.sum( - (delta_density[:, i + 1] + self.density[delta_index_xyz, i + 1]) ** 2 - - self.density[delta_index_xyz, i + 1] ** 2) - return delta_energy_epigen + poly.r[ind0:indf, :], poly.states, ind0, indf) + density_poly_trial, index_xyz_trial = self._calc_density( + r, states, ind0, indf) + delta_density_poly_total = np.concatenate(( + density_poly_trial, -density_poly)) + delta_index_xyz_total = np.concatenate( + (index_xyz_trial, index_xyz)).astype(int) + delta_density, delta_index_xyz = combine_repeat( + delta_density_poly_total, delta_index_xyz_total) + + dE_marks = 0 + for i, (_, mark_info) in enumerate(self.marks.iterrows()): + dE_marks += 0.5 * mark_info.interaction_energy * np.sum( + ( + delta_density[:, i + 1] + + self.density[delta_index_xyz, i + 1] + ) ** 2 + - self.density[delta_index_xyz, i + 1] ** 2 + ) + return dE_marks def _calc_density(self, r_poly, states, ind0, indf): - num_epigenmark = states.shape[1] + num_marks = states.shape[1] # Find the (0,0,0) bins for the beads and the associated weights - x_poly_box = (r_poly[:, 0] - 0.5 * self.dx - - self.x_width * np.floor((r_poly[:, 0] - 0.5 * self.dx) / self.x_width)) + x_poly_box = (r_poly[:, 0] - 0.5 * self.dx - self.x_width * np.floor( + (r_poly[:, 0] - 0.5 * self.dx) / self.x_width)) index_x = np.floor(self.nx * x_poly_box / self.x_width).astype(int) weight_x = 1 - (x_poly_box / self.dx - index_x) - y_poly_box = (r_poly[:, 1] - 0.5 * self.dy - - self.y_width * np.floor((r_poly[:, 1] - 0.5 * self.dy) / self.y_width)) + y_poly_box = (r_poly[:, 1] - 0.5 * self.dy - self.y_width * np.floor( + (r_poly[:, 1] - 0.5 * self.dy) / self.y_width)) index_y = np.floor(self.ny * y_poly_box / self.y_width).astype(int) weight_y = 1 - (y_poly_box / self.dy - index_y) - z_poly_box = (r_poly[:, 2] - 0.5 * self.dz - - self.z_width * np.floor((r_poly[:, 2] - 0.5 * self.dz) / self.z_width)) + z_poly_box = (r_poly[:, 2] - 0.5 * self.dz - self.z_width * np.floor( + (r_poly[:, 2] - 0.5 * self.dz) / self.z_width)) index_z = np.floor(self.nz * z_poly_box / self.z_width).astype(int) weight_z = 1 - (z_poly_box / self.dz - index_z) - index_x0y0z0 = index_x + self.nx * index_y + self.nx * self.ny * index_z + index_x0y0z0 = index_x + self.nx*index_y + self.nx*self.ny*index_z # Generate the weight array for all of the bins containing the beads + #TODO if you clean this up, please use append instead weight = weight_x * weight_y * weight_z weight = np.concatenate((weight, (1 - weight_x) * weight_y * weight_z)) weight = np.concatenate((weight, weight_x * (1 - weight_y) * weight_z)) @@ -190,6 +327,7 @@ def _calc_density(self, r_poly, states, ind0, indf): weight = np.concatenate((weight, weight_x * (1 - weight_y) * (1 - weight_z))) weight = np.concatenate((weight, (1 - weight_x) * (1 - weight_y) * (1 - weight_z))) + #TODO this can be done in one line index_xyz_total = index_x0y0z0 index_xyz_total = np.concatenate((index_xyz_total, self.bin_index[index_x0y0z0, 1])).astype(int) index_xyz_total = np.concatenate((index_xyz_total, self.bin_index[index_x0y0z0, 2])).astype(int) @@ -199,14 +337,15 @@ def _calc_density(self, r_poly, states, ind0, indf): index_xyz_total = np.concatenate((index_xyz_total, self.bin_index[index_x0y0z0, 6])).astype(int) index_xyz_total = np.concatenate((index_xyz_total, self.bin_index[index_x0y0z0, 7])).astype(int) - density_total = np.zeros((8 * (indf - ind0), num_epigenmark + 1), 'd') + density_total = np.zeros((8 * (indf - ind0), num_marks + 1), 'd') density_total[:, 0] = weight - for ind_epigen in range(num_epigenmark): + for ind_mark in range(num_marks): for ind_corner in range(8): ind_corner0 = ind_corner * (indf - ind0) ind_cornerf = ind_corner0 + indf - ind0 - density_total[ind_corner0:ind_cornerf, ind_epigen + 1] = \ - weight[ind_corner0:ind_cornerf] * states[ind0:indf, ind_epigen] + density_total[ind_corner0:ind_cornerf, ind_mark + 1] = \ + weight[ind_corner0:ind_cornerf] \ + * states[ind0:indf, ind_mark] # Combine repeat entries in the density array density, index_xyz = combine_repeat(density_total, index_xyz_total) diff --git a/chromo/marks.py b/chromo/marks.py index 08c47d1..25c583f 100644 --- a/chromo/marks.py +++ b/chromo/marks.py @@ -9,25 +9,31 @@ appropriate `.Mark` subclass. """ -from dataclasses import dataclass +import dataclasses import inspect import sys -@dataclass +import pandas as pd + + +@dataclasses.dataclass class Mark: - """ - In order for our code to work, all marks need a string name. - """ + """In order for our code to work, all marks need a string name.""" + name: str -@dataclass + +@dataclasses.dataclass class Epigenmark(Mark): """Information about the chemical properties of an epigenetic mark.""" + bind_energy: float interaction_energy: float chemical_potential: float -hp1 = Epigenmark('HP1', bind_energy=1, interaction_energy=1, chemical_potential=1) + +hp1 = Epigenmark('HP1', bind_energy=1, interaction_energy=1, + chemical_potential=1) """ Heterochromatin Protein 1, binds H3K9me marks. @@ -36,7 +42,9 @@ class Epigenmark(Mark): arrive at the values that we actually use. """ + def get_by_name(name): + """Look up saved mark by name.""" all_marks = [obj for name, obj in inspect.getmembers(sys.modules[__name__]) if isinstance(obj, Mark)] matching_marks = [mark for mark in all_marks if mark.name == name] @@ -45,3 +53,31 @@ def get_by_name(name): if len(matching_marks) > 1: raise ValueError(f"More than one mark has the name requested: {name}") return matching_marks[0] + + +def make_mark_collection(marks): + """ + Construct summary DataFrame from sequence of marks. + + Parameters + ---------- + marks : Mark or str or Sequence[Mark] or Sequence[str] + The marks to be summarized by the DataFrame. + + Returns + ------- + pd.DataFrame + Columns are the properties of each Mark. + """ + df = pd.DataFrame(columns=['name', 'bind_energy', 'interaction_energy', + 'chemical_potential']) + if marks is None: + return None + input_type = type(marks) + if input_type is str or issubclass(input_type, Mark): + marks = [marks] # allow the "one mark" case + for mark in marks: + if type(mark) is str: + mark = get_by_name(mark) + df = df.append(dataclasses.asdict(mark), ignore_index=True) + return df diff --git a/chromo/mc/__init__.py b/chromo/mc/__init__.py index 407ac78..366d15a 100644 --- a/chromo/mc/__init__.py +++ b/chromo/mc/__init__.py @@ -1,14 +1,15 @@ """Monte Carlo simulations of a discrete wormlike chain.""" from pathlib import Path - -import numpy as np +import warnings from .mc_sim import mc_sim from .moves import all_moves +from ..util.reproducibility import make_reproducible -def polymer_in_field(polymers, epigenmarks, field, num_mc_steps, num_save_mc, - mc_moves=None, output_dir='.'): +@make_reproducible +def polymer_in_field(polymers, marks, field, num_save_mc, num_saves, + mc_moves=None, random_seed=0, output_dir='.'): """ Monte Carlo simulation of a tssWLC in a field. @@ -18,10 +19,10 @@ def polymer_in_field(polymers, epigenmarks, field, num_mc_steps, num_save_mc, Parameters ---------- polymers : Sequence[Polymer] - The polymers to be simulated. Epigenetic marks, discretization, and - other parameters should be specified before input. - epigenmarks : Sequence[Epigenmark] - DEPRECATED. Should be integrated into the "Polymer" class. + The polymers to be simulated. + epigenmarks : `pd.DataFrame` + Output of `chromo.marks.make_mark_collection`. Summarizes the energetic + properties of each chemical modification. field : Field The discretization of space in which to simulate the polymers. num_save_mc : int @@ -31,11 +32,12 @@ def polymer_in_field(polymers, epigenmarks, field, num_mc_steps, num_save_mc, output_dir : Optional[Path], default: '.' Directory in which to save the simulation output. """ + warnings.warn("The random seed is currently ignored.", UserWarning) if mc_moves is None: mc_moves = all_moves # Perform Monte Carlo simulation for each save file - for mc_count in range(num_save_mc): - mc_sim(polymers, epigenmarks, num_mc_steps, mc_moves, field) + for mc_count in range(num_saves): + mc_sim(polymers, marks, num_save_mc, mc_moves, field) for poly in polymers: - poly.write_repr(output_dir / Path(f"{poly.name}-{mc_count}.npz")) + poly.to_csv(output_dir / Path(f"{poly.name}-{mc_count}.csv")) print("Save point " + str(mc_count) + " completed") diff --git a/chromo/mc/mc_sim.py b/chromo/mc/mc_sim.py index 2dafdb7..e4a06b5 100644 --- a/chromo/mc/mc_sim.py +++ b/chromo/mc/mc_sim.py @@ -23,7 +23,7 @@ def mc_step(adaptible_move, poly, epigenmarks, field): if np.random.rand() < np.exp(-dE): adaptible_move.accept() poly.r[ind0:indf, :] = r - poly.t_3[ind0:indf, :] = t3 - poly.t_2[ind0:indf, :] = t2 + poly.t3[ind0:indf, :] = t3 + poly.t2[ind0:indf, :] = t2 poly.states[ind0:indf, :] = states return diff --git a/chromo/mc/moves.py b/chromo/mc/moves.py index 6290ef3..d510c02 100644 --- a/chromo/mc/moves.py +++ b/chromo/mc/moves.py @@ -95,7 +95,7 @@ def crank_shaft_move(polymer, amp_move, amp_bead): rot_angle = amp_move * (np.random.rand() - 0.5) if ind0 == (indf + 1): - delta_t3 = polymer.t_3[ind0, :] + delta_t3 = polymer.t3[ind0, :] else: delta_t3 = polymer.r[indf - 1, :] - polymer.r[ind0, :] delta_t3 /= np.linalg.norm(delta_t3) @@ -129,7 +129,7 @@ def crank_shaft_move(polymer, amp_move, amp_bead): t3_poly_trial = np.zeros((indf - ind0, 3), 'd') for i_bead in range(ind0, indf): r_poly_trial[i_bead - ind0, :] = rot_vector + np.matmul(rot_matrix, polymer.r[i_bead, :]) - t3_poly_trial[i_bead - ind0, :] = np.matmul(rot_matrix, polymer.t_3[i_bead, :]) + t3_poly_trial[i_bead - ind0, :] = np.matmul(rot_matrix, polymer.t3[i_bead, :]) return ind0, indf, r_poly_trial, t3_poly_trial, None, None all_moves = [MCAdapter(move) for move in [crank_shaft_move]] diff --git a/chromo/util/reproducibility.py b/chromo/util/reproducibility.py index 14ed934..be45289 100644 --- a/chromo/util/reproducibility.py +++ b/chromo/util/reproducibility.py @@ -16,8 +16,10 @@ """ from pathlib import Path import inspect +import collections import pandas as pd +import numpy as np # get version number (includes commit hash) from versioneer from .._version import get_versions @@ -37,9 +39,11 @@ def make_reproducible(sim): f""" Decorator for automagically making simulations reproducible. - Requires every input to the function to have a __repr__ that is actually - useful, and that the wrapped function has a keyword argument with name - {output_dir_param_name}. Also requires you to pass a "random_seed" kwarg. + Requires every non-builtin input to the function to implement a + ``.to_file`` method and a ``.name`` attribute. These will be used to save + the state of the simulation's input to the output folder. The wrapped + function must have a keyword argument with name {output_dir_param_name}. + Also requires you to pass a "random_seed" kwarg. The versioneer version (including a commit hash if necessary), the date/time, a unique folder name where the simulation inputs and output will @@ -73,11 +77,11 @@ def make_reproducible(sim): ├── paramN └── (Any output of simulator goes here) """ - params = inspect.signature(sim) + params = inspect.signature(sim).parameters if "random_seed" not in params: raise ValueError("Requires the random seed to be passed in explicitly," - " even if the random generator is passed to the " - "function as well.") + " even if the random generator is passed to the" + " function as well.") if output_dir_param_name not in params: raise ValueError(f"Could not wrap simulation function: {sim}\n" f"Missing required kwarg: {output_dir_param_name}.") @@ -95,14 +99,21 @@ def wrapper(*args, **kwargs): kwargs[output_dir_param_name] = output_subfolder # get the inputs that can be simply saved in our CSV file simple_params, hard_params = split_builtin_params(sim, *args, **kwargs) + # add the extra outputs that we promise users + simple_params['version'] = __version__ + simple_params['start_time'] = pd.Timestamp.now() # append to the CSV file, unless it doesn't exist - # TODO make thread-safe - sim_tracker = output_subfolder / sim_tracker_name + sim_tracker = outdir / sim_tracker_name + # TODO make writing header thread-safe header = not sim_tracker.exists() simple_params = pd.DataFrame(pd.Series(simple_params)).T simple_params.to_csv(sim_tracker, header=header, index=False, mode='a') - # TODO add support for non-simple params - return sim(*args, **kwargs) + # the remaining parameters should implement `.to_file`/`.from_file`. + to_file_params(hard_params, output_subfolder) + sim_out = sim(*args, **kwargs) + with open(output_subfolder / Path('__completion_timestamp__')) as f: + f.write(str(pd.Timestamp.now())) + return sim_out return wrapper @@ -111,8 +122,15 @@ def wrapper(*args, **kwargs): # builtin_types = tuple(getattr(builtins, t) for t in dir(builtins) # if isinstance(getattr(builtins, t), type)) builtin_types = [bool, bytes, bytearray, complex, float, int, str] -# the additional types are not allowed by default because they make loading in -# the CSV a little trickier +""" +Types to be saved as CSV entries by default. + +These are basically just the built-ins that permit simple save/load cycling via +CSV entries with Pandas. Some extras are included in the split_builtin_params +function itself. Please see that code for a full description. +""" +# these additional types are not allowed by default because they make loading +# in the CSV a little trickier # ..., frozenset, tuple] @@ -121,7 +139,8 @@ def split_builtin_params(sim, *args, **kwargs): builtin_args = {} non_builtin = {} for arg_name, value in sig.arguments.items(): - if type(value) in builtin_types: + dtype = type(value) + if dtype in builtin_types or issubclass(dtype, Path): builtin_args[arg_name] = value else: non_builtin[arg_name] = value @@ -157,3 +176,36 @@ def get_unique_subfolder(root): except: i += 1 return folder_name + + +def to_file_params(non_builtins_kwargs, folder, suffix=''): + """ + Call ``.to_file`` for each parameter, handling sequences. + + Parameters + ---------- + non_builtins_kwargs : Dict[str, RoundTrippable] + A RoundTrippable must implement the + ``.name``/``.to_file``/``.from_file`` interface, or be a standard type, + such as a numpy array or a DataFrame. + folder : Path + The folder to save the output to. + """ + for arg_name, value in non_builtins_kwargs.items(): + dtype = type(value) + if isinstance(value, collections.Sequence): + for i, data in enumerate(value): + to_file_params({arg_name: data}, folder, str(i)) + elif hasattr(value, 'to_file'): + value.to_file(folder / Path(value.name + suffix)) + elif issubclass(dtype, pd.DataFrame) or issubclass(dtype, pd.Series): + value.to_csv(folder / Path(arg_name + suffix)) + elif issubclass(dtype, np.ndarray): + np.savetxt(folder / Path(arg_name + suffix), value) + else: + raise ValueError(f"Argument not understood: {arg_name}={value}.\n" + "This simulation cannot be made reproducible.\n" + f"Please implement `.to_file` for type: {dtype}.") + + + diff --git a/tests/test_components.py b/tests/test_components.py new file mode 100644 index 0000000..2ce3d56 --- /dev/null +++ b/tests/test_components.py @@ -0,0 +1,14 @@ +from io import StringIO + +from pandas.testing import assert_frame_equal +import numpy as np + +from chromo.components import Polymer + + +def test_polymer_saving(): + p = Polymer.straight_line_in_x('Chr-1', 10, 1, states=np.zeros((10,)), + mark_names=['HP1']) + df = p.from_file(StringIO(p.to_file(None)), 'Chr-1').to_dataframe() + df_pre_round_trip = p.to_dataframe() + assert_frame_equal(df, df_pre_round_trip) diff --git a/tests/test_fields.py b/tests/test_fields.py new file mode 100644 index 0000000..04b39aa --- /dev/null +++ b/tests/test_fields.py @@ -0,0 +1,49 @@ +from io import StringIO + +import numpy as np +import pandas as pd +import pytest + +from chromo.components import Polymer +from chromo.fields import UniformDensityField +import chromo.marks + + +def test_uniform_density_field_roundtrip(): + marks = [chromo.marks.get_by_name('HP1')] + marks = chromo.marks.make_mark_collection(marks) + + p = Polymer.straight_line_in_x('Chr-1', 10, 1, states=np.zeros((10,)), + mark_names=['HP1']) + + udf = UniformDensityField([p], marks, 10, 20, 30, 40, 50, 60) + udf_round_trip = UniformDensityField.from_file( + StringIO(udf.to_file(None)), [p], marks + ) + assert udf == udf_round_trip + + # ensure the code errors if the wrong number of polymers or marks is passed + with pytest.raises(ValueError): + UniformDensityField.from_file( + StringIO(udf.to_file(None)), [], marks + ) + with pytest.raises(ValueError): + UniformDensityField.from_file( + StringIO(udf.to_file(None)), [p, p], marks + ) + with pytest.raises(ValueError): + UniformDensityField.from_file( + StringIO(udf.to_file(None)), [p], pd.concat([marks, marks]) + ) + + # should also error if the poly/mark has the wrong name + with pytest.raises(ValueError): + p.name = 'different' + UniformDensityField.from_file( + StringIO(udf.to_file(None)), [p], marks + ) + with pytest.raises(ValueError): + marks.loc[0, 'name'] = 'different' + UniformDensityField.from_file( + StringIO(udf.to_file(None)), [p], marks + ) From e86bbbf6091293c941c61ae4014ea2a8239e5714 Mon Sep 17 00:00:00 2001 From: Bruno Beltran Date: Sun, 13 Sep 2020 11:47:22 -0700 Subject: [PATCH 03/15] DOCS/EXAMPLE: an simpler mc simulation example --- chromo/mc/__init__.py | 32 ++++- chromo/util/reproducibility.py | 8 +- doc/source/mc.ipynb | 211 +++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 6 deletions(-) create mode 100644 doc/source/mc.ipynb diff --git a/chromo/mc/__init__.py b/chromo/mc/__init__.py index 366d15a..8f1af93 100644 --- a/chromo/mc/__init__.py +++ b/chromo/mc/__init__.py @@ -2,19 +2,42 @@ from pathlib import Path import warnings +import numpy as np + from .mc_sim import mc_sim from .moves import all_moves from ..util.reproducibility import make_reproducible +from ..components import Polymer +from ..marks import get_by_name, make_mark_collection +from ..fields import UniformDensityField @make_reproducible -def polymer_in_field(polymers, marks, field, num_save_mc, num_saves, - mc_moves=None, random_seed=0, output_dir='.'): +def simple_mc(num_polymers, num_beads, bead_length, num_marks, num_save_mc, + num_saves, x_width, nx, y_width, ny, z_width, nz, random_seed=0, + output_dir='.'): + polymers = [ + Polymer.straight_line_in_x( + f'Polymer-{i}', num_beads, bead_length, + states=np.zeros((num_beads, num_marks)), + mark_names=num_marks*['HP1'] + ) for i in range(num_polymers) + ] + marks = [get_by_name('HP1') for i in range(num_marks)] + marks = make_mark_collection(marks) + field = UniformDensityField(polymers, marks, x_width, nx, y_width, ny, + z_width, nz) + return _polymer_in_field(polymers, marks, field, num_save_mc, num_saves, + random_seed=random_seed, output_dir=output_dir) + + +def _polymer_in_field(polymers, marks, field, num_save_mc, num_saves, + mc_moves=None, random_seed=0, output_dir='.'): """ Monte Carlo simulation of a tssWLC in a field. This example code can be used to understand how to call the codebase, or - run directly for simple simulations. See the documentation for the + run directly for simple simulations. Parameters ---------- @@ -41,3 +64,6 @@ def polymer_in_field(polymers, marks, field, num_save_mc, num_saves, for poly in polymers: poly.to_csv(output_dir / Path(f"{poly.name}-{mc_count}.csv")) print("Save point " + str(mc_count) + " completed") + + +polymer_in_field = make_reproducible(_polymer_in_field) diff --git a/chromo/util/reproducibility.py b/chromo/util/reproducibility.py index be45289..adb30ba 100644 --- a/chromo/util/reproducibility.py +++ b/chromo/util/reproducibility.py @@ -94,8 +94,10 @@ def wrapper(*args, **kwargs): "no default value can be found.") kwargs[output_dir_param_name] = outdir_param.default # get a new folder to save simulation into in a thread-safe way - outdir = kwargs[output_dir_param_name] - output_subfolder = get_unique_subfolder(Path(outdir)/sim_folder_prefix) + outdir = Path(kwargs[output_dir_param_name]) + # make the requested base output folder first if it doesn't exist tho.. + outdir.mkdir(parents=True, exist_ok=True) + output_subfolder = get_unique_subfolder(outdir / sim_folder_prefix) kwargs[output_dir_param_name] = output_subfolder # get the inputs that can be simply saved in our CSV file simple_params, hard_params = split_builtin_params(sim, *args, **kwargs) @@ -111,7 +113,7 @@ def wrapper(*args, **kwargs): # the remaining parameters should implement `.to_file`/`.from_file`. to_file_params(hard_params, output_subfolder) sim_out = sim(*args, **kwargs) - with open(output_subfolder / Path('__completion_timestamp__')) as f: + with open(output_subfolder / Path('__completion_time__'), 'w') as f: f.write(str(pd.Timestamp.now())) return sim_out return wrapper diff --git a/doc/source/mc.ipynb b/doc/source/mc.ipynb new file mode 100644 index 0000000..72442f2 --- /dev/null +++ b/doc/source/mc.ipynb @@ -0,0 +1,211 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How to use MC simulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main entry point for MC simulation in the current code base is currently found in `chromo.mc.polymer_in_field`. This file shows the basic usage of that function." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import importlib\n", + "from io import StringIO\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "import chromo\n", + "import chromo.mc as mc\n", + "from chromo.components import Polymer\n", + "import chromo.marks\n", + "from chromo.fields import UniformDensityField" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First specify what epigenetic marks should be used." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "epimarks = [chromo.marks.get_by_name('HP1')]\n", + "#or just e.g. epimarks = [chromo.marks.hp1]\n", + "# making it a list is optional since there's only one element" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Epigenmark(name='HP1', bind_energy=1, interaction_energy=1, chemical_potential=1)]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "epimarks" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "They are expected in a DataFrame format." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "marks = chromo.marks.make_mark_collection(epimarks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now specify the initial state of the polymer(s). We will use just one here." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "p = Polymer.straight_line_in_x('Chr-1', 10, 1, states=np.zeros((10,)), mark_names=['HP1'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally create a field object to contain the polymers." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "udf = UniformDensityField([p], marks, 10, 20, 30, 40, 50, 60)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As per the docs of `chromo.util.reproducibility.make_reproducible`, check the `simulations.csv` file in the requested output folder (i.e. `{current working directory of this Notebook}/{output_dir}`) to see information about all simulations that have been run so far.\n", + "\n", + "All inputs are saved in the output folder as well, for exact reproducibility." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/bbeltr1/developer/chromo/chromo/mc/__init__.py:58: UserWarning: The random seed is currently ignored.\n", + " warnings.warn(\"The random seed is currently ignored.\", UserWarning)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Save point 0 completed\n", + "Save point 1 completed\n", + "Save point 2 completed\n", + "Save point 3 completed\n", + "Save point 4 completed\n", + "Save point 5 completed\n", + "Save point 6 completed\n", + "Save point 7 completed\n", + "Save point 8 completed\n", + "Save point 9 completed\n" + ] + } + ], + "source": [ + "mc.polymer_in_field([p], marks, udf, 1000, 10, output_dir='output')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's an alternative implementation that takes only \"simple\" inputs:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mc.simple_mc(num_polymers=5, num_beads=10, bead_length=1, num_marks=2, num_save_mc=1000, num_saves=10,\n", + " x_width=10, nx=1, y_width=10, ny=1, z_width=10, nz=1, random_seed=0, output_dir='output_simple')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From a5191f5d74570049b1034ae083471eedca382782 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Thu, 17 Sep 2020 12:51:37 -0700 Subject: [PATCH 04/15] Updated source directory --- .idea/.gitignore | 2 + .idea/chromo.iml | 15 +++++++ .../inspectionProfiles/profiles_settings.xml | 6 +++ .idea/misc.xml | 7 ++++ .idea/modules.xml | 8 ++++ .idea/vcs.xml | 6 +++ chromo/mc/moves.py | 2 + {doc/source => source}/mc.ipynb | 42 ++++++++++++------- 8 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/chromo.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml rename {doc/source => source}/mc.ipynb (89%) diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..e7e9d11 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml diff --git a/.idea/chromo.iml b/.idea/chromo.iml new file mode 100644 index 0000000..4f2c9af --- /dev/null +++ b/.idea/chromo.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7a85af6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ea896ee --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chromo/mc/moves.py b/chromo/mc/moves.py index d510c02..14154b7 100644 --- a/chromo/mc/moves.py +++ b/chromo/mc/moves.py @@ -7,6 +7,7 @@ import numpy as np + class MCAdapter: """ Track success rate and adjust parameters for a Monte Carlo move. @@ -133,3 +134,4 @@ def crank_shaft_move(polymer, amp_move, amp_bead): return ind0, indf, r_poly_trial, t3_poly_trial, None, None all_moves = [MCAdapter(move) for move in [crank_shaft_move]] + diff --git a/doc/source/mc.ipynb b/source/mc.ipynb similarity index 89% rename from doc/source/mc.ipynb rename to source/mc.ipynb index 72442f2..a915c00 100644 --- a/doc/source/mc.ipynb +++ b/source/mc.ipynb @@ -20,6 +20,9 @@ "metadata": {}, "outputs": [], "source": [ + "import sys\n", + "sys.path.insert(1, '../..')\n", + "\n", "import importlib\n", "from io import StringIO\n", "\n", @@ -80,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -96,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -112,7 +115,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -130,17 +133,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 10, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/bbeltr1/developer/chromo/chromo/mc/__init__.py:58: UserWarning: The random seed is currently ignored.\n", - " warnings.warn(\"The random seed is currently ignored.\", UserWarning)\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -171,9 +166,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Save point 0 completed\n", + "Save point 1 completed\n", + "Save point 2 completed\n", + "Save point 3 completed\n", + "Save point 4 completed\n", + "Save point 5 completed\n", + "Save point 6 completed\n", + "Save point 7 completed\n", + "Save point 8 completed\n", + "Save point 9 completed\n" + ] + } + ], "source": [ "mc.simple_mc(num_polymers=5, num_beads=10, bead_length=1, num_marks=2, num_save_mc=1000, num_saves=10,\n", " x_width=10, nx=1, y_width=10, ny=1, z_width=10, nz=1, random_seed=0, output_dir='output_simple')" @@ -203,7 +215,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.7.6" } }, "nbformat": 4, From aac25d534099d73f2db17468f331a5f7cf4bd642 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Thu, 17 Sep 2020 13:43:39 -0700 Subject: [PATCH 05/15] API initiated --- doc/Makefile | 20 + doc/make.bat | 35 + doc/source/bd_sim.rst | 108 +++ doc/source/conf.py | 71 ++ doc/source/field.rst | 69 ++ doc/source/figures/weight.ai | 1119 ++++++++++++++++++++++++++++++++ doc/source/figures/weight.pdf | Bin 0 -> 150504 bytes doc/source/index.rst | 27 + doc/source/poly_models.rst | 186 ++++++ doc/source/references.rst | 40 ++ notes/chromo-derive.log | 6 +- notes/chromo-derive.pdf | Bin 188127 -> 189721 bytes notes/chromo-derive.synctex.gz | Bin 15108 -> 15802 bytes 13 files changed, 1678 insertions(+), 3 deletions(-) create mode 100644 doc/Makefile create mode 100644 doc/make.bat create mode 100644 doc/source/bd_sim.rst create mode 100644 doc/source/conf.py create mode 100644 doc/source/field.rst create mode 100644 doc/source/figures/weight.ai create mode 100644 doc/source/figures/weight.pdf create mode 100644 doc/source/index.rst create mode 100644 doc/source/poly_models.rst create mode 100644 doc/source/references.rst diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..6247f7e --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/bd_sim.rst b/doc/source/bd_sim.rst new file mode 100644 index 0000000..3c25322 --- /dev/null +++ b/doc/source/bd_sim.rst @@ -0,0 +1,108 @@ +.. _bd_sim: + +Brownian Dynamics Simulations +============================= + +Langevin equation for translation and rotation +---------------------------------------------- + +We consider a discrete chain of :math:`n_{b}` beads with positions :math:`\vec{r}^{(n)}` and orientation triad :math:`\vec{t}_{i}^{(n)}`, +where the bead index :math:`n` runs from 0 to :math:`n_{b}-1`. +We consider a general potential energy :math:`E = E( \{ \vec{r}, \vec{t}_{i} \} )`, where :math:`\{ \vec{r}, \vec{t}_{i} \}` indicates +the full set of positions and orientations. +Since the orientation triad forms an orthonormal basis, the dynamics must maintain the following conditions: + +.. math:: + \vec{t}_{i}^{(n)} \cdot \vec{t}_{j}^{(n)} = \delta_{ij} + +.. \label{eq:constraint} + +for all :math:`i,j` pairs. +These conditions are enforced through Lagrange constraints. Thus, we define the constrained energy + +.. math:: + E_{\lambda} ( \{ \vec{r}, \vec{t}_{i} \} ) = E( \{ \vec{r}, \vec{t}_{i} \} ) - + \sum_{n=0}^{n_{b}-1} \sum_{i,j = 1}^{3} + \frac{\lambda_{ij}}{2} + \left( + \vec{t}_{i}^{(n)} \cdot \vec{t}_{j}^{(n)} - \delta_{ij} + \right) + +We define the potential forces and torques on the beads to be + +.. math:: + \vec{f}_{E}^{(n)} & = & - \frac{\partial E}{\partial \vec{r}^{(n)}} \\ + \vec{\tau}_{E,i}^{(n)} & = & - \frac{\partial E}{\partial \vec{t}_{i}^{(n)}} + +The Langevin equation for the bead positions is given by + +.. math:: + \xi_{r} \frac{\partial \vec{r}^{(n)}}{\partial t} = \vec{f}_{E}^{(n)} + \vec{f}_{B}^{(n)} + +where :math:`\vec{f}_{B}^{(n)}` is a Brownian force (discussed below). + +The Langevin equation for the orientation triad must resolve the orthonormal constraints. This leads to the three Langevin equations + +.. math:: + \xi_{t,i} \frac{\partial \vec{t}_{i}^{(n)}}{\partial t} = \vec{\tau}_{E,i}^{(n)} + \vec{\tau}_{B,i}^{(n)} + + \sum_{j=1}^{3} \lambda_{ij} \vec{t}_{j}^{(n)} + +The Lagrange constraints are satisfied by setting the time derivative of Eq.~\ref{eq:constraint} = 0, +or we have + +.. math:: + \vec{t}_{i}^{(n)} \cdot \frac{\partial \vec{t}_{j}^{(n)}}{\partial t} + + \vec{t}_{j}^{(n)} \cdot \frac{\partial \vec{t}_{i}^{(n)}}{\partial t} = 0 + +This leads to the solution to the Lagrange multipliers to be + +.. math:: + \lambda_{ij} = - \left( \xi_{t,i} + \xi_{t,j} \right)^{-1} + \left[ + \xi_{t,i} \vec{t}_{i}^{(n)} \cdot \left( \vec{\tau}_{E,j}^{(n)} + \vec{\tau}_{B,j}^{(n)} \right) + + \xi_{t,j} \vec{t}_{j}^{(n)} \cdot \left( \vec{\tau}_{E,i}^{(n)} + \vec{\tau}_{B,i}^{(n)} \right) + \right] + +With this development, we now write the Langevin equations as + +.. math:: + \xi_{t,1} \frac{\partial \vec{t}_{1}^{(n)}}{\partial t} & = & + \frac{\xi_{t,1}}{\xi_{t,1}+\xi_{t,2}} + \left[ + \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,1}^{(n)} + \vec{\tau}_{B,1}^{(n)} \right) - + \vec{t}_{1}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) + \right] \vec{t}_{2}^{(n)} + + \nonumber \\ + & & + \frac{\xi_{t,1}}{\xi_{t,1}+\xi_{t,3}} + \left[ + \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,1}^{(n)} + \vec{\tau}_{B,1}^{(n)} \right) - + \vec{t}_{1}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) + \right] \vec{t}_{3}^{(n)} \\ + \xi_{t,2} \frac{\partial \vec{t}_{2}^{(n)}}{\partial t} & = & + \frac{\xi_{t,2}}{\xi_{t,1}+\xi_{t,2}} + \left[ + \vec{t}_{1}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) - + \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,1}^{(n)} + \vec{\tau}_{B,1}^{(n)} \right) + \right] \vec{t}_{1}^{(n)} + + \nonumber \\ + & & + \frac{\xi_{t,2}}{\xi_{t,2}+\xi_{t,3}} + \left[ + \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) - + \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) + \right] \vec{t}_{3}^{(n)} \\ + \xi_{t,3} \frac{\partial \vec{t}_{3}^{(n)}}{\partial t} & = & + \frac{\xi_{t,3}}{\xi_{t,1}+\xi_{t,3}} + \left[ + \vec{t}_{1}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) - + \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,1}^{(n)} + \vec{\tau}_{B,1}^{(n)} \right) + \right] \vec{t}_{1}^{(n)} + + \nonumber \\ + & & + \frac{\xi_{t,3}}{\xi_{t,2}+\xi_{t,3}} + \left[ + \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) - + \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) + \right] \vec{t}_{2}^{(n)} + diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..59bb2d3 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,71 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../')) +sys.path.insert(1, os.path.abspath('../../')) + +# -- Project information ----------------------------------------------------- + +project = 'chromo' +copyright = '2020, Andy Spakowitz, Bruno Beltran, Joe Wakim' +author = 'Andy Spakowitz, Bruno Beltran, Joe Wakim' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'nbsphinx', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinx.ext.napoleon', + 'sphinx.ext.intersphinx', + 'sphinx.ext.githubpages', + 'matplotlib.sphinxext.plot_directive' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'nature' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Autodoc settings +autosummary_generate = True + +# Napoleon settings +napoleon_google_docstring = False +napoleon_numpy_docstring = True diff --git a/doc/source/field.rst b/doc/source/field.rst new file mode 100644 index 0000000..aa682da --- /dev/null +++ b/doc/source/field.rst @@ -0,0 +1,69 @@ +.. _field: + + +Field-Theoretic Treatment of Interactions +========================================= + +Our treatment of interactions uses a field-theoretic treatment of the densities to determine the interactions between polymer +segments. Following work by Pike, et al. (Refs. [Pike2009a]_, [Pike2009b]_), +we define + +The simulation has a fixed volume with sides lengths :math:`L_{x}`, :math:`L_{y}`, and :math:`L_{z}`. +These lengths are discretize into :math:`M_{x}`, :math:`M_{y}`, and :math:`M_{z}` bins of length +:math:`\Delta_{x} = L_{x}/M_{x}`, +:math:`\Delta_{y} = L_{y}/M_{y}`, and +:math:`\Delta_{z} = L_{z}/M_{z}`. +The bins are defined by the three indices +:math:`i_{x}`, +:math:`i_{y}`, and +:math:`i_{z}` that run from zero to +:math:`M_{x}-1`, +:math:`M_{y}-1`, and +:math:`M_{z}-1`, respectively. + + +We consider the :math:`n`th bead located at position :math:`\vec{r}^{(n)}`. +We define a weight function :math:`w_{I}(\vec{r}^{(n)})` within the :math:`I`th bin. +The :math:`I`th index is defined to be a superindex that combines +:math:`i_{x}`, +:math:`i_{y}`, and +:math:`i_{z}` into a single unique index :math:`I= i_{x} + M_{x} i_{y} + M_{x}M_{z} i_{z}` that +runs from zero to :math:`M_{x}M_{y}M_{z}-1` (total of :math:`M_{x}M_{y}M_{z}` unique indices) +The total weight on the :math:`I`th bin is given by the contributions from the three cartesian +directions, \emph{i.e.} +:math:`w_{I}(\vec{r}^{(n)}) = +w_{i_{x}}^{(x)}(x^{(n)}) +w_{i_{y}}^{(y)}(y^{(n)}) +w_{i_{z}}^{(z)}(z^{(n)})`. +Figure~\ref{fig:weight} shows a schematic of the :math:`x`-direction weight function (same method for :math:`y` and :math:`z`). +This shows a linear interpolation weighting method, consistent with Refs. [Pike2009a]_, [Pike2009b]_. + +.. figure:: figures/weight.pdf + :width: 600 + :align: center + :alt: Schematic of the weight function :math:`w_{i_{x}}^{(x)}` that gives the weighting of the particle in the :math:`i_{x}` site in the + :math:`x`-direction based on a linear interpolation method + + Schematic of the weight function :math:`w_{i_{x}}^{(x)}` that gives the weighting of the particle in the :math:`i_{x}` site in the + :math:`x`-direction based on a linear interpolation method + + +The number of epigenetic proteins (\emph{e.g.} HP1) to the :math:`n`th site is given by :math:`N_{I}^{(\alpha)}`, where :math:`\alpha` determines +the type of epigenetic mark. +The :math:`\alpha`-protein density within the :math:`I`th bin is given by + +.. math:: + \rho_{I}^{(\alpha)} = \frac{1}{v_{\mathrm{bin}}} \sum_{n=0}^{n_{b} - 1} w_{I}(\vec{r}^{(n)}) N_{I}^{(\alpha)} + +where :math:`v_{\mathrm{bin}} = \Delta_{x} \Delta_{y} \Delta_{z}` is the volume of a bin. +The maximum number of epigenetic proteins bound :math:`N_{\mathrm{max}}^{(\alpha)}` gives an upper bound on the +number of proteins that can bind to a bead, accounting for coarse graining of a bead to represent multiple nucleosomes. +For discretization of one nucleosome per bead, the maximum :math:`N_{\mathrm{max}}^{(\alpha)} = 2` implies binding +of a protein to the two histone tail proteins for the :math:`\alpha` epigenetic mark. +We define the number of :math:`\alpha` marks on the :math:`I`th bead as :math:`M_{I}^{(\alpha)}`, which can take values from zero +to :math:`N_{\mathrm{max}}^{(\alpha)}`. + +Protein binding to a marked tail results in energy :math:`-\beta \epsilon_{m}` [non-dimensionalized by :math:`\beta = 1/(k_{B}T)`], and protein binding to an unmarked tail is associated with +energy :math:`-\beta \epsilon_{u}`. The chemical potential of the :math:`\alpha` protein is defined as :math:`\beta \mu^{(\alpha)}`. +The binding of :math:`N_{I}^{(\alpha)}` proteins to a bead with :math:`M_{I}^{(\alpha)}` marks results in a free energy that +accounts for all of the combinatoric ways of binding. diff --git a/doc/source/figures/weight.ai b/doc/source/figures/weight.ai new file mode 100644 index 0000000..840f5d3 --- /dev/null +++ b/doc/source/figures/weight.ai @@ -0,0 +1,1119 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[23 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + weight + + + Adobe Illustrator 24.1 (Macintosh) + 2020-08-02T19:05:18-07:00 + 2020-08-02T19:05:18-07:00 + 2020-08-02T19:05:18-07:00 + + + + 256 + 52 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgANAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYqlv+ItLXV20m aQwXuxhWZSizAgH9yx+F6VoQN8VTLFXYq7FXYq7FWJeY/wA0fKfl9i169xLaRSCO/v7S3kubazqD RrmSINwWooTvQ9aYqyXT9QsNRsob7T7iO7srhQ8FzA6yRup6FWUkEYqiMVY/5284W3lPTbbVL2Ll pz3cNrfXBfgLeOeqLLTi3L97wSlR9qtdqFV5Za/mx5i8/aro+l+WFfQdXNrNcXCyyGWOC8jmMM0V wvpUkSCKM1VgOTTR04kc1Vep+SIdfh0iZdbMhuTd3DQ+tIJZPSaQkVcKnwluRQcVohUcVpxCq3zd 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 l8fWn2cVf//Z + + + + uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7 + xmp.did:fe646f74-ee7e-4b6e-92b8-1740a48566ef + uuid:b5a937fd-0226-ef46-b8bd-32e27ebcdfcb + proof:pdf + + uuid:eab21be5-e766-664f-af13-7ab4a523d93d + xmp.did:cc4dc041-9a60-4315-bc5d-7e2d77be13d2 + uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7 + proof:pdf + + + + + saved + xmp.iid:fe646f74-ee7e-4b6e-92b8-1740a48566ef + 2020-08-02T16:40:33-07:00 + Adobe Illustrator 24.1 (Macintosh) + / + + + + Basic RGB + Document + AIRobin + 1 + False + False + + 6.000000 + 3.000000 + Inches + + + + + ChalkboardSE-Regular + Chalkboard SE + Regular + TrueType + 13.0d1e2 + False + ChalkboardSE.ttc + + + MyriadPro-Regular + Myriad Pro + Regular + Open Type + Version 2.106;PS 2.000;hotconv 1.0.70;makeotf.lib2.5.58329 + False + MyriadPro-Regular.otf + + + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 0 + 0 + 0 + + + RGB Red + RGB + PROCESS + 255 + 0 + 0 + + + RGB Yellow + RGB + PROCESS + 255 + 255 + 0 + + + RGB Green + RGB + PROCESS + 0 + 255 + 0 + + + RGB Cyan + RGB + PROCESS + 0 + 255 + 255 + + + RGB Blue + RGB + PROCESS + 0 + 0 + 255 + + + RGB Magenta + RGB + PROCESS + 255 + 0 + 255 + + + R=193 G=39 B=45 + RGB + PROCESS + 193 + 39 + 45 + + + R=237 G=28 B=36 + RGB + PROCESS + 237 + 28 + 36 + + + R=241 G=90 B=36 + RGB + PROCESS + 241 + 90 + 36 + + + R=247 G=147 B=30 + RGB + PROCESS + 247 + 147 + 30 + + + R=251 G=176 B=59 + RGB + PROCESS + 251 + 176 + 59 + + + R=252 G=238 B=33 + RGB + PROCESS + 252 + 238 + 33 + + + R=217 G=224 B=33 + RGB + PROCESS + 217 + 224 + 33 + + + R=140 G=198 B=63 + RGB + PROCESS + 140 + 198 + 63 + + + R=57 G=181 B=74 + RGB + PROCESS + 57 + 181 + 74 + + + R=0 G=146 B=69 + RGB + PROCESS + 0 + 146 + 69 + + + R=0 G=104 B=55 + RGB + PROCESS + 0 + 104 + 55 + + + R=34 G=181 B=115 + RGB + PROCESS + 34 + 181 + 115 + + + R=0 G=169 B=157 + RGB + PROCESS + 0 + 169 + 157 + + + R=41 G=171 B=226 + RGB + PROCESS + 41 + 171 + 226 + + + R=0 G=113 B=188 + RGB + PROCESS + 0 + 113 + 188 + + + R=46 G=49 B=146 + RGB + PROCESS + 46 + 49 + 146 + + + R=27 G=20 B=100 + RGB + PROCESS + 27 + 20 + 100 + + + R=102 G=45 B=145 + RGB + PROCESS + 102 + 45 + 145 + + + R=147 G=39 B=143 + RGB + PROCESS + 147 + 39 + 143 + + + R=158 G=0 B=93 + RGB + PROCESS + 158 + 0 + 93 + + + R=212 G=20 B=90 + RGB + PROCESS + 212 + 20 + 90 + + + R=237 G=30 B=121 + RGB + PROCESS + 237 + 30 + 121 + + + R=199 G=178 B=153 + RGB + PROCESS + 199 + 178 + 153 + + + R=153 G=134 B=117 + RGB + PROCESS + 153 + 134 + 117 + + + R=115 G=99 B=87 + RGB + PROCESS + 115 + 99 + 87 + + + R=83 G=71 B=65 + RGB + PROCESS + 83 + 71 + 65 + + + R=198 G=156 B=109 + RGB + PROCESS + 198 + 156 + 109 + + + R=166 G=124 B=82 + RGB + PROCESS + 166 + 124 + 82 + + + R=140 G=98 B=57 + RGB + PROCESS + 140 + 98 + 57 + + + R=117 G=76 B=36 + RGB + PROCESS + 117 + 76 + 36 + + + R=96 G=56 B=19 + RGB + PROCESS + 96 + 56 + 19 + + + R=66 G=33 B=11 + RGB + PROCESS + 66 + 33 + 11 + + + + + + Cold + 1 + + + + C=56 M=0 Y=20 K=0 + RGB + PROCESS + 101 + 200 + 208 + + + C=51 M=43 Y=0 K=0 + RGB + PROCESS + 131 + 139 + 197 + + + C=26 M=41 Y=0 K=0 + RGB + PROCESS + 186 + 155 + 201 + + + + + + Grays + 1 + + + + R=0 G=0 B=0 + RGB + PROCESS + 0 + 0 + 0 + + + R=26 G=26 B=26 + RGB + PROCESS + 26 + 26 + 26 + + + R=51 G=51 B=51 + RGB + PROCESS + 51 + 51 + 51 + + + R=77 G=77 B=77 + RGB + PROCESS + 77 + 77 + 77 + + + R=102 G=102 B=102 + RGB + PROCESS + 102 + 102 + 102 + + + R=128 G=128 B=128 + RGB + PROCESS + 128 + 128 + 128 + + + R=153 G=153 B=153 + RGB + PROCESS + 153 + 153 + 153 + + + R=179 G=179 B=179 + RGB + PROCESS + 179 + 179 + 179 + + + R=204 G=204 B=204 + RGB + PROCESS + 204 + 204 + 204 + + + R=230 G=230 B=230 + RGB + PROCESS + 230 + 230 + 230 + + + R=242 G=242 B=242 + RGB + PROCESS + 242 + 242 + 242 + + + + + + + Adobe PDF library 15.00 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Resources<>/ExtGState<>/Font<>/ProcSet[/PDF/Text]/Properties<>>>/Thumb 28 0 R/TrimBox[0.0 0.0 432.0 216.0]/Type/Page>> endobj 25 0 obj <>stream +HWKo0 WǵYQ`@71:쐭{`-v&`SGESZ.נެZ7 7wG_ۃטgP:FVĭ"/_jBA!.1<#d$x`j}gL6ՎLi +ہĺp;ĩF0X<(T{ gj',zVZ] +Ca{?Xjq?.#:y:ϭyC "Iu";hmo"lI`c*"7f)z.>QRRuG3urmp#tڀsD;#hBSR{SI*ʾ)dh2ik Faᓕ8!6Jn?7ʃL:KRkUL\!w(b}|,$0&Z0HF5b#I1 8Kzj J%jMffl*Ch vW{>u~?^󹌿t%W9tx,inڲ6=K,[l~4kMK7!|=_ g1v⸠х +F p kQF^2o[8o@>stream +8;Z\ob726@#X^bOpL-\FBqU%>K6lg^MBro+OFa>O*PG)opC0Bq"d2^G8Uo&q'VK=_ +L^36cdBd!21_;+uTU2Apgt/&fpoK7mAJhk?s3"LWZU/5G%3eh!OhO+='QIO endstream endobj 29 0 obj [/Indexed/DeviceRGB 255 30 0 R] endobj 30 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 23 0 obj <> endobj 31 0 obj [/View/Design] endobj 32 0 obj <>>> endobj 21 0 obj <> endobj 22 0 obj <> endobj 34 0 obj <> endobj 35 0 obj <>stream +H| Xd) .Y.Ⓕ4}AE\ĭ\Ps ܻԫ.7-擅=뽏<3ͼsw~3i)mx8U-щP]*#t*)&Kh*M},=SܵRYcOHLO!89ql]9mF:gII>Y;OU1Dssͅ&=Q QU^BuԀj[FE=G4 fYVOcMWd-hh耎ī:ʾ@zz#}  śC8" !b`C,! H@"0ɘ" LTiLŷ1s00 KX +`%Va5:>6"%؄؂؆!J>vNn^'؏8Cy8ϐ#8&s'pp_gp_y\E\e\U|︆op7psvZ@ 0xUI3SV/\SU2+_NuT}TeSTZrWR'-UGʠTԖF:CָWg/ܒw șx_µhm-Vjmmnh=H{aZga*11dzlgbGorE^O7VOoAN~–*gifi%Zj6[#6s1equtr++ ]+9*:_WՔ*AuV!*Tũ$j:SʮTꐉD|*سBF܂[*4+,-(-^KѲlmmvkeV~ʼM0nJMwMK?to@]t v&[';|DNv.QpIa9E7dq&'{W +$M' +ěũBc'3b(4.܇7wn4!>!܏pQMCF=DAJx? 1- ,{%yጐc}D6Agoݧ{/O}J-yyjxXȃj=Ujmc;$I|É&j-&UQըcm&4!6uXhT46lAFcu@W$ni ck5}.˵D==߽|]B+%^RTbK䣅xx| Ըqx!.fټV*˻ +~1 ;&ig [ [+E%*:_:F +'V#V()sS6>[೹i+ka& +ӿZqb|\G=*. ({U֨Va[U'W/cpvsv[D!\;sBuc%^g#~p!\7pÍVs@8TFxH-lVJk o9ͳ!f v  o11" !Ô-{W0@ Z +bu"~Z5 Z7I:'ܱ;:Ⱦ|/* AQ>,j^V~|vIu85i8h8i4:\O H#>sO0 }b /\z^j}M<F07Y.soz#+Άz3Mgcs2Dc+>NW/mpZ-6[U8Zn"͸ +Q(huL"! +l&R,MLf!2YoU;Qj zjsfʩB~}jX:LƻGsf;ir(VfԺ~~IY}(H+_GM{1-cA Xa }79' Wp82x0geZ2 +l55z}![VgS+O:T{,Fl-zO+3 t|Vwbtth!X޹G3-W;>l`Z!)% a'fL쬨AjfFN@|YqAzlK8STOP_m"{)‡ 54%vfs7֏P_}SzxY(l|-_N^AXGY=cZrW(ӈNQ; ~Fmdn>v 4E=l=\4ğCAAays46 ~w#ۘ%1T'lJ6|Zq)6(busU_ 2U3Tԡ7AZ~ٔdCoXC @)Odm(MkD?2rr4d 8Ŕ1~} +}CvL)ȉԠg*ߏIr}GԾ7lЦk N?C84Sz]&D=B5cv&k+tio'䤱蟢Uy#-47_ig#XV+;o]\nCc +<\9\ЭЯOO>c5FM~1ODO/k@+t]~.Zm)o2үJ5Y?f挜u79Y mHE̦J\%WN0\g R-eOϳ=Yo釡{}p=&Vt=9z2{J<*W ^#dTBﲿS zFேRt Ŀ^vz߽|~9 zxz~ZCƬF^㾼3߫Y>oϚ]_W8u ~Jb j~Qo9ނĕ*ӈwWA +*G?N$FaJK~B݋~CJ(AGnK}8@x5~:2gK<>a3) c2Xoېׁ3AJr lB=uo,`! D]<4|wa;}`g~gq`s75X4.Mxqf'{q{s >87b?ohUeǿ fws9-LsP٤:umk7wl +_"zQ(7z + AA 2 ,հ!Y>9޶Eo|<<<9*/>SʝYig;<Of眹5a63RE]ͺMd΂~V(=жQ@;!E\2I EViN$=C=-G~+82؝<5w8ޝ_ګvvKQO݊k@G41Wbڧjfty7W9ݗT26߸6FIlV$jMh QhLV~Tٱ|"Ŋ +"'="3L\gvZ[Y[qt5Jx#2oLw'ک z endstream endobj 33 0 obj <> endobj 36 0 obj <>stream +H|P]HSa>zYEb}7\ F~Ƙ˹9΍?4;h)P4q^Tw]IAHE̫HBQUBw淠sMW}/2(8{.D܍{uq")C>5B2s {ҾGf=X"mPnS(yfZSXl !^`xTke9?˹Ɲ^ P!pȥ =cH\nu"VC +y|HBg|9#]-lO< _P<3 6Jy:JOQ<Q T urAy`|!GdH* ̈UIT+¡ԨVDe:_(ӣсŘF'ߞȱb쵄 +ȡ:L..n?o׆&iCi1sު[?QFM v&Jh8m( V]ˡ5Ya! E: 싅V{VSĕKJ` 08al9x4$JNNE L]֔'REDzYC؎{sg.OfjM>IJ8_) 6齤L\Y76nh`dB7 endstream endobj 27 0 obj <> endobj 26 0 obj [/ICCBased 37 0 R] endobj 37 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 7 0 obj <> endobj 16 0 obj <> endobj 17 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 24.1.2 %%For: (Andrew Spakowitz) () %%Title: (weight.ai) %%CreationDate: 8/2/20 7:05 PM %%Canvassize: 16383 %%BoundingBox: 32 -145 395 -72 %%HiResBoundingBox: 32.588231612538 -144.40625 394.588231612539 -72.14794921875 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 408 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 -216 432 0 %AI3_TemplateBox: 216.5 -108.5 216.5 -108.5 %AI3_TileBox: -162 -396 572 180 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 0 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -82.2887423922857 86.0357908581646 2.75291966104253 1780 1011 18 0 0 168 140 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:-184 -408 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 18 0 obj <>stream +%AI24_ZStandard_Data(/X\h^ *r8reoi#H9vT R 3n.JB(qq2"eDfݩѸ-Nt1xO&zqsnqXYM-vZ;vUU=QumsFf3bNkfFX %}X-StRoԤdCcZF$OƜ rg*.cj%\O[xijpn|10:I5 vAEt܄~ uQQ0I_Q4BqV"5HdEqs}Z[b~bȋy\_f")~uJ(B ;$[2Ng ?*w;llfAÚ&>]yZBojA!_F:иZƆ޴32/lEQ?sI(=vv"~<5ń^5tUG#\UkdSG/Ĭf۱C/fCoB ƿ]:F_"vsuWFg!rBqgr)k Du2D%-ceDdr3"=4V7,?Vg c 7踰=fTj.%~!r6>Ue\lUР>eT\UJҽ;zM(kδ2*:vArXQ;wk9C2+\%{ OH7" k7 ^;JK T.-F efjTqQZqQ+>z4\E_LU{Fօvt'mo2Xk&9rZcUn +wT$RVϨD57ŹGݣ_Pu7pHF#.hw-HFцx+̘[ +~)kYdRՆ Sq[-QޢFvªFݢWxqlAI u-^.jvg:``158UDR4\KbT$f{Ƞ u|BIN<\unL%bA"(B'8]6k2d1rqVr^$"$ $$$$.q&Q$aHHDDD@D b Q5@0HQPx`K4H8H<Ї΃@PepCCÃÃCCăăă@(@ ! + hhppxxDL#AARB$!B BArrbbER@0@ uK\=5ϮnǓ0shbQP j$tdDd" I8vpﳹliZb"aanleHCw: GFe(D!Ї:ԡ὞ZR]N۲R)C,Ta Hp` pp`!…ТbXȂ 3CK;! $[O_UUC(m#c,.d  8 &(,@0  P\0 +, H0 &` +*E .h  )ń \` .h`"ă +ɰ 4qaB$T4 Lp\ a \ (,LPPA +P`BB$T4("PX ,v tX , HҠA,P +Hp0\` 0H@aAPHP.LD +$\A&@h@Q + +h a4hPQE  \$Ѐ4`h@"""0@0Q„X@qEHxaB D hP (\ BE * D (  (&4@CCThP"PXE ,B*(L $DxPQLDxpL0 *P\ *"\xPa&4P! +@0 $P + *\pC*LD  @@ (LX@aBPA\0A((4`$LX@!`B&.h`"B h aBT " + X@ +( 4@QA.4`pB &LЀABEEEE N@\x@Dh "TX@ + LD4ŃHРBE + +\( +*PQ„ $ha,PT &P +(0``ALx ! +@`@A)‚5Xғr5 PQA PT01 @q( 9bV/\<:Ȩ[]g L $(P`\YaB + +X„8AD0o@ + @D +X@!aB0EE ((LศѢ>XhqB,hKaa"PX,:^k,Pa&,`x@„ +((Ё  8@ +$TX@Q +&,hk@(*pӀ '^,*.88( (LP!E&P + +( 0Pp + + (LL"Laq +$L Lb (*B +@aB *P<@a$PXp Ȏo`qXPYѨ@A +0`P3> 2 ,p H  榸8E +**T(  0l!m8  *P11, + +`q*,@ +,T`&. Hh&H0`. aBE +pp h`A@a +*\(L0AA1&@h0@&'$6,oax&L2S̈3. "WUFEF9YLfvWrDE훹W$Uh E{#G7 G,#GD}>kA-bТby|zƤ#۾V0HYR7ESR~^LQTFG2%5S3ʼ!{x]KCc #ߨYTIiјE&Tc_3<S5zU$>8f\E[*W.Z<~\^碓 x<|&k{:סỏvns G03trټn|QECGk+]z;LhZCzVYQg.\V,N|eTU$.,ӳtAZ ΂|;,fdįΫ--R׭?wіV5ςl<b~qgn&~>&M w3$MYTH_#0̏[y,:nATDŽ3~\q6¼"7EF3601_KEdQ-Ë[UYd\b(*/Z04$Sjfad*F/I)Fbs>*MDRutECsEd*y-*3Q/J*-5hrRG!|%k,-L7.qq^]sqf3Z6θ(ӇxC *Cijƽ MgO:E-}{aOC|FLƜkC5#9hiA'!iΡ߼hQIn,Y b63fCSTZꦨFJ&Dzhar˞QBQ·q=Zr5rs"7˵C!*ʪVɫεUT,QQȧ$2΋aKdb0``j,KsݕfFd"CfL1Jz"GcjkT왓yWSxLgRf?ӘZ&{%]b\Rf~dЕs!5*!/NdZTl|f֢P>0d~]\tD5,YLӜR1 'g,"Ylh~47jAf85.HRis76b!Z}aRgËJb<-q협F E7KkUnsEEjɭ2lx6Dv߫?6DCx%i#iN*816oEdclaZ^E?_nk1SkTťA_5guFaRʓkF0|esU~aƳUCX;H?..7&Bd̍K_nB9)fU}A82~JSUb|ld^MO.GU'vث/Rսd2"yHv ulhֈ|D"7u si,4[IنFJiǔΪDWbmE&vy nj3Z|KQtQ}8c}bċ4cqJ+Qd)fd8kpH] >"+"Ϊn3fPfhGCrΆ I}g]eZ2dϜq^.jU+|ti|ER.JTjկ.ȮߚOŷ7M P VWkf+HIFϰi*Saخ\br[j:M>D,NCYe\ DVRI ͭXͯA GbyƎʡndyK55KV*!f\ƒͧYaQGGC1\mLoX\txT+G48H]Mh j66;Uoʃ6.\$qAt-#aQZa:f֗ ^0/2Mʏzq2!^.vF6wA/E3sva)jd(8 +]n iQ󂬗ꕎTü)=Bs25uúQ]pD*ew1V+[,512VlFɤ<"st>8.l9èxCÈ*W # Ɉh>\U;בp >Ƭ-+:o[hcb*BV}LPZhXd-X/'*Y7QS6_Fw^Qy ])! +iXX&ush^X&zz mjε%Z+k9c +[gjn#-!"-!uWP̮Cctņu-uWSo"*(d-:*5rH!KJ_dQL bœlڮl:)'I2\js܌9ҺA6SDŽ6DxMDN~T֨g4yK#&FY:yՒ~ +f|ZQ9͜:T73T5! Yʆ* -s sg74.وhql lF=off:uT=5l8ѡR'uH)OM>f͸TlbHPd̍!%%cdH+C 02DCCo972>nReHe>xHǙ!Bbt3CFq ar;34hfFM̍hyx!#Ӻəq46h[|aa2&0 YjQM;C,$Q}Q*QKtqm2̣TDDd%qu.t::6vi%!6 _ni'ac GDGG%pk&k'uY6B)2V_D*jIm6~cu6ŝ<mAeۙ0*Df cEzG("qnxG=f<8?f3^"uYnHuqQF6SQ ,)48@aa + +8Ѐ`\0 8Ѐ}16+))e$g nj'v|bGcU"xTolNUZ{B{yk͍\)2JGh6}QVTUbBX*ɬDduΊz3ݕ}XVUfzf.v,YkxbD;I*]!:;ݝwԷʮU=\ ˊ>͊feoo3t~.ҏnQbM)#⪑XL[7cΟ񊤳t+ۢu+4SSsI%"NjH[ef݂NCsEqnA/3:IrNttfh},YYc ko\ +IN!?*tOaER4*Cg[|kA TOm.EEUF;A-~ OE\j'ɍ І{S3N㺠j kXǹ0c_4öv ]kji);񺠪΢؏IFR!9RRXQ1YKw5̫]FfSlfq#Crڡ}~rSUZH#SS5TIhzTHN5TSTvYY]b!d5ZTTG4G*to9VтFV $$ 4Ӻow/YT8uS9!ۉ,|O,h<EL3 +iabl~ULgQu{PY(yJhvto1zb:!~Sr"~77LrcrSQѺ; &z #.1".11H ⢴nUwVS)[uqjf!Xg:dH m3Y=6u$u,':.$5ewfȤA jy Seq :xZgj$#-l}S w ˪84.|4f*s W,XFrOQG'n58#-*-]tը1,C;#juev&lv*N$"V+!|XФŲHsjnŢoHsSCXFNTnTUoWi'&sT8?̨/HEԘX f/Hf*4VhfR3e9gl5,:*NyPMyf>3V>qG*g3,d1Mǵ}7E̍=fr kԱ>7's3fi͍37vOfMCd(Soa#? )5Cv3Sj>vX4w tEez!:X3t#㙩1zk["S_I<macR}*Ղ2:a-'Njx.3ނ&5`[!_Ԅ2殮!M VzG#kɑ֢LBsi94Jg\n&.s CþOj_Sc8*|hԾ 싺gF_&ٝ9~){_TL*&j'+Kl峊jNѩLSBF63\67JJGU.0eD"65;Z"q+doʞ=攔oPvfO>Ko)٪fT9umAR9q)L8>K|.UjШ~;oΏ^B:})LYȬ&;ff*0#^929.6Je5^b2ޝĊ7椫HTƣ\_t,f0He.Yhv-RҹH睦l,I0V|z<ʈ2X4|;_j-\"eӍmjrg]q4zscZԏn߾b+Σ͉O OrБEƣ"_%] ņJj;8*gh+z22r4"kwd<ľUu{h&ȞzM˥:Uù6rp(Vb,9!C_)w>)FԨ)V\}PwsH6C7=D҈Bl_+/D6e9w U$hEl؈gTڛ߭>Vnn޳b2WNGQ8䖋,idǐb֥t֡!bDxpk5)y49)d 4]4gfצhCd3<݈şi!D0eTljDr;Ӊ{fsx2xgvqҥxnX%d gu:]ͅE1#ͺKFcGGxt:]È!gCPniXސW*/)՚9!kdql$ۑh +X9j3K&Zb#Cz%yjm/ |4#7F2ԑy7smyW5ȭR͕EfMb&tq>{XM^C6uֆH9G)HB9FCv׺|# B|^#+1߰xvZZI˟[X]qj[ٷeع_n2NvD4"b5oz&3u3S{7=Kqz:#Wsq)2VyZ~z25uZ|:ߠMsokkKמp!s 5fB.YK[Nm>}^e3nzStnZ]v:6n][ΤU )UmX[Uo.V83kjbWvUT2YތYT9Lf,éƇaf>6\\}jf6Hӎ~:YhG^REttw#Α ;Olw20`xpv7ӏG"*}Q*yqZP8D8N:dLc:ZNh\3qW%5g 6l6 +ʓ}r#rDzjIsW#Nb͑ՐJ˯ +;e<׫xab/StR*/!!19Θr)骗g=c$j0g6")8(BrB^AK2Pp<'Jreӥ!K:Hjq|VBv(Bʐ*pt(&g.V! +Rb`(aDQЋ!lV G@{_DN2TT&JD iC (\􋳆@"v(K2i>9؍!ʯq1DE3eF\}A JFa@ϣaLrÄ!` %`t`09ДrN+.Zaå^ZT`p2^8LZ,6܅8v!:tz + ~-BTJ! BTI> +tg b*bȩU- T!0&޸ThhaJbU,_Z1"XUhf, ++,=,w6XJi +NVjW\[!° +V: +'ɹҏžu<]U/ +h+OW29,,cq +%WʯTmbiXucA*7k ,+ʢJx&B2bSYƔ)v) +8gI @A -C}ɴ`( `·l-] -b'0r9!;iKw*޶/S v { ɫ &xp$3 V -=+ZDh.%xz.'.->]JXuy|ND:JH]>Ҡ&f!}# 9   //r@/@2VmGK +'(F|!!k}}iBa59؊Tq'«j!" %<Lb<*oE6g*MÕe{0r0h"Ɖnabu & 8<>[AbHIhU&9,:?@_}0\>SK[.T&̺2I292`w3x1.]d&h]33a3aI˚9oLG$Zs@7q*Qh'g ԜL 3(Y*kgtj0>s Ip4*- -j4Mh ѱgR9& %S:{g4l2<T!`줹1ri1 KCH81H08TOs xP;`ʨ!DJ͑ OMzʩic5hiWvklɩP@SF +g ~i ZPXM,Nk8[֌3,8_W ?RY+&h9jט KhU5v O} +n@*,u [#"55 +r5" +@+؜(ش'l`'8#es+!'!&hh>@isLRK׆Ll=,o/y%XYwHܰ]678@J㺩*pxua@ʽ빔Si1}{rD9UMx֧C /sS{%}AOx(W')[tR,ZVi)8d.lV8G`H3 rB9@ .9|NsF\e9vw9>sɈ Ӣ5loΫVsCZ90:WdԻ*:tZr/N:H΋ݽt#M)"xRY>v{P"(a-p|u>5`|ؾ=+>@%>Z!G=j,dh9AB, 8@D|x`rilblNkM9@K)`hPTl->'>"(o7BAki2(2& ƺ4" #Y\y`E[YW *Zy?/ ITvm߭V]]W0I]5d߱.S@LRUǬQ;Q06EuHGBʠjWy^=@x)!RQn76iߞځE Rа +O6ՅсU怿;p?q䀄YDvlGG'{UТpm0 +Q;TcAP@Ә'}4%1Na,ԑqqXHqhƔ8sP]qP6,P,P7|3+H4Cgx}}s^(yLxXY0e#mՀt MN= nw O*qM3`1Uy@ @TF/6 uQ"e\IHL@y˱y&:7jp{@6/mdj=0H?f "e̹ȡjl؀Y`΄/Ob7v6LG3 g . K>f s ƨ#^f]a' h:pW^3IӀ).]cEd ̓au: +Kp7F{P6fmO;;L_UVCy{ 0AӐD!1nE0p!6kCs|E0ޔ x hИdZP5QI{:TL`#'RF:!  5^yʃ70| y\`LAx9`B㦆 B` .nA0zea GHS돛B/ 2$ (о_DwK,t}l+L2аypg52@||y< +<#;?v  a`ᒍ60) W*DZMYP{ҝd)x #Z/٦̺pGfi V"]' ?\0_u\BWT0{wĻgv?%b-#,LmE/hM($mHC>'FХ-R 95. |2Cq)UOJ)*5Sq]W Eyp=>ؘZX9#Ẃ}~tdHf}4rh.nAþB^HC}PZr<}߼ +I>s#H>NLV@BU?N_V7~׶L_71su1H]h)0`ўxSu>k\171Ji?QL4_i[L=(rSǼ)E8?GBwл( 7 bFB Or(AA/nPj˧XKgʴSSӜߌ/u¿W/XdX'h +$Bw>co~tϰ{xads %e@w3~+meX"aw]֍[XQ:K/V  + +U"PSwhHQ7((%~J\?,SM0Mb1+6n3Q\W{/qא;I5ʂ?M[ ~k-^4?Fzpd@! ^.|3+ #y\H‡r:޴bL/:('oًD*Gf E.# qheJyøOH>P6"!EF\p\D# &&>嗿P^ z@ƟE^4!?GߢGhIdPCݼ7,Έ{kHSJdc}`&Ѷ@# +דocooqCPIWR",h# dBjRʫctPe6-30P +=24AKV4 3a D0g{/b(`3z7jc!Ǵ6u;΄:e"^`I\P)J}S q-+$fhgcތzƪ|״}E[%he-& MCɦ9Lqo᎕>5`6ֳX]z#r|YKU_g*#R `?6mf "sgXԧ'A$:=3)k-C'mM|j!.۠wT)85҇a+d=F߫ UFW[{/ڃ#ι8 C/+M227řځ +?LiYDry|O΃.ufu7t^ -jx,kz2~XndH#'EA?-u9Ɵ)x(2~XJ [µ'"\>?Ŧl.xZvZ +4rSS-e{&&`KbC!OU (7CamUx4|/ɋw@ `W«,34Jݻ3|}nF%nwNT)x&dE8_`صUDrׅ9yEaNoii/^g䉰u?n=^ <;\{F 4_,΀O$gQATzݍfZ#^pS 3]`93T=x'{Kt;pɂ|ػX2\fj2>!p8(I udz=׸svԺq͠!3|tSkh[-gz{bLdnXvZ՝ZoR$~ˢVu+<'sr569_7x]/ʺhzT6gc~|DmbH,eLUܮE"1 oՅʎ.rѧ}#l -p@l9*BRG珸RQ/lD]ﯣ6 _BF\TTs\ш;B +=n=[q@ǵ+[nh5>GDY10]Q{|\Pm\S: gn dtΉ^g$]ǎPD*"tVnjD@Ʈmyi7*Y^m%ry)42_!?F3ä"n/Z k ۹ +Lb0@%{ _(Z';՛:҇I#֟v+9p nG8w673cp[LW}hH؛ 8 I>+T,&=76 xzM+UF9 xO +hxݧ~L=1+!18nb?m=QU~03 p˘~/y)IG獊 @HhB>k˴栂EK:ߴ'?|W'G]+6W}#a ZfQ{gP9bVRJƒԊT'HDG&BB]θy/@O7qWpF)Ue|qv7YVxk&h{[T + p /CG0j@[OW?ns%On%Ew/ZjCT]?t(S_'tGnka|-O Y{AL9 s5[Y"u]p,9;eȆp1n6l5Uw7 w|}PzQ6nRk^b zk,0\3ZpS$xۖϭdُ.PE8p@ywAX.q8Il[մ%nh$dvE^{܁ YMpo@1+tL ʶ[Vf ׏./to;;)E( xM3LԄ |f+(Lb1Zq MimqPC*vٞ(~=0#)!t A#+< ?#Ku^{kN@6*BG@9K=PC´s~c(aB$8'*k0'm)M$hE-ɐv-yf=0Ֆl< *=Dq 2gmQKsMfybjvF!>p +.4, G5To.-n%X2Q=%>ٸJu !#[\/2dGւCv0*2c7mѱ S5++$fSd1b\23Wb4*"`0&;@73_ Ⱋ2D?QVa7L&xN˞ {^9m 4],b2O׵wMhѤ~DH_W9/Jk=k EH8:5 +"]+݉|4^@4^l4զv׸,<dJvzy50گ`/;;GF|$56T^ć+G^&7o=!;QhȏR0 +1BZ?KXH!?}mͣY]hֈ} XYpAڳ*FDZ)T>CDq!b+9WjÌ[dX0VO_j^6\UC߭A"zXQuoxi~(T_e*sQ$q?5" j_N=6hS4<dԶxbFvښ J*I-hQgH;#`r٢yonD} Ivj"]1ƈ& 2/Uwbd7maO AUi^v9vp4ptvNB֜VmYLdvoxSYAN4/t,uck|{n:o :e(2=ȉ1 ;~L[vu4B kt,-<ܕX?ҋG\تF+Ta V揆c'ޘN*'ʂI%-$ݻV{O>tfҺJPH{x裝Ƭ Ge+B :Mou^PrcwN܁Md + U&3+F&fM1061wW`\5"d*s Za189_B8̀3/;b31ƒ0Oa|ţ;a@ [لYr YI^|'I6UKaT0aVKB +S,xI5ꌂyI.8J >uo:0&:̽gL +AEfYMKW| vΎ FP"Np#Wh$Dy 3 +\ r6U=Œ]tV{0X Q`ff2:1>de/(F;3_VMc+D}yL2 eGJp0L-M)^n+b7#9|.lUl"޲;,s͊ejK5MomfH򱬙%cw I>6Fl]yP]syLZkAUuI 16 &+dkn `f7)k־.Opr=N2^'p.6-lj,R+:9%<2Ks{s*fs\!3DڗٔGkp:fN՗v+v^@v(hF!yEw2%4MRʸ5IN9]Fc]:}ΎgHkVӝ04F(ơvG;Vl|>lbqt;<^F1e 7(-1"BK?iBDzVB_(ߠ9T +ġ%i\ Xඬx:襔::Ed5,J[1!ѯr8Q6ءPܨ0U}zr:Ot?jHՏƱ2 Y~~Hpi(A&NQ;I688:(}M)&JRMPf5\GpK2񹦔v0](@NLoqA*|ں)Ҧ A8_{0NP u\!`m"O,e)8Y6 +XIUBPаtVQgPGD}(: +Qa`J;|RV*Lj>*URLpP<aA,#~Rȥsj[!2+^jn¥sT< Uhʨ`ê֕tZ`NAXUNX +!b1Uxՠ:)|Lm,<Bvd:-c+F4qVr̠uUIPҚP:z{Il cVkMpxNߏƸʮ\˄JHĜ* r=x9S^wiI^%^ђ4G}]·_9'`Wݤ 1ٵv!_a'dacvaIS?'vLbGRA+*^~͓~A]U]Ar.GMlU{}Nƾ __0֨N瘛%RI9 +{6rK>IHhG!(-k +I[Ŗ:հ9l?`Ԣ-[NjqYN&v`]2.^ǘkL: b;Q%|ŸM[a$mv).p[*v: w3+ )K8mr6 JumBo.Hl.Ldž:B?L>K⪪öbXAr|(7bF oRl/ +kT}~:dH8!]knL`Խ~q0u=ib}n&HKL&4.=p7]^3-TrĽ{%ގgD..xP;_ 7`a/8 t}PU0e:2'=S2e˾J$4[Tq멯ťqc6vA0[P}\pDB}s$c&Vsu5A Pu:yʻW䱒 [^?v +]wMo5rFbo{;=O_aBesP_#@TR ?C-*@b 2pg~%,WʥB7̲;wJ5ÿd{oƚk50|GJgp8qo,^o–zoaή+_MQ | s/v [ޡ|VϘ?i/442}-6*WR'SN +[a7sglڑbW2AR|5x~$*sGS|C!@VUsڐRDbdIR_UNJDorƗ %f!/'ZXߩ!W1ι~j}zs7Xn;$ėU,rN촉2dzs3,!0F5\m؆#E|7NB| _+ +ķ 7W+oX V[l+9pY⋷3CGϾ>*b% j0;fy:0|F;{W;N㪢F| ,;pҚ bS[N|Q"{H]p{SUEj'שj-ӭlJψ@QmG0oBUQ|VALm^ZݕCJݞɗ˩oA-IJXKR|92PqpB KX/&MkPS|7. cߛhWy?¬Lҽ$ !Mt8_1}l?[r_XABHWC7.&͜/a윯33">|ACݽWRB/mz2+<*qٟˍ󕹉 9ss/T[9@ +#mҧx{$`DRy#7 +y}#&"E_ꝷIWj)7jIz\5{7QFoYp!%+-1yOUs]o;صhگ59os]+[-IFdWiL/E,TeOe<O.:(lnELeFJp2js%k + a/T8 + qv%kb +c7\&]Pos* gLU`hŢ3pը\`N̬ª̈qzl9҈ ~#O?4=U Yl^5nI7;-gMͬL] ÄNH O6 !FQ9a01}>RGD +AP_11;9?dCUoB6s keWfgv[AcտO@%4Ε_(F٘nE$;q+~MEs)b}|XML|sky~%EGhTLBN?bJ3z zm6>!΀"/w!7@?dVRэGƴCdO` g`-ş#*J!`EٕEKUrٍqQ{/pZ G腁#sϤ(q>Bko a rn|&`L3ŀ 侧}EodO_ 'ЅfdD1Eؒ] +`Kr_#,@^{A%Of fI\=ȡ$Z(XJJx[Jm~0F}ESrDJy[JV=m#x&%[O ׈er(%'ȽrCBIe=ᇷh LɀϠ4KIHQJW\7G-XEJF\ՉUa %jlU_,&J"8kJdr[A:5C$>lGftKd2!R; !Hye6ܝ,z$ye6rp& )iʘMy?E*(hm4 Iܯ rj<-C&ü!b2Fඕ?2d}_l6<idΘEdܕ*`̗t{,Qo2f +G5PJd"hffSZrs-_fnF9uU~MgFJHdsy? ]3vP=|_=Io?Syje&+}+6h`Yh=z*G͇Y#:^0$+ )X,$u1lMg% 5Px$j`WAxC FP@TaBP99A=0P+MP(/t⒠^03Ps^;Cͣj3Բ H jy;{+PÚ X3k +­=A@= 1oQ8&uz=)- L}pꎥ`GW(Nͨ* +1R|Rk, Yʗz0#Vb](*0UWH꣙ 2꞊ɭU3[Zvnmzc(񥿚 X'/F/Y'h֍hF{aaqm"m`kk+HYk)dL ƴ5O+Bm)el+"g Tml2-U8XCIQTZO&.ZfN"uMb3.^ztru{J/1eAO5>bwQkz)BGWt!nխ <[;!4o]ԿOҏB +1z5Bo)2z?䈮 Ƥ7z /b:;X[c.ehf'۲V1Zz%aK<0\䘸\>|/_.嚼0.8uhU3k1FɯM2.{^Pع>/ +k및Ç ːH9Wئy 9a;LQC\l*=e=&f? kvȦeu%?Ř_1s@U)V="`\]m ml;z̟l~?=)7n=],ǽ{2WCe e =thQQk&u+̌v_8GջS.7Q`&{p e?wd/0)jo@>2|<ewpnajٷߏo[ww3pk +Ghd~BfopJ@ꗄ[(Sis4=W p8ϛywZZt Q|O +U+F V_,\[q/缎'Ǒue~\Dl|#ka'GV[MfYUa9ŚhV6A//f؅L~ oB3'1Bs>0Ӵr(y,q~4" :@ow^E-Tp^86j[cz2T14Cgz}R]stΐ,>*HEKu { A/ +`-E]ԯkUtԬ▌Mx:-yqJ\։{u: ʚ@OV="vNcvi@5xv*>Չ0]D 4%j&u{0?x!tǁqt`6T莎s; >6cN;ٝh»/{7a}Y:Fy+sT735j3|_S^<£uyqK HܽzP(V xxt)G*Y6 IE! +:%L:d֍^,},-ů")1KF +A'XS,"Yxu㐕NȻ!97 e>0b5Tk<;L jEig/$Lّ蒷Pne6jLX@`a~d`I%gix0y_ŒzT$@EOS4KTBϐVD?P}F`~f8]ȃr[R]顧1G e=w|[,3.g`h@ 1Zg:һĴkSbt6ܞ s;pR ]L~Mȉ#X%A~^{vHq>i!~8yӼ{J5Kϙ'AP+2k_/9|d' _K+} > +}q :,sҿ;JQ-`˾}rJߵ!?.dή(9 )*S[kc3"th9j +wcf#ϨLX*} M=mNhݻ>iV06 +j\r z7 ߳+t 57C\ )DjL'ob(:GSKJr>IZ:[;-;a;dHv < (=Pmwm'y0`[`ܲr,j jE$Ee%+?U8rVLbu.uf!7N~k(5y_'?tl D ʤw2틇 +/ԇaYcX؂|myXy\[aZ2˛Tj:`VT٘o-E_V +,$I|>iebr7\U"D$E7B')̌]2s<\P֕*l*ҳNNpN,/-@@Q:? +R/k/jnH𮬦0v(ݶ,н`]^5$ Â8A8A. b=Y;lC!P6Z?3?~Bt\68X!ӅG(x*KsΌ\殂ϊZe,(ͳA5M2xBo]Cq}^yAƃyhm<]v۔݌TOtMnɒJ{Ѝx̻!BT#sxӝ6w/Kj(`U؇:k+ZUX\Ŕ('LPϽ67]1"2T 5yP +OrPc1Xq}ԒF&fN +Uf;e1r(">gwX?{amԬyF" ^w3sEG'.uȒfWлHSVO9esQI Y ӽ~ax-I*b+uJסN!JX%m@;1~767"S= Tg+UIg7F3+zcAMN<|E%XsB"+ImRZMPV`VpSCIpo>eC ͦ%2) ްc#;Zqי2VF|c=N{F_2 "YSS`?g&<ȣjB&H#ORQhXq:G`640q)@ύzBDC5"u@ StZdpPes~6J1IZ``^I҃!pѨ(;R;; +HݻP\Ƅ)^&Ksx{X)t<)\ԊW):ñVPAge .{a쟟5,F.j|"1Ē^7 54TGzcAD4ZwS(|BЃ9N35 E.z̳RB|IĒ j_?lU% Fm`H(rWي %BBNk< (/mV{i\2p3yB veo,2gaxH\6K{C<5;zzqgn#=6ҡ*O@ouu)Ksω*WN|FD)*>bѳ@W;?qu>H[-{ ~%WU1|m?G9 ʪǻ*BuWL麐u_Q&Ia؅]趪l?Ow+ sR!#*gJӟϔYP{R) +L{; j^P&똖4O4LHJ_T⏅/LW] K裒o +#oM35p;Ɨ'2G?L` gvm:I%.M) ǐ +XZJyĒo4ǡ,@+` +}IY38hw]?2Km+E q +p +9f+F-I1֫dL$820~y $*,s" "F hƫCy`A8`.ՀF^HxMҎ.\RI>wL 'ǘn$D(252BL?,TߠSi=!E=,>Nӣ^l7G'@t745"+Gs|'OJʮfWV} 8P#m jSҋPcdBU4्6 |ِqp@3Tˇ`vqo dXDQ"4ﵬ[t-=#Sn g٥ +w7(H9lz7%0s,ZyMsmʹ.y*<>0@0#k]Mw9R5@84ND/ԢyƊh;g3R/}j"D̶ckrrުi,T=9>yɳ9l+Zx( i7:ȥ\[c8Վu^ỷΗUSZ $ă߷h!x1_apa¿y&*QHmӯרgE+n1sZIցb]S&b ^1:Hp duGx1DQRb `^; `"l]|ޒ@Gc?2hwd<J,\y萊ƾD9C'Agiƣm\7" Mbb3g܅yK߰ e49Nח\6 T^fv494%?>f2ܶ!_Wa<И61i0 6˷78rҘ'.@˒Sʗ[ј bg w9[!Cx6%fXu. <vk)[w{%п3%;gI|wW~JwVKTB؜î69Qi 2xWZEA@~Z2N.X.dr}癸=gi|yL.5rm mL`B!PܢRLJ3YB RbȤ,J0S5 A@LNWؙm +iFc$ "W*qP YI5)1`#YP2e$W *>؁,'X@ {Wc+9Ii7̗dj$ {CA9l:I1`$KTPR}1#IP<.2*\ + sD~ޤXwP0u_D\h9+WYoo̢nTi\/3R٘);Ǹ8 FRʱ湁iQ"/gj8*Z^ 0&{ݲrbJa+ =0RәC:4k6ĠNAn٧#1bM +代/E/@.to.HYVފÓ]Pg]HQ +[(`4V@4jA թȻm;<]`b-x*tLlAFFQȠk3J9Sշ@uL`s +P^R}>mmϑ MtVAZaxޖyZz+ۦز72~̏.6-Ha8aFQz-Ȉ {ۛpqF԰(ƴR{#ɶӻ4/cMfZ>!"{^1` eH7]PրKS<7 AWk/hn5GX[RUg ͲwDZx.=KO{'%3ʐ(3ZIMO;xS%J} Z!# -W +laGoI1'6" VbBڂ[eescAb:>f|`t|Ռ)ȣ9VhgE  @Bھ'UU>0XXfX&̀䝵 +3c/qv[~95I|tDR>TG .ZaC:z/`yn#\C@7N5N%3ei??'(/@P^SMU9c8{aȡ>G0/ɯn!zG0Ug( IPD̲99#"!gDKVUGa:BOL摫șzbC z c8s,_1Yr ,n2o*bwiP f2ׇ61p`5(F! D(^=՝α#uAdކ(Z@x8_8-ء#nhځ_/uo/I3)vAƹ4aVgOͅdn%[N\X%Id FYu&A.ƹ 0[uSf)Uea(D p6%*wD,ie *dsRi6%z +{}㱓W-\Luݎ=ZO ˠG,1`)i&TSb`27Փ4C0%u#+[۰}W)-peJ ֪%b!:JA%U܀puU%@Y,LTj67OGm nU&y+^/Kn# Ts/Wv4I7{Fb؍,xFV?Cji͕>f*+<*2Fp?آ:i9 '}ftgW^6>LӛYs I( R1b>uCZ[4[tVjx<řMYŴHdt,\Fl6X)˖NDHnb^mcb,6w(DDMQCW +n\䶗 裍NfwXP:! g!я1iBUn,{: }~~2_=zyC3e奚l"$">VhsWB} ,X żgO/[[?<͡7/e@Wwsw;u_y)`5[mH%h$֍u6@7w\3M@3fۨ)8 ,`N\ $Ea`(BQs{-wxuJHrN7SU + P7/z7xZ{=rt Ѷ]r:>[*0}d cP,NUǥqy`2œd`h-՘eDre2@9l^}L)T^Hk[;ZX.S+6( !ɍ#MS,7W,Hp)6V +1 WްyCk/s#%yȿ3-Y9t4@ ̴ F̎l^2M zQs͔aȴ3*Ya SxkT Ĝ}&O$ir-uh{);Qǥc3 C(zQ¼&ݑ-}'K&zjP՛DҮ+]'-z{5=y[c@uSFЕ .b6q q j)K71>e+dB?zW㆏Oe֏Sz&OvMix'ܾ.fPKD3`gF۵, +.'7 v0/ް`.z̈[Jm[2|#GҁV~dPb!OBo 镦2a5h0jQ0zX 4cJ3<;zW#hMҵcgy|l@wb s0qXC ڤfieEk͔6@~b\$Sw;ìRsh644^ ti#J-Jv/``gѶc2kU0pXfgQG X%kC]~1"BrfY*ˎGD=JIYˮ3y(G|^|TaVr@f4.%[dL}'x1 w,$4X+WJ9dJ8Kk+ñCi\*K9-(2ŀ0-Ua_HfP[oZˋ0mL̛~2XNUčre"P[3%l+ cQ$T$~7&OU.u3ALM hlhwkrsc"?thJ;})d.M\cyio\Ӭ(=+Y81ƳABA>0ofm+|Xx14 J!~B +4pBȾCM]N(>lh'Pl ]8H%~e!- eLWzWNa<'DsXMԤ8A?9Ty/J.dB Bh?. +֌_ܞ_ >/qXJfg{:n6sHC: .~O娘H~%Q=o(pֳ 1}I_%Qͥ65F.b޵xCbƿ#}oKk/Í-PzVunh*nזF8_wQycQ4.}Z~ɺv&oVRb**+xVOc_mŷI_ wv +˱OȓCSyγ0@m܏@ +L M 3;hZ45/7}K-{<d^H`^_vr EK0( @z/3*~1$P 0P:+Җa@UP +3 +49H~z s1˫E@zo8]"}ږI\ۀ4 +-K:PJqJLٷG" ݢ$ +4ueV(ehmN,sSnfr]_n)m0\xXE+:zzgZgɴC=Ts?߁x\} h*֏yD A`(O, +ˣ +K]AV%TJUJTT=8g}/4˗L b@T)"rt= p4Ɯ2)]-v +/܀{=n + + lSpi]a# #'--M"gqj,Y^);ҺumJ< +xfj'),Dj9ʱ_5:.ͿA 9t[}T5stIn=,--2,?Џ/' 0БEeN.E~dx7 2Y/4(.FA`5?^w׮G"M5E!)Z<>6"صiY UϤ7Ƣk+83яFI4, g MCU yLĊE!n܁Hj 眜-D tq|V*|je(sCCk%]_a!E~pCI1d ECQ8˟"(wȀiCP`΋̎(S̈́9+;-t@hA#G/2ڟDAQ.W$'n]=?g=--ЊH Ζ L0{: D3%ezJZC|è^fpD/2oF4"ꗾ5*.OOfi_sg4d4%( bֿeE2C=E=mRџZQ#~L3;KApg) ec)*lw4CgS֎qGsHΥڪ"a~Hkm}kwle|%ѧUdIUE.C1ݪ=5]wf]tۢU.LM~97R9|w^śNN{3R2M4#-dg2oLVkC*\Esl&l&qwg펇|;"ifiK[3C>}G:=T濦5-223Yլ3gPYji_rʰY3cAPX[KUO2Dۍmn/iVݛa⎯2u|6~wT s3 C5sApdV_X"__sSր`A4 #_jsjMNG@Ijh Ed + X' Xb@  eT Qqx0df#PVnNsѨnM=ڠE^KVu;u^6XV\g5V >kO}_TE9>J$)^2"W5W֟L^EjXN3<ўGTQO[z:](:SCkMi.j)swNwvƻk^<#$o:Ԙjƛ33YnihYGq׋73o ׄsbke <(ͩkZKh$;4̛IiIJ}ٖ,Kn-gvph2Y7YxVJ5TI*i))U8^u>4g㫛Z:<ޫ^W3׎ݯZMD'މzΪ7M+5>wT}f6u6g>۽u;`jM/}Kt7RއwxFx$̻rGv7tRV2$&}wb-FfOV^P<(LJvHMd97/uz?i^Y6XPٰʆXz#ˋE2ozʋc398I2T+3MIIydKKK,[^:f}͝3\b朱Ls&Cf^}jմX779NM$Φ)IJ:YJҵID_h5*jWIk]ړn5w8uȺ3Ty~ ^Df"˰EKcs˷~VMo+G լ:giKK#դG1)4j7tiӛZM5RG]ygi9guejΰ3.ͼs5qp84#-<պgw<r·Wttvtsnq/|/ٽ6TzOm[>oY_'~[ys{w^;O|jehmQ}ý/gVd?3Qt'!l &Lp͌eg>mYUUiٚ3CB  &" ,$ Da(T!APX& $B&Aaj1P L-fJh1@ D!р8H G 0ps o@, + `@$r8r8u8CCҘL8 DBiT$ʄFHaRT CdByPi8Ypph,=(FcTDCd,$Bр$8Y@0I<80$ dA84 CԘ`Y(@&0Y`@Y ɣȬ"",ʃҨ< Ap@ cM@$c f +jBE"( yT < hp%B.UF TS/k0WDAWD_*Ss*[]S7Uw u;;EEUAl+¿z}\߻ȸBng3d]Gg4lx-!XZ!'w 9r5eb#wSYE2(f$ ȍz9ێ1_^62Y~tl?&v~dx9˸6ă;LDݐlQ5X[DJPG W:?SEVc(2CРNaY +}î2n-7AМ*%() , }*4C +xM21MbTK 8O^zCPv?i ۔(O0եj Aw%13{9#%t6h"V籴 X9hKF{jLu27bjDF>1#<1@3nQku՝`c?e`^Y <8d'8 틐U싏"D:֪]Rk[uϱJki} }v2%KiJJSHe:Nb#@p?Ugy\Ga;DC3Hpo"fT3Gb2vB>݆SŕRrv 4EYz _iVuYhնQΟb%B`d,.*7gE'5ĽOY҂Ȑ9&d٥c{}l:XЭ`D{#r^ nQٯKopۋ}C<Vos^= #ھu)]v4id_c$ 6@%]QEC`#0}jpWf3bF~ n{_5ȂJs) }[1.zgUWܭKbp?,#vFnkW+ 1Ը-Pq/׷]6g$%!-R5KGk~ndM`=U/.}f±`ȸL0(n]2^?V>myPtܢn>Pr2yt^X8ׄBe3겿MuAP+*\C,j72h(#u42Al4[㌾ٗ0#0X~%[RSg/Yť; @d?lG'^2c|-bX{rQ4DМqj  GS SAIP. ZK"o\jW)<$c`4}{ ;DG]:FddA1{*!aDd=WY~%fԍLd\_l#bRHl2pbH#hAAg+'8ՉZvPn=IǜܹeP_pZ"{3YiͅuޑW4boLNg=ALzer=p-5|+ fEBt'jGV[q)_Ixp9]be%n(`<[9om3,lɎLOM|%,hO SbI%JQs?ԌS;(0@qC{M. R8N3Wz:nS @2(-Cx#Ռ?^wEZXrj&<[Ȳ32ADP-ޥ9]-d} !w!vwRpa;_`{fYl"S^9p&#}s<N@]i=9%h;w + = Qq*2Mf+eP7]6*ddMiFaixc|ȩk+c91V#8t1aV3Wϊ4@0(g{.A p 'c)TPsI%>ycp >6>0hԙYpTaDkPenՑ>]Tq"OI1/yxDR̗fenrhrdmCn01DMѺAySW#Ҝ&j&κQV;t@. '9\6R,Q&L?J ujMV|2q14f&ӛD +#ɆKky=QxS1Xێ܇{%{&dBJhr3\Cqe3J%X2FZ t0ru0@}0vfd9>UJ:*Mxo)V*-=ĜFzEraJYRēY rc TLGϑj}_L p~T+|&l cd\>3@`KmBD<{_2jƷ+Iig7q2ǥ1Ùf` {zu%Ưö b,<qR2B[Z3݀՚st37rȸ;,?ߕ}iqR\,xB,7RMLFE.ՂzNrsuGUEedvpl0F=mk2Z:#B ] Z8=@xGѢX=gvˠehoMGٿ<+@sB˂>62rqO >JFpM_i0"(19gn'zN 3' JB5l Bl=Zbu<$t5-L ؐyEonM7A>4Y a"r;FXU]ߛF"ָsn/3~|FhAʤ!(@"ZK 6-d uFmz9x隔\1>odjH169%0'ԶDdLX # 駹7~7Z[$ VB;˞zN%HJAL-#GnN~)r4.xL.1z1!.GHjRPR=T2Ǭ Eꊴk6ĕj΃ZɅԠ5ODRɖN6EȾ C$[jCT.eMcp^gL}~nO>J00)- +QN*ɚ.~W%|%9cm*[M֐odྲQT)f[0_9 +@mAOR,d-U?~+OʛիT9D@}!+>=-4|:.}$Ea< qodtZSeh/pO˸˓X6.5I=Tk|D`ȉ+0th4%Ӹڇët'2lָ >7rO@Q,'Ru$|L8ȟ1!{`?wQ]`3 c=DCG+2̘7b0%iV}ͯF+LM[7LI_  Թ H(b0ka(gCa?oX]isսRP+ -pX&RWCLT_I _=G 2_h$6ɍe'~kl~i !l,[$\몙cF(QY9L/O3a,^)izlk TO@&uwpKuh+і% |7.N Rc~n!=X><Ў☃NЫ`>pN|wBdw>ڔcL>Xp8F6.,ގC^z_>_AGEn4;zdpޮ IxyW4@Um}p"gVnl49- >؋l0nw`|L~2[tJ'W!c3"-AWt>tSwX:0L^8'&8`Š}9Dc%}c$ѦY\3Q„_b'PYkTgH@ 6;Fϻ*Xv05p"=ÆݟQpZ0HhbUڶ;Іڄsì`mq4}1Za"Ds< 3DD26G[5$V)N{nHhfCPa䨧0Kz8ɭ_bU ǧtR=f IR*l?GɠB+B쪌V-0Ѱ]zULx,fN/mW*hdDY-갰_9ыh䪮M,Oϟ`c(+@*Y tFV`AdՉk4r Sf$cR\PR,lL-l|圐 &\4"Õ{a]M}x窎mE|iE˿E1qKʄ9g~NJ8\:@A3W2Fne:avGݶӗ;z$xt'|mabc]zvriZi_j= cQm@ 4Vd}eR?l$\XkOR.V]ĆltȺIL9-xP4nb Я*incy +LǻɫnwԸ|̒XâU1+܆u;r_h$fv3j.s~!}A{3y&5%h~ܸ҇}􆳖W?yZ6+p> u8kH@5ف^!+Ϸ O6ˣx%LPg7}gc1Zz4*NEԭ|1&*o:70s3~ʩx44ӛ9oi3EPS0C5ĥh^M:b܅BMS`uCzlr@j#2{x4f8vmDœф/h^Q\Ҟ@-݌ׁR+ؕM$P^ fl\$$C"#ܛ̥gU,0껕"͕*#D F,_m1QoEf< o!ũ**HO qǶt=; ܚS;~lAQ9으!X?+F!,4$B1h$Y7(1^YpgD25 +(d7W/q /11SFy !Yʺ 7%f6n5$YdM+ 뚔_$R EV:k,NiE$,JufmdkqV/呥 ByMSksW5_L^M-Y.h>m@G/uwUBMUC_if}E B*$fEZCaULR`kg ! cb '/3 /MliKVR +JiNmPG|$1ֿ(tNnXG2t %Uuk|i&0vIpezz72{9۳NIXնVUryV%{ )\Qy^P(DYZr +tԥ&XGsH|IBx`1 +*b#֚gipm;^G CD&#)-<J& ki5OymABE*m^qڧ+4sR${Aϥɀ6C tO#kIYηAylk0XxFDы$&=i90K>z$r1Oz LgmIYZ +\;_;&]c 7p2zUI+s'׹0clt6uc`M[c= Lld8J9 &e!I4r x.H>*|wYq ƎPӪf k#0QM3v}XWznY\NcXٯ?{+Jn1hUGI5jsBEn +̺r66M4to.4?e9'$v&PBZ* tɆ s *D<Ԃ.T=<v=4ۈƣV[}iErC_-G&ܿ !ҭ"g.6kԲ@'9rq5. s{Ml}G +z5y+1ŧ8OP#ċ2{}լ$\w؊|+HẚWn +j9̅eb{ ["N̈́Rc/Ny~U,A%;SR +Uk[ŀ:;Įŧѐxq`D2JK^[g]SDuv}ljb"XsOQ<m`[&I+?܅z]؆QTH<ä4hs9֧v(a/gx IPʇtY~ iy55d'c#i`錎"UK7O +d;UܾEO傛6!~>g#x`,GEJFr}猉1&"zg8AcAG z-9a,16EQRX 2e #rj +:EI\58 nY##q)?& 1woKLrr0Mb_"tNY7Xw^Mb ͬIŃ^aF!/JLI~rK Ed +]#ŕw i$6Կfz5-n W%EjTd0X3h- v2~[;Sej YKzՅ5);&"4>nS9&83xJ( +,2Hi?/]V>kZ E +*v@PR|~.J<؀+,֎_3Zhv'!2PSy0U"昃9vF M ~EUs:`C<%3#c.hS]N\{REyC6HxOWF@P XEյ#U*fW؏{2Lu2GP5tfn(JKG +c5`^5 i3Jƾ@\Ndžnn]B3qgehK,N*1~8 +Aw &WK\ʪa|z@ysLKm <-YZ/k\՚v|Ʋ̦qnmܱD2mM &i f|6+AAlNcm( ܎Z҈=of%1g"+:-Ҍm E~=i5>i(Y…(2b#ܖRFՀ|mͩ2@=!e0Cr%p [oc`i$'dž&PTXa1 d%}I@ B–pid2gXUa휑i0a8Nfdwo/()KH|xj1{)c]T{mj`8Ʀ6#E\/< Qln,u$E[_.#\UF2P8$HWŬeN6tZ=g-YE=XB6mz;H ~ALD4*m P}g $FhنN buܝ ˞xm4^ 8rJK91 + BZKR_C7CC{G}Ii8*t*[nDo`V(}3QQDJ2`>f>B -&&&vL̎2pRsG/{78Aan$:6GAvHm$Me h+ŗß2I5ܒxZУ[/KlI4| ,@+lUp5HOGBRN*GKu֬;kEK{6qJ(ŋ P*53AFH! +qncG¹@thS-x&M}WC'dǛpB+*u4j^"~Vb,z -Z=؈ \嫟Z pq`CEsJ68g( >.Dm+m 5_fHAHEA$tc'zZZ=W ͅKiH8"A@ܕM %M0iȘqr0J*%̻(y/>#ruz?lR)FƖ8NޑPR/ |;(s{`Aw__ +D6h`\k}58c[ˀ}o Y\xehKV5an+Bm)VP{낾ռ qsXr~-ʦ10JTVh֘g:$I*P3/??2_z4#$sbFce2azA%X_(W$ڭGW6΅<wnj˪M#xռu0jsFƌ? ×-%&XW6B)5Fj(dt +ٔcd.A8PVd@!ޣ?3 d?X}rPu diG:?kz݈+Ηj&|XEz0B 6ûebeXS˂sY nb|%/O@/{ 7?&:ns֍nb$i䋉T/^FH}ܙq's/E?Xޡ^쥘̬xrE<ɡ?^&\j D"R=}q.*BO!sZ.@b@ a!҉X8DELkY`Dc"D-9n!A h]H@|:z e6HD0h_0o"TB b>"k8qT !1\<0G"02`̘Yైئ3}bh菈L?La5ԅ!U $֐t bf@D` BopQG7"CBox/2p`!DTxZ= ^0&7p!( IDuwC]46dhh;0?C>1di5 q> .+!B`C,﹇Dɂ(ȣRӇ'dkB)?`ܸ\Bq5 3Pa(d D)sAeE ] Oì 0uAX@hTT5 +A58 ȇWj0DHGF$YbGA@F36fT#@T r@@$d|YH a!azLG[,L9FGŒ$3Y?l$ ?$P_'P_c)eXp} w%V8KpW@zX-s&Om5ZjNq>8a5Ze =儆l:aȚq Yk6[A|ƇscG{ + +|0cQsĹ,=Ę {Xr)NLb=@rSj)?E^AQ0zp@*@&py`FΪXyHV_"ôv+(xϰk PcX;zF Bx;8 РcPZ};S P1 +v-` rp(ŜH\R)I..o.d DB[ ["vaou@RC^9nr>z[鵽(7ҁE`K:/v:쎀@0Hi0#/ 9Gͱ b jY%Z)̱ c11ɱ6 D$]$7Jh9o[42a20: pw8m}1U8Yg9 =8)8 xÞCE*iٕ}5 |EB|8j,7Oxd5wt58Սŵ1tkcn(% :> [ڷmL YJ HjchVk#kԆm6w1d M ٍILo$mc :.=mr(5!5$q!Q2EEAw eF*3Kؾ[Cs**% #Bq4=2[c 5l1<~qL58*>ʱ˼zǁϪ1ތj8q8550Rcְ:h^~MD{Ħ8F1 0r^=iD5qi 'YDpMh+F(uAIg`qA8vI8b"q8=fКBklc߀Aǁ&1iN,C" ؘ1f8^f=4 p͗1f ZF0,ÜM22aÓQpdC2'CmÁ c֏11Оp16G1~SIEWh1ίbHD1Lbˮ&uNhh-tnJ5 l71 t7 c!`>({ Өc_8cJ'ppH`l c_r8Bo8_ G\8a +(_Vc²yAǽA {ARz^ Tv7w ^$¯8fqE!/BB8r̍@6)ϼZ`#pxE8r%ڔ]|œ2 -t9Leǎi0tGQ<:f`Y upMt]ux,fkxdH 0=qV,%b2,wy`10<d}+OhbЮp]c2=or1м֊Tiq嬘= +/@b+F|*@\(UcWPUx +1TDL TPA*ևDqPd & KOo ^NB)DMh1`d R)xD얂WxkL)ؽ xIU "M R_Q5q:0A!"(d!l"Y QՅC 2Y'*I,.+*XB9(Tb'!|[v'[f= =v<h>'N 0! i/9y&Pvc:cӁքr b2&0p&0U$$2AL=DŽSܐ6GzWn/gy@l7+70Z % +%rH WQv +!s*:r̞fCJF \BO$: 8Dmr8&AZ:Jy@)PIBzC4v$đuzH DA{xBBB I|KD2H"9- Ꮀt#1r#5]R`0Kfg?eD&2Q0E2dH],"hYN̤ԣ8D#t<;rDL #VR y*DLI ADL$>^୉CP"s8| :_IRC$-%ABIpa +&$%P.BVA#b) Q 9`a|/E^+A2Alr,A=)@b".S F uɼ@K@Duw0tm{cZ3 " 8Kn,x%A/\e | Ai.>&&&7Srr=01'?! ny@Ӱ<8\|LuDxXp'wc4C2t_J3dAZJ C$&V Ў߸*R^k5ODIl/>stream +ckV{s3VŢkVk߶~~=z^yrOu9oǶbޯ~]q:goO/hN[oWOsV=qUWq;}3V鶸z/ݛW{3kuX[Qi]j1>og]᫑\r'X(WX㸐ez3`o;M)P{kX⫵8q:Yqʔ:#Qن'Er>tb +/U/mLp:t8۶fj8۶mm$,m##۶M2ᴓm[3mmȌ3T@ Vc6HE`o۶Ŷmܶm+gN۶mmPm۶$h{N[b+[f-dd&Lrd+rS⪒JPi['hV%^f5WW)[}.PVPUMR&U3*IUOYZcʱ% AG+P-ujU $?bxV+ʕH^UY Ŗ ˱ʑ4 WWWTB +MUU# aTy^dzt}//I$I)1" yAQWqj,Us%PUU#D(%d(j/34[(6zU(-M'hod3+4g+ pAj''h*7Tf0/@ʔ5).QRk p4CWkg[ţV1m/w}wko=f=}nߺ7}Ww7z{nY{oǘߍ_}~{onhl1ޛgn3|k_wǞͷţw[<1cs--ݣޫ-#ʱE1qǙcK2oww}g[(M~qjG̓yXSyy[=w;-?n;}uWuj7/~loc=gousyƞs9^kV-Yo{u[m~﫫oϛg^mg;nq|5z㞷\kmy;os{Gx][?nn|-znvo{{sbܽqw5㋳b}{wc~GC꛻z^/=gs볾8_s}9zޭZ X0Wš~ *MC4F0CBbpΥU.,8ﰠre8M<B.Z$6 +6p* +L +Ѓ@" +:҉s' b;I@ dpKP<*SdL-Q .i!p$VĆpJ *1.9` +dx a+! tF 0g^.9<N#^FBF(qDEP ^ !%d> zDN& Ġ| +f@2K4Hs>hB~J3ZqN@@ mRb=2TgIx:uX߹FïCT)M?sTlVB(lNE_$Ȧ6@} +DB`%9͒ڻD@Gd Yf@!Fp&ExLXaT#.t_R r.*q,tη1PȖ xXD-%E3P6)B Qf ֏B"T]xB:*Tu +F ]بnln eJ$`'٢[bNXMr)a0WI19#:x1R )~D!')F q39FZ|$cI <3"HcCP "0D*6ć4`=Vģad`p<*of8)HsHx1z$#\p`.%D9 +9XtF]t5thʃаL 0jPG&,h1T!C4-\q.8 K"d +Z͔Z, b TXĄH BAItfQP,>e! ,0PF7/]Lpfdz, y$c1@'V<4n v~k]XMd`mj!"Hl]b㴗%q&#ö6ȴ`̬ m  HT:@l)ƃfD*&eAa6es$6ѝQc7޸,o'#o`7P(SՍm( d"h@<8m,m{unSIv0JDc5m۸n۶1 $bX?>:m۶6`m_l m,mN̶iJζͶQ|X-0BۀdYgTM+oOf(2m0 $*3eRzWq[X z@yShef>&h`pb]KZ! +RuZ1M@:,WLLE `V3:"0W4H*KAB@52H † &80 vH$*\ih50LC"{ ǶH۶ T!l6cJmi)ɶmcr) 6`8Mr(^qCCwЀRl pQ H8-KYh}CE@ʼnx*v-n‚* < JBP Ges5 :ʔ) eDy$I}#6DJBSdN ! &#TB<3/9Еl3xTAlfp1ec y`@ qbDž?ؼ ̉9/,<|>IRP#YY$X>*Ge9[;Z|vFhŭ\4hg]H2p4s7p"<(\Me#}x E2( d"72\MQ#jDy\D.npbˉZ'2񱚛@+yb%%V\L ՘`L|CB"CiN7 +&DB, +"=i!*`r#!2q +|*yfp1#sT|mtBa䋑 \ XTr6ss^f4ܡ"<0Q8qx +Ͽt2/gEwy,ۇqڄ3w=,Ł +@zpÛT`Eq.9"p{LFvRH:XE^N3U Em9zN+Si3 < &QH,p洮dqEY xD.De )AKFP3 :d~DyI#3.N&M"7! Ql NNdS r_FVC,hLb8hcK Hu\$$D%1V3؉5}/8M$Rd2R|*B"yx ,4X?4>x@HHS'Rp8, [)Y l$J=?X2GUcs&d |A1 +`QD (/LE эf貲0[jƸC o5**sNN[-O+cUfTBL1ތֻC!T+"ۓtZ|L%auH+#_Ȥ,-RVn1]єĔk +1:nLx&kWC;ncJFIQQ=.)}lq ( /"" H.]jVjv x3.,g5=4[R>F?iVi^=J~GW'&6mE^TuBr0?'}Ç~潨6lMsA-"NeF[_џTUWA9<@0sۨ7l|,TlϰeQ8ySٹlЪHSs?(?ZjQô"Fpf_^x^Xy,/ +hd2y%g-A^>beձb'tX&3Ek.WnC,4[VBl*rA=~tJϮ)]u̱'ʢ(]|02'" d9THx:yAq阸Óq~miܦ^g>ho3tG6L+7=w㒸^)KO?j|_ɓx@|ҝ6Sb{EY :=Plh |&xJ7M5@pOy +Ni0e[º~;amY%{]@5g{ju.&.,-[tܝs7WjѭrJ( +GઠtT8fNM⢋(>8` jstJُ=Xt:\q(@>@)t[tw4:KcDpO͚%Β <S+a'=(}Ua•SAGZd d} u5gN954 8%Ê`UMԬp{I eU;Qhł3 S1k-!KFsy8M}̠d1(4x|< CA vVpٴ\S 3Sne}kBv32-rab @BI]_s3уeM(6Ê%W{WR. 2F}d=* x{ &{U+@ +_&)EFP4 Jnc>"cH,c#LR\U;U^%|AJSĪq$| B[>~ߏX}K0~#&792 -߆CNDbZ^M8)`T #䲷.T +^c.|W!`bCO\"f+KM'~6u5 c>kvr7> adwɘ~uTA3Rk@|^Gz@omIFe6*pXIϪ0_k O-V6IE-XuzZHd@P:6Hy5`Ί?W O;LcH`KِVdSh @-ᚷwȐ8 +1(cDr>fsh>iD6D |ј/`G1uL  [vi@?ڎU | +Ƙ;\>*m`zCD@0I\àn"ſ퀛:ܨla:r> Sxہ)0Hqk Pc*7ۊ^5dVꣷFp=fD̫[6w@_s` $`F@0FࣳN˭m{mi39?x ĤbDϩ]h[?2S#@%+ +JK֐F%&X;2|ݐcGDSatG,)B~TBiizx`%Ы9cJQ[;Yf.C\>0AqPf3pa.!Q 4\er?tyB^91svd< {> ƒRpP]Rzئ0Ne8`]Aw4_b Pau,͘)>9bp舙C={L v_4QL&zK] ? &T©dPZ3޺Y 4f%{})V&pw%l`6 E}ԼXʒ3 {yIY0n~2 +┮:{l3qo {R/VpUt8b @$+~ng;=ëy N@ܲrzVez ܠ̵..2b-V<`ex:g/Fi[#P3w24 W%l\ԋ?>+TȖ]I` {uvS-pA'`ۚFN蕹?׬.Z0󺇚 7Ù)Ζ{@R%/F} {7ʁA@vt _bgTl\>%r.x"wfҔ- jo\\XwE̸ԫާ4FN}xࣶVA}l٩4ͷma:;y~m߿}^u_5%jڥ)*{q]耔\'K9~.A+ZWQLF81"19iYܴF\u=5TP+[ ?15`0Y%bW у]`y̳G u6m庘'~ 4V.Շoh)Ɋl+E]iaN->H) s 9.XZk?3@NFDo1q-Z:>1þ~ߓ΂K;lD{DDy1mn41s-9犉l!dGCϯp 4WV +_Q.dEq{E3Uz0Y[{tW- bTp^^5K9T1}b\o:q.nN[\C߇pճ${z+K||=!j`\6UX  Tb%-TT=eX9Băqzˋo̧BrPF]ap7aJNk'UH$;-1j46PfU {|FJc^Ih|qwc`b,5f L|`Y0Di>s($xfH'NY`0c>TdZҦ!ŢĸP9AJPC%%ePt&[魁mZ'§L{8?6DȽ3l乮: vl,Z/H +?[g A^Y1PY45$P'/'.UL ݃M9[bl@n[w~ b~jxޱ(іB0m$ Hk\KAIԏ-NjqPeǕnٌk@g$9"9X4 ui% +dRx6$o!W艍EhP )ؙoR@ KG\"n`$;p)*yq&9€j1yqdn\8*Q b',?TИ5z|]r&?#a6kG$3w wss_9 ̔p0 %مYQ]G}[\轧\&4bYI6KC2}pn=MHjN+)r +f=4t=d;9C4m7dIC.}4Z%/.N(*ǍJ#FE#}VROz!TD.(0fUКiuW}&LN+w\=hR&6*f@[\ǤԜ&ǑBްJ_%\1|'k_h'«G\>}1'W u&R (oMb +e`~4:SwKZ +Ep0宔54J|gY¥$AS\Hy;~Gu1+xSl\<ȓ3WҺi\D2*F]Mc67 A8m:6Cru@AUvm2(Nsvak rm-|M:P:JR@s3ek-/T6[_:TN*>"od}_DR]wlVfQ;UDOpЄo1~O?Z.W啤 pp_1!\RVO8\[iE T؄_8^0G|^ܝcjb>;ο|UwV*d+7"OV"\ßW;2àlNTfWU+x*rB]C=}\ wjJ#Ȱ2_cU\4!l?F*,t׎栜ɅV|֩"{?BRb7(9U~QQNM; :tdxT[q;LRӮqA' ]ZW9>I#fԊveĺKknD|I()8J1,O%:~>6I+T c{( +ڍ&l*)pnf#82RG)nÃL,v?!Iej\=2 zfc[z6HAEx}I)W0Wxpldx;Ӗ.]zTcH@^lqnm#{%S$g"٧c#u @v` ېLz>dxy"f[#DF@hZpt@wM7t+dazD#1%|cdσA0J֙^4(k|a^-]꟰G ?D,Z!$ qͭ\<w^bO0ul.9$0xg2fBCaf~ ce߫Zq}'*_`tqP 6$CVwKkP ;a)A˟ChA<|XPԖ,:jl#L'f1Ԯ 6k)tO| ` >ݏl2aE5E-UA'enC72GcCHVq\{.8#]sUsh❫)RY%30FrZe2vgtv\.bs8's7jBX>0sv 7(De3[W 0ngk]ŅhGl @™M nŠ!lq9Z|ܙ osfB> _6'.gZ& yj /}[OAr Fo~E_wBc!*[ +SfXw5 ֎`_@.$&+Fw\91Cy ,b9/9 +Z(*pdM i+HV7^򡟖: +Aq4RXOSɧ@7 dwq@Ⱥ[5Q )nѕ`֥IR'&P#-L Gǝng,n#&~? 2P̛J`,ͮ2SEB>pS@2Ƶf +E Pu1u3OH_R*<ֶg˪,G1CFGhb);H3;6fT7RpZ"įq_CdpƮUIw|Q2 +?yu|V3Fmc|u=8gfgK>[5FPnXm«! O(jzz>C0@;VZ_:R[p0ڃM[BkFe`x hT#%a5CY` CȡZF0RaHsIy;fSOZqaR|U6NGJ>U]$6hدi1* #S#__ib0}$PkIPР~LQse 쳿Ty>.3k‹?yg3aa@{Xo6FP9syN٧GDgrc?c߂ 3*^'–aggՕ@p Tr㍹qe[DQoz>4za !H> /rUT&)\i!x.qT[b #B$mV*vA:gW[R p.`Ѹq9,QaoS˽۱*L4aJkށ<j:t΄+:r$@[T~U_ZK\9 +YƘ6x +JfRN57mc_A9<JkmW[Q^Iހ95o+ކ ]P*,Nvqn-R\I٣b</[v=3 ٓ׀w; Hs껡B`z0":h>|F9Xh Xv"yL># ٶ#[%2^Ro/5)_Sq>~gFdjhъ42}, + u[l8!qൌC$vPua|`˘j-&TiO},L:#655 Wã +bSBod:f% +/v^\ +iJLUN9SHCf4o~Go1t|3}VU82С)7uߣpY ɅU9BC(EٍçcQ|kj-Ah/uD|2}esM{gLwzPmZG;/<??n@\ldB,#*vz5&qrx{&2F?W˿Lȿ :@!y4N~T8r/W WH'\.q;a)w=..l:U9m ab'MJ[}@LL!"+1xIOXtiqqzo,=J:::$ژH4iTVXvàq@@M%gdƮ}-N>$pևA._hY2d<[3"ÔުN) +xïO#{jNF=݂=b+yL9m(J䥮>m4a*B3A0`0$n03D@OjDP'z@&)1jDd!-j}#\56v}ptT96Z0LP`M4ʳ`U/DË0WH7kcTH${ 4pݵ/Lcޟ$kI S{܆(,^ءN|i'IG3 .9_PZh߯:~_3R / gۙRL -l5u]xiE0[mJp#d%H/<t/͑r_.a=Ÿ ^4셤H"SS8r_ƶq/V"Xp6U +yXat$dƯ2?IaZDP 8 +J77A:ERsj[j\_(!2zNy2)S&ʚȮ굪u`Y x?MO+"lo{un &|;J?dg.H>90 y\lMK/J4QS)r<VPbe ?uicݦ>W= X p<0E#PD2 hƍH{[<1 K!lߑv;-kg(T˟^CPքy}{%csUQڎZz $4VH hhpMD]&ѻ(5@0F~+}iSM+Iˇ ?z6 r1 +~=o8XksڝU)-u ;ۏY+(!CƬvɐNfЂ.Dܘw^E/a!pvԼ@+/YVg 'ICaYM8қYPZIWDTeP,rkHN=?uV,?QíL N|fc,hsj*WFψH򝴹 F +Λ]xNALR'dGAaY4U֮<7BÍޡ +jԶ @H;q`YxvNO FH{DH±@D:-Tn,D4.㰲4/kC:h|wiШ2_TA' ~gƏ> d|]gFy[au(b2ѣaL-@,ѯصqUWTJKW,Ε?:rnZUT$sJ:mD`=qߎ S1.X Rjdbr|y9|EZk_$.2lٸF ]0KZ 8/xi4 H=]_$^w>`_2JZٚtS%rִ\Sܱyn|aJ JuX6|H( SOG`:^ 'X?;=Fi߇](Z^ViVgE>/՘\* )8 H@6Ml׮[9fE6H a> "&7ńJǣ[TdJօT'N/(0O}apd!U% ǂMCΫj17h1A7 i9[G(tpPt˝~S#vC9Y/ +bjbH9PG @QC Ξ{C!5 3JI +<i {d)MO,vd6a=`A]ZabFE /S;~S}U,ާ\#2vv ݶHJP9 $>n2%.%L|6&a'Vȴy5I2 x9ºļ3w NjI -91r0FهfJ( +Fpt1O~+]yW"vֿ288Pgɷ-4PuzpTd[T_ZO>eQ J ?VBţnK*N⭮GKvFYtt{X=_(WA ] +Vd8:%jX1{}Ybec?c+U>vg0 VԺ9}?p&u75qLpZh9ݤЗIƺÅ4},0%{z +}ӬV{p\c[ت!g?Ռq|x9Q ^K̳+9ӍtP1/͝c,TFTC[t7 bpIW59yTd8]dLݓOC9PPuMJK) i7J;fxbIJ2$@6#@H}s4zr{6R4zѤ2RAèݽ?@3Vq]$D. + v 4Ee\,qsz%!h-^]J!cZMz1i"KtPel^aCj_ I֤@`NZ c(=v_VuK6usZb4lm0k5"Lc"|0MՊ䈭 A&4a%P,dڱ⨲aN +p։jbY9잝C#9RbN7╉*Y̪!"r:RCN2ZHQVga(+K '"F|$wo~Ɲb՚Zעi<05٪ljgr[N/FxF"[ka%zs0;]wgf}Zڢ0 @0<)Wxg00usPsp$G3+,D/-*s|Czd# +i +7J T2JFP{.%B\b aU1=qe0=i..xQQ ぽ˾<>d>dqt܎ۉcx &c/6hiXUpX9jw=X;N[`~$M-0b$iJ$#9)ju'xsbԦ—}]CD:I^PyA-S@hfF1䝦i<;m䍑)ĆiyGn;ZE46C%5ˉ͒Jкwj-o  c:8Mh[rWfٿ"N3Q@_Jykz,W[-RMs| 7G8q + #:nn&`jϥו9^w.0ʰ sZ  S%>+O-wpX!YJJ#7d<崇CoyF.+䊉g9^i^ª!eizQ-T!DCrf(5 q~og)V$Xͤ[I}L @/F7/}.n *T&C%5ۯkk4q,+p~X@Nc_#Io3܎z=dzMۜ&!Cof=D5x#.\H"l)l7@.'XJz Ԏ2xf +f8dŒYuLj;S`R>+Y$sX* +`ʃ@P0{M^֫N"3LQ.^˳ A ހ\5Ҽbc`\A ܯy!D6(?x̂iTTxޅI>> {i P-Đ8lY qPg +HooٓpkRMx؊j8 Q [Rkg0*;; h,B!w /ě 4/"_j]# ɝG_h]Ldq`% r%_*N|tį>Lk')9;RKN?ֿw>i(up#v.,ƯaaEAxsay#{#_Z>ZX5܄VQ/pe2'8 wyW:v>27pwM?&9xPg[EqEZϩP'`,|5Ib V3ޜ_dG` KoMQq9T/ ^-qIzU d="~FIڜ_ E{WC&ś4!h UsqFoW vw;e`1Rm9FUjhخQc`PU`r$|!ݧda4r0j˦jA9Y+$- ڵ_PH/qZ'{&|D lke1 @@S qQp0j7)"&҈h]$+uxpr"#EyD;9ި=dVSA}XzF)GhxW|CP@p,nʇH/}tyCрއ F/h̡\HI ++FX}=R5i-Z 9S +$$jH2ZI4u}}XM)t>0eG5eE'\WslC8 z@W)0m~5񽉘&røj8rXo8Qc;MRrr9e[4E EC }BӶ^a#IO74j8]i hia3I\Jg -׭XՕ@,p^/c,5bKOHK= Hl` ދZ~1[:ĕ^:|+MZDxȽˠ-J"5[EnTՈ$DQ|ޕ^oFIƯW4_ lt."x~e^z1TNEt׻K6&'k&{sv^7xN[+6'^1CDԢE2R"w/l TJx+zדTrwNJew^aW.<}:# +9nQO4qޣ7,=wQ@◂Ť{Jtr*NW/Mş$]œVb,R^O5\$P۰9L$Vhx:1›iCb$#A931EaϘI^px' V w./h!'[ُ Fms)q/-V*Tv?J?}fPJgd}M 'ls@ZV.Ym', "I2k4lup0AiyIv͔n4MDMdr(=ES4,M-g(z%lwn[_SkӧYO-?Os'7:PSc &jzw_e?ύ'k{?'{\G]9H"r|prD"%X<Kzoz>z;iL~q H(K'\ V6a&6\N 9}x՛88m)K!BmD<:(#-Z,g<V A_ E.,i&q!)MۈƑi)b,Df&~L"qa*RVZ;iCERuXΒ 9M3R"'O^DBl'2`J`~14 i)%ѸAY*d$,pI\ǚ-cb%m ;84$.2+-1WzQWᬻr L ShKK6 j/rWCLeREze(({ږS$U8Js{cD uN^W+-6#^Ĉ+ &U2Rnkԃշ 4>qk+|K nG\ql KKjCuG K5N X|.N/."&ي{AALA)bSm+`fVy߮*EYB.kb1"1f +%7!'4hPI\4_Jj$wHD_1| + l1 jg`gA#_s>q%?vq4ON,6h-*t9 K߶DV!WfۚK7 QDB?Eh)V `\JV VCARYHdIXfdCx+)1vz ڳcI,x d 9 +H9#l@, XlU +(6E*{*t%iXDVY-Wx[ 4vV:pƲAk8ЖvUOpNom1YU(!H`)@jFGart܈kSa8Sb|ű{tMb**0OB.Xw؃Hku(͑t֞yZ[f3FEgԎu+8, +{%Hj13)e{W̲/ϘuGfoQ ̳6Q]0dHP֐GSft=aɍ*ʬgf[Xe&b=$\IOCQ{z1N&Ǹ&)eכ_V2+qaa#/1H9 _QSi#h!|mᬥ<ت60P$e徂56_QԔv[axtC"$(a2^e +wNVICf|D$FhtO욡בEL.4Wn r.&eڀV_M@,?v[%el!`MӈZ{*?ʬ%2`GR aչ A~(]J%08R9zr8ik-~`6" B5#M*YxŠ0֖ +(``kUWdxxj`ˆ%ȜIWuο5 gQiA3e]HN@׿ɘ$G PATej@30<OASkM@('Dɞ "r>o7}\nr Ko=r+h~Ip@G#R|V +=NgdN}S'ǘTgRErz<#~;b! Ɇ#= csYOt=F{Mg\H4]Ji~)l%2fɨ +w ,$|B@blwnAA$vGf5ՈG> +< +r4)V 9GOg8<=ZIHMDn*eeG$VH;̮rP<'-^?W eAm +%-\!ȥ̺̋"BG1sXz!-yJtPA\QcX>/lLp4XHR2hRw)nԇʋ8&bNM!~]QcB(8*VT,+ΐtrE <#F"T7QTX$jUZyq\2ȧ'Ouc0:R!^;%|~s(ת__;Z8~ :%Yik +wD.o_}(mP. h. *!XO6CE۲vr_sk$U74-YT>TBCVgl(!#uX*`$ҳK4miF_u +j>Û󷑹X;w9paw~)l7)7Z#TOPE`[.dW?FY1p%Q#md/9 +ͥ;O:P9 +ldJ.*k3 eb8^8fRǒ1A;lx;>iqU]-Qha>48Xմ ?[X8$&( T, S~0@ އz!ޱL 7]eii@]۶Chnuм?riI/lWWzzK@&MUyjlV--kß15nmݔ'7Z(vP]x%`JJiGjTDd dgK_'bW4w5W!!^]#z>@{9Ct GLYLQXdg +C6g'Bc?Tvxv>>_6w(;+84 gMI9ȷ!A2IA#bD(hJq' s#}ПK&܏2~7x *2нBh̓"W|$c.&,ƭ6~EHr}9 `4jH#x -X&+7nUǠ1' =dFM; ' :.EO'az;ZqF-b*B)/Py&oOјހ[uL QemVoVQ,;$.t%UOYZ#3;k|8P?=Qb^r"DD +XyE. [ +՟9㝏O'_cuXt9pZTI=HX1۾[홫4"\d6X%QM+(aL' ( #ф& ,rB;X&?;U]Ni]ί +ĪP+WE51dۃjHCDg^BO9|; 5TB8{h!.]&&P'IW hrYReDB;.$aܜ +SI/&FnXob F>ШT^:& &EU+~w3]+[I)G@5d{4K%!XQ?'JVsg F]|powEn(qe{m'$x Q@Vd?_dжmdUHj(j{ ,;9k}3T).}ŪM `O~t`j2HhA8aU9)IKa9 -75o .ehp{}=e{lPDݭ3u]}0P~G#ys^S}Up3o 'cݶ2ar IDCrU80Q1)F 2Yknq:^ .VΜ@ yOl&]ȽrBoFZHՒ Y%$$$|ieph%6W/H'tdq\J:e#[(.i*~_B$Qu%GÈO +IŴ{R +B8k <KAA8}Jq6VDv{"{zSUsRv:uf"+~o."Nh?^5I0%f8]gl]"?3ՆApƘ *\v"BmDq +S@_B`8=#£/G*c/܁^Um732vr0Q.2'(ӷ:gL<ח˄ؚnmQh[U~.jV 4: ?<^qoFݸXWqv0W]qyڶ4V.K:Ʊ!BAXdrXLP%ϴ_/hpO}\f9ϲUd&g`nv;Jm0.t*Q&TհRƍ؁Xde9E1 *Ak);q%g(9.F?2=St֑(| 8F@|KȚ7!5OP3v"`QZo6P`w@ZY5ۯڹX49~Ik~ȁwzs(FK.mܑYz479Cy e!+ Yχ0*d~)rD[{/*]4~*"+y+UdM]Y NYP;iFYpXAP-l!Ieb_8WA2k[EnP}B9"a˼fA|@z65N~ P9+nxvX[@UmCVD4/(z1+Tr ~Fq"yNopq\6bpX8_zV +( hWp\ueg,HJoz%((/U^~s|QڇS7lO4Q' +G+}8O_i~Y5lD +[uS_ Oo{Ͳ-X&Yp#̺iG?ɷ@(2R=њ۫5%!Io1\/M=i)k+M0<?fYQDXw%#P4/PwYrla2Yn4@q6b&VEHQjrgrӞzWlcZ>{Pַkl{l"Y13KI(<`7$7t⼊b*.SMU8D KRor!6*/cN.A LdVJsR ޚAzwnZyTEH(3"6T?+d)>,^a p9s{ֻ=K> P!W`*睍$uD1qd‚hKw+?X(FM{=3?pFy8 *d^z +SNJ#)`p&\Ю~`QGyJ E +JDAAIJ[ҽCR@we" 1ӹtvB:˿vql-RjΓ[9K2ݜk +)S\/9X,}.|.ATDpf#{WU j Ǩ悶٧GŞ(f6{jTMhzb` 22NggW͒I#m x- >4ePg$H+Zи[/FkBF^u0_[T7_p:HiDJ(>˄TVr)E@ŖnFN.rC3/ƽ&va9]7${zF(YNe~LF,&yhZ+rvEf;YGNq4qcY/wA)3Lg 1uԌA`? +u|1~_ @t!9RJ2'{Xz$;a,.R +5c4Z\}MN$d#r|@,<$gCujaCm7:ad~i@e7L~[Q05&!V"/Û;b%F2eUشEϜW9uW3PoCZigx6^Gvo +rZ;눇X%Oc=# +AFe#TVe捥siD/˞_W+i=!!oW<hJ5P+$#cڅ; v֥`:% ^::Z:P ǥ@x&BnM`Q9fBke#p!uli2kEݫ-mm#|\ߣ#W W#* Rߖ J9`ES584nBF<68xs/ע/lu ɰtIX@ͳfRs7ucE>WĉALx<<$QW1f +U{>1x?ݑ2^ `kP}Ԝ.{][پSUv#Ac5@mVQrЌo =;=Q#Mnju_^5QWm;F%E-%޶ +:XAglMk<an>Re*/fDԨ; 0\>: d2{OpX ]i}'t % xJ™oR\!Fd+L b3r"pce/|tXnx#!udǮ1}aR +M.atnr)1 rdu6'̃"'vifweIAډ&Xbdy~[<J&}RU˒pZ&&p` z][<xl >bM>sR{ ޵Rv#̫̈́I=^\F0뎴vTp d7Bۥttn{"?/L;mtc98̡az%%ɖboLBge cM8H +1˜޲X^m@P  ݕ0d{8sm`NΪt얬Rᆍi%U#K)~tՃ%4 +w +1e,x'rDI+˞q}̞;FEhD5 endstream endobj 24 0 obj [23 0 R] endobj 38 0 obj <> endobj xref +0 39 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000039285 00000 n +0000000000 00000 f +0000039336 00000 n +0000000000 00000 f +0000052193 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000052266 00000 n +0000052440 00000 n +0000053596 00000 n +0000119184 00000 n +0000000000 00000 f +0000041595 00000 n +0000041917 00000 n +0000041408 00000 n +0000155045 00000 n +0000039778 00000 n +0000049510 00000 n +0000049397 00000 n +0000040562 00000 n +0000040847 00000 n +0000040895 00000 n +0000041479 00000 n +0000041510 00000 n +0000048341 00000 n +0000042251 00000 n +0000042494 00000 n +0000048628 00000 n +0000049545 00000 n +0000155070 00000 n +trailer <<127DBCABF56046DFB7D3ECC9A5BC80AE>]>> startxref 155256 %%EOF \ No newline at end of file diff --git a/doc/source/figures/weight.pdf b/doc/source/figures/weight.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c8310c8699d2a3d52a02de83460ee02dc951d39b GIT binary patch literal 150504 zcmeFa2Y^#W*9NQz2ul-CKoAHZHSFHp^enrJ>Am+*Z<3o{Z+ZX$0RaW+Nbk}F0i{Tn zUX-Gu^e#oI(nZQYNp`bKQQyVy|NiCuzx5?=a%aw&ne&`7cjnwXtrZ+zE}TcH)%wiY zeLvR9fpG+!-|VVYPyk8MFk(f*2#yG@sUSI9f%yX{7IvZ`P|5-SX42 zsLvjD;7ANIl>n(D=5UI@AeBIA%97p{6@|hWig;_~6m*UU5Q`fPRGpM*EJ?S8VQtyDD5oHvANK~lV63>f*W(N2#|v8`petxT z_@259wZx^Xgx!TLnW+MtL8`#9{TPa)<`Hr&1OgF9W8}e9GKos)h$9k+1c*R{U{Wpt z&L`0Fi9}rSU(2E#@T~x|+VWK#UU75aS7A#>I2_1_pja%H7bE5QF*^h^7>pDfA~6@# z$PFcYVI-dG3$@BHDdEFGLl(>#2s`~gT#7GZ_D8~nEnB7<%Kl}>Wwm762}CeYx)rMh zLOrM#^@T$aoCibCqXW{(68b`UY1!mi{9Y)I1OO4?uZZ|Uul?@{?U2)J|0{B-^zVti z-se(=!YZ^>pwI1ZD6Ky#G~|z978F!(^}Jz+!rUm3WHB=T0V8e{i1E3soE}dEC@B*5 zW6x(;ro!JzRHOI@frg>L^W_-|bDZAiw_So_Mk=5h>I(sF0*dw=9SVhczW+!lJpW(F z0%#Ne?>qAR5d_MZ$rE6J0w6OIl(h?>_61f;zRiz$k#G?b2zZ;DO2+}Qx=@>L3{v}c&-(-ArViwWl;=u+8yBnC{yQ2 z+RW7_S*E-6bn68`PWf!$*MQDw{C-bS#`6eEH3>%~=fSvkQpDo)h5aE%`vT}`nlb~- z7NHy@j25MwR4##@OCV}sMm~X(PXa$_`2<24CYhQ~@sRqhPFvzX;ZdgM(>#jf%74VA zY~82$XdDr**@rkip{InLlKhi0&OllMTdF*OU?DW+2nt)4c!IJTRH_3hg$150KjyTC z9YsV6H7%ktmr8r}ERiFv3q=%SDN*sIzoRNvU6F#zFQqHK_;++pF9@$i5W@wLnM|eH zZ4#;MOcvA5WvZDhA(P30Xi8>C%XdVrd`1%CGh#xHG$Lg($x63J#>5kt=|2_|)KC3! znQdCdnVp!*6fyWyGFcFw%;dOvZZlEjVe&QU%S;<&W(q-}UCCuJwOp26%VXKye3sHE zV#n-!mfbGlF#Te7%r8ze9*{@ z7+1iGS!5h0!3bI~@*P?gPvuXSrx|7|mL>WRze98|P^FzI1H)y;xT?&MnL-s)DOG`? zahXVZ^a5sTbV^Vu`={hFV?sUCDDWOWGrD1q!|+M ziljrNc88@JEk&X7SdDsJz--{br~y`aOkS%W(FZUyAC8!b|1|tGLp;YL((64Gr^y?L zSbQd`%^j4x0|?>^ioL-gH4(;w_$Y(`MFVQWWOGw0#-TGAT5^!aGZ=%OC|($r7<5E} zH_Z@H#tf0TLvK<$lT5pSk%;4YRGnWbqw6%16hWGb#?y;XBNSs2Y+{>-;e@G-xCBwD z*>WgKQV8WnbC_^$;$Zw`;XihmTggKOSUXn>o zs3HL>Pp@@zjX|eWXM`w3I$2NhC^TlXPC}G;(hLJhl0}Bu3@n>ng38gLM51w$Bn(cww5Q6#f9=x7sQ(6r&OlC2#6A8Xv&ZfJ(QYk@~W*CbGv~D$9 zEQNJ;xkjTRklhwohX(L!q1EOfI89cw)Dh8GNgO3UEEJg(YDDSQS;W4WC!$hXbbg1{ zq6@^?K~mD1W=H`RE)jTCMlP(TNDK^eOrv3l!yYMvW{GH&5{@~bBa$ElpO91HI;mAa zk5LW5L`0%jVhUc^qIdhH7P^WqaGA+zh7LT&)5haEqBxTJ2wLM7rJf*3lDN)TEbj7% zgcNqrPgiT4LABoIb0r|FL9Jw~)htm`O^BGtM5o=SP~ts8a>l`$@d`6f3uQS1wh|j% zh3JVG7LZCEzNj@R4T(LlgUM3RC=R+<7f>>3lrN^PLZ=rPo&aKct1A)02W_EHgpIf{ooS_bAc*+O;(K|=)+vjLZ(=lKwci5QLw zI7m<~bf}a(KN?n%Fj8D+=lg9QvyI9_6VxPL?_mi1X@)wAIPQ+hm_Cle50m3mx?e{M z`xJOch@ez*&}EY-C_$o(5_F;lo0Q=ZQS@{o->=a~V7t*A^oW6rQwDezNtD1#Gvq@F zi_WB@*y&NKjN%}m6oOfA)|p8fNr+|k5-n~qS!buxf;xFp%n4a^s1?<~P`1i0ArRv_S=dAexA;L;PtONPTrr-0_t zN-TJv+!sy=h#n}R4@z}v0z$#$4z3C{`XP+xlzHF?QAt-S@CGkeC$-^2VI5vC4!OcK zFDYW=X7n&j;d$+Dfmp6%^K}lg-DT$KG(4>nRwQ*Sj#Z!uOB`mMOfMi}dahl>Gei|) zo5Lj_Knp1-)n+7xgK)qa z6DiDcv5ZT#V_^c35dw~j&h(R#EQ*cJbP^mySfln(sfNsufr2=-Rtz;o!%VB&M&&qz zNE+^>4*bG|x`;50ISC$?%jZ-$M0{(Uj`xbeEk%$8+w=@6!As)8kX&ewljG?gs%T-6 z5QG__I1~p03CO4luO`Wg%1ts3!5VS1`5uNeN@sdPVkcJ+6U2={pVy0M0z?lnNDMp7 z0dq`(Pxwh9x<1X&NDJ94n{YXks6^l}@bm^mKtTzZ zhDvfv`1Gj6&I(x7UNdYmF;S0z%Ca#fVQ0_`Vph6`>Aqg{SKBg?j~SKA~O(mVmu?Hh*HuFT?l3-$uX+Jm=O7`F=K!xfN7}Iz-A+2xjJcA z*|b5r6;2pn136?&P}n}2%ArFeZEoV6cVBbaj5BDBhgAR+rzw|R)TsYd=?yp zlo;6&&UhQ0(FHMuWO`hsCxoO%XH+5=D^)hKpR4tUVFM%JbLun+lZ~e*gIR@3DPw|Z zCl-vtZfe+;#0(6vIwTOWXeuyM$jDGbH1M>HvQf`2pfDl48leY(%}Uu(ptvG1ASk2w zK;1o*pxqhq5@>2NAJ*s`j3Ch=WUJ6LLpnWx=Syuanlb1nLLP)14G^L>X^2XqQw1K5 zQCRFYqQV&Dwb4R4HJdLMK}iZM77=uQFFin1ha60?M-!B#84|@@lrIj@L=-d3Q40_< zJ(QI2xSE8AfLh$dBuvG-NkqS15vD7EK}ZR%q{>8s!3_+>Wz#V9N}Zd4C;J5oypEq{ zNFtheL@MSC0)uuNytHJLVxkB1Y*Hj*2olL2vjZVg?Fj=fE=1iHu2|=GTigtuAPJnc zBMM9C2}P0>v?@VQTxo`Q4GEt#Dnl&HN_Idbh{<-j!(JDM;SeXRO0`s{wIzl0AP9M4 zh=L;KfZnd>>U~5h8lj498YiD7!@G@41DIlEWT;ANtX`2Qu2U%FQHqADqBvl=!XQ(4 z`3}6v=tg8JWQLq%YCTain-~^`WnrC*0&a?2TBnJIs<@a%MUYdd{*V(Bfk@0|5Ryp-#Sasy zE|)VT(}ZLq1C`9z>D&>ChDww;(lT^9OkSlp#9xwKj)Cw`fXC$$rm{-M6!lt-7%}}G2I2{%nMT$Tsm%&C8 zlY=oDJs=YkXgY-u=t~%4f@v8sg243D%#0z@07Vyr={6${+>8)X(G#d4OtU1AjJNSq z8D?vOlbWT0(fUPp1uN=|>*Q7;9M#AS;iSx%WGls}G-L{f+-586E;B)s1tG6988X}T zvM?W?2?0omj0pmas4}9U2UXEf9E-wW1}YGw6kSKslj%u~M8f4HoCK8V)+e-7G)N)_ zyaEuoIKaHzdMvII;jKOoB1#XLt225C0-Z+(Ze7_R>hPFgTR{s&6k<4TOh!?>J^+VA zB!w7>S$LS-h^KN;nG2HoNX8(Bm?%MqC*lF(5%P=YhdLL-OY{l>>~yXl&sV0c+84=8 zcSB4_L4y(+gEt9zS!T$o1`>|ay*89bdzDmqoF#&+DudK*O;Uqe0nu#;;Ngf=huXok znnVdA1_VQh0*Zxd1-?1m!)RP%@Q@VFI6j~=;wf<*4;i3AF)E@+k4Bio!(sB(+9GL*R4|ePJ5KoKQKTpj2c6y9E)dMQ5Of`CuC; zK(V;VLBCg$RM5d~2Z|WoRtnzWaY#LJHp`;YAPFZcMuoUoER3iv#SBTx5MmYkcm^*K zqw4Ue&Fy8=VOxSn(Q8x;sW`+SQOr)5i6qSyl1!ls(KH01Na$mk-8z>gXrstNI*l&@ z0xN}@?jhb}<%hy*dJ?ZOnkjrRLWd$Kpo&yZjLTM|1cc;s2N509nxf@6F}V-|vSeGN zh(sX38(_N|VTzp+ECJRB(+vGgmdO~5K=G7OKw7&V438x6Kr|tkOB?W7l2<_|_!SZv z(d$Ds5;fiqCPG14Qh|wMTy@x%2ulPpU|w2PBm;^c0do&bX_e|s0mvDpr_3v>(=iq> zs(>U&vw7nnAmPK1&=UyYF`-yRb(pDmXTnAeIU#LC>I9K4nC@XLsf;QNkX)k=;Y|!9 zK~ATKFb<-32oWWhiZX-Y7}Fl5aD6Vf)CuttDh}BNRxnJA01v_=a<`sh57`owkT4d{ z+}=vS(t<7^;zM4yg=i4DQunq%$I^Yp2bduno=lHIz)mnWLr0H;Y9vYoHPD=3!h?u{ zY6PsP=^0L$2?XqP51j}COWh7HKIpP*g<2LW!VE#NG39KYr^MjCJ?#|I_v`>1gWPA} za?ErCOtEI79yw?W>U4^f2eF}Mn_L0O)sQDhAw*yTkT{j$v1qhg$seaNPuSR77Frbw`W3`H_j3*n7C8(t)H zVnCJ3u39nmV9Fv=khDM}V!V`>^OI01r~)C8DM4*Q*2myXL~$VI9U z&?G|!WsIpvMj(nR6(7uACm60(ZIA1G_*9&7DJU+1K29+xs61ZGOef*JY!8-X7zmu8 zEF$sYX?Tf?Dp2@<2xOTc1wyOSCNlUW8ifpRk5l15$P$uaLR#D@w-KURmP^LbDia!s zlA%*b$PRE%p=Rqcb7&A0MFPmfmC&Ftm|0|GNYV!A+4*zk?vW`&AiB>*F#tUy3WBLQ zqb>AIB}EdS0ne-e;6?Ewi8DQ9Fgpxfi2A_Q+2p}$r!w^7BUV^|7_^2KQW`lv7j50`31B{o+NiHydN3+YR>4jCTi=OVG4s{)XcVId8Bq?HLOnTZS`-34s5eH|Xj8qVnuZrZx?qyUCW?os>%R<(L!XSs)&c-x5jX z5C}O%k%-fp&)|}{6gGoN2a%1#f?+z1MCPz4bRLJpC9{~cbRVBjU)tT`Hp=h@jpkVa zdjf%GMu}!iE}3DY<&se{l53`z&AAjZ!-}Fr27y$(-v*i}L;ehFp)V9hd=|8%+hhbL z(P$_mmy8h1xl|k3mTNW>h`ET>Y&KJ13WGug`^TA~m!W-zuL`8HI8z(WY!4C&6$LQA zAM7`#_MS7ePnADI&p|O~6t(g&zc-!J@y}b81?jAZd}rx^QnGRaS=qqiC)GwH=b|VL z%_W>oe_>t9^zJ$I z&ua#I5}V>p`w|H}Ra(lR1iCWNl-YAGR#kyB1a|8aWeQTlOKmo*(cqI;OA0^^LAf@g z(@81$h$W?6MIi)eNvi80QKjTsX_rekqcau$g>t0$mm&Y_HewFc_e5?1HJ?n#CxJ|; zOm0D@C+S*$%_QWvg<}YYGVQ>n{6~2Y8MaT-{WX8Ey63Z_)*`4xbR`#_CV9TAtQgS! zXFl*5tx{<}!K*l}2V^upKeOjao=?>-!xMO6kP((IOD9zp!Re8dx$taF0TR+V zLr${?)nJG(1mX(nvm}amh$n<*ssEzV-*J;iQ7nLgG^D>|Ra)a&K2ju}8UfhhM*l-+ z2vip2spZFtK>lU=FJ;M@E2Zo+s-3#(C?Y*o&+();F6I~UIm1OlpTz<4TZXlY19Yv<$jC@L}@DQ)llPJRpr{8bK2)2;QHT_rZTaL zG*~2^l2x|hbirTK0?kWhE2_aJozGqb1E8%i3bL&-gMYI0uepG1)&N*F28nUSwvZt& zz5LgtDG+$TB|HN}UN~$i>Bke5p62yG9cD@(P4`He06Sb(;I{sqUS!zd0G}s@lu??e z2lTXN{X3JQuUJWew)kCI2BlZcFxCjYnf=o!@VK+j4#^8(70QL!i8Pu7?5p7K^DUQFQunW8Br zdY&tLGKfCm%8J+t#P?51T_goAAEdPZV?8740V_@aSdHZYng7qPmAU$4hqHr!?jTDf zppGG7izD+e!;}8&e|A<6!UjLzo_b~?ZL^$ACNVD4JTBdSy2E8FJ=@YNC_|O`{m*n} zPXuIcXB$iZ{7b6m+d@`a;LD55JhJpD6XEBVfu`61pT7K;{Y!PA6r%rS#7ZoqJb0DR zlnbpAqKbtTkTy=0S~_?+&?;5={~zO35(odAAu9#?zr@J+DNp~hm|2OhDvy!<*CCdf zyS^Mo_P+>NDb5uylCi+F=)c*%SxrfAxDM*aty-Dg&aAv5yj6hkGEvJkh`qF$fax!Ceu>Tl?<)IyGtVZ zMT`!N@`bFfL@X7~>L@9zgK1QN9i=1`RDA3xFJg9JlrMr^RxA|{J7OxZV^JmrNfj{HKil&nxHByNOMoXhUzR(OMZA>0Th{-j*?mK91x!;M5v1-Z1R zgyENF5sXvD`_*a3v$F@W6pi zzks`Zu~3)YRj+W!rE^k9=}8K)8kvsBIxl}mxD5*R?7%XK1^s;-G72fnp1zIljvTL8^v%RcbDja$+ z1)v8EkX1-8xnrvM*k#ws%Y$9kT+0PrRw@+@IeN zF7RF~rzk6y3Wr@frzo9L^z!W3y;w?7)>z9G>#|a*aLA=I`O*or*$nN9Z*eHfWX#{T*}Du4Mtju&|iN9N5LrEiP@&6d2)q4eT&cKXWDrQZirB9}DL z%k_pBcFIpl!K%HnkVwFZ3tyTAV3<%M_3{K7Vs_WET$)cLl&oLt@vp;v*!4j)4j zq3nu5$?MDhyW@@u_^Zrj@kCa(Clm+fk~(92Sl54|i|MMIAW9>xVX2X|BaQz=kZKiVCozk_4Ch9C;(^S<%6R{tPu-}6(8^gj*G^DlQ%E~OW{c zdZJeGqGF~w4jQsx&OrJQv{XUns*1xa$^mWXgO@jY(J=D2Z{p8x-2K}x&spvKw=AEf z|G!3_mC4^+`9E>}jc}eV`af|!E0e#u@_*v`8{s@#^nc=dRwjRQ<^RO>H^OFwuGAxD%oXi(SF^HEs%8Y|rz~NAk1ohd&4jhd@DJm+~gdD-p z1A3|dD52*1OZtlw-dQxV<>C?UwX?qIXTIo~F*tH)W|y_KF7=BJzH?#3*rsh)o~3Rg z%;3Hh$T!tCw%=R8(hGm+rG0t~GrAW00w-H~980 z2OcxjnRall`O_PwhVLw{rK$Yzix1`xbk#WiW%sr1_I~?He!Dl1PDTz_9qAw1ohG(M z-|pR^24|~feB+t(b|pTZS99gi-&Rr7yVVQV(bOk|nhvZVCM=!vBY#S(`zI$}Wl~x< zBsCrV!=6jiCtxSqE|`C*=$Nuy*Vp!kC+DEoaIMe1@#VpGaII@uML%09_&*5>^*6lTR-`2<0vxuK9s6S`MdehaM%fC^~mj`|}Y}DCr#Dj9`wc7vg z(r+d$u>}{1M!we0v7t}5vFx9}WMSWqA2+)77|+!q^VIT@x2acqNt(#(O=a&|vwZBs zO0%XA&%htsqjS2=tFziQDev02(a6!RM`iH?dk3Bq%$zUlocl!sabfP|Grzi4KRC8d zPvormj`2gyU*^DV?KkF~U-HUpuPk9kJ3Q;w(#BJ41uSPcq(Cut>Xb`g%I@jF6iDxNnGf)c0B$x|`(zNp4pjE2wQo(om=JqfW#P2`H=ck995>6LL=(D16)CzIXsMCU`PR0V~ zJ%C%#luWvn#EA6ICtS+k%Bk4JkcsrNLNRoc7jc8K_gc4YEAR1MYxKR&qE4;x^mYui z$WSO%QPrKD-Hmo8sjyp~fMek0sowPnCGWKii11uRyVispb2lpD^2$uU4lN4X%9SQm z+1=QoV_~<>>^v5}tJY&@SRI@WEuHKxojMefdioV`mlo>o?K{Kmg(k8!66l%3g|QY; z#}0%p9T<5CPpBfcG3T;dg$fKF3QzD}mx96;t*E;85f01X6JmM1BEQN+<9J$2CC09K zovlSuUk`>R^(+9gas~-B+qYfhD@E*Mr{{})~cWliH2D` zN^uYsp{+Vrr-4b|zEu*}^ttQQICw zR{EY9Mkhjb6ba|I5^WjZBWI;l=5X}+l*3)2s zeI|Mv1{vx4JcUVxreges=}?V>(~%8IomSXRf+SE7F571&3vxCe(uTl{0SBIgNXN#k z8l`A5YNvCeF`#oHr`=boWo23^KJ~dcDi{B1#{@GL6jwGz6Ulj?U2v3iI5kfJvyqq| za~FZXk~UL{T-LO(hy53P>8hnXHFS~xIPdf!9lvfsC`Ud$eI1kb7G+|IA$2b zkttA$N68XQYMMY#jS@;tOVTx9A|czMRCtCnVoA50b{3&7BtmMassAWxKb86Z??36_ zwN?Mjg$SO0{<~UaDydtk0820fbDO6H_`GwM|05X^o{?dCw)qz_EIt+aIbsBUiInzD ze>a@}Z_6kYS{Y%&Wv9*|ODYz@M3@Y*kw9^9p;E~yyGR%1l7T9L2xJf8NW`?rSgDC% zE(I80stl+e*t1D7=$0-`ox@DTf$J%KOzB(7I!m{-Dcin^aVX4PHQ@#^+k0~)WI0beCq4t)RNtKnHgcWtd-U&7kB`uOnrJ0@DDs&{;u{-p2mn#Mk3_mGRX$j7gI zu|_m0x@_0kdiWFjUTt=CM{CLOD|MGz35r%#X1o?$xpTtwKf7$KvhJZ(@h2VrdPlDj zqvi&?nvabA=&td`oa-41z zS~H~prtI0d_4D_>T`TL0eYDuz8(+t{;g!#)c4%@#(r0JK@$Ij6m$KDe7cW{ixUKWu zZS10x)%K0OI&)@=i&g0#Ft)t1F!vs=z1~9Ml6_+Db|ojzWSC~OHqE3|+F#ZCeeET)3-f2R%5U+8e+KCU zr(t+pB*w3^ZV>Jk2fD>0+@As6Z&CRn{K{)}KVmi-)}qlztKgbj;7YCFoY`th}pl6E)2s|EFL%gi!x1)x?wR4kb(Pr18O}z{sN8-(!_bjBIVtY7wqNUX* zFRRjJS*_-$Eo0Br@BPu0L;a^78g%^7fc1w4?_1jZ^}rj01C0{&5B7~3G5hO}E%dzA zp-OFoIrD;5d(3*p9<1Htbis!0Rl06%-F5q0UAIvlRO!3zWT5HEQ&oLu8a&GDbfNa; zcAUD)Mg2!te%Gnk_15nT>vbN(vCsXkV~-73H?8u-?nS+|oql58Rz4gjl`1B>R_|7J zInX^Kn5tQ&9h#iq3_rl7?n6{}X)NUb+VS|z=7zJbu2a{4UG!&2T>I1~$EFU5+XudM=V!{>IXWf{yKNT*6_hw zV}2c)nEuDYKboH(e7^afjT67U{poE}vhetvE|JdbS2Uad`mddCzjnWFjV=ofy*uhY zp8nZHbnduC(|-O<2e}JB-*x1>#-8CzkM!R6`qr^;ZyYoG!!0|M2fzQmuBXu#2fpao zm>fnOUu-=;;bL#LR$a7v;R9{2pM-M_f=@+h3qyr z>esrlpr3C@)t>uuYBdhl@Z~lRf4;xx7mlUFRyp?1S{~2ke*43hD=4NfR(3nOxakiv zhkp4{)3Q77{mI1N%%N=>>t2I)pd2R^-iK;E+TY`c^|$kruXT$#_Y28~exFiRnp^iV zf53#CT4NojavN8sCqJ$_y5@Gvg4VnR?s=bfK7MoI3e6?b8-!t|GfRdZ<;|$;J~YhH zYIC(#)a2VtUc<@@t6jkD=z8#wYS+CkKlIo-=*9pZe|Dcg^7xDn)qXLY+ZnV9r(YIe z@6yjSUG_;M{@8EppSkD`W4Ex%g+~md+w{FT$LjcX$q(~Btqs-6+uOdoa@{NKlDEPl z?#+*M4fo{Mqc(i3{9)PBbxRi=+DMpr-EeyN=EZkb+}U&Ivpd`FbnLaJ@TUzYn)URD zF70q%!gsq#zv{fTbeCd0V@*eb8x8r{0?Ap6JXSc{7#$ z1K$Y`y@Om%%)D$o{bOs|bnBzw<~D6-->KG1pEGmHl#k|ZnDXvB(l;8k%^5sq;MU0l zw=G~<+I~zLxP7y^Sv&Hyyn<;h=Inlx=xfkyA69ST{b0+Y3mc9N9Wf4+6?e zC3({J{f63Smpv%#{L3o(kj?F;v}`xJ6}{^pp=Qm`xBDcFO`g?ml6mKL_#Npo@+W5; z>o|!@*Us*1*S{WPymu_8KBIqI1yOp2-fYM31=CdR#{J+R-e^CS_;uU6XI@)3edDS6 z%e!K~G-2JG0}XL4D5=-~Zs6v;E_b=iY2N zsl~c(XXeyGZ}|3}YClDCGtpt=mLKEwahVe+Bx^1B?`J-pqJBxbpTcJ{HBC?Z9B?DMN8 zl+qjLq1Eq2yXGDatr+x0WI?l^E_~Jdlg0`*vUpg`qmkS|fILKYM*?gM?yFWc`JEGuHoha;v_Vr;GmW z$9q?Qa^;Zh!OAgR+y1`7(y30{Xyc>KS=14EeHNp)HVs_gp~LX}pBs2tl4|{zFBr3Z zF84K^)N{Pe+*!&GS2Bn9oL#5t+f7F(54_rK)J4^i&vJ(?{^^Zd{qL`Nuy@yrF>5~i zw)tCzKWhcW>c?-+Bix4Kcmbxc&S|4Z3%oVi*U>hRrw4>^JW_R6eu$p|19Op8osJ zM{6$nQTOxas**Ri@0hn_mMLiN-L)zIo$a@Mym9r}+bdUUSas~7GsiubIwag~jd~kL z^RX-NIpKrP7LLLHe7@lpSW368Wo*84xLT)Ei@UY#8v6K+FQ(SmyqD49@)~%v@80El z)p|XORqM5cc_247YXfKkniBGT&L=h;q^L-R2&jMStUZBbT?>2Tz=$IS6+h zt{(H@%}+kO`RRvC1j8k>w`lLZ`~A|loLl+9tJUZJaC}q0lXls%yzwLZ9+rF&>v#Kn z@_dyki^dyW6Hgx8I-q|~a(vgQnxQc(cK=4aduR2O6C38YeWNCWwL##O4$pm~dj93_ zmTkV`nID749JU5^OOAE^c`ajVmrsLj8rR>`r`zw}PqV&%`-iIYe#+}}vSlBC{c6=u zUOK&2d$0Q-(u}tRhSO~-9Uivn(-tF`)A~=~Dd)WRxuqT)=hRfv7h6fe$|KD|dUKDN zNcgzs%vIxu?o5&v9eI1$J?|%t_3r%^{iO%f92?snn@(E0SS#E1){Rb=2Q<)c`QfKO ztos}Vg|h}7m_Yg}j}|?7=+U^JWa4q`WyHx#=Kfse@zGoA%T4cycaOg4ZhD=|H2ra= z;J!z6d_e9AqJq#y1JC?uXqeWd=X(dQ)!$H^wL0$PN(Xdl(t~U(c+UYs>lm+{Uk-;&+!dM^2DPmcqK4qjY*caUfJ$6X!>`@a5F7wz<)?DEB)X131D zCS5w#oqy|2JlSy`&vR#U)7;NT_fN`)<5zq^8d)=ZxVJ90-z@FhGT+mC`5VWZT`t;i zV)dzaR*&0Jc^im&yGajE=PtXV@3f@IbE2oI#l7|;THmNu|MZrF$cABS+kV$%?#7+A z_vgME)oEU9w!R^DaQXIKp`u>ni4R7+`AhAK8~68q^hV?~xw&ol0UX+y^3`4DPaBo3 zj&hZ@dECo2_ngg1;Cc+G$u6osl<6DLvH#b&_2$|=dKy;_yK1hZ9CBr5wO${bx$Inc zuI>B*&;aVF-Rs{x&E9&Lf8Ya2)kOcsi8`$hQAJ<%{q4f)CN~GS-?mTDZ^@?oqwQ+< zEnGJw*dSE28_8|bB=U5zDAfhaN`J7^G+Y#lmFOz(k$P~X_9;0FWd7PpV_x*J99Vg6Wn?1@*8Io z@BCiC`ss3_@%FAwj#ls7jKApd_Iqzm>m+>tXL0v@A=}fB)w?cv1G8=~%GP(y{A0#x zv@@)l@g?m0)K*eVc8?)!FZf|(wW+ON?=$C;)W{w5`SRLW zTWh1ytY)ms&F+0!$6yy)xTkJOv9sM-Jr`DP_xZcdS07h03toNP^wg#|ouVea-+cek z0Mp^by<6}6aY+0N`gm5=M^3E9<9Lk~EkCKYPgyw4x$XX{WwA|*H=arKKOQvY$ULvS z5C5V#*Yv=iYpo%<`pqA<_Nde&Iu2gg;8J_zy&IuJ!+*ejxi;aK?`!`yv&N}Q&g-}O zEb80nohs*v*K)3o`1OKe+Jj?Nr&B)=9~GkA!mr<3+ON-hHO7hKuirV{W96LBs-2jb zH)GHoblv8`+~v#1&K}*b)t1Zce>w98M&?GYFQ^~#c6@CeaY*dVu0(a)rFR-p&YoVP z=oIi(;%^x}xKfYnsw0P5oE&p)ccZzdNCDc7yrsjd_wMf&^{nxrYd!W`!Oe4jIqY`~ z>G1yiRV{uA2@Z@tHFb!1sN%@2Ru@|hQ6AV+_lB;|C+p6C+enVorc|E#`I_ck8{W1b zSTLV$Y~pX}KRKx2qh+Ta&bF$lV`{D6wS7d-+LTw0&wcP_e8&5tNSjNJCS0ee@4T*O zDF<-(M^(Qw&NA}P?@vtIG-+Oo8jhV?+s_@=;?9p3)fbz5nYR)-IO&HGA5E#&eb*6Y zt;YGvVBu`-AMYRAFCG2ksks+B&ANkbJS={QuKkdjJFv%?H*U!S(ffxRCAV*Sd;0E` zKR3BHi#GHT?*5pIb-!FPb5$evs&A*!7~TGipXf1D>|R@W9@_cU3$5D@zs-64X5k{% zK1=gibzbow)>k>-eD-NR=gvmw;&Bhw$Yyu`xS4VL!Z+ogt!xP>Pa5YfIZS<+gRQ8) zVeQO1qG8|b@nO+*33iUqJMilg<|@|4qQWITPIcyOe7*1P`@?1)Y?Sy~M;o^Uj~Qn^ zGtPG`{7BtX%~8+?a>82#@+vX{#Wl`4j!`q z(mhsxc=u6bB3~cbUv);uEdmZl+c&D(9ZtsubLdGA-hs0i{zQ3<27=OLP zHvP<6-B*ph{OP6TTU$*Ybz$ON>%*~^=4-C8u1!3>e$%CEOE;=(C3!nfEgAf9q$*r} z{j#ka8=dbyzSoso`R4V1&cNUM;5O!|f9u_Qzn{AOpxuQPEk~T|!@1o2%(~X(JNe5F z?u4&?3r}l*rTXQZ2kSp7ywv2I3s;Q24qjMRbO%4>X8xu@x<_1*d1_79?8#HVNv>6l z@qgQAU6q@ZA^83`wN?Aft9y<5)sk;MeeF$6(Z}(P@~Ic$+Je#RU+;c=z=SOaTK%!C zegwMzQ=N7*D+imeRyM2J9olk-d+L?bKN&2Y?zR8zoeAIep8i>0;!*uSN73(ApBz&) zrB8cRR`^ZP_I>^sxH?$bg$|4KbjHlk-q4$>F|XrQ`&D_ys>{D!mvKH zj~H(m$k!X5zBKupbMqhN)p_NvG=8o6bz9{N%jS*jwJG@h-L?Hs-u&hd;krMo-TA4` z{5rkwR|(vDJoq72WBBZxv-kSiR<7PTi7a(=n|wez$-Qdw+@Clup=HvCUyL(fzwcY4*~Tr$UOlsraOc6u zm4|Pix?T0r!)}aqtE;|!@bH%Iiw1m9`@Z0k3U z)V;`v5eq&!RA$J^%zWsevU2nD9o6c7DZ>)53@As2P zeK&u&n3MPRabp;Q+AiBP?Dvmvc33s}SdE{1UH`T2-Q=mq9~sr#3UdlOGqyDy-tC*_ zjeDItntNA$dGm-hRk{x=+<9;Iu=Ts|jTzSY-rDs`t{-VQ@z0zGC+9SXYwY@dq9(#Ci zF0`yxkA4IEGx$rTE$*#-`$TNUWBY_3Us)0wtEbo8k!RnFCYZIvO09jtBbzT;T^>%X@QO&YbS^}Pw4pYuJn-YH%%?$oLr2IXSG9sh*e7mR%i9BWTMu5#pb&mNb*KG^)m{nInLS(a29F}vr2 zQJwY%ufBil*p$aLzodAV9MsJk(7pM(#rEOXmbCf3`OU4r-@HW|eXZZCgpEv*TzU4u zn9)sUt``<^9(K6cxyh}w--cefP`SXz-O*Yy_UGs z=dt3%e(3QzbK$hy!=sD;_jpH3agO)k=exfjf=Nd#(S5nXtZA`i`VtKxPpj^8?sq9-_fBd;KVajh;uD(6Y z=X88c+pxODk$l3)%O9=0-I+!p9~yV0QJ;&4M%{1Pt6tN!b+#T!=8x$!_|Hyi{@oQj z?nWbZT6a>fx-0IqoL@cSSXH~-TXzO6#@bCLK?GZr?uf;mqzo!dHk32GYJ{ zK{w~}8}bfyI@t4*`d7Xi8r!eDEPu7?D*^ADO`fyGoZ9#)UfE`5R_qxRV%fEP8d%u} zn?@kddz+kkcPDnH_NdJ^q2 zyH_}nMbbXI_)h`}HP2oAe|D?u#a905f4}fgrh{$plAX77SN?I~pGv1Zxm(6A-7^LY z|B7w`HPWc4M{kW% z^;%!jKWp$&o4p_Z_65FuwFQoeiMNF9a#o0T*1Ny=L4)w#HNP&rcII@S6L)(}yL-Bd z=6+tzD?J$}6h{pw$Nu=nnZmqSt9?xix2%ly>b8!$yu<7L%rbrL-=uT;)x383@{~Eh zZ!TK5{IPP@VZoJ3r?yLW0 ztm; zj-ETysqQ@KqnX~v#z6%|bCNULOy^r{)cJ9H5;M$qdQTer1*hKdUDdX3 zv2Nn*{=M4pvm5Yc^LfqiZ-?%ldE>wwEyq&zL8TtU`?nka!>oI&7c>*Y zQ<nhC6KWoTCaZeW!P6^UZ^%3txX{d+lT53!5ihzWy1Z`5j|R zLP02zPgbw@Qg7`NDYhrR>?q$ga`~=n=+wxpb056FYR_F5cLYd5sWOPw z;5q&wl^Ry!AB1Y04e^9h+i@j3ZEPkE&Lco_MRAE-AqB~IY9=lWc03`q6bZRORp2ku zNnY8+GsuFZ>HL8VU8%*T6V{3w{LixF6qqv#Qp0e>;w-kT?LN_UDR`QIgM<+rF_V$T z6oM?aV$#%g7zf@kn%Z-Gx&UlOW>Vo&34VyvhhjPu3pxEh;L<>nADT+DE4e}>L$ZjM zCTmmK9l4I!)3GFTDMTBbJHmVxg?N# zSgUpG;x6Rlo=Gfdr)m!dl}7-Tm_mAwC;OV8DuVNfppfUs@^S5$J}ZXCa3G(^?T$2n_0&q~(x@s2U(lJTxY8i)jQ2mybO z15hl*IfNu{=Ah;b5ETDEb^fJeB19!b;o`u*fddW1gvCT80B!siGZX$_Wl}eN2m}9N zFC``g7ez{n1O1^q?0g>sp=sdM0&pI^|D{TKOLHhavvKFp26!ESDmhFY+}u2#awxh1 z{89=4B5|vm;4^^6V;dl({V#9|>Y{KfMPFw(dqA(Y4ggMKBFLM%2&;d){FfsFbbG_Z zy2+NbQhyBe4xB7~09ko#N&ovafXsgr|08_|Cue}ZXmj%tj0J$}zuf|i%EvZd zt~YIgGba!w2Uw;z-P{x!Iy`=ILxcPm#2elz03Q&@20s4xga4`v$ntMJAyEkcZUpeV zkm8c?n{fMo%Krx;fHmdtRGQ<)O>c_CtpEy&!GDw|287Q6D1iNcO7wl*9K4L&0WR9V zqA93L{Rant%j)0;DEt3u|8KgIbRJYYlrJpzF9 zzf>GxfPZ_FvU>2u!QIf~hHN9vA%uhr!;wfyF*rgBh_3?|7f677ix8KT5;thTHftRzBv%9pAC{hgIF8s$3B&}4vobCTd;Q+))j(>Om$}0>AcC(3!O2I{> z-~e^v|1L-B-%V0N6p#vduMTMSf6BR;x|G!o*AJi}{}*_G@hWNm&)h^rgtZL-S(M%F z0UqIvdw5g)|CjuK*TMhy8YCeuj*$4DYZ_oAxR{k0Kp}RwxAC&Kx>-N@oA3R`GciXK zS%whfCW{0G;Sp2(8uXY|Xcc5?TAqn8^F{Xa3`%()?BcLyD$DDe+(i$D2D3q4lNV=B zf;i!?`^SeEJC`+<&TF2R3FdoQ53=fp9~JxeH$HLSS_oVhZ5C;iK2sOR6@ildrWtCn zJ5*B&v&sjQjp2#er9K~6TEkOU!h+sVP7ils7%uF%aqibb;!$qMRYNa9_{d>C2tZoqV>r>MvVwd3pUVpEN*^N=TS??cj z^>+T*D~9{m-x&S;ICFv^vW()}aRXtN;;cTiMygze=0>gub@sS7bxfrOs;7}FKg;gL z^jA4DmVfMcMs$E`D=nw5w^qQmtyTG`RBp6WhoZY2XSYqDJ#=EyDITmt7uL? zZ{OmFF)E2pXHc&_#aT}$uhRm7L|2M(lrJ1rJaw|mgPRqyEBfKEfvT|gDnfAH7i%^i zlkA&>?f+w3{Lu+>hw(cVh|w;Iyn9%3x2^7eQ}?l>VOU94HF2#=^Xe`Oop8l2&yV^b zsMn#y1$|VMoDsyqJf@rey_?Z_<#c|koWnFLv!Qv6(UeBRY`08+_AM}?A082xly2(z;Y99^nZw@1Ywu$tFfT&^iYj||%e8s+AN+uEWC+~t^74{H9&?b?l+pZ=$(@r4 zN=*Z%27|#=U`j9rI06|N!a+i;L{11Lz zuc9&uTz*mV)B6!e{Un(B!V0<<3X-Wf^{&R22fxL@#vNGSB)WE^_Vv`q_YPif2`ejg zIC@iiVPJ!Xw&J`ET^!uPJsfs|5hSFZ)<~%w3ZE~xpiBy+8hiSciw7TdBjo4`sZ+~h z!k8iMjTu@kJOs9^gKJyU3am_=Y{&eHe4milnA+bK60UH2(Q}BG=eBW$*TV9EB{wHG z2R9oxD>sB&*pr4=kA~YODzPj~O$~)Y$)fS5TTNy-6crgp zGUA04!w%XREjSMMVho)&bGWqmeVs?tHvNVbM9f1&2}2cPv_`&35tESMgN2r$Sc7{! z8Q_VT1ZC_o`mmyRF@fl4-(Bl?Z$4olWqheQ`^447jmce(0&LsCc6LpL;m}JImlsi6 z-ruJp(xV=jey97=-#R#fmP91+M|$OF+Ny&IDZoL;NRBQC$+LFxi#C8d!*Q^639;a8B|-7+RJ1p-m34UyKEuv@q8f&<&6s82a4XRR+Eq*XUl zcq$}CjGy}#*iG4X;y78_2O~&GUgbk~IsR}MP>_>agEf@d_NR#vTvzh9CBC7PsCyIe zi1A4n>0unYCL&OUULuXi!EkdYJE^3Y$g5xNW#&NS2}GchXf@*Qrz`?~#Mwo|*P?!g@Jat9q)c zVq_WgsOfE}89b@u{ZUFNr7$4%D-ogy0V_hG!cc^vs4%riLLPp-D2NfImE@) zzwZ{RZ^ne1Cc=S>JEWkeh~E$|R96MV_Dh87#g|Z7HRO$>$^xz`hFn==9WP)V?xEb! zz3rKRjzkBe{n1a*XtaNyxQUXuZYWDh0fk!vag=H{6rY^?J4PA8U^bzAcXv~sicW#1-$h%`$U#p$J)ZvZ<;yo90t4=ekc$Zm z4GWbWzQum^ZaQKzl>L`H)wwQ}1J(B@R4=cT`jq-Yfz)@a|5iVshW^l-Bo7V&hx7N# zlM{wQNkTZt3OUGoDc8Xf04TvvfaDLP;7A}P+$54UlvWrQs{%Ehg1#bm7*vsiP?2r3 zM*&i_=H+E;tIUScXQFv0PfR2t4|u`fBVXblU1^%;{r9u`#8;+j;@oS7lCdHr-gU&C zIT?w|gJ@eCdOh%#F2zMdMW#zV6E{f++b-ZLKK3Yk2q&pJvX{#5N$A(ccDHzEGh5DW z8@3V~cefI12Q|D<0;cF!gGy{qrCH<1RaFXU93uHq&>zzg((?st-MP(X#rhVlIXWL3 z^aYd%x)O*&@nD8+c=f?xn_dDAwaDNn)@5Jnzzrdx!1;py$&+{1(BAOrLWYK2+j^7X zkeh4}qU}(LDehczPKKrvO3wZ0AbRP6mC@_Z!$zq}OkuD1AD464!63cU_{1cXSYi7f z4m`S;d;(B3h?Vn?ef^6WB+YG!~y7*+YFhluB6WOw| zNU+U%4?#FFaH3SSwy`Ck;pVU*pyt)8lMf@Mh1HQLgoEf<8R+<7Ch7jx_~GGX{AGB` zVYlfS__eg&g^8hniir|B21bKPu{vDQqj+a{tmHv*1mQy!HUNMY_ zjyE`%fD;dd598<8LM4FT5z*6f0f&Yh1?xS8L?9SJ9XL4rHXY|xFd+k&Utd?jCImQS zG9e7MAt2!v`w{}81u#%lCSv5&3SJ8#5dm8EhJ=xk(I$vM2`I~6g_6+9S>uxle#ytb zr5pwlPDgVbhZGW!(g~!43tlY`goTsPfhms7v#kljZ%VCqID7j;$w+AFAk!mt>1Dya z1f*hDp42uWibQk_+=gOhZTYXlZ!>ae%|1%jB@<>SYb z1Mq0+>Xzjzgp<)x>sl8mDiV*?fiDtT0O5S7E?J*wiAQh|mE8S>xZP%qIbfsHMx>tSf|41Muqhgb_0cYoY4C z0ArJJo0BNq!rZ21;FU+q>k*KVv7-Uig##I4XkEPm0%bxFEr*@3Lhk8cVliv9 z{4GvS2qy$0BA+0lx7Hg5Hp!Rw#8(cFqEgHE$For+B8mnXg%F4<_L`2HBhyfsIDRkti@d+8s{pA6}MukR25i_FS z0n?-da~hgN%HJXbF|ui)#L@w92nYs3BZ%qM%JQeD^8w2yBLh4g0x@sT=kFm5Cxgs0 z(oqX0=<2=d?F|EQqrchg;`I?R!gLMuLrAH4b<=~xqRIGKnMAD1tQ82ti5Rr}gE^of z__r`*^45{^UwRY-UiF5AN0HEo$D3S!pH24KU=Syvr(^i?j=b*M4Bl;^YXBlrT|*I3 zd}4B@aY8zJrUZG-%jS;UK9E+cE~@oO{c=h32x-?K8t=kC-femLJvNobbrC z>VgTQLEK-y(DUo&Td(6Ym`A=dZ36?AL`G(k54ckp5t3RV1bYjWA1s1T;2|FxPDaX@ zFHgNjK!iF3s!Yp6Z4?O^Zj0b6E0Y4N!k4zPnL;^YlO}X92|Yu;r{XObnoiTkhO?K5 zLD%G64@}yU&NVn3@D>|FI$l_tH31R6zkF|4G=KvC^eepKbv#N?J|3_THz4K1$+!(o z>g4tCqse$-=-^wf^0#hb2Jra>)61UV-<}I5CMM^zWDO=5xD9IqS_%1)y3n;?$TZ$70sWYfO!tz6amGkEQC7Ogm5cVz@KNJsGf#u0yhUwP5B)r09?|KR8=s48S zB=6So=y=tD!KZuHged_Z0SuLn>B$ocwDr4S1xzOxkBC4XSgc9O7y!ov7vN(7n6>Ie z6cpB80k#+(BZ@b08(61A2sk@~>KOgVXWI%jH?b;@{W8 zpbsxg8cY9j*57_;^yaIIvWiqip=n&juvXltqu)a>lydpNQC54^RqjLX4x!Ya2U(tJ_39a_sKR-~4G^PU(D~>7RO{guno4$YAg<44riSXV z&cie5-IL0^hIUp6`UP3+7?_@!(Lg+a!HAoFK@RC?zM@=KRPac!@1b!0xtVNGk-6ng zVR9mQp1*7$@5!|5^DF811#6x0ei(OeiqEQ@BJBttujQ`Zxe52H-GjiZwyT8L{lZgv%rZ-B+;J6asu#xY1Vq&ujXnxy2^7hbA%QX(S&>_?Do6XguZ8`!Lz9(4Li$JVt1(T* zEiFy|9K}67DV%xTVl3WO5H}U#CObrVY8%Ap33iHe=Y6vfB=@uHTRm@!wyY9wu8y`W zBfP$}7@`QmTF^gJpgmI20MT@oH(@l4- zTyiEYn;gr%{6Kz&UA&Wnt=NA0b{KJ7blt_R&6sOyII7lRRmufv6v-GE zk1u-kY7}j^YvjEyi`_-@m6ND-w}K!G$hE(h^W%L zr*SOUAta9W(q~tNP6Qsr^31uygtR1uE8a$5VaAEe4?P<_Emq-_480h7Zj<_8@3?;# zv!@iep`ukB-!+(h$CW`zoNGi1eRkV`pzeMQD|~NCVf$4A z;izO_NNe_OzobkhZ@2Kh296gMFpsvG^_m&W)uUxm#L~9!o@VOd=6hQ`ckk1Vn0eKR zfA(r*O7s4_1>uxD92jf9E>gm_Lj{wmMl1fjHZF;+AR4LsRRGDW7@lmd2sJW<;q;oX z=Jhg)!mo>lOOu(o;geV!O?%rrBGz@*E>*B9&64FA?~>J2$3d0aLwio8rXP-4qB9x+ z+nlO)E|HgOu7-yh$(?nbh0jjAQXf_|87v$peP`K9@IQ>#8h6s4aQr88F8$l?53?!W z=R8ddBoXx0^Gduy2^ zcazTv#`*K_^b*+A4ILyV8R^oXFh6kNh!igtR@28hdv{1qO4znmLd|Z!u+e9paH{IV zVrw=2*p|r(QNHv%N>4md!Mx?jWIt1mz({UmHB)z5Tv?6W$H%hC7Kbqoc2;&iy4&ep#O@D>esL{*gc_ov|>-`gid-k27+0JL^mdhPEO__pT&7 z+PcS-e|@&MbF(qCeEUIp;U6oO-(|mkxPMr34gDa>Y~X6xK2Utxc&1=QS1+D>>Gaw6 zT&2TCe>6GXRpqTnM4*GW5ld{4&0yo{fRU1kOa)f$$JppU1sB-drO{qtVM$)aH%Arr zuaCOVz-w(sk>jy6ne3WY3GOvvim4e=bEg93c`?zkKYJaGetvnO&~lB02Wc=GUxHX_x3xXkXB!a4s5Ti@G^O(SEmdyb(_iSehcl;fK2zI^rQh@W z`sL+i9EiSj>$KE2(G7jI7>Nx;aejI!8SNXN2lB3Me($`MunZG>q`r(%8PIS}`!SR< zSux(fi+b2=`&hZ7;0>?evsI4Vp_s@h>h}B!9KtNBdw4fcQ;)uS+~-Z~0#mzQ)Qd1= zv|SOl{e^8m_FByD=g5?&#@+5wJ$t6kx;p};6_kvQt;~Pzkt?H1u20lzCoL!_W92yS za?bANO;)%gsN%r2j=F=6i|CBZnhI5=5-f|?B!*o5#lBOQ#Wx4D)k(Ph{#5qH2hXT# z;4$hQqs;odfjK^Rs+|MRa+L4r3zumaQn@g)MlaNMFfR%Z*FA6&4q%n?XLXb3SSOu;7ZVz}4|?mYRCymC96|bE4q7!LH35 z(a2IwiFv~HudYjot=HP4ahH{I>C%tq+KoMXg>op^^3<4)(h8BOLv5OQY%(a0K8H91 zW&B!S{b%wleJuINM77Dm@I>t=h2wcrQq|3E+sy7~gK>kS1r6=h?)I(EG{uL-HI4HG z8=z^U*KKDV7mju2SL1_86Qv#BOq(ZXZT8py=xr8mtEwthq=-hCXFt|j*jYbK_At3! zZ|;K`gtY9A`_~)ZRmF;RrJoKX)!ta7XcwWgL2&~v+l3O$>=H6Y?>$CCC4|knBRmy+ zhJ?6cv0FB5$ry~D*-ocTv2=&yVj6j=<=O2FY^!XE;$!XK?y05rmSbrGKXT|lS~G4r zRBRJ>@*9-wm&D(5td@Qr&rEsHJBog9(E%+9+Ba&S$r>wTgjIN9*~CB}Jr60(7|$Vk z-K}vDV@4&m#(-vtDs%JHd$wndEZO1r&X=vnHXzp&TR~f0w?J9^!G|= zJseBsofp2H`r|FGFIbNTUi^Arez<|QWxFioym;?$FTmlO^Vo!>E_xHmv?we{A*z6bs zg|80RPv(W9S_Ws)KCdCT2zY6M)+>4j`GKB`x7T!50`RXs1vH#k%@DjXHZTu&&!QS2X&T1 zrHn2u#Hzj@+io=P#w>S4xgX1xF{Csw8(^UxlVx`9W=?UgX00nj6sDPlps6Agcy(SK zV3w7efs zo-@%B%bPJha<5}?M=5LC)!?Pd zhl@74Ff!UperWUwwNCcHPl%T5u02XzqNaX4MvH|;JBxE}_%mrKTjA=8){nFJuzyS) z?RVKGe3GS_!=5VbET{KQjqH`;9%+?Ne*d{}q9$${INsM&h`Y9?sA!bZiydXD>T$7P zR;{c)^=#6>7#+D88a-0dis4nMv?6{yt%WsOwfFPtPR4DGRvjLie6PcK1KP%qk{dmg zGdC)cp?se>{3JGpJgr-DnB?_zq19`93t5{qDgjc*fsgFC@JnDDD-e#&D1b-3aeL zqStIV)JU`%w~y6J)FR!hu^mYMo`7}xP{Ww%_A67GrJhBAud2JKg;pJ&H??!t-emr^ z%EkNr!NlrHjMN|Y_{8bij=6(#h0?h(34@_9i6qpd|5b%HN+-yWZn4Zs?9Q{%Jx0yb zKU}dTyedV_3_nf(NXVsX#HG|kc8;{6B%*x8P`nCC zv0z#iF^XXoOr;n(hP)B-rnvTAbz+wkD;3^cjzmLBJ#TdK)s6hxEj?D{{w|e=qoXvg zZ_;UNEye%xQ?3X_e_~JYM__CR9 zN>FDicG3%E{rdj-7;fBa)r=B+Gdkh&wxAK+Z1~*{QQq7M7OA ztfj{a4y_+ErbSpf1tF-ah$u($X1iTw$~z|kp~Jg(RJZv#FZw;*hx`YZST{}5r99r_75>f7FSPbpIKeRJaZTkp=L%0-Msg+Z-e zcLF{Ij1U|=ARvYembbA9SqC0fA^s$QP>Dwli%l(2QRi_=0&e>~}z3)-R zWb|PGVm0*z*2LJzF(4z%QMkOJA@@3N*bkOyddKzL-xejKJ}GE%3jLiY-6&J}dNl|8 zbSHVfwIcd_XL5D4#^`=y$HY%_^3}0uxzE!R(T)xtHM9*LzYu9YLBj2`@xR^mY!kEA zPlvVl=tcyZxRSEgD-yFzwzOs+(T7XgozG3?okSNk#udHxxm*4==XmsEq3_+j-@gtS zW`8k=Z5tSPtMhOsv&90Zhu!lvwMPz)6RRQHI!fN%${F+%p6&|w5R{$Ld+J^~%_Tm` z1#9^qW_+?7zoCa;z?f-Mb4*RkR)wmKTnyvh$dE{tN-i?`uu(W zw-cdCNQ|)`f4QBz5$oh-aKpigCZyA-cp zHLRlF)dQ{1TanV&uSzk|s~Q%K%`{!v{E?#>^HjVzJAAw{%|hh@=XjE7;5O*!$yI>s zpoS>1cqM))coB5z#b97$HloH=+h|}Q{@RdPJ#`2jP;U5JEk;M&kj>z_!qCsOBrl7| zG}XekF(b1QYA_YrYh*;kt%g=JQJdFW}MN)!HDJN?f@b#Jrb`)U~IZ_U&42p+cyzb!j~s4 zT){2w@O03zWVlEHRGH|K^Q?99I|rkI17+5wXH+;ynzH=Z-)w%fGt8t-gS2kpc5vQwCeidW_52i*%37kb4}W#g)R zd+y?mNUmr)pKds8q~a9 zX59x0cVt~Ji{0G9Bo6I-i$pbR5fwahhfQ)-*-IX3CEfW=FRO7 z8hKPv@0oRm|TTSCA1AnZuG1`oOz(vPv2`azCk1+L`_SX;@ynSW+# z@W|k{hYi<1u?ge?;!1v4gn^5kUunC^SFxv{WS`6eWru)Fs5I`=I>rRC<5N<_z_pQ4 z{_(45fNNG>%Acu6oCa3vgR*0z#E)(4^j`=rgutl|rEP>hKvw(tE+eyxbzJ;U4vK^k zEuTVoseg(uSU<{vTFr;STUa8#mJ~x;u2QF5>4D52VPLTD2LxHX6?D;nw zxeJHbjxwi>NEIvI<(xRFpc7^R`sY?lh8bFKD_4ICw$$+czHs5AzN?w~J8!`)ZmTi+ zaLc7tCu62utDxTCWuKyo#5f|?TtZS~P@^sVgQ}76SK)=7Vfi)RH4@y|GZ1cFp0DcVCf;<^Th)?z<2W6`L3mNocJHgh_!Y!?ZOtSZapV zE*K9Mvt7cc2%?#_UuqhcuzJqp@cA{s4DDxmyP)T^iGa{XJ=kz|HP=pc38YODJz8k$ zet#9$@<4^z%f7KxS#PGg>D!~He?;DofRb>pKXrWOr*=;3a2Z*MxFu$4&~D7GTr2Zj zdt30c;nTm>qt~ai(Lv(esOZ(-%}I%G6$gLl+g4*N@APHnzLpe2*d;mc`|>tQw6-a} zX}X{IqHf<0c|KhM&oj`xFY4?h=sWT`zRf5FE*Val9Rdz79VSi%aYRVnMQO5nh=BV%vOTo{_vcK5S9}`j0Us zyccx1%tu9suKOR0{e-hNG=~sLu|7#2MyI%JgE`L_U%#69bJm#!RYsWxt`3U$3O*U1 z^X1rjXk{9cy7Bw{jOrSPybCwu#SU<}WpA<|m1~#7pW2$58ZX$-->-A9+e7|NDoRe( z7Gitjhb5K{ssPPx^!!XI8>lU0+>Wm673j*WROMa5VRR?&5YzipO_d zKgS334I^@z4IToqjhD+6DQOO18UHJ}+;UfuQ95dC?8T12mX_&o74NxBY?I@AS^Y{suMeq`0S#B@ z*R)b`v82wE9S!N0NmOhyD2FZ~)%9$j;Y8_bMPL2m$=CF*;c|}DCvP$YM?|=0ESsd@ zbW)4L60`JCCp8)|4&w2awpH*?If?zzlG{a}Vt$XYy8zd65zuC_`fv zU;}cO2 zI!GVvdW}veDi7i~tuC^7IxJcz#+esLNCz-A+ZwbkGG)lB!U{o%6PopI0P_Gm1ztGg zB{slGy*~fZb@i!zMqx(bPwEKS{x?S3zOoLIxp`NX>UL)?a?gv=qr4ZxxdGbs^<%}- z$(0zRzIK|1YYDH@C;Y~?FsUO`6HWQudngHq_~99;r#R4%5%(Ng zxh8EHVAU=$H@dxFiabv2U~;NrpEYd$koCE`O3pZW+}*w6Q==_B=V4Wijw~qxe0Zfy)SO5**w#}s}m`C}i?oB^&&4MJ0_X|7|o0k%> zr>Kt+vk-G~yo!5YvWr%-M-07Rn~+_N9LQtCeRhV%C8AD53RAirO4AI7qEKEkIW^sL zQA5vPI%cF_dPk3c$M|F5G5$_|p4-C%KhmkOF_Fi!#r}W$-MdV9>{~c!oXUKqEn44C zge!}3O>}6oW>u-!sWPkj`$)4`^hItbLX#()lyKF$L+(R=S~gyI1j>YFTkoldMy!0>9N1 zzfYY>se~3O`Mv)0z9W!pc7=3Au{P~IFzM8i>#peMx;qE{+iCD9WdiAlq zA2`;eM>TsU7M?DwkBXLCFCG3awO2r_+~GQYs2Z{8V$Nk-@i!g?Cu0G;2wz0m9cF{) zSq$BhW%o53nmy?QO4y}4_rC6anBro87`N$t>L~!*;5(|`pImbIM>m%r;_{*1$pLP_5O?NdPvCZk^+-ZHhC-=7Ug{4Eo z%NT@vfWe%P`-+)Gb!5)MzMr&&`$4_MQRSnHzKe;;qMR}#_6-Vw2&1=)Opi^zo;@8P+g|ca_68m`xYH#t}z!eTp%yqMDdC?31crxxi@^ zLYN&dYcS{F3|RZ?jJ|S!FWP-EZsXW4C&9u#d1Bsd{^HPObJ%fIVk=qg;A{#ENtz#- ziwioJ{$YxaNl`6iwj9t`mTlK>7^mJFT=TCFD*U)a+exxjQ`6fK)tl7UPbS5~_bGb8 zE>YIMsJw75hT*|Kb{V_&P1;^f+II1ehZFb`xqf)=y4Bbxpsk8yOx|~?`5-8xY9?*_ zWe(hSaAOp)2!>{#XHMCAK%}n$rCcMrZKU136Dz9fR#GyUZa?^`)R*=%GMUp};89T! zs{UkUKK)*$up?a7hx)({QM79^pm&G38jk@VY@nT!&1L`CO9l#4WJZJL4E4+@!}qNMp;J2oF3 zQ|2t_>tc;b$y@}sy;nNx)5^Kn_;6>sKeu%5(ypq3p<$-r1NzckzTahuHOh7=EgG%u zEWS-PvFuM-ZAVh~c#1qXOu0Xsh}~yX&r7y{o9I=3&i1&JBy~J)I$lLBauN++wAZqq zHmyW3ex34(!xVRqPw;G66dl{~@l?lMcnct`j@?quV*+O;+UDK#bu3Jmqy+w&K%_e@ z*W(|?+m&tyRxvLh8V+t_G*s%{JC zPW9g$alOfcD)ai3dO9C?EkC%H*m|U=>WoaIDIEKrQg!{bv-8unqoz_GMAW(V!hJhE znWua5=lJ$w{aC`JpBj6C)}B)nbSElYXUC$$6n<>tlpTZ#n)o%CF6$Ei0av2;Ui@*i zQwP*RT*M3iYwA)qAD^dOSq+nk6C8~)58Mu)!fX0jMXddw_-(}PT=$%XO3uYM zx3a5latgjk89vk#oOzZ~w&=-brVH?Qi*%&zwPaDm?QniSTpI@@es6&rv90hShMDc7 zU7P{V<)PTn2$ETqZ(}ggE&ZC=zF%QbVP1i!6KD3YdA-bKs1G5&VP~g=V3w5h&G0;n zAM-9&C>d!R0uN0GN@Fl8lh8Szl!zRK_z0r{Duz2)aV^Dds<~?MiYntqy~+i1Wi~~X zzvKe%+4S`l1eyo&K3pMNik05)&i1_f^x@jNc76K(ASm#(gvy4Py4`(;Ug z^s0?37xeBJxJb#_NpDn{ZRnuQPY`j7o)3A%M+cqAqYfn8Y9z?UMw4G8zFqO+^4kB3 zx~#kmc{qTb8QU_zZJ&}k@Ur6ZJz~qe8ejt+>*gtTPO?+QjlyrDR*B%}HBe}7% zyn~iD+`rt$w)hD6-P}*>r=$8Msoh19g7=_MQK`vvaDA1RK0?I-LIfq&_NnTuP#0D zH~66aK`W}eQtINsexJWZeF2a+ez`R&=uy91cflt+?zP`8e~yT2M9PZ3I!W|#4ha;4 zC&oz#@bE&Z@$iuRl*G3b@#}-VPHxfRk-SS+v`p()C;)4Q6~o8z{%6yD!YaGSM=g7O zzFw!~PkTGa3GM_H# znS#z&nfqac`-_J!Ri~Th;@wClJ%nKX!QQtUz=+}%1BYH z=v<4#4lc6CFJJI$si@GI{F0^HBuR(F-~T6)L^(yL9llcW&IwM)Hd^Lu`UjCxqH4bX z8o&Fy9J59{QK*+g-CS`hbc3?^jixkRhZ?hsXZqj3EXwdAV~nC7|6%T);%I{4yUQnZ zKKz@!@0~`33&C5l#+VBz*?0X2TWkJl8x*zPG&Ti#=2m@dOu2YcL!KC{D*t?J`ggPy zF-j-pJh5O2Zn!~W$g6>>A$L|vNh~JcNar_?JI6L+YDHcj~I>t0w>nWOFRfx)+S7t^Gd~;A)Gmlz(L8L&gajG&iXd^#`OZXmcqm|&* z7Y1c6p6&r#C-xE(g_84ZEdOdSKt7$f*cSoXjEuR(J)kF zZk+&1L9a-}ILMI7(iL9z(vU!XUM_{q#|d<4E4b6mU^`siWF$1rVF(rB{nW?^D+2cmM3N77BAT@3TC4}xa3*G-s6MUD^422dRpXTuo5awH?35gLF z>ZKW$vlt%KFv<3P7N|3Jbf*&~t)Yf#w2+IVN;#g*=Y8c!{F)H@A`Qz$DixkK2_a=2 z0#Q?wZrr=q3a0Urzt{bTTE3hSen@Tnx|{W}D#`4s<`~&4zBl~yD(@Bpp-{-0>x=fV zn1r(z&evEx%HN8M3^w8~rIw<>S$}5@qwzfPF-&~DmAAHCXrOaMC6$~6v0!r2S0wE8 z<2|-U{oI~yZeES zZIkaJ2k$0nFEWPdjVxF$HT@Aii9&8V8!=%@j;)&dF#5C685M6@df(UEQm~jk>3`&{ z2EoTKM9K%vE98a;SPWz@)^hE{NZG%E_z~ap6SVFgzKRpxPMHhk2W7bD-e$@l23N}Z z?+u%ave`Q(39x?6cOAUaBrgAiZfv2u@GGg?UsmAd)|4bqGji$i5QjOe{sf|D!ub~Vyy#zVEf5HswR}XT zjrx~&W0_JJ9^mW`TB_U;W-sI3FmHO_qLIgw1owCn3+ff4&$9WPZbclD&u8P$&`oKz zaUkk;_;XDKUGbczd{SIQD&)LR<~Vlp)ESSSP>Kl(QM`*68g>!8s@6tx#1zcbI|b`U zV!%?NiP77<6C6AS($908#M~m7ujYH<;O&`RS>}AhB541x^coo9&K$|K6f3zG^_cg@X zPW&(W(D~uUwBHf6t6L(?NO}JvaknllV;hd7xJ}-mSq0mQN45%CcLGfYWzIQ+8j9YS z>7LaT5}9a^!IpGfk&pT)zbwWeU`VS^4>^eb=?Kw3G`$;)*Urn7v5%H=d7n;P$)TD1 z2fci4gbNY(qj>Ow%)O?#L|$+oMwH=8@ra9vb631ooXqQ|csD1RJTXfH3DMn`OWB0{ z!#zt)b$ocQ+#;>{kX#PlccG2fEPPA_jnFyXGBmnRE>k|&**i`vLBDzLujadg_ZY29 zx4!#Ct@xoZk5Kk|ZO{66OiWk4JymPp%R5-9vyhPdhLrE<+0X!Qbd(FWtv(6I^Plsr z=(72h@kxGrw7Vzapgkqn;El8BcxBKY#fiv}h2YL3xJ+aJ4FdO6#Juaro7 z``&T5w?WU^=5wAeO#OQ=IvL9Q6(01^rv>}-KP2E2prlKA#Ok9T0yE1to^lo#LfQ+v zu^QtDC-;%6gb4>5Db{M=3K9@G3u_eNbYAcBDirTX$y1Sr2un2v5?1E3>Ua}IsBD?n zvQ;}s`Sp>UK9!2CCyA8nqkWZ@?mZI8QJOJV7=f299^nQFnev#dG(Otg%^so;ssCR9 zH$ce0#B<0)2wL?ytS|_i20B*{1fgW;)VnG=bOr>q9vxb-axYFgNY5Gl0M3h#-M!@0 z^a6AvO{lQ3Df__gB6z=2Sw41qP$IJr@cIrY9AV%saD2eAr;&9NJ~g6Xe4yX?85Y0T zzC9~GfP%*7K>Lj)KJcPi79olcxJTflJ!;u3*#l%~IYB}!>i{>9 z2gE`_xoZ+>to0J|05XZ-(kQwzCh~x%3&y%Mlnx>f7y%rj2_spgTn~9*Mc??c8e5B5 z69IYU`UAqBSFbC1) z?%+v{ja?V#2sPRFWFFtKtu7LtQ|&-Z&{9>$th`Y>kd9G>Fg8VXNbSJRM~p(splVln zvJS-hm%i58(b0jipY-m8haXjt=77J-@jGxoapZu6jNDn4$R3=bL=KF0Y)3~9 zs3&`XRo&2{aDWtTFdm%hfC>lBQ9D$*V?j{iK+~8feKaL8wxLeTVJwZ*k>h}Is=yl1 zaR9gkwxh*Z^BqXtalnIU#+1V3H~{B!P^Mj*!*PJ1P>Jd`+$Ep zNHm26r3FK|0cUs-mVJGSbJ_r z+;oAj4c1Lg1NQ|z3kGg?6%DN8PmvcYapq0QGhn-|hA~x$d957??co_f!wVn|;ThP^ z{XkUwMi&q-)HcJ#5D9exgHa-7pc=g7TuHRBJZ0ce*iOki0!}&iW8gs_L<2O9!%aj$ zA?Znr0ls;`U3*_wkZaHvI^+i z+wDtm*f*O3MtdEaP&SsK0A{*v{m{uzod7$+JNiuhUsdbquIhtUl|$pr&v}&qdmyGT z7(vsJ0IG)kgSbQ?0U9x-ZtK5AFamJ1t06XP`$GV8d=5p){}3<}klvID?bCP+0%*R_ zm}H?^!`u&0HBp2~dpdzsOb=iqCsIbI=e#r z@U#Iid>{sS(_9;1iKWnl}kM@RwwQwQshn*c&D38gZE{2QnwfchXP(7s>UM1UK2ODsG| zY6${lkkwo&&eE##03ONWm*Dj%;Q)&BR%=sS@!B&0$8bO43K413V9E<%HXYl#>^`V~ zbl-h!6#(@dE3>BKjnPa1xiX;M9*gfC0?@FJd9MR-tJ7yS&;sDNG6q2LeD{2hc|7K$ z*d7YNkURj$BN9750CondARp`?0?pB3*8;$}q==k`n}h*i;gXG}g*E^%-5x0nr0*2K zSN{(xM7jNcxmrzvSr|~r|FZ*o(w)Q(Wa)n?9Du6y)p#HyTJzww82B%l*`|`Tum9+r z0R!*Mx^VtSW(Mf_|CHis4OSxNUGcvW1Hvby5aEv?-alM0@AQk~?(^*IU)XiR++4Uq z#8>^}^#9mY8>G0<|Gd{Qd--?I2*kT*cH*?-KPAf#*#=_9-7Wkh4LSXTH7*V1kOh1)`a^Lk zC{DNyFc!cmVq)D%0}+rg6xmOYtoJ&3bLRbLM}c1(q5LJF$cT_Z7CbwN@$a8F|U+1W*MFqTjH>L8%|r&yE8?ze`LkpdF!6HHGF9odiTStJ+wYE( zK*yMf?Ry?NlPAz@v>h5}a%x|WLPDE!MZh_O#$0$H5|)#aL{`i`mLuq(SI891fywNv zeSUO^nX%o$iR=$#NM?$CG^}!y`Dmvu*x&hXL4U)(LSFygNUTGBP+D@;+dSaJX;tBeRxB8_2+=K2Ee6Ou|+`Lj6^-#O6Q1 ztWIB6H-41q*R}}KOkX!KfxzH%_WtOo^mQ>1(gvLShV;9R6W~Z)Xesb8`e4zX^d5Lq zbw2dTYXV&QG3YmiG0jSZlW9NSQB1`&?63~HpI?{yY4f04)l5Afh|DOha-Dxu$Gj;; zxj5fHghw0aqeAJC8y)wfwRif^yC@3`Hw?65lCDNV44F>?w{pMyC_zClZcwBgYRjjs ztXTI;yuxRX%Cz$T{Q-|t$WzmtlJXrD=HHAjhjqllzsXlGSi%HkvXJDbSSO%p2jPVZ zB=Y^K-Uvb&h<84uV+fFMnB9JK$Iq~P-xkRK-S~L0uo+>SWOE?RCC+91^`gl@#PGEB zcM&sw>nm+#rVv=o_#$Bu5B!Muz@~Ry{ML=>TdAn{<*iszzYsdXOP2UARtcX7r^piD z39AbBq6)=TB2eN}cd2N@NET7zHu_Wkz(AAV@F5KN!Co$WGyN;k_8=n|d0a@s zhjKdl&(|O1lklD1v|>#0`hyk{zL624m9NA?8A`l_)sf|TOT-b^Sm@6l!4$RYx!USRCS zNnB9&87YEFsgHeAwic-W3~?>?)5C1}6XWi6;C&JQ3>s;>VWz7HSRLzth3>&d1$O!B3~?y&XLar%>lkF9U@ z;f|HD$QVBBHDHOMp|_$o*0b(dU3&GI4%Z`ce3)6ijOP5VI)O6otXMy_pHm@)j#SFoHh?_s)c5#kB}fDb7xq&)Tbxmp+WzfBpo_E77+3? z+bRER`Yqem#6u@-tWA7sA+!4~+n~YHccg(Gua{IQ>60Ef6|IE;?KRSeVHPW7ksdv& z1&~JHs}0#zM(bDf&Rcsg+Jm}?=({7%xj5sU`5;3t_$y5^5c=8IA!RPG;7y#1e_neGO&=BNz7w%#VX7>d9<^DJa1F0h%$(sk?kX zLe!J&Y>k&&Ug{LzX|HO`WqD+AVB#WBS)TX^-P1PidV$H6KM{1!o+IGO@6kUbAU`5A zl|Mz7c)K3jl=5d^waF=MKTstK$`f;UsX`8>VVwMz_~&XsZ18!>mpQ_iFxw=b!C<*b zId%OZAYQ>)3#g_=3utaEDf$sC`MXM6<8q-~CG;?_Aw7{r=vZLB#yns}}( zi@zLy8x?DMGMD4^e(PA}__}T!WD}1_?%fe1Cj+?gtVI^yK|d|S=yf>|#-Ay8D3CIK zl>%6-O1uQR3&vZ*wdW_3A{Jcyuc!aEr-wfDia&?NruP?YE~a=|o1(LJ;>%hJG#;?( za^l)kQ@btVWd(bewI(KDm`kw;;_+fbAx{RhzlVQSkqaQpC?AZ#Hv>aqZB=;Y%rtzB z1TV>p?!L))K)~>&0~+qLgbA!*SNOuKkdqVs6)ZFL{Tnn&-Mg2F@D;um{irh<^P(Mm zwB&ur>W^;x)euG{?51uAci~P4R4I7hCi-MWh`~6FUyooA>DaZdsqh8fRYc`-*M&KG zMGwGX4xy+{Z)s_OFaKU=>yPJ;{r3Tfr2V||-|!Xd=kEgKiLiA8KhfLO?{1G-xykX}jb;$@0oz(5 z_Px8*-^yO#a6EBp?+~>XG==rfg;ES4%tY@mNl37?Lzl9d_ima8rkLTCKghdaRdT(e z`^>s3(TgR{grY$G{O$>dV4@jIE>(qfcL`m;_`Q!F(b(=#KsT_q3cxML?)97#Aa?5J zT&Q)|lTnO_NISlh*j>9yg9SeT{0#c!|p9o@4GuJ?CinWU}QB z>tGxzw>6U7t83*lEE_TEwQ;xM-Gdy)s^Ez`(x_2!1EU2}xIf;Fhqht~&h5h{s6EPOlP31IgDwECAXaT}yNA5n1C-d9 z?Gf%v7$T+F8;0#HFU&?nT{{zY7G2&B@rbpf6Q*Rk_EjRnMm1=8eU7%JPg&i-NnPGPXw z-vkz{V+MX@48-hb{g2vC65g}yj?CzJ--r^S?D9Vc57*{wxY>C6D`D?rpIkt**~ZS% z@w=mgGpx}TyO`M|jsHCtyRCv6Aojv2vEL*jS51G7moQ=)l(@-f#yGI4GUh z0ZGWw4RvJ8`|o-^*SOSg> ztiBjxNT@7j;!Lkq#{=B1sK^LK0jjR>A~E3%hHv>C)rHEAE^_bDr=Ek2gnjXgBW&s* z4K0;$zCgxossExK&pDVX#zIm@1d!*CxWZDgQ7;#z;m&NJsYG4L8t<>8HlL=KkqPzZ zx(kaI0AKk+fV#Lwlz?1Rl2n|ib6nAg13S$^(-8`)<%B(%oNhf99$T#OkF)M^K*zN! zTW-&>yAX=MHN`$hrW-_@Suvi9_5(0ot@hXAq}|d{ub_K;sa)yD15j`X9L+JUB`~B>=_nNq^lg8L@FZk(;En+^S^Xf@YEjh^loZI z$3Xnl8@=|%uDWe`tZB{YH!9pba&o)gMUQz9gyW5Ce59h2SXe)o=rN9`Cq#cyhYv@n zm)IOSg)fbuOD7(Jp@-2O+b&oT@RArNPw3W#Az%+Wc$Z2J$@sO7_r+DvmpUe$Fj!>0 zViKb?FwnQ{LwP)4psT5##`Jy64A8$2jQql3NDbPbm!RB0*YopM@911G1e*1E0r~Rx z3+De3pI3WsiD^%1$v;DVL$<}`ZuES4d@q6b+Ry5wHxZPCWXC34ew7AXQ7{4_jhgVopv(PBsnb zGZR84sl_p>I45R9kR)B=Yq~gj;M}pjfpok%r*vEn+1tF%!U&9H9)fKf6>nrtLA!8= z=G2^ZPwUNnLYg4F$as=4@NORd$PKPx$4WC!2BBM+~ggz`}5_K z^|SVg8);Nwm+u(SxT=1u?cnkVEoYg9!ppIInEE?VS+3X&Sdj!lprTgp07FsgwtWs* zVf}B{*08fy+L3V<%P%{ zh;}mYQ=lB7Xd7Zgf9EL%5dL`b9fX4jo(3Z0nPZ8ZI5P}~4)98G$n84hOZk*YY9w4hLkhW&(&DR}`hq;9XI}>u{tC!V7u%2y z1m?#>U~;!jVPG)icOX@a@hi*oIM_sEn5ZbsFM7vKg(Cc`UM{oM@#5L=tY3Y)I&S^^ zF{Jzn%<)wMg$9*(9ga&Rv^GnVdD4wn(Hr_m6Ij_er*Kc!jv?tWHU63--G?dFK;!+C z`-8t+#@R3cTu_vBZ4RpBd30gi4oktxD5q9q`QmC3L1+#wL<4S|{JllLQ=#;+5UpDL zza?I+(=+>v76QUMtBbIBRdPt5K!HNYER{gqoAgOp7R#ErAsTEI#nB;V=Z_Q@NUS~Y zPtU}Yk>wu)LQlXYhy4%E!5iXBxVLHBpS}w{9Ov|?Azo36?X6gkaSg9noYL3Oe7JHP z&XdJZ6dq136~lltc!1I2a9ip`Z}{Ey!=}O2@Di)d4bStw@G_i^`?7-bFGYZ0_^TT< zwsto07H%kxu0-K?)TZDH4~Q`NsLwf4_`Z|OCLEjlL<%)Yc%h%_f0->dfB@!r7U=@Q z#UX4jI@)*;JNV6@#~OprHh5fR0C53rK}z`JiwqthM~Z(_W3g<(70{K)g2hzN!1JADk1mZ8vfeRdOP7Kg% zw&`2=?W|n3@dQk4z~`KK8h|9=+A9i;oeDkz-ZIq|Um*g%Ke@;N0Y<>h;xogfg(A*w zkN_{)T7U};65wkI+qnv$*i3+%VxKU+KqcUN(FtEDS|^r(I|tR9I?{(3{7Jy&1Cb+( z1D@8Ot>%CS6Lu?rmN^q}{UB~f8IQF%0e77?{+oa|Gh=Y6s+3!wfS0dKu2;?kynV-L zNC()PzX>?~zYU*BKAnIoRLU%Y2PWV>^fxw(<(LV0uFiS`O~5NvxY7i?xB$mSISif@ z1$a*i8)%pSc-^Od@&Nd`9{aaUx;+5iF)IZjG5NdzIBsH_qoTrpKNRI{5UBt2{XM4| zQKnUXww^G-mA{{b9y1AWzwsQz6U&$r@|@|n?tU+-c`3gg&`GkqN9Y~=zNw1mjf(K= z6880h^bX7xL`S~#CPJUo78m{SLhp%Pofpoyd8aQxPY0JbaaZ&O>2O8_ zDOF{ze9>{d?d%pBb~on48=}a-Syp&!Ca7qXdw;-Nk^ofVrwYE??;vo7%F`L%4TCR` zLj%_EN6+0bscJx5&QDj~KgMpg8@z#YirF2kB@a)On8I!)MRzX~5zOLRx$bI1RQT0h zKh4#294J%w6!Z^Y&L``1)7%;8?MI4~ZforGz5-!mgkXYTcWC^Vdm3GL-BVjgnbqRv&vX7a>VxxK6g zv`p@B#s&xgOq?o{TX2dZw~j1XCU=-`>9yOy?&5bdy4uf%CQBW+SCkA3FX3Lty%9GW zqzvqxj|q)GdZeu@pZ^J~#FK^fX`7fVr`O}I6(33i7*aJZ3wFTf(O+z2?o zIoz`ghifQ_pw_)zLx@*m;vDWlQ?-S6x?aC2sr4 zda3PHfPyMZ!+lVC(owuN5^hp!lj&X)VhOhbdTT5L1FjP8 zi7;I5Gg{-2aI45uB$9Zrgxi+Stz?tgkIcp4F0I~By1Yd=a2)PHdF~Q-w~j$rE^*&D zNo-r()wKB~ZjWfCloO2PB<^Ip8+JwFUVHSQzTAP8!ws-mgRM;%1)%QaaBn~{pw=rM zbWFI@9f=Lfwt)GRid*8TRs_#xAjAON;G0i+Q#s4jZhIoDiPCm znDOL)ob7|Cv7RZO`9aLzwv03 zh()^QEy<9gjhq&Y?S*!$Es=TdW<3J!$T8LJOs>1uXH;2}P63Wu55E;PjS)-3%Dv!O>dorY8aZ>}!8 z;Vl?$C8pz8_Rt@XGQb^C**%rjCHAYMKH0bfO0|v2?sW|z$Rk@^o`>u&moj8Wz}A98 zb}+aqva6Re?PE7>#1ql6p$`dD$TjvWE9>BojO`?5e^X@5G2dbnT%!3hGyB(9qK1}Y z5B@YNA_8FWpfISYAAyAdtB1h&0K_Iclt4FvGhZO$u$wYO<*)&Xu0Os}R``KoH%uHR zrVe=ZvQF6XfdI>%htvssUO8=u2?Ej0G}8OFf?fVB0b&LMGO$maj2_FbXk-tp`F{>_4&POIYhj?(C%@=|8Q7wte@#;GolOw1$?=qnpeX=vkW;ALZKx zm|YfV)`;%^#O{5J3s_m3aEOV5LHCNt+Oy;;M%Kr%6)BKZ^^KxFLjvZ5M1%A6aUsMS zVjC+2$@@9DJXjA;1oc;Ey6Dua;hPg-G$!9=SI@N9<5}iIF_Q!YYQ)tFE})}Of{?9N zN6$W2lZwx3r=Y`(0$Yt_tXL8-R!^i~h6QS!UbTU@1(n&uHe9GxL!aNRjzO^ktNOGe zvU&$tg1b?5hp(s3Z~3B>coFt#ejF$psEbrz(q-z%Dsuu+og{Jmxf1t3HH^R_32N$J z!A?Ckklbif6P7eQ@Rc28$<(&&j(B1ds7Ah}b`IK_l->?sSZcow|1E zP8YC3*wWUVxK^iaSpt_#y<~QwZ_MeYc;Hj3@vd2oK^;!x-!$eg-E=Gfbt_>$(2hSFo$C*GJ&rz$5M z!^(mjgGqxWE&U|jyW)-Rkyd+8KJJQilx7ss7}C1fO4IvLwdfy6-+OozxdP~;or1=! z3#msuy4B^qSjHPa=;$8|dhlA6v2S!+d0G9NZ2G81<8*GI%;-T|xW{?^Zm2{6Ymd?~ zvere5#0lTLM*%X0MI#^>3LbbECE6|B@XnZh zVx73Z%p#iC?vQ2!IW7z?@GC2bz6CHD3xg(7^3aKPU5cs>ghMN**CS5{&(O$6$4(|F z9lg*Ark{W$qWJJrg>I+Wdw|DJ3)mMjQu0^>VIdWvGjtq^p*LO4hX+l?M}*Pr`(@Au zpT~nB0z1wWv?RyoOd#mr6t$WLy{z5^I=Wejl3Wew+u--L0bM|PwM-3sBS3>lR+O-j z&hP%YCqZZd%77NDwKWT|X+I#fNIzE|1A;R|;g-P9UH2T&YryL>sc13eNdtc>C#+C{ zr|0uWgGmI``#`J4=eXkO5NB4#de8eD)X+TRu4vCqf~b~|$<3t#Gu~J#LU@ir>qPln?&Uj1@0`*-Y}l8`8*Ij%e-;E= zi*_dX!gCyeas4{i!S?J*V-GWitj=pJEw414y#w;PtqgmfwN~UKqI0i<@B-|dW3U}@ z5#W+JSDxk0oJ+jX>{!{+ZBRMml1-^PMUvnhat>Dri!v-Xq{y5MH~h>vmoj;cI$j4t zoX7h#{&OsRa2|6D7vGcC-)#N3kk>0^!IR#6rYO>*b@Mp%!RMY~n7A2d2%x#HU`(;C zvd!zg#K2fgWOty=CUEBw#8Dw*b4B7IuxwK{u=HND9RGDn^^DexTycRvy*pNOs__en zVTU8`N6i(2s(@il^BT#ck`Iw)udXyaO|@=_=0(X;LHfN+|I8QFr&2q!rE!Jn!u3A2;nE3D=W%esV>Iuml0RcMT|CmkG z#c%hQn{^xWUf`Eda$}~&9EX~BPUqZ#P0VBp;wMt9-Va z3wFVeiJ7s^jtsr5Moc3I(BD!VIu-t~OQH0QEh> zjE-Hn^vw5kR(rVgk1*$nSRlveQD6~foMyu^l(9OQ!L%{Ix!BUz$3DblWiNl>>gpWm zC`LQ%Gxx0fUsjDxvgTtQD@1*Hf4fXFAdl*0N1RG<1u(o!Elnw25^kF-?_!sM8}m0K zpZ}FPd@hff!IK@M!MJRm6jf}mBBA{K-m=8f>%lvowk*ik^K-SV&5C7e{P9b)9I&r7 zO{48^%K>d>nd0t~1qMj+v80A1#D zdG+|8O!->*YkKLg0$rQ#S1ZpHXp3g3)d#0g?}q#e+as3nr^}X zjSQyoVAb+wHz{k@zPaj%7cSaQaB@9P5u5@tUMJpgE}+E-Hk=eK&g$yJ_Q#1VQY$*j zIVBuC{u?q&8*>(W>g23*@+uT&>#Y-=b6oVV>69TeM1kD;0}{(hE^TF)15FB-4&WN&PFJf#-R|`@2T;2 zzqv=EJA_v2=WOv7p8kC6>Ox;A)B@k2q3AhO3dEtPhxXLv#U&1+ zXtUj>HI*IOzrh^*Sg8^ap)SDTOArnM#?snYmKZO;DC* zHC#t;g^Rf>*6-B23P zu;+B}R#C+tXSGmA;Y59?C^{SxiVA;)p^8x-VPN>cO0Nhzd>m4TRw~s@YOy|`D)sA^ zRrFFD=mhIb9rgyDaH>$BvB*3XVL{a_<0F1j-pHlx0(0rnY6O~FA*nLUD_&}arP)|I++TC{_pu!>;wPQ9!iL91A*RZdt6#`=L8A&ExfE_D@HWT zaaM8|*36)FRY_2^(wb1@vKiGndaZjBN%(A?ik7^@>b<*%S~|2cup7w*WZu1 z#<;4=u7a;z%Y>rkxk^Zp#GJ0Bx`r4P?gJOt75*xMAc~!G2t9bE*AF>UUUz9pm|i8p z5uoQ@53$jbui`XEt$n4fUBb6tIVZ^*{MTSt-K6>p;^PArF}IM}wefZ#(q9I!xVz^V zVJEQHWMQ?Y$72W(suXthVZlkegH!OPm_Lc$Cw3jUOvhsNN0Ad!LDdz z;?}5uPP2#O=a`!%l~PGL`wOnZ;m!)cdp3r0)k_qh{XR+BNNDN3M?dSzg-fD5&{#gU+PPn}$wsv4$ z%jE(xF0fw5n26%?Yp+Z?4Pv|ZI}lNkt*^5se8QhiTVd}c>9uWkDK2nZqbhbfxDCH| zGb;%xq)UJ}(`}!owQ}zEj5dh)g$qh`818MP`<6m)hyX4Hp{Ph~i%@KZ$;!li0fTElIYXlP1KVV6d6#YgEuW7i6T4~ z@6mI9QZ$aufon2eLUZUWvxAG}eO)y#&E01{xBre_Grb1@>Mc}q{N(-b#J#5#5qr0< z^d;Bcj%NTw_bw0sF7>_Oc<8nsP^zHy!r|RJUkSzW4L4w6moE`G0QAiWfDsFHeXvkf z;V__OIx;7S>xAz;4;E9Y(lUnhW#10Au;mZvp?}N1O3x&kGy{cORQtzqnxuuR>#48B zrQ!u~vZG_EzBc8%cKAUsTTp$$r(7FwM5IFB2m*Zvb0qy^=o{yjCcYo^jk#8H2JUr+ zHS-xk4N%5)zKDN1dCI%f`5srC-&aNw8P4-cazaXr94ReU{o-cL@k6YfMd>`tUR+k6Qm_KPRr8MU>-7WsJ=vRa=rS-mjeBs{Ei@^y(MNLk1zfmCt6tFsUcUaz7qlth`uq-xt#fa zlYapDp2O#AqlkU@dcB>Mb07E^#5Y)Of)^CxJIN&Soy3<__bhUQ_)hG!i89Bt5#RLU zb2F$P@#PloETzgJ7``y#8}LT528;+bTy2`j*oGrTd^ezzP8LFZ3tuY=pBTiq4vZZP z@tuS0s5it{D}>qqiEq;8Si=og;#+L;jVpw(Iq}WgaQ^rNS>lVg#4|&xN4$!P@6W!5 zKI_;jV(=yRrU}$)FtHn<2M{~W82DzEc?LS*>oB6Q0esI!8<6d;y*s;r%71%TkFq;X za75Q4u1Qdr0HLU2w(WWp z29s6!$rs{9YNn4G8YkZw1(nySnQ9y55iN_;t%ArLY!{J~uMSGjh(J-?ZAbAHFw}2C zRZ)DC-Q-pfK}@i1qT61toBXc$THTfALkLRo-Ja*}$(ILhH!jTN3uB0u%@p68XtJBhSKN6&!mLcb(!Jm$AR*38&gOLAIA6i`zs5U9Q@1JM-AJyJ-2^uQiO-6glf}zsGZ39)v4f zEtdT9Nxw#9lUK64xU0Ttu;om+Fa1To_1i2|m)i%Q++|N?|LHux728kS-7cA?zro-- z^84=dC~Wtd#0m5r zah7)dC2L{|{kvnbv+sX52d#HVB${9tjxly%!qNFdeaqb@j2#z!Q+7z(ufode&`#i6$c|vKQukq5>@IT zte9DBfDvBSHExx#6|qS-J1vE0O|s3bpTp2hUHHEZ!-SL>PDl;&)Wp))4No=|2@L}w z9!3`%QS-w&#$hl8F?~MuQXJx*4w=1`{;S?coJ0!6L4Z)=lwXj^F)_^mJLtq5134Lr ze?NksWQvRb$U{~9Z@WUg;x=;&8Ea*US7vAN%IAd0!^Ob&;&xk@K^SAzzqacbPZtKc zjN?F?6D0;T&XpQp>?qSl*_iEa%+y7UB#t{55Y)_ZE8%{aO-0wy_l|QZVtstU^H@zE zOvA@~b8C5ij3q_b@<(W<1M=KdsH=la?g#2ZP8*Itpafz{GkS{5AbQ9Du5AbE4mP_! zAlFY@Q53!KfBPvS$kRhSSV5Wsd8QGQYx9Z6A%hg4W?Bmc&o>iuDf+&u%xp^zk6lF!5_+*p#C zv`U#u=6DAZ>s!^;7urf~eiP!p88Al4eG)~?=g?Df2k%76O3BlC8LWd5kXuStusv-f zc%G=#0`us##U>?NPn`ap3)hIH7iw(DRTLKc zU%V_PN+JO`Yf1rRa-;ZLy^_i4szKHG;JG>jnT$0fH5a&rVNfQ4U}yJm-vf*za~0OW4N8b&$) z5(Kby&Q;!i)lFwcmP$yhWZe0psdM?@c|Rbx3m;w6GpDKlc9!Z;&pj8>>#Ka0lJU6D z5nls6?dJ|j!*4%R0|Lhg0=J3iT%4=U3)dw@n&9{7ya zrpqt&1WgP{cC~4u?GGtn_u)#n*=gd7u)T1e67@myrypogbL{f)uooEh$_Um$62AB| zUPwSX>VdA^~(o2m7WjempJ1rp1=CS3aPOoqfpV-j>mpYp+z7uS; z)FY^N0JYRd<`Uhs9`Nic)sao|2i$I{6+52z+fsvh4Pef7Gfr{@;W`FgS6WLQFvhj| z1d1PEIFW(?!9+DlUBwpuzaoUB9wIU(y}6)Mk~#!F$X@;*FeJ4rm<#qPSj#NTBy};p zZ23(FoIFVCNKV})sik1w;hkp&Nj+csPzme1~*y2SbbqQ!;#vV#5NsY^Rx}v2X z1roe0_5LepDq(441tYbVq?DacEWk+Z;)rI*sw7E0u$ZSsFcw%qQo~3s?7pRb_ZJv9 zB4feFQd?>uF8M8}=W4txb(K&3Xw^~|h@-PxYA|vy)iFPi)XOwFjMOIj=5*dk*`p{U zH4;qIv14S9)D1uY!;%+Tky?~^Ww_RCEHP>ddVdFRSL!7^BC`Y07FX(fmj|fn9<9{N zq}tBY)QkTu3{%geAk@Wl`cn7B=_N11gm-wUG5idWSnkQ#e10D%rlN0v+lT_dEABQ24d z58`wFrfY%o-DxHtKp$=Y>i269aoritA~oYKZ3x&FGU~_=abipvb-=&4_{~R*`g`nw z{X;`)G@?|01l&SIDm4%sDiMqOsMn};{Ss7G;!(%V!$zA&k9rse39d&ylo47x!Ba&Y zlNf?6pN8@?4X&uSB;azPq7DtnL-z?Vuc(n=MD@|Ly`q*Ame53#ih52~0~dI8MV?D!vr#p@E2}vzj1o`~g2iVH# zsn$c-=1JqQQB1WkFA^HH#IKuJ}H+mSUCKcZB3oYkH=(Db^Vfr$VjqN31+?V929Gtw#!Y zM62Q3MX;>pqFefQ9JPL#I}cKBC5&28Yq>fR5GD?_b|S#bXjJXZMXgo7nB`#Wy#jFa zn$C?>O0doU8#&#~she z)&TuO05YjpsTP8#F+NwDp>)pHA#T;JjSW0oJB}eVZ(YvC=+wW=_)pT0w}wLP+#8JU z^41FeG2(hPLI7{ADT&B3m;&BbmPLIJLX>b>05%8ffNKo!9d->EUa|7Si7_Mi$AhvrRGrE_#&c*hYib+NI4UkSH0M#c@6c(-Z^2UA3OgAOi}u`LtOEpY$^mjW!d;Wi4-Pg zKMQMi$fmQAWzWVIq1|-|C9^-pn5E79v|llE)fzxmDUMc#7OXvoB4D}pT!p)q?$%un zo04s-=^z(^*As2u-)!4Er+TuQvCGP$X=R}_}q6+?(+xe2Rfj^?h;;llFV_V|wwfN-DyO+d20h1zamYSP)alHZT--UZojpq~gB>+f6scZC$gcYrf+lWPjR z*hk=KWSX}IenOp!1Q(BH{kh=(Z*WSV-PJ(&>X(FDD1}pLzQNyf7c@PV;aBnipts@A z4j}7r5xLaFqh53n0tbWW5Z$cI` z2Pcy;LUS5E6EL^aw3q_$a_-q2D7$$qaenMHhav-}4IMh`yg+Zz*>_$=_$~C+RB*Ch zBfLuYy!j|Y8HtcU{`T>^7-&XA6gEbADPKC~+R zi%3P>OLeB_4SOKr^v2ymo2M@nllcnjVE!%5MO_vWrPQx$`?tMSbn4WsuHu%Atxfgm zc=@WZIxTtfak)x=v52q^@u+`X)`|an<)(ERw+TrYPS8SCV_Q(6QI?zG2&|8b{uAF*KWy*9v9=#Gwa zJB03!AU-x@`nOK1JNMb04;*O1yDych7w_bhd#vW2Hw0k@>wQ_a@j6EJp?RY3D|1xs z|Jyf!s=qT2f9n9RHEJ9)@UjSewSr$CQ<+{LJek6yb;)@d{&9$$5%2Iz{kay zy|3MRP#c%{C|2zt$P9#d4~Fls^Q3}!y>z1Pt|=HE#78Q*S)8&q8JHj*)k#Gm3OW?< znI8cqo=iFrWY&#dEXC8*eJm}-uOh4UDW&-9F|*?MA4`FxM!^a}izmKV@l%-OEF!4^ zS+#hw*>&TPmBq{B$4Kb z^`jdvBut>$k;mwgx1|^bP`++uHmLk+%S^pko)JKk>GIqfVCrFhWaPGB=1Bo1x0+}1 zk7;=GztPt)&v_JI{{zL6!}H~Oz^(FBr6httue_$=MNd;S#luTfLeG%%R-{BfjZmlV z9DTB+=SGHLL_er7oRz=d6!$bt#K6 zeE+svk1Warzvr$GGcIRf|7Z`7KoPqa`_2rVvXAL8T4#@{I?}tr#I*lwsfP91Q(_+X zxV@K(bidp-+@1?_m^*O4QXpMS7`VT^hMnYoO~{EO_gEL-B|*b}UZQ)C50JTbpGeRd z9`A7z`118W0*c}qX`P9j?~jAOe<1~a$T;}GwD5V;yn6@!N~ZVXzV|hVOU8fsj?bCM zCyhZ+rODqFD}VKu&(Gg7q4|w#i(i~CIrMxVWY8xJqhCuaeIP!7i3%Qlr*Zy~4EExT z{1!Sa`g4rZzdHecO3u$w%(dBhK4D*sM7c<$x~Zv%>H9D%OZ4WoVYoE*lG%Q#}i|k zW|gn{Bd7(>s7(J@yDFHL!^atzh8}$&O+A^Igi^+Uhc8x&j(pP|1g&P2;jamq~%I-K1o`uI)__3EjwYg8=A8Z?>l7YyAK5D&dW#+b_qO?^6K^L zq5L2yJy30TZSw6Wc?B?Fv0EFGV1nGT#d0hTp=u3kMI=R@f@LM8-uj^{x1~SMRXC9Y zp15*W<@8LO`C@hNF5{L2%XI_RW+A4)Hxdp`erqVLv^D;Dg6v->**|oxY~~Hl!4()7 zL?GTtUsj(Ah@vd$ zBd?JlUC~}OB;O6gf;hXcLE1RzK^}sQ=)f)vgkn9PSv#3*L;tKH z?(k4HTB1KQKdkp2#(u}t-a@OUbnS;+Hk_I`n^=}1(}jf4%14YScq)xc4#so7&Wv2< zu7b~srCRo7Ec_D%DBR7nsrl^~K{ZV>!g$ZaLT_CaLveir4qkbm;z6XwgP8f0)p`AB z!fiYR2VLIgcK@WM4viDp+mzjmRG{%sbcIdk0qSn)+VaVgN_)_a0lb5F%)5sn@y|k% z^z5Nj@gs+GyUxLQ)15YVFZ)XzYWVU7D8}euRoI6*YXB?mqmit%T2)wF#gvOEnye@K zgc!6;P|v+K^z1iX0gKo%2awAmGKKQJl~e$O3+6T8d99yN3QuxSjHB=q(`no z+cCVrqYj(n^Brtbq(Kv8cPi35nshVRX)Q=nAcNQPl)O{ zWrlN6Nec*qS(=03;MEJ@4UF%-`h(NGuzmxTVSsooo0SepsIMx5x?(G-fOSgOp#q5A z6Z}pS)$oHMt4h4T*8Er{ZNRgEKs(vdG4-^5fj8ea1Edn~_BZJwQ_}uDmAawj8Vyuu zsVnnU;z_z^H`qoqkt=#*i>RbQn@vvL{ycoFMHL4n2)|f!LeC;Aik3;T6m9rYvRZ?R z2u%Y}x!>PbgJ4z;q;OLZL+nZE7I2xcZ$4$iLkrEOl@zok|AxBmGLeWWl$i_Ou&^2& z2aCF6Bb0>f{5x84*O@X86IMoi`(xp;Jx+U+M)|p!wy9sfGLh%!4I){VQ&Zz$KW8R9 zlJ=9xqnQZlun692Lcskd6wpYWBgIb>^WaiZ80HcCXaJR-iOR&m9P5Y$w60jkaiThw z%15_gwzoEwrj|4SFmVSd0zl7=dKBc27W_hq07OGIB6UCsj~WpZQ*;Gdf~sV^?QozQ z%gRs~ndcM09%bQkel|)mNm>V*!(gXiUY)1}q1Q>&(u1k=jTIqq(Wodpp~?hOJJCDj z3P`$xlAN0u;@!J{iKkGvmabgJgekRNCb#TM)^m7!&DU6lDeC5gbd%{k`6*n~idWO- zhAG`T!?FJtR=6G!P(f#94U;Z=;sfVl=$u6II%(GG( zLa5}_eAr3Ek|1iNUjsjE1XTznjH8B}4B?8^*+v2qyZN$hU`P??1SoR8SG?JZm*fp4 z>_S3LYdj4oz=osGFKt$PoM~L7GH~m-9y8qac^^XJ9~TUEg=HG?Z;2GYEHY@qPl%xxh6O-xb>wx; z>?x~DbCUGWiNFZ6_P6ukvv0MWCku7LxeKvz5SKc=B^ zb^5fo06s{<4qNSxEqfXbo_?c_C0D+xRn6dO4Faul%ZKrds6Eu3JAB(0ZhAlJI)9o zYFzI}_?oTvK-o^q*N?%mskA*LTOtGw2;$0x=3rmvdqmpmB3L|e#GafaGa687A zCo-j}M?V@&ieMni+xvmgXA!n`Z8}LME{{#EDF^)w$B+tGT1t7=#FB68uQdMD$Dx}a zEZ;!$?(pd=&F7h501AnH9!XikGu#)=IL2sqT|e)I{GgD%4l>M3j)bV>iES&XMGTRb zaq0?i`Lvtm^a>alq&a3QMlGvJG2Pay0%S}i28lQ_FqD1;c?={fEU3sBv~v{hBBjI) zt%@S!Mv3o&#;evtn$r_`U_p-h@Etgrg{WW-t{i_Z)qoJXMqZpq@~e0qO#sr4 zJhx>;@(5aaIi9enhuGwCi!)uYCu6DNV_}j#$=*89OG>y|o}k4yq*1{e;}TzWX%tI>wXJEND+u$&;|f?l?cc;!v5t<+By@ftlnR1h8LpDf~Y)#W|9l*CeL zz=7oczbDR2UpnnfC`8vDcH`R^^s53rn=?Jl|JV^FM3qt#<)C?TGQ30wvy(LZdk1;s zj7F6*P-l9G@R$UBsomq?w@G;gAS_uTQ`6(d#wn0Wv3FgDW$+(yDr84ne-;e$78F^< zU!zq-1MN4IyAp86z<^SElO4Q3h?kBTxlRf3^`V_7Mq{(SB%-LvuTvgn)XVe7fv>iI zs@%#-STj%U&TIKensczIgp0FWe!3=46e7k_rOGfDIVJuhhOQ>Z8_6b1QG)Y^(am-i zn?95J|C=sc+EM{YKJ#}>3n!Wc$C#sTgCs;3)2BnOBp$RxpBgpIK=4}lYYEzKU4~EibjW!9z zeA$q3@bQq!8?11l!9b&(GgN=ehudJ`0pNCViMfr#=a6p+=KL09Sh7T<>Wfh#827f3 zA2g8fwXD=zbS*t2{!?xT4cKR@(b=Wq3ZIzQ0e1p7D9sp1IfZO`2f)%dCFO=N5{}Aq zhPC7@1zHC8u@SI&1_P2!5EXN6_sY30c>yZs_&ltJI>d^m)dLtHA*RhiICCua7(QXERc@6$dXEeamX2i=mg{ zB9MXFM1jn*QmLu z0k>yGD~#T5F>_jl+exVbnbv_~_g%JAz60uk1tuBz^kNC}wcK9dF*@T&9&in?sbqCW z*#h~NfCH&`F$hEx{~b|MkjMaHAYfiQ%*P;w%fMjdA{Q5IU3}h>K*>kI%jy5HV?Usv z$uiDpj1zYTWR({@0ryHQ?Ob_-=#YxWz7&K+y0wcCIl|zrLnpA?L1(aO2l>XMlx+bS zTpu?MB7*1S2~C1xVw)S3Gni-3+=Y1?OB=J_unr()G!+9mPS=-}^y+|It~MaHR9h9wk3M8IK5NGO&jd1{tT^wx@)jA<@rY_@!4AVZfjphVc8f%hEiHn$Vcm z!ZtB!1mv?Y38?-y`sudH%eRY|H#l{<92H)TXz#1dnM`6 zzcUymJK1MRoymN6SImA&jP!R_OO>PQq8L=qLfD+cuIAy-^fse8QN(G)4Klj6co|pK zTA>+5y+Of1eii~+jWV%L@h%0Hnpm+e_2p!8!J&QUnYgt*02*f&X?)=6srMU{c}y;i z2Jkfja&7*`@CP#JALIv39m(wAk2vF19qEhEfN;9+U_gO+9o) zyV24~t~Jiz%P9sik6^STp;=IiGG&n@SMVU!`YOWt&Jd*XKGeq8ffA{Zu`GZmpID}+ zKnb0D8{=1FE3(oZIh;vpj0TT_H_Vr!9Nc8EY9tGLpTLqsL6SKfx(5QnY=;**N${rn zrp+FwxW9lgU?fXa#?28>Ql%1oF^eOB7fFjyg9JP-G8BX=o2gvX3JY^Yeg}ddx89_$ zl<-)Ht9MW^xwxQpn3xocp?!gJ+lq z^wu1qYRZ2&&nmtI>G)b+i0UAg)i4?+&eMAm_1&^^v(aMRN|>>`VJoGfAc4HuJpwRN zh0~cs0Xj5mHV%mE#Guqpp$~wn%R!diZrP^@BQatK%@0iq-ioKP!NZeX7|R@p^iXGA=NL%R&K&?z3#kh2%UhIQXeLigjZO@S)O}p~v@^n@~rUal` z00fK@0<;FN-(d)N2!P=Pz8LMLz2262*6$u#;2*3Sdc)o;+ossEhc_~Q%#Q>vHnPq5 zsx26>(*j7rVZbVA`oIzKEYpx0Sr54ajPr7@xC)Fhu?lZ07%8)2C^8>$H%o<5egNM9NJ9tyAx4^{3 zCHnMAeGH!ITEW;M9V5RD^x^soEv?sAn784Z6sVsH9s1O4u(HzUVFI2%JVzNTof?H*ksQjK~5599_&j>+cIzDE6V07<%)r_erln}_H zIji`21OtE|=|Do-z5pk>RaHLYFj)3jX3$t3^d`-Kh0^4mwF)z1 zFBEZ;gLdYX&HP)FeyD&sHI7MqbVO1K9_thnXGlvzr8)b}?X+MHLv#-1#CnzuC9TpT8K(ONW!4XhiQ)C>N)IAW0KYwCzNuk@L*5g1kATp3XV)BN4eGA;4!u9G6R0RlNd7>tQ+^LQhQQ zk*n|M^~jm7lKi)NVnY%Qr_p*1V~UeF^K&d;FGBhl<`y5MNQo7#b200g=fv)M1^b?0v{$VoGc zwX!L8LC(gx6*OU1XSV;87Z}6ov(o8L&4uh_ZY5hz6PB%wTv#O#Ny6mI)?^DtS#_=^ zL96Tm(AO@;xeYK|iQ08j(hsJ(vpi){xgln(gqt1!T<@x{{Qq}~3&Oc>Z=vcWYim*g zWHmUzAfL>v3qtk)`adpeUL1Gv2ZhP>8K3H*%8qxvCfkBm09E>q)%vcJbD>w2+SU>U z>EnezjYtv<+}kAo$vhP1BQ&tTdEr5HHo37rX6~N7;3<;_Rb^rDC=;wi41eix_5hwX zCB3f*DgdancacOKiJL5G^Af&g399R^^D5T}WOLL~-R^0~Hu&i!dj7WxsFskmj~U>g zd+{2)7Ma}vmdkzPv6ELA=+wy+&i1SY^z$uTOx5%Rjdk6Qu+|(s8(I`k4HwIx=SLVU z@-bimhbfI0*THEfkITnYQxDK$`mgL0++Z>{g4L5WgF}ok#Tg~%+6U%!BP)aw1zQpF zu-mYG&sWbC1E}rN>?xqLr!8=~zXq;lz2r)QgbCKF-@@i4iDHY&A>}%TNAlAQERuT&Uni=))yun`b8r0X}J`L(-G zN2G1D&-Tw63~r)T&*%Q&0w#I;D--*|UH~sk{%#{6#8e-L)pLd~#na$d)^-;(-VYZ^ zgg26e{+fG6qSgpv9PikT%Pfs}=SEh*#6LsiYH5F~u8_6Om83pqDl0rHGDdJe8Q7v8 zj2Jp;j5+HdCwPns(6z)?-0bTD3I4}mUMv_1?v`hxf5bkz4)Ca2bi7u z5tD8AU?8MIfgbFwuV&ETy_;chju0P@aUwFpHW#?ZzPtOWbXE|W#(_)4q`w7%gKoo7 zMZKqZ@-U&qXT?i-4I8YL5GVwS8FVMgJnsCW=T%W2 zLe{AmMrXoSf>qJ(Jo9h$YE|cfzo=8@ky-Xqq;;71y8&6H$0)cwxs>`as+Wo;(MRQ6 zw-e=()_e(%TY$`7j=^|B2QH3vfcV*)6|%uVcd@IwHd00_NjfSS@Y@Hb zQ8wDx`0g^a$tv2xZ1D&lDo3~C(efn!GkGUW|dy=}Un6*1*&R&z&=Sc0veBxt*eE z`M_Mo=ENd_xa<6`7eE9dnw_ZNb-u$uzOE4>TWE7`1w`?DU)V&eicWV|TrcW$l}3Y4 zpunK9nT){l9OMp;W;{;x1d`WbjBYVjQ4)$mi0?#pFm9X!aA5{EiQyprp@9uyP|WO$ zkDABMj|v{Q9M-eam_1K=#lHlE!O-gosVL_`h`fK5@B^7ZpWSNrm^uKEfH zZmV3G!M1@&?FI#@9NHAsikI7zlr7A<>U9X+i)7^b#Ep zRc@*HEUOQio9FaeSV&PskSn%uwTqQdK3ND5ar8xwnN}EW#y%sY$BnHB*oey zocKQe5LRfthRqU@a~)UVLVeH1AnYvHSpJ`?gTxD@#k?1!xDWgN1ZVM>8&5A1TU$T+ zmE!0;1kIs0n=fTRx>tA1a{$zLJC+sOb+H~_7I}av9AGuF6uQ~(m0NA}zmZ5KXqAv8 z&K0EAjdeCaH{Q+UcZysRs`$0!n=?&7jx%Q4sOl-W0TYcl{|PMY-C*0vPL=Rn3?xPR z_+enD1Q@U=LQ&&$qI&?s1F9{TcX*9;y}91a*$3pwNnoF;Z+I%_uu#p zP}(;ydX(kU<~Ml0!~EJApT=77d)qzOa+MPgbRd!!(YEMaayrL8#2j1au_`cqWPl0! zo@14x&rq~1huTi1l2w|=r2=tznuuUBlZC~TWMF75=Y`dnW$g3tL~>=K@g6cj1vzZw z2Zmn3g?+J1fhhr00$%de^$5M2^1Dc$8oz7yTRW$LT3FvMwo{k~E5*$=DAM%}nByVm z$&HMH>?7zE^-WXE(kwTvSMDs>NU5|BaM&rTHUX9swpR6`3al{;-u_qKuz3K*_Csr> z$}bz|b0e4nC3ykX>GjCJGpW8USvhopG~lT~zv&Ikv9{*sY58x0D6v5wZgotCYh{?OR@ z(3Rf|F7>^fV(t+F)5^f2vfeiNf2fhg;^N-h@W8BbxeeCF3~|{S32LK?<0+9#t2g(w z+c7?6E8zfS-rz#|KYExN0pIobm=sszhL2D8@MXi+k5du+P5a(yfOsd; z5U$+5F7{^r#uI~%P!dZ-{P{D#8`)rIM%%S43dk-eHysRiFs#=v-mqZfsp2l~dZrZp zi_D1RTS|?%r)|y<7}Hxa*z~S^BS*5a(t-M|R(@nqv0@>LPoMEZZw={{rZQo$2Q_Fg zYKpYvQS*qY#V{A^9ETcuh!|KP|1_p!f2&HqGd!3Br#l=PdRHT_Xid_!V}xgU&3v5b zy=*`McZv0;{|2C9gOKap40ABnaaf}p*F%>L+N5S_WkqYvlr}(qv|`!8TqG0PQ}Dr+ zcRRzZQU|)z*X7~&56};D7uIN`HZ+LUG{*y8>kD-LY1tzLN-d-mndzOwN_MUM_dKtS zXU*~H00UK&nB2$`u^tS;xLBi=5lqj@f~-b5x)+i2osuZI49BwbZV_>7vs0HlB5eB_ zOf7$AaeRZMR$STF&wMDv?VQQ6v*7dLf6^mli?L6$=f)sZ7)YPUejjXsyT0+`<4;*c-@6v5+Q_M7vahtvcIreJ5$ zwv%Hr(f*{MYgI6)a9D|E?q{)uo!R9v ztIQ(TLKbpnvDX4wD*yBy`iRSp07ub8jXl0fNvnfd0L!j3n0dJxg~kFXN0juRe2C5U z8j@aoRAE+f6tMh?`9Nkg0xkynCGUr+$H!Y_OnoQ#c!aAl3#ifp$amoKES4N3@-$ej zD_4fL*bmm#N;zaoILF|R&-a5%Yp%2_2oANV1mld(!?8n&XjdErCkRrVQPy}0-GbI*mE1L~tQKBSNsU&`jJlj$iAsk=nrZn8y%@Z%@ zG&0-2^T#4u|L}M|<-j+&laVG*e^oAZGeJznO`r4?oe7L+Y#bAz*l4(^tkHLCa)opE zV

?&Oa1%qG(Dxn+JU<`ee3$E=?U=WA(t0d1(@F1jk&{te7Z0@*FD!i}_gqI5F_X zvq9(b5250j;*3Jd4!0SkgXE4uJ}__EW}w0xZ7cD7;@((z0Wmbl#ta`yk|BOV{|cHk zi;btTaP|8_$i730v>NnH2AEw=C_aGBY?`!a;k74FY><$e4P7`$8rb0_exJo2#u^vmdT97sbIo3Y0_ z3od?7>Hy)b<*1mCNYs80B@oY1>pgEMvxji=7y=H~vjxTp!5IY}F`Io!UnSuGQO%{L zHm&D1M%*r9-nDqOL&##lyT-rV%OibnOKX)c!;LLa`n!6)R+e?3Zm!U1^baa-y1l5^ zmZ$edI9~&;ckZN7f8=>%QPMPsE`3_)e#yH0l*M)?fp6Sa`BDX9Dgi3Df-Apxu@qLY zPh+WHZN<0pNngH=7~citAocCobzuYb$2Ps+%Xlp8}5Q+eGJy3Vtp1(Ps9ZQPH? z_N71@3IKnDtEZmk{!9W5P3{f5k%a&=JF*yP_ZqOZTHrJp05vZNH|!V>eM>ESJhun1 zWaC~)2)VLgx?W#)tCw;c>kE{yh(${}OFD#5<4P9i;J?olaj8m7*|!p_mq#Cq zBKQdb>dDLo^ON18ug@eC^QQ`bG#quP>Fc!Ore&E{nJAkD(q-ZPXc}#_{!Wd_@+_Kj zQ`Qb{-P>l7z;az*0&d&G=_zf0Fu}!KuXqCdh3)59MY;dZD>}}4dYWhL&06g0XUVif z>HqybRG{X(6s>c!KN8=8cwDZ3y?qR5rSmGPqSlWPdH9w58U6G`0`&9^L13;Z6HhGN z3d^JW3QJu<-d6S{tyIBE#8pbM%EMIA?o_J#1mQh6-WSMceW{`EnJ+Y-;meoE=%GxJ z#UQM^AY$`CR4F3%obz%5vY6s@r#%V&aI}D+G|~wM1=Jk& z?9>)Koo_Us&#&+SUmlR1$H@%P#veA|IN>l45wQK=X?ksKNeM1`SC`wk&uOu|p*B6y zLXcMP>*j}`)T?Sla8# zYk$Koc*;j-J8rEku$3c>$gx0Q11vv8u0WwX!gwfF#ez$#u^f~W5tJ9F1@ zJiki}bvpODXm-%c20J?tPEcwGSN|ppM&AhS(LiFcfZB}wke5O;v0w5Z-Vm5$c3K#J_Af2$@m{Zl@sXa*F1i@aa5@>3u~?%zd~S z1m~!f4V9b`Eas%jhKB~5mKXa>niNx85J4^w;L-U>P}A$b6Vm4RVWAJs>3_$gr#FmG zP~w!oM`=Fyzb&J$E!5vKEI-hXyf2t14DyLE*U*vjMP*JdisePr`LKpOVyNRNN(yZI zn%Fu%@_xKzcsHORy|x{wpo*UDvNG%VS+DB!tuHj7C@x0cLCj$I#`fRc%EmQ6UZ%aE zhq?rJ*RF?0t^*>f15F+GHKdqDz!@Pa?^^Nc?>veKJ~krQwP{(_)(KV5r0X}_zX;f%Z)YpqE3jqgD4H&Jw$m zd8?01#EL~B<8Iu6`WHyJYU&_?l;@nBE#Sh$M8B^L8q;*}6mbQ{eBy;x1`mcGD*t?* z7_Dm9W&5(pD03Y{-4{b1sriSP0rYF+#3fy&mtPZMAw_=jkZ|xrNuM!f1`+=ZMIQ(n zmqQT{Q60cI%b(QZBEKki&JO9wfU)>#Lr`GW?f>_^7C%@mkzl6 z!CgK7?CJj;8RI{kX9DUyr7bPciik)I8^MUqmJCcVd(ie62;~Pl!08~-7eoUyC1rX_ zq*|Us^}z#t$HS;zumWZRZ~`7g8ZR;&Z$_dtB9hS(@rvq~zBSj)DlVu`PxEGJUvp=s zgEV9`;w6pMC>|6G`oXiJlVaAtq@!h%wnZ|`Lp>Urp+%daqdnVgQqiAU@=<@|BmLQa zOfx%68GSTVLO{6sTsUwroE%{`$hYOAbiU+3-ea>>fD@L4k(W8^`xP*___l~qqNMB9xMZSig| z&uLc99L(LDVWr}ZuQK&@_qBXBrhd`OcT^t@s_%21GaeKSwnM3lHFJjIL9uXTR$o}$ zB41yu{d1O6{?r%NfM7v13nR~8i=G8)5~14hbC$Y>e`-xm>7qx$KuH*C7-;4UMP%{C z843p=Sj;CB5g=HMg27@G0YC_e3CaPI2ZZGS31z8N8Vw)-QE_-M;ACcvm^^TRh6VC? zKr*2eph5Czs5~qT63ZiEvd|EDG>9;9KmsyZXsAdQ2W4rXA@XR@SR7cen47R5pusU= zSRfA?m4^cY6-fdM7SGcfW>Px;LH(B5kk+y?%@_8msavJ>_jcC5-%`);n3z+Cb6a0h zx>2Rn(^94;S?O!UWowj=&CU_6`_&l zMk*>D^%RwTid=6gClGN;m5#)ZUMz0I04 ztmrJP=WU9-m9|u8=Phs5x8{tku`S3W@#R}C z&Kc&i^Vw~NJ|o{yomRKL`Rwq>ZuZblbK{=TsBTTgJ)NenhLu*ZGy3Q`sYPBivbM|-dt@TcK?sn|PyK7!Nyd$C{Z#vJ^ zm}R#ascW_8TE9zZ)g;?Hrq?u;w9K1HY2Mt#vVEo5mh7l3&Fo92sC+dO~H82sL=URN{d*N)we7YLOQM_OeYceM`M`H&Wh*cX&p4B+R>{a^mSniFSpAH*``~ zG9)H_cklJ$*5YCc1;-Y#N7tP9xsEdk}V>3CqIJxRc z` znV5*)OuTa@L#Ae4eXOZ!)wJ}|ST{G9yt%5nsX0zf%*-U~=+36<7%8bq&q_L)q*+So z($clE(@DidU!SL_r?-l_sA#CCH7aVRs_Iusi-^3oYpq?_+S-%q>aOao;^x}zS zcg{HHu65VQy0$Y^d43HU>FJ|hM1PlNz5ClD+uF_<%dkaDW7_ohv~$Mn%eU&QepXFy z&d@8S&KXA?)EcAS3>np|j5=qW-f8NoOH1dBBmLE+NBS`->Ghr*&oGlWNYeoHH)XyttVDqWX(-#x-#g)9`T4IJ|!k z@y9g6Bcv@n9Mam=x|jKvmS>1}Jl@(6v*r%(@a}T#?9PXYS9ElCbaRH1>27f^&wMYc z*}d_V_cq>C^!*Uedc99=_OV;(K5toH$j=#uC-V=DhJL?W+vj<6^8Ds|cZa8yUOV)y ztxpHl)_iJZwX~bhu{{upgheZ#%kFU@CGWIr>zQPR)obgL&J`D_fYCaX;K*aDr` zaIzB3jAgZFqdsj}RaI%(nu_WHGeZQag+dJ;4JIOw2^ymkERY3{Bn`?$!C|2&R2InO zA%VgK!oxxGP*^4)4-_QJLV=*5peEeJ!^6WtVQMj@P!xfK7PKIRg~CiNW=i2`F{MBY znnV`L0}>(8fU-D99updn1|W-sM*|HBFmT`&bD0fqK%^`V6AA)|4GkI+U_cKfl5#j4 z4stjg4s|#j4u?Y-j>tpOn21a`91Y1tLTOYa7RrQ11W3bSQkhgBkjKMAWI}mRzyWDE z8jIusS)lT8aA+(P2+ISB`8_C=MuZk)4-`~HLxGB9i7bu=BtqiRfFw8oSsXwXiKGFs zFoA(dJUEG@9xx=52NDT{31k8hL76x-AP)zLiHAeO)R@CrU?QnNCL|Wh1Ik3j;oVzoM^EuFb?xfsq6bM#P0HBAePbUhg%(@p!8CN4UUvgUqy3&;|#)}WT@ zEmLnxQ+QXmMXCfSBnk#7ARu%QtyJ5)^Fu>RsTesXgAebBIc0U}LxzYQZUgr6i-)qv zre~4&QL8y3kNr+f7oV#t)%%>%a^@JyMxWY%04MKRcovgIJC}*0r#VC9vAf&drB&f? zh-FMX+U~9bi=$^T3oFED&5Y;fId!uz8Z*x+?c`A~P@6PLNjg72H}zCUn>)W5!C*m^ zMgt262?7cQC>|6GLqi`rYS!T3dA(*lJiN)8-8#`yEz!`OJ%X2pnP+ClOx>(1Ewju= zs?2zWh*oH&ibg~-D%q71(ygeZh=^HdJaPt_J*afGd6Hf#5dZ)H67vxVfJh`Biv~nu z$wZxg6o3R`ZbHIVCXIxlP*B8-foOmL1P}p+5I_Jh&d7ks?Eqb(j~TAAG`!Q!pAoKEPBLi;tCMkoXE$~C0@(xC3^rf(SpPbH;GN^~c4=rBCNgZL~=vhQOE9YfQnlI1$ z4XAg&bF2#l^~CEB5oUQt@-!ZTwt541q~8YMt1~s*Bjby2fqf)m$huRA&T=Xn$>3$C zzLq<6bI)5xk&56dfEK?*>f&^-T971}LyaMf02D*bAi}PJoKk+8xO?j_;5Hq23BiF| zAl-`qOljyi>4`2qG949B87EtFezyB4>mCzDV&@k*Fy+R3%Qs9QXNl1?otJXmp*>v| z9;D=p`EonUI`)tTT}7+!nSk;zLQ!iPKlFj8gT#>y`$~{Pu27ihGEIHwYIocgl8Zf9 z0r&-iq1%u3ndxRxstg|-Qx zFo)`1{Ra+IOSW}s$Z%|?4hQ~g+~ScTsX$2QUZfHQR>W+;oev({4W3eBMdtZ222xU= zY1vW4){oJ_(5YcXmh#FJPYz1mjf50xSJ55bU*;w<_s<{QAV#dg#iBqZnA&+d#O-QZ zZXT$YhV^3mpNG-Vm#w`!-D!B8ED$dxfEZmAU7hzaK1WeM_7 zJ(##(bPUfld2gg7&|?9B5X|k7`DKnYv~V7c`2TDd)u&wly?K5(+o?A=-&y4L(rmkX zy^xtL3-k(S*4ecEO_XqQzu0jBx$05n3yi;f*%Z#5M2oUj7omq+>0O1M zQ#YPfcOZ4Qlslu!J4Fvg^;Moh^skC+D+ibSwY$Q91(R_0^i>#Qg;`|i9$ z(4gGP0ZyN$s9~2`o5Bho1bv~yt}<>d5gHiiH|;^F(458Z5f~Pr(9Y+qDzzmR(9rxS zh$-6%xv7`nEdI8$+#r1_H22~>TB1@rurlf)^(v*tY1y*2>6ORS&8lWq{MR`+a!KTU zeLuNH3hwE3Ud4YMq>(mcr$<;!+H~oyRN_?^EW0cY*$7|~hrw5CVyeh^6}3ez0R3IM zx)ld4CWr1^&Jmz4(Z-*6S?Gxa+|S#dhBf^`DRd&}-JWN~dr%-U{O!cu=0nH=Jd5>P zsNd^>D|UMCXTI?(DkUN`yj;bv0 zzclNSuQ(j)7->y-F?vZEa7QD%PVlm|8tIn%nJ!~?x)_&wF)ibGs^vq6^Lm)qTBp5R z5%lXdkIvx8iVshjG{1(1b0sHPae6R3y=9Fc%2T|{MXT!eZYC?21htXqQA8C~jqPBc zpp}Aa6JcDMmBm)v4p0fw%hHN6wL($4`(#kNZ7Zf=JBrKpx{3OT&0 zXPOM5nfB4rH+9Yt9_xmj@UB}rsg&ywF;dEeLFUZ{{SABrcMt<*oUMP9a?z%=J}6J} zFx91M3zV9zL8o^mG34;Q(aAG=-Z_dR%_Sbj6LdBMXr3a$6tGt3v9usq>HIlpn3_w) z)JBtg92aWBOrr&LGKx2#6=KzDu0$OEMm{n6xFe>94m`H@G2t3OGls@)QESI_)twMv zV;>!X@jvR;Wnjf#^TC!`nhZSJ0+s>JA2?(u7C4j);H}r~i;%Kaw(N_Ku>e~@q`x8_ zM3Lc(I@YR)T^>^5Yg_Ym&#_8tjH79N4Sl3`^)e-gOV?@pN=oMeQyfUj0{&Gd%1mVI`CM~tzblZh}iohkOS8Fa*$pN$bW8zQHI&C zOK-1mzuSv}xqUlP{_+p8*?vX2P)@hhWIKOs_B~Ze67j-Q6;Y zs19B~xAInx)IN%B*BPsgc~I@Jbe^c(qVt_@K2UPq0;#Ps#d-LrbiZDNSU4Higv~-_ zsERY{vcG>#bwN<;D=LT;2GJY;T;@ZBER1S5G81ULC_n~GC}#$Y&2Wr zjK0~I&H*qZFaub-ekEIoQd9HJXO1t<;oDiorJ+0MAV6gGKWs;VCtfmR|9tK(Vpw}} z_Wp#W7*RCdM9`e^ag&c~v53eG0Srg~Q|1g)LAFUyw zDWW|1u-YVJVEB@NG<|#H2|Gmap8rSn|M86+#a+)jM(fV!jbsFxWbY9C_=`b;f6g(D zlzWpZ9?~HP24VN8`b1=^y&b$gSHKnKS$-vE_SB6`?h+YfTwkrGY$Fw7z)}|cw@9ez zY=HrmGL~>+NF%q^Xb|T?L1!x`IJc4n)ro(uT6R!?sBRJQmHyH_NynV{6yn4Y+_~&! zwoqTI!tUO1S|WSZGg;kfnc-*AJwez^*m`B5 zyK;^_^>Cr#;R2#9nz1!}5Y8*-mBZrV-yEx&AQ)!qt3|IuwR9(Hmx@Q1R$FluDPKu= zzn!FT2svGb^o|nksPuqu{kSnDsfb0mlgJ z{i;z)7kL6K72(LeguDcZ&WR7oniyI1u`Hh?&`UI~gE^l7m2ePzz~YJ@{L)0D#6h|` z0AjKi(~(E8@Pv|-rn=8N$@xgKBYGu(5`o6kFO)8{`J==eWu!Do=%>;@s>2)`!Wg^A zMPLw2PHX;jlh(~hmq4CS^6PAdBH_Uzjq5bo$KU3JR*u645P!&%5Y7uS2@)!~P+$he zb=1==nMh$>mYazV`y%T~!9yL01R&ynz$sE#a`5M=Q_(3*W)PK>P$8{4MSUyS3`)vS zz=6!Uo}kY%qwopX;xahqO3Zm1f@4`l;36bfKjN`O;GlRIl_er@MZ@G)&_qBCtLcS+ zK$;$a+5_OI{Q?LBOcpl&U(J5cOvs<2PUSeEKh_`vb}6K9hD8+mab@$=OeW_Qlp z&sk7J06`}THgI+xb8QC`aJx69_dP@{+Ko@!ZkF5?-t-bli;pgAPUV-<2rX>u6gNcT z!m2h15z(&Lk7RLm*r}hkp+%;oC)i_aA~%)%R+CUU*N^{r7cCyVn?KVNoowk_(n}%T zt9;HfWWg{%+0v&z9H%oZ+ibSG$&O4bN|&}#b3fFK z_1aTAC@>!Y=0I_O0oX&TdrcC~F0#1#W{=AgqT#GLI-NL;rXq zx7CcBp}9X^cN;~rqMo{=;U9w4S{Yaza`_OT{%X)BJX_MpvZpg2k}^ROjYJ4gf0OMk z{@noHr8!-OEo7yA3z58nA$K8mcT#X+?6W({U$S5Yd+}z|1zBv)BI#3Jx8OOZaEh2F zBYkr`1_6&w?m%4?p=muiyTm1E=sR}`pQE}EPGEM9qX2=*TWl)J2H|_>q zlQxYi7Y1Y<7i1PqY2mL%VQF}uW6tcj$9%}Cps#ByW2_!I1DY{bBZWB44|Jw6&0$uT zGmpntwa=qcv>&{W4zb4dpg z)g?Z8W8rYS>>xfi>ySPLFzaZB)R|dus8r)0VMJ?C>=^?XW!1-S;{hF{0GZX10zScs zlAv8waUxIC!Jn(;NipHCFL~E^+C)+h%$E>m-Na?w2=4K2a>i(KWNnYD4nuC{Ffl|; z(YooXL8E!a6PHt0BhsAW0w!v-CeFH1Ry($IKnUC}3?~ISvcg>LyoNSXEZ`3xQH3VA z|4frV?n(`HYE9Qxs0{nBguw_OKW*OQHpp|)-hPy zj@j&k+=r%nCB%D;CS*d|O8#haGhF{egT!$YozZ3coimc-N+rbCSOPMny+&FMbmh+J zFq9c`b@ebEKz%TF^b%$nWZw?h=^Ht~KFs^BRe?%6u`2&f90GU`Zz+JzRw^w$nUb!= zoJPXr=(c)AjN@{NVM6@4cO0l1vK_aMkS7ey{x#RR5Nd>??eyhLtAAY|9B_t>KGgT;$}T2R<`|Kw#!e zZ9)`8JfoiWd(`G%GQ?`ew<}4`Y5a_Wh-bCdH|+xSaTGGgr7_wb!~RHuL8riAn@>F&@4O?aZ&>^_V+^giM{Px4jx)F-GI8)nse9`ff&hj z?-(fbWoYSdO^rvOw&AAPzdS3YK$^JqbE>cBLhj3gn1ud5HlCc5 zGMj0Pr9?gj z3+o!$VI3mOay#-yShLktT@v4$Mx-M9o&DChxb4StZV(SIGvI!VwR{9d5@Z;}fT1yGq@HUq%9AqFCb;bo5{ujs8Ms2{0dO3LMnv|1VF|9t} zf^TH`8fr-OF*Xj}(K(YF7bS$BndY%D;3t~urPQ{i>_ir=Wcs~Kt@*MR&I4G-2MLBF z4Wa3$xi=bq-Zxt72$NeR&cq7~mg`nR#XITC%bw}!dX7#dzr+uoNJ_t~K}^f`EhFoa zNBbQRZnsW;DYuRhlyZVJuP%5@E-`@7dNI7!o&xdYR-e9j#?duv*F2w)Sxv_L>N+&vB{RL zACC{7PL4L}MaaJK8WaqYLnN^DTaFwCYOq5V%~URBO%P*n5nh021_Dfq9DRPpZjy-V zPd-Y;9K6#MFou;dslSIQEegs}lTIqR$(pz>oqkuXC442)&pBh~vTdH|DqHfLP1cZa zWRV)+zOt%O$>*k2DP~&))G(Kgn_s&*3P83KoNfF;!Lv_NhAd<)RUW{AKYlB^PoaYI z55gU*bd>3h^*A3t|dU9^_8iyZ;#{p1>!xB?jf zVD-K;Ag1qQf({(j-aQw=M1Mm^D~q-kG6urTm^Z{?FeQq-X;uj41;iGd`hCdd%FVAv zE0w$i6`D*vNaC)xA>j8c-_=z&oQ%#QZ!p0873LmmW7?KP zFk50dzHFknAh=Bi(HIzMi$JzvIHlawpXj5YWNit7e?Isgb$9-7nFvd&b!aOZxY3r0 z>h~q`>YNG3d^glC&>esXP74$i?@}FOe&G(PZUE}%Ap!4*Jy_$)(a1jKx;)U14vDYi z;+TU@1<Yd(>Ltc9A6YF1z2j@PYU$3u0yGKQl*AH$5!Ob*(J9@@saPR%WqY#9X z-mV}Nzk%XOu6VqXd82`avXjhLG(h=PmTk`5!olNxa3ZL&oM(epZk-Pm{%rEHG@S)G zlPw+j4L+8`*o*$Itgvh_^WmDnscv@?uTAD%h&fOCK(+#VC>w&ij%XdeUF#6@;Qu; z8AQJJV}ZjZ9h`jtVi2vnY>axW(%cBryHqKw4bZF0{o$mD&uVEKRi>JD2MHuo{-RY z@Ac}$p|Wu6R>eh566a4xhUP0-KH&gI$)G|3E9>H5rGnn8}zt@M$h8TR$xJ7w*J+L zYcv{xa-OaUQ{raf?U)?S$|T5RQu$m^e~D5oY#zW&gB>l41HP6I!)&XlqmX=_%>LNr zoRE-(3?|`RG=Cx=!;u6_m4jtcMdM8TW*Eow0z0*K{Yv6ByonZ31D6VxeQ{U8(t>oO*zEasz3I zT4`Tumh?Rf7GtNYQP%7hZN@+#G{q5Cp=5n!Qa@}YT+&#PYk{**9Ml?8E}OS)g%ECc)VPn@(kLE_0Ei=Z1cO(H+Jip?yJnGkGT5<2B)dCHiQ7xUk%~r=Ze@ zpu2<1eH8SDvzDIuSJ4(fn|ZlfHY;!v)&xEvjDU4GjL~a^q7WA6rbs{lHTI0zfnFgi z&$oySPd4YF%cF-JsF8RG!Vo2>j!aNzH>cu#@MmKjF%nvOiU2e!PDRwMdAN4Ko{0~7nxHn8oq;~gK>lj(7bD;WsrfQ{rnb=3cr*kT zu=Zv+b{lQ6$OJ^foT;h)mXFbdoG+?q|D%oUfcJr3!KIB+f}!W=T+*J^6F@Ed-Hg|P zQY+Y%O(eEZ9sXXwkPBwi0c;vvBo-tSrb8kdBix&;%%z4LXFOGpL8)98hR0$Yhe~E3 ztyN?P^@*q@Kep%(Ub68?!T^;5wkAkYq@J|HPk8G*x$@Au7> z9~3HyfDj|GLsn(>lT7dw8P(rg?-#!-WkIqaOgAy}k8D@N=g zECw`yB=*5VF=!-NH;^bXURk3baGjt89cSYHL^2XJg$?`)k0@lJH&=}>aSSh$F|HUf z?Ndg1*w_vbrXV3%6`}3Qx(PSHCARfuHXgoiH6#UDWKDpD(<>nBnv?|@9{FDg$Rtt> zMa)*LI?rn?PNEYN`xj|N*CZ^2vX)AJb@Ab50PAfKWNYveuK2YEaR-rBFXfS?tsp{q zzfBy%Qy6RT;PoAkq`owUY(H7e&Aftjj{EkKZaJf@Z*;t@XV{ z0$K(`oMEHjs8!iaQefESruS)ePn)G92LVns(C;kawPX($7r@g#VH^^hzW?x@fi*`wbdl zIw^IHRT3B57Mvu`p3Pg>pAoquqc>RfIVA+y3u@H9&s8cvl;2S@rtq!>wB3V&Cervc zg@Yl){TlJhRbwaa-#1&oe^j<-1Ot}G5Sw>4NMSc(fP7%i_b|}TD8N*3S2uA z7+*Uk5}RFPwG20saPBhX6`^{$gs7Gd=T+kU>#Rxkfh+jNb0^oiw#G1Hw`_Dab?%a5 zwaH*jTVwG(ti}l!Oq^`(=gRwJ&f+*q?7;21&p8by$YtsQ>mh?lG}92ta@QbuE=UnR z#43D~clQ=qkZ}$Ek?#H2#*R>+v(u_(h^Oug5^MA$F!NEEO*3}eeOOnr5qiDu@NV&0 zT-@CnV^0CbshQQ2B*I zT9N)L4RpcDhJXA8mkV>?9On+P=M0)EL_C`qyycG6f`cwpJv@=^0Pxjzus!?c5H#@H zh@J1j#-oB(rlY-^fm?lPfkkqsL!4jf@ecBO=d4l;XF~z5c1~^aRP$P_<=fJ7Ni>NYtebubCBwTl;7>(Q5ihL_b z;kuev2yPzq3e;)uAzZa+2r-H9WVT9~=PkGc`v+P?N5Rfh*G9OA?QmmB4!rl376UnU zdnFOKGsY+1+L*$~;IHCrF^eg%VHv^V;0+fPF2kgU2ehW|OkS%YVq0nSXV=tYmF^4Y z?b|6*L0r&FvE4(rsW{CP^!-Kiq|S7S-2Xz_7^t*oIM5`-&MzJj0|K6B`Kq zG-&_Hb2$&zr*Kg-cm){qC?B|S$z%eEw-g=n^ zXE;F>>HA|rsgy?xdbTY&VJtC-shzQ$leIRkMHf+02eF)3@sRTc3o>P(pbf_9BXVjA zIz@y@qyb#98|laeH8>#MZXWl%StBE-=HKFRDHcBfCKm}Y8h3A%7)y^#pmK6B_f294 zp^8-tflnkN)g61C3MPvsip39T9#S0(pF-D-ytf1UQn`&7CZ%N?wZ>xN{$hcH;clQZa{0S;&_ z!M`Bo26hkWGJXYH)d-Rl1QiE62veJ7Y6%+@S;0$s)rA)G9Je*DDLW=2?4>k5Zn#sM zo~(faIkNvItvoM|SAlc^0E#Cy_3_E`WX480T>%Pc>N$;>KkAGD1edrbaa_gS|8(5v z>E-A0SOFv~Om0$9u3gT`nD0;bkiYsE&Q`B9H zR-hRlY05pB`>b9A(yy)sp+9DiaF&MpFQ$a4r3vrhkl1s5ov6+QDW-x`YfFULX{+iK zc}=;RUx1Ge0e0@Va)msyEFiSa_zV#|xl3GXLq-KQ>!^m-q@NrNJq1KFM3AwJXHJ9R z(w#v~b0}knP1plN9+-nvXJX7}gzK)Wa4U>axc#{y_bNtMlPn0_d&Ge`0ZrFCf z9^;+!waEB5G8;c=#Ovrp8V?BkJ;PynvREK!Han;w=ts%sgLu=&hXY&ksRcN2@dgP) zL*!WshD=u6V%lANmw{9ms~K3j0KEqjRn<{MyvgY{-8HdpyvOGvPkbKTiI}z#nRy{o&*<~ z-WssM0R6L0N z2+%|J)I|_@U%dcuq7C2kUdapYe4IfRqqv=yla|7z$RP_5%~!O4KsGU9!p}?DI(^Fl z*Xi1bilORBcxPscTi!b$Aww_)KFc_`0D?2Mc#No$qohhG3KJ~&uQK!zNRz5*KLRgZ z0#?208NL!eYpYuS2}KIR@G5qVK%h`k27Ks#F8rp8!xpEx#!8nw*nlhI5|8vO){gk{ zU-_Tp$}?JM%XTNt9U+D?mQe4l^Wjs2*?BNkBGKlUgNG0~cJT#>phmF`$W0B%ey##V zhu!JrRdW>S%sQ%Iyvi8>twW*D0R7`U{K*0(#pE->1tY;@q4qAyXj5GTPF#DVQuNLNjso^=DjzM<~CfirO|DgWlgiD89ob&t2s$unwx_ry` zxq1V8gpo0H=Hr~tx=?@YcE3-kD9{NFSP99?yiQ#R%D5nLVAl#0a z5n9rSk3DbV>!uEbW+kXG9~iS|A}g}7IT0wvviI z@3U#Az`Q88S;B>^hSCxEC^BLrliZe4wXa6@wcz>P)qtdq`h0E8sWLzTJt1YAFpfjF z0fg!R8`E;tC2+2@3|rR)Z)3P%X@Mli=Flg{h9*!{Si@nnF_Q2glw>9B@qMtSNgj_t z48i)Xjfz6Tma}l-X=F0JXOD}|00!PzRghuq?VOR)2C5I{X$~-9gOQs!PK_77k7gUt zWOr{b6^srjDND~te0ZU1F&uj-V_j77dyj~aZE6)@|KhX}8I(B2ruUaNBSl;SFOmX0 zp|T56g=}stb+ROyMUjoAi|gzXouKkty-tm^O5u?^-?h1m%Qh^ev28MY-cWSVA@&ZF;MpJCU)9Nai4ZoI(D@Jfd~( z5Yn)0I)RD1vq6k7@~h0)AUn68_9%z)`v#3+D+0%?C2hn4vi$&8dd1*tR3K4`gu)D3LP7MNsVi3r6;I7=A7zxYEp8a@j_cXGcUKtHIat7N< zOF1zL4b>Pzf(VnjhFVLV_)=d(ufI1#@Au-#`$P46M}0|Y?l{`h2r6_cTkzl>ZpsBj z^^4lK0+1u2@%~6hAk!!u_h*V1Ox<3&&-bT ztmp+YtN-+daHvwQ7_5VHA4eH4gyF*e{{wqB<+}hlL1Eu+Bs!!Sfz&ofL6ggN<4A4b z^CaI*=Vhtd42QpHD}=?D!=H*WN!K;y+>-5h;2c`s_RynSgT5JrF9J(!Ni-Ihe659kWEc`&4wH7OEyj8T0a5brq>_`<)^+!TdPNgbGgrQ5hb)eR)I}>ZUMN1BQ zHlx@Dtn|5@uyGX~+Da((559cWeV@ILF z!nx!17eI7}9~)@EQ!RMF7bc5?O?}l@9JKSELnrEF9InTk*z~f3a6&68bu?;TB7Ol@ z?YM+unC2{ch>?Q}5G`6gp4f;9T%_fzpAuRN5(NhIg_>~K7;&Xw%0un8MH+KTzBZ#5 zJegT}5ZHk2bg2fVRIh3A*za#<(r0IuSP}t-_l=O=kVEoTAHmJaOYBO~w2R)Jp~JJG z1sft*!+#h8xcx9jpUxqk#9GFs5*(Pkgz%<*mD&R2*&2$wB@o8`T2GM zsg^5EW*M#F_ujKEr7Z~63uMj1r~~BVmGFQ;C8#p()nT3YEb?sTc>Y02xf;*oUA2M- zuP*%bb0?|>DVrE~oZw?1ShkNdNl0ZL3;$=2f$=~%p*CgxKIyzT>t`qn>w!L?p)U3s z0z_@>ton)$!@^_D87CI4dRqM# zT0K{|37O4>f=g+u^{GfWBJcJ=wwOTNl}!x|{)ERR(oLc;X`INI0ddvXaxh9Ng$O0g zySymx@8@}`FFubWa&`EHuzEk_q-^%b$WkeVMvnU*&c>EFP8_imhu)E*P*MaK6az20 z3(<8ympo##P!UtjTv3g<+)kL)(Lsc4$bU|ehb5XwB-_+d;aM&OLJ7aOaP zeIoalU${FV$N6@dLt?;EvR1 zlR%zk_j_V3R7q9kh5mK9&$+>wWbH?>RaOuTrRb*O|E(+Wh+YW+gTlo_g6(Xy$!MXf zrGj>Mp~Zj+=&{upyGw3l7Gh;Vs1g~+2!W9>5I;tEOr-$wx*7Bq)q3Ks=IslJl{X6FuQ#Ln?`)SM+RC*5wh`A;69$7d|AU_e;vNtC@fq__d$Q|- zzSX>x#{CWB8G>N}uGqHq)(+-a4AY?xXSn_@Oa!_?3#?$m&`GrTJ;D zoku#RKWoc+-H5&)EA-*cm+5LI1bi5ZSViZ0q_8kTjhKa;k^C2?Qp#h)+N-(i)e03pYO|Ivlf+ZgU6`xz>#nscyewB*ST% zt^#M36;H1Z!DfvqXlFV zAd+ZZNI-lSik8SadI1p43#8QVg=Nw6bw z*rqe=xqXHlVrb}(h)h2kz)Y6~reVttHPnTOAyp0IB-W6?bPbKR#0Fw!v*AEQV5|-6 zLImV*!*CE$M>miJB161^v>!sPZ+N5Os!0rp-8|}fKF2pP1A=g6CU=Kqq1n;?ry+p}^@PQ8%vM3+O zqYzTlhtnryjQapgfmdc5rP7biIAl7VJL)%WFQ!SA4Cu- zbGm})m_Y_*Mdu*+T_Da+4gmkdtOmi~%pi%35X3MD*X(sckgyQTSP-=E9nC;!R1j1( z#O4X2%qu~(HHSFk47|vPz^qql+S&RrL>Nd%Mi3+d74gUeSz-|gM;AfhK-L*XkTVcA zX2kIV8B`-cR3O&g2*eV|a*jZRK(_D*BnM>3d<1|2SrSrU--KWwigAmTrk%Op^te~e!zf%pBfxljUM{jp;y zfo1+!aDCzr464ND{Q!3*R^&KKgxL?PaEVv_Ks+z8LO+mFU}6e2S5!>=V186SnSgry zSS@oV@K5XUoQV~i6m6Q|sr!)pHNo0iYJ^VRaT5{N&ptR|HTIEO^<^ME<%EWW@@zU` z$ePP>+zDA7navYxHXmE~1lRIGo1eImeC!1j_{N8G78Ho$V-825z+^y?MPBJa1yO-8dT>B0K%)n(CiHNWsR-?PU`7?AoCnUTSfzPLqE^9Q zBJU2c7_6wnJZi^^@5%!yv|>AXfMhFXk%xY`g7bJRR#y;bJg7d!!?e5tx%}&PyzrRp zE3kvdD8T|2c#O}m0Q?()1@5?G zP+H)9JC;)mP}?yI*8;G1jF&B7?Y5u`a<_1!9Vo!XoY?_LT#S$%QisD1DM>Caw!Oh` zE@Zyt{S$IFMOq>=h2wIl>VjJ%i`qpxw_nDLBRj4S0dWoYf#8=yF9ESWc;wok+xc!$Kr80HvR)G2&#<4NaR3_}Ps~!%Ug4tHMTGg08(Stun#)aXkHxXej3b89Kb|-odyQPrV*Yv zMllV|Fb;BFl%)|EJ!wQWaS)T&5@`%44w@Z}=@JK{j0Ram(Qr*18fc>v8i6Z?MksYb zgU{grN%s(*tPkgBV6?<>`-wryIChFjpxzm->^Nc~qU3R;1ex?W(miI-nxMKFLd$Dx z24mlVLCx^4$AOb3F=-r5n*9~W9xOv5;vm?VF$SdVW;k9KW|%!R3(#=1&6hD|!vUVl z@Qno^X)EF@_Qj5;g`$vY#>V;Nsx$ev(s3MOW#?@Qr9O2F|Zy zNE(iRL^0;rOpIc~0rtzTCUv_`Xo$f9?Zap-bQo?*9PKp>Y&S6sbQ1?R3u7UJ!e9hG z!YF$m4AZCvV_!HNtOa9AC&A#l!~xyFaNuy@NMLOJ1PtWpgku1{km#A*U!Zb0_Cjws zlDS`yn(_;O4oBd=09@kO%Qzfi`oan*U!+!vW8%WHdBZ`+y@d=%vzVQA zpptkUq?iS>*zvL~W}F=el!eJ_2Y6($9R^4r3kSFZqOmYN-Emed5b};CVu8IfEP~W` zkPsH^fya4ZF)%#9{uS004`hAC!sCJ1E4EJ_XuM(=<^i?Pu5h8zA6fxG}@3;qE96eb!VOHToB3&>uZpAZnpPMks+vnfPPfgEUxF<@kh zk_-g=QjoF(!GI}vL=fzjf>#p+c%`6g1p!Pc*u5a2lY)2#0ilC~lu3$J@*wykg-s9w z3sTHqgrMb7>@{%|_^gB+ItDO7A83Knqu?4>qXc?8RJ}0$KATXp85tSi>%?W8QIiYzSmXf%|CXCY% zP<9hzraB1K2V)b{f!2iPa;XW=V$uYX8Zv+;Fz<$}a3(NSB$_1C?lM8`hTxSUz0Xz=W}G2#hbWXL*-EYz~<>m%uAG-4fI=1eaRE3zsF(3WX(dNDWs} zuEcf;D^%91=l$$aq3R>mNd- zAhAh^kO2~WOGFL`@VgPIGVDkqe>nodEs^c5=FbLbOh?A903@l2qPRZ z(Q+e*s0i#e!d zI*4CMQUXJSrzF=c#LOi@xk4C~NpPfI!nr1_ua0h5BBcp9 z0F+B^EO?wB(%&Vk_(9~u056WuT${;d_<#ux{d^#uLFEG#X@V|3jH4!i;KLHNCXn94 z>b&6|+}S3L&mNGL$4^WFfk`Tn};DFZh1hTxYMwcJUCpN z^o<96OyU9Zb;3k=Sa2uozXNw;@8A=1eac1UHi3($Ti*jgQYF@>{i@K2|p{YPO(lG_)B4%TUQ)FGqP*fgtcIxIUMPt>r= zUQ&nbd64ZyTpa-aPWH0Cll;(tx^_~&wVc~_vW@gRiBcU{Z=>&o9$D$^mCW z$ss&sActFV9s;a{0;)*rY%P$0(mKXJTTz!r1U#bN1JeHg|F5JchSQbH%*>R$ohr{I zE_Npp0RSKX000R01>FT;2VFf@k8#GiVF@a_JvxP2pinX{T)r&9re(y-=6PC}LHaV0 z5X&H<6*sIKeVE85UPM5V(W%qeumlxRhF+ZQ@j{`jxNsqHrw${^(2Fx(;=-4azKZx| zAsB~IL=o`xQTQYM_}E(8{_gI5^0-fqIY-;Kc0UNRKo(`fmjWPC3xX_=ycgH0>4+YG z%B~iF#@HVN%RWu0Ak%P{)%!n!XxmBWbf-?cI<7L`EBib4Yb%bqW^Ac{uJqb>D(l6y znmRI-JtxlBn$`1^*ovNU#eJ{D?$fipc;Y*&oO4Q#)3dDge|nAI^j&6)R-e;tzWv#2 zrI%k!>CN}z=(fA!p7nFv|DX1;oKBfKqEGCO)5&$t@&naGq$x(>u$;S`m&uGy~od=rCZ!{ewGtl!R!pDztX*BsY4z-{chc+G)_fza zRZeTwJ28!STG!o5e+x^u{H?C6?^b@NMsZrpuT!I#-}2hjC_kqDE&sknjoz(X zCzaKrMpnKReOl3LUn{y5t?fyro%y?EwbhE%iWB$5c3ROZ&D6rw$Y$!4X?pgLp(<2` zs`{n~j$(JFlX`!p7fXBdy)Nt6@5Irsb)2UasndxkW$K9aaqjE(`u&?T&Q#KB9sj(U z`s~|t+B@l6`*yaZGE*xymeYz06oh5}+q}84S}RT({oaUgyqFXF^puD)UC|#~uWoPS zh^wvEGqw3zG+SF~JDxbtN$c&F4cg#Lfv8RVwk+z_t!U}Y(mJ)VaK$gL6>X(9+25(n zY-z8Y(W%XplRoa+vgN-O?e$vaw5k;+wfefO)^&@@w;ofbzNn4=_qEuHU#*C(_*UMC zC!IOsN^PRoN?qoNy{Gi2Hqq&H%lfA_^sVW!zEvH+%#`R>(xQ^3M zqElR`qPEdzIo&6Ao3Rjt$U%%WP4gDzC(GS`kM(t!Q(ulzx>H&si}b0D85@SP47-YP@A@X##!Iin&(@w`uuM!=hv3D-fJ@Pp( zYgzMerE}tTD&&gYR$QpQv1SI%yRkCI9Nk(`=9u52Mp{*`sgY-M_~5 zu98}L&iwRR+tVwxvEDnaIH|vsR^$?0)Tpn=Tt}9bEo#)3st_4{Se9`;HfW1af#Or9 zXi->4rgh4;Z(nw0ZQl@yL zPl^+}L~WwGMSVo=0y#T>ok&-n9Yw&G9AqCohqSi4)|r$S;=6|vj7 zE(}i>h1xoiX#sT-*9ol{!3Aw~=0< z@twBIGj$sU4P|a*b98cLVQmd%Ze(v_Y7H_qATS_rVrmUMJTFXTZfA68ATu&HI5j># zb98cLVQmcx3apA=fPEgPw7={04ajj_w?Q;42(=OBb45dmL2iT zxi)@Fv(tS0&X$k4Vzx%Iy(KYLx)Ukcrk8kxmFP+y~?|CW46K(!EyW)Fm&!;}Gz1DAa zD&1dprE^ZFU+cHUKeIo@wP*WmYyT_$ne)U=Z&PdO+xghqrq*8E-hDI9EjzcZlh$^6 zW#hKDXQrO%t+}!FnQe89C*pjoQ`vD^o7?fMc3RojEuPd~YcW^!i}A#Xf6B%^oqneE z@2uEbN@?4f>#UFGZF@21iaBFEvHGP`;-=Mp+c`7N^KZ{8JLcQf9dkuG9pj0!daaFZ z<4U{Mue5z;{8YBB73Vo|&er0$n7;qhn)8%BFUGlZp7&)}d-2o9_}_o_tp2#-*)MzA zS#QO-Z_e-a?X@*$&zLJV#uIV1xT(*J=WN_}X8Z1s-TIx=Qi|QXR*LDQerv5h9oxo} z`cH34F}821+s|2Idz;Sbm@8I_@x*V>Q#O?y|7MKw|D3ntTPwvm)26l3+wGVu_UD!z z?e*^Ll)n90Eu|Pww6yy5OuIInp6RuJ+n+kV`OZphmhCv(iLqm@INf_rOxxP8vTbL2 z?LX#vHDC80UMbS88u{%oVe>vZK$=*HY~DZ>6%|@${azbNj6B6uZ-j z?e}MTWxhY(-dZtNq}@$r$NRM2+?2L``WDwbza2N7vo@wZG5*;(Tk3OG+n(n~x0wE% z6ZhM{O)aJub4ACF@x)u_-=996*6O*tJ6~*ZceOW9+Wy(|w3c3rxgySv@x-R?SK{ub zwNCe*`P#m2y=`};?~n1WHdoJH=ijdvW0!M2#uI;L*^%1+iY><2f4)zrxnizpuUFhJ zJIlW|U;Eb9`nU6~)YjP(bHz)Y=C4zBme;#+`~7c=v+S7tyUK3wjPXRLQ+B0ZumA0T zx1X_W&)9EUk9K0Nh#%vLcYdAk{*AN!`CT#YzWBY)`Ppxl-SygwWq;SM6m!KqF`hWH zV{D!HKmUDvzuvd^I;GS`JFjPK-PUZcZR^**b^31G?`Nm&%Gf8hGuQsc7f+0_1siJJ z@$6gQ@z0uZW3OD6eV+g9j;nnuJ^XKdS}*M>v(5L`TJvMKElC+hygV2b3hThMFP)QQ zgl!jv!a7D46cs>+$RZ2FY{M)_Tql%2n#wg8y?G`r!$7#5uu{hPsNbO%YXqR%Jn_rI zQ-xzJt;}ubV_O?LzP2x>IA&TgcG`1FFB-_UW{*zoj2$nPZpHqH3l$ljP?kWG0A*NY z;A!-Mqff)UECGqzL?g`WC~+HsSVsU~CvquETp;-{5@i9uj3Z`WSIVwP;xJD^Ct8nQ z_i_5aN11}og}Q8;25})(a9M&*25$7WX%L}yB5~a&{4k44q#R-f6+JdwC`(*eK+!<% zWBDq!4>gTTsnnrRmbhsUm$=}0nDm&DbYGY;(m?DY8DU|@CelES;}V^+#7pF~hIq*m zXyGU`VFNC4fog~x03A1Rp}^cT&PpSNTJYGhqkD{(OUI6vc!^J;7AVw0$ep$;M4_x0 z`i?bY6I$?LA`O&nA*g*<=%a}2mQW>ifeUXE9$zKfM|-7Ejg$dgn`K+ zK*hiU{XS22DJ+Oo@FFY9Ju(X5folO)8o+O165#tPN+F|kxdSw;1D6oeMh!JAWY9}v zh&T*<20(}JtEi4h!{D3eYET6Qiwr_TM-xb`5Y}oEFsP^ni64P{8=wOP1xY9zSWtK1 zX$%UjqH6FU48V%IxHKRd#3Pp+Fv5Wi@X!!lQ3xghDh5geg40J)F>R^E&?5lM*~5QsNhACa55&J2@U}eMWu7P zzKnCgU^5krpk^u$5(pwXgP`JpULZ`6CQLk;$|QrPlpx7eCLLMAnr!5#GMVtKnvh7e zg$aei#hQ3VL@W~y2FEg~C=N-cGBLm`%0$FsU@D*S=n@CRU>rn{cyftzg&Ggj;bJyi z1fWk*x%3Q09x4_^<0fK1~MWduSHgYdL(1ZEt`0nl+I+$n-usf!tSiW|mpxK9MJC^9;MaindYhsE&J zEx@*jX)$(TBxM;FPu+sAixw?%8Wxg8u8SPDdGXXO$Utx-N(hbxheZ&J*`}2uhs6+1 zOMroq%R~T(V2qha7_$$H8JLM^cu0ofpDYBk==ed=Hq$#T#4s{Ybjt7r*yqv6z>U{v z4dXoyn* zu+QTmChESC#x-mw()@#`ZNz;n-m^{9sDF`s9RT5{F?AorW&!qjT$|9g&Y~1@pAZDc z;{Bs>&BHb!oEB=N4hKNT$xPiRGU~XFA_T#)aQ|qy3=Z@1M*{%%ak5PlA>d(LhIb|I zBkClw5KM}?5fTpDM4mPXzcmfd_ zB1zxK)3y?qXfaJdfmU8L2aoJW58ATL^l#ZQY2JW!p9C zI2m}7rBX-AvP~pOOd;OqVWvom5Lmtky}sM|a-RFG-JEWzhK@wDE3Au&94B%_Wa`QqcJU$adV zvk==lP>azWj3n&~i3>(t_F*2#VP6>YN27u9%RJ1B`J)LDMURp6VVx-au$VuZE<9=C zM?(T)CKBe^DK(FDI}Zf44eLe~F@j+BdEO}_-msK`aK@GE0?@uL;!oXX+p>*k2{KSz z5NaECx`-j1mOmO$<7Ar%)8Kr*EaX05X2J$+*r)@II!=g1Y*_{+I)oY9c7ph5NLsd} zPQkPdi(1HGHUKSS+p* zAR}>~FWXMh{a&xrC}kk0`G%bKd0&>Gi&=s%1GCS|LIs^|%Qn_0jy@?4Rg?wWFi}ik zeYev>vM(ygHc#6|rPv=KSNPI&UdQ$@@@1JJ%K1Tl;#0%jC3e>5@7!0fY#UlybLM`IwGP8unr_@IO;%0fEG zScs9ZFf##A0)4>(1qyy*e>=lc1~PSF*oi2iYNTzT15g6PEF;V^un^;9n`gqn22-35 z1`FrIK*8daVDWv401bmDSeOzlD3%0LS0tg+H^EdGWCs- zr%pTvD(b*i*bAbq0}uuv3zP%{K|~R$9fAVb7YhnWcS$-fT|*PrWJ8jvOe{zt%fxCl z7$zE|kY$o_fWtB&fWfg$++l)Y60)#00g+@XlZwh15wT1z0tRLB*Q}_E+>{y=d31yw z*KZI?JUT$p7xHAj&=;zx5)jX{4BRqs%fKxIw+y@lga82oAcg@}0^$MjWH>4u92^`S z8-)^uQY(}^JR6XXZx}Kl9as258yy)M1`;s4bQ~VbQejvKVVOb*%X-4AOw?-QVOG?H zH$g2-RCnWHUNlTx=1IaIBuX;Etf&MEZI}`!2?R<5!jv$bB>W-7Ac*LY^BGC#P#!)b zpPzIn4RwUgN)%6@?56_n8ZWsOgx#2$6|p|_@^+y{KCK>FhT~Hzo>grrgNYpIiAHM(>VYF z((%rLPFMlb@y-E{^WSv|7SH)muz1b~2kfqng5fzI3>OtuQ58jXEHWAp2LvEwh|Y<0 zzzJa-n@6M~6N2z4P~=fbFz~qE%1x=O+?0CCO-ZEVdJoH^<9hGlz$pC2QW{EKQD5i_ zc`{$9q9_fe4nHsoFDVTcN<*nD$}(`LFu<6FAEAJNSxOX2(^8^P@;p2o9Sa;C933B!j&Dj7O3hHBP-@C$ zsgQtKV=A4<58vc*vnVY!oWt zXXH~+2O((SCmd*?gDH^uGvdh^YhjAOOjy$Jp^ob#LOeNBQ6U)uO*kOTh>(Se4&|W| zVL;MxeZ&-HDiI$M0v_nNz9bW73Q!tK9VH5-_K-NTk*qgDSk@krCub_^0D%Of@D~Pl zAdw4P?;&|8BFrR{bSxjCfPlG&O{pstMY${`FUnLds!nE3 zTqgq$fl(|J7=>3jg+7@iQ-LUXk>?c!iaeRiMwqn#u)8W1^@Ti{%7v3K;hCO=B0vIW z-8qn8vhZXo71c?Q7TJO2k*QpOCj6n&;Q;CQg@J_@kAwvT9?K(B=~UF_@hl#lYzGa4 zdl-1B87k_)^Y94BaHu$F82rM(yvuN+xM+C5xF!}S>cY~oeELD*4>*~~rJ^pdyEYmI z?d=?G3A0>vP}=5YXtbkGPq4-yhc z+42~G6@>t!&?>3}dm%v>ba>Ei5};xbsTE~eU=-fqvuL=$V8=ki;0q#*b~&I3Py$W) zF$wT}rw+`e6*x?B`PjUT1BH2zsZ`X=pqJh%1eJ-)wb_j1wSnmHB0vV{6yRuhKosD3 z+y@PajY4=4Q2E36jUYti%$0$3{94#dDu#s)0K2QAL85pW3@B<_k6ebqn7YGA5XmAH=!o-M&FOak+8Q|SW!r)@UGei&v5-vXwQ9Od|6pVgf zonVmug>uM-S^&s&*f`J`#8MhD&=-WEK!<@IF>ntGw8h7!V+r&CO-3Nlpa(02qa{8l zX0pN25g+nSPG3&~$dbuM*AEJX0F9O(lLL;7wtR#nn~V-&d`1=BDL^rS2}N)01PRm{ z`hWrIhXR!HQvj$j1!$)tK&LG{Gzw9s@?|xXsdx+Y`zp#ak>(`fB;p!=VhVp_fgqwO zoyf@dRTTvSZ9Ghp4yGH4kQWUPA{Ez9CK3sxj)?HU7*uw^C4*l2V*tifDk@u;*fb!_ z3Q0kvS~`>mInwEbn*>r@I7|+~8ZZD?l;!yt&}j^hk9%BSGWaM}5tt#9SUkFh%7;lH zwSbP!fs%@%U@9!VnWwK|62KE0V6(%JD-jD*bYKnmD(Z6)b{O~u1P9bX&=et*hpelp zP{)A-mH|}*iMBDIf&eqn7UTkH7>pd)0~(eBn-2>hQ0aiK2a7;ce0ZUZ!U19qa5yl8 zNE!zgC?9B!=6ukKLZD$OGCtZzWAXq20Xi@zD(X}M%IM06#Ve5$5!qIOM;;)2GWZx& z)V(l)`YJ#RNLeq%@-Q&q1M+SHsVk}jlq;wNvS_5SB!xky6xBcg002`G05B*h7?6o2 zlcA!dnC$@+00eYYDnvLqDkzOcW3fma6a@ovB*ak=hCvX7G0HKdkTa$ec6ae|Twr!j z&2fQSwT{U(7TH;m8%*ffp-#;18FI#QG26!}Blkccz#i3+4FGn%jM>+&y`H7$x}rt5 z0Jp@U@c!r(y-hA9!-U(c6yvt%d|mapZgRu?J{SNt#Syna0E6_&PS?eTnrXxC3$Rj9 z5a1KS;X`$$a!zK?4U+|rWsFyTqJ}FLqU_fCsHlp061lcW@4JKP|Ka)Hosrp|G4!fV z@bzLF>p{WH5g$}`;jX(b;E?I?p#f>v3{hx6F1t|}Bc9kl3`|OOi+wrqQ{b;`*&QdOM`|ls;k$LUBO3R_N$t41HQ}l263cO08)n^L zE~4>S4o>SHB18=!5WkLyV%|Url=e++mg;gJ;)5vOKjP&JB-$wg#5lP$#_+5`98k)e z`ZA1$ovA4GSrSPZ`iJaIbS8n5A~BhPD6yrQzW)J8q!2VR(LQ@&B7%2L;5v>DqQX?K z6e_v3SrtOMWKHgu~_E>aj@$7#Elof*azRmEk2~w@x^v%oTekPkfLZ zJyF?l?6AIlU_5tJ!L`&Y^%FoC0Zzplfjj27r)wwstG-w2X`)o`3m>$?+B68EsAc$e zGOwXS0fS*Pqlv9>>u)cHrz6yfpi-0xyoYXTS)RchT6iLRP5(y81`XosHyFg%hTQYC%&|?}sX*muetP1*p$#%8(Ba#blWqe49dKBXZ78V0 zGr>0#_X#QxZYE?+o_#cV+=cZ-xLrzybux$d6w;VEi5rxhg6Lc9LzUbdKc6m;tOJI( z^@FOn2USpE*u@E|OHyE47t_QNa6{rA7*KHy6%xFw@jl*=!dA$MCGS*!mVZ(oli0Ij zt^EDd2R<6AcLm<4#H=Ax6!t45{*e31S|dJ$MfX#umQd`+L15zLCMJUF!?Kc^$q zs)c7p(0Q#cmkEl%alms&BjNy?Q%falW#B7X%{rBALS@L75ihfPHy}KuVP)$L+PX4? zl}=C0$D$-^M5C#?jNqc8x-#UwOdMqFg>pEE0E0PT(J5^p1+=2^U|c?p!JzE&rVva? z&$gzNqoe(13f|91#F$Z5uN%HjzT?8CSK!}kwhSYU3T^gS;C1mxr-Tb>hG&*XcM2_?{cT-zWHBl7f%w*(~q?<#HjpG9`8Cph=)W*zzO z^-9_t#Is!0U5Mw>V*(0EAd=^-V>C{&V>;`JfbwTaLbc1)91E0edW^y!Wi+<0;oJ9| z-9zWf3xzSc9TmdE@`z=`P{5hHKhUrVKIj_y-^l7YGIg=_43ETo?7+!}2RpfizkYg< zCFv`VST%i>j-hpSU#A>&M_fQ9lXAnX@>FuI$svePOq$_n(AXAgSfl@j4gOVsn(*^2 z59W{NlV(<5YnqNn4<2k@7)3BzywOu>T=`_mz|>7&CMK_pP}b#J(f;;C(+kUN#M8Sq z5RDbfv@uh+x3d&%?poEAL&su~ma05cHkG&=wHJo9i2Xk1=9&$m2!ix}S&*$cuEV_n z57^tb5-zIx_Sy2tA*lEG`@O!!NH9iTcH0J9!-9ls#@W(JQ?tLQ$TJEdw$OXFHZcv+ zLDUS{7viQAPgIQ0Gn_^TA)=n{NF9VIyDltwV~Wc{hkUvvKpc`4!nJCTkYMJ?9pM;i z)-fpyA&4jM;RZB?>mVxpsJqji%Dwd9Ttl?7dS({F$9CGhe(`kONH*+fV1hH~ydFmx zZ49Tz*DC^SY=U}jc1ep}FQ1PEbMkNnUQ_ISzINH8E*>>WAC<ZV7hOT&(UnvTmV=@z95}j?t3oY`E{fskqRmFmsGp--e$lOO zAKgmF;QsMzb9BL1bm9A>3uzB2$Q51SOhQK&$e0Uk3r46LL)TpZ2kQ@20a3g{3zfw< zOs6bhM58)2R&5sEz7*JZxHk*04&X}L%o-jQ-% zhl9AaC8umFU5<|ufsNQn`{t!%G#=*f?J-2~YXq|#TCZ6x1T_`wIE@ZNgPzbC=+|_` zZUUvk*M*_IB5t=Vt)1tW_BC7T3sjXC+0z7=I^naz)`zLUHsEey!39xoRofE2PrswX zcdz1uZ`bt`{`)7HS|m7p9&n8^Ac3;WjX*i+j@*Mp#ejUVVD?Nyl=&z0QG8@ae1{K{ zDlHWL$HS3^^?Q8zu2q$a=?Qu;p`<0 z_k@6e{TGv+6oQ(1UX~d*Y&@{XlwSePt|ACl0MJyIjo50NvqJ(NYI7yw%>P8k%`rAt zl8$%qO+3y!@=vOl`_U<%GFVAB4RL(9gzR)7Zx}Lo)2fHVg6`@_+b}yE{|eSjMiZaa z3=U-f^uVtFf`A#C*LS0=M)x%mz|-%h_1g|D_FbO}9wSXtvKU(6C6)Wua9vDhE;{s9 zSe3#Di3uBq>BoRZ!`fM%eFZz@hqY>l6wqlR*{nm_$%tH{P!em}$^JPllA${du-VoV zo(+C*@(+)Rx9?mXOZH=}cBmZIr>iqvR0Ucd#Q(k652j@`cf_?~7$S#ZIehnE2)&ip zqn+~IpEy_+PD?`G!gVJL_~6r&3y#wv&-qZS^_mHNx)1MNj!$Ao?UD+l)}-S+k7@FR z`RFs9kT$AvsC11tQBgMu;n6{ zVa_Xqikm?9IUaQ`J4MDWml|F5Az<2Tpny;Eft&=jCTkvQA&!%|#wX}B1c>Fz*~WOo zhll0Ixe3giHY%&tyr^*i+w(!TflPPuRW&n8UxU^Q&B4Hd!muw%hjC-tmsd$9;YB2K ziX~pl%qF&50NHA)84?U)?AT7-nq$7{5*nHvD}A0X0LzFLOe$;Jpl|2%=BlhiM?j#* zTL>@?`_wub6_@aSuiJ5!I=7B0ASDj?eNE)2Xn|Gh7)58U4Mue1o!Keq1~3Z)En+}3 z`B30n^5#XQ;b=6je5*w%zSLh-S$U}Mn;Ly|BWm^lr4V^{FhTO;AWe(YYXW9@qy`k* z(K^OCgc(*tE0?Pd{f*ItQ*F*kk=r-B`x~w9_OG@a{=1cFszH58K)s~8@7~5_VMK?m zpIrNu{WaI2+A^bl?@1aekCQb6HIdIEv$RS(89MSU8Za1hC}-8{NCy8pEJXoJloYEI z5u|E6pW#U{M1;aDHNQ8o2tr#WFA6oJso>3^J~LH_p9Hg%hF2<1SV&m{(MP5hnXR=9 z9q}WC@4%(NW%g?KnO&L*0>y=cny5Q!@fFCQIME4Ga4{quk(D}_ z@i84HS?J6jzfKHFq)?m+pg29%Z~lat$pR1Cd3{}&%zgIsArBz%7rflm&I!t=VAOKO zdr9`RssCb52rJlE7js4(1os$F(n!Aolbs!{3>D9Hf|>ULHtOL&`^8m;xx(5b6BcPv z{|;@m=BA?2$-l$)^r(+2ypLl=)g%jBXAlVj>@eA~y&57IYy_)P5dK2<|DbOWZTqx& zTw^(;t6Uh6m^SDvr!QkFx4?ie#BgM`qYql{0q-`fHA3)ZTGm2JyW1+5-SF$Xqw5k` zPh|2O2mRZGh*ng;&QzDyCWw!5YA>bCV3|jIU7(m6W)1eEl2sMM#acZ?Td7_T!OK;S zwJG|7w}bq)$rgQCiU*t#`|mKr!R~42;LA#-DyT~kkOR@mcoYs*Ak2?*ZWrkGAVi!P z&mkkT<70b`dT)tZ@zYv|Hn7G3ka?b&P&dDAYX440W0s#``B>mzwa$VT^WxvCOFZu7 zI7rtm*O^zjvNtg+@Zx!^`AznE)Sm@+>opr0WxRso&ETQ_??hAqvZ)HcQT6S`ZK~l? z&NCkL>gV+-FA=P$9m?b?vE!pND!kLN`?4vZUD!2`yg|q}R=3~z>A3W%8@!yleV*!rsF_R#paAn$GV5K$$XR9hvG{-?{S9v=6<9ro`SBBXWWi|ZX% zM*9zSFhEm9kj1ltU~FDl{Q%;#H45-}H;eX~$O-;3G$?*$!5XIMq?qXjSh8g&6gdaE z{W{~Z`L1OI(94&14grd<%ju~V8LmFmGF9$_5lSPH-U_Ke| zFbL)$?>>7I`0RAhuo2r|yj*tMpOv1yTs-_?Z+zMJtyjFT)Sok0jCOlnpV0#jhX~>F z;LRi}$(U@&zw+s>TzZ|hdmJO)w@fkJoyJXuO2oad|qfhW?5jAOjoU^?>` zZG)5lq(ZWjIMSZMs+qN_o_-6_YIPsonmV!083LoL;gR{#QDAK@RgvumCj>io3?p58 z#o82#uu0m4g2(s_hrNcsi%oy~xrpbot;)(zCkrxfRYIHnON`6(3^WKKGH%jqs< z5{~BSn9kGATy!HtBk0XQlHJ6XvVkX`&q!)b9Ckz_sc}dG4U;Y2w7iZ{!TCX4iipdf zk22v<=LdcWWCNr>>Mz>S%b8|>u3v&aUhtx%+OjlQHU6(;l_V`Pg`AD3Bun{&p(=4= zvVC>S3fSoi4~am6K2k8EleVzMpPc?2t{BwKheTx8Nv$z)vUx8I>L64$ulzBhcbnY1 zKSRwU)PKqZGf0-;R>y3}{478M(}llDoCFsWZ|K307A0BOIwGwD1o!Yt3MtVm*-T`Q z@9@=6^SvY>iSCai`BXl~uaci+=wxMb$}wsQaNT5g0S|CzS*3av50;~(0wa1N^(TH7 z5co)osCI*=$&Tfi>BP4T%jMPa)`?sUtk@GLZxI5&zP}1W**_G^8F67!3{B zDT(E)brDs>1`aG4{(_UjFLlWd;t>Hy9o|ls5jz3WfWr$}pdD(gBV_TD-UpGSQqNzQNJ7+r=>ddT4PJT)o zrZ;aXDwf4Mfpjhnm<>g|%ol`07*mK{#oOZzKWE;8);t`St=;;P_Q%(FwL(aOnTy3? zg>NsLoR*zgfFubB6M?RGNCfr=tMe<-q0Px=cb6QBKf@}tt{YQwI6?p^ZJaf$`$ z+ngf;W!cSoa!;{{7y&yCs7L0eS`&D_!e*lsr_>RHT31n1l2?6RItgQZE;G456GHdf->9(V>3Y*9OUw@N!Xf zJ*h=f`WW8}_OT*AIU7~snauFRhO1M|_rjzF-=zkR_O+&$39btEam+G}M#PE)9g`I) zrAqff$Wl{;)uOi3)c_dLQjB}!>?1VB0WVXF%A6>!Q=gtyJzP48i&v^f^u@~Fc;;~) zEAW4R2$~=Le^SlIAfp_lvqo%o)t-I1$2V0tAklE|l6iVc_iI`{J(7hFcwN-eICP+Y zgpT9Hb?2wGkH7O|`Z+oB3Cnc$a{{b1 zH31M+i5B1Eq5{YXDR~|Ah2!T%g?5ITMG7RElisJM(oT58Z#G+_;Pr)q_^52kI8?_^ z@;Uc`*g&CZNlc*ZKJZeA zRk?1LXdEmj-p3lpX>h&9GQa zwrue*NjvqF^llgsP01<+=I5=438y+bQdma!ns5BJJd1#gx6@c_{A)2R3F-E*I34d#;w&SV5#c6xi ze@pG;%BtgU0?Py7EYY#=B7}3V;Zbehkca()Z|R9xc}>n`+^_uT6X%gqI4n?jjC}_L z$aT?Y1J{ud0T z5`Vds?v5C~8l~!PI(*vOknM4{GhaQrM@NC8F9D?)@}ZrSns0MZ1%*S1!DXvMZR$)G z(Z$}W1YUU}c)O2xpnI(YXUbAS|8KA)nwGh#E96m6Q9_DVXsD)op9Q5tcWhWX3cSS> z7X>P>I~<_hY%okgCwuU%eYi^JS9McN`THD3Gv|cK*~cb;vj+i3?-q!x@umY_mR;G+ z+(477r#5!dWl52`j%*H`PPO-#f95ZBS;_%c`aXunq^u7WM+!7$JlQp5IPiu&)PF!l zvZCw8oN^N?3riZ67d4(<-rmhriPfwvvpk@*^8VUzsz~^IlRbB^vxL@+p{=WTdg=$E z5qp{6Y~Tq=xgxXPI#+;gyGKBTV4$f1X12Br`uaGVHXvhKzo-QO%And+JiCOacMV`b z4;~1BJTAOXw`*cJ4zY}62<*F`X%~|OalO2?Ar+wQQLhkM={N7t+$djeok_rBIC97P zVJ;b?{63f#31jvlMmgWHg%qE?^RuCnSP%j1RI!d{eA!o1RY_Ud<*N|yMKQGOin&hQ|LOd-U&()Xfd7b* z`3OhEPzsuMgWf28-Aagu5ZL6Wm6QFkAUTLVb)pZ0lV^AGV|}hUhcP0;0*EI-;^|`r z6;Q)Wh&t9%HA4bzF{3aB2|CxH+j|wQ6*p^>pB3Ze=koBc8Za(DCC5Bn>^l2tzTxYo zLix-Xn+~oAnxW&Qyv1MW3+@u5Ohd567hz=_k?wXv?X~0Yl%xampF;>i+O`>Gd|0-^ zP*jvGTGiP4_54M^2~#ou-)ae*t4eDDO$!&)BB>ZxDc+zJFD%vhc;gI9C1gwjAH=xq z`N)4r2c)so>20WAn-!?$qHQ^PnN+?t-Mx}6{M?9^0{W?c_K(aYz(;L*B3#eOxjg2> z-A$_^RutzKMNgem#xB@EngdOXqUEdVRy2?KL85t)?9#Y>v!kieLk_6jsZ1@)qwLwC zi+fqXEm|b6tk6xoJpkfroN4)_Fa6!7IbVFv^8$47&eaqtZCNF?rlx5!dxN#%M#Ewa zG+<0+X6eqzGKjGSw?xe@7u7hfNAQ^LS&*!yH5Z*qaXU$B8+pp4B_!5#A5e_LbE`r%O57&1K=3tf1F3+@%bbQk=x`ahD;b$ zi{I7rM#QDqgnrKF)JJ&BL;!OlQ*;wW{bxR798v2GDULSf3(=CV47en%G zsYCMh1jJ;?ZW}J#xf5s7m9Q_{F#ii;5QOXNpftpcrPq4dcYYs?@ZV2PlJP87tfz;4NB|!7U-vXR+57O=LdtFpyTC>WvS;WMuF(;Ay39qEn;X8vl z#7ifp)Au>Fv##W5|8u0$w~%kvi8?e0S-~#i|fXZo1E%FCR7U|eZXT;QH<=1T(=s{%bBH2lo^C7P0AjSiryA~{o zwDhLsBeK-g3-u0B75>Tm*Izp!Ij$kdaP_jY*+dSjW(U=ki;x0r=I*->-roRX#lgG) zGwTc9FlsJ zhco%|y6Pwr2|1gsuO;a?w({WC4=N%clB{NJz62wha|jTq5Yv%@Q>s>ks%t0lF&nvK z7!1}4hE6r!9{ehDDD?3Y{AVb%*c74<#!y+x6>;VvT0#0mJ|u??Q63=dfrzUVj{d2P z&^8v*1=(`^sIaq`A}1rpjNL>r4kNP#L66#Q`U0AGB(duR|8PV$vUmM%(}fokGh~)M z0mGjME(g9mzd=hG5=FU2HeMKx6XCqOW4croa3lC#?eCypxKY;hwzYgild2TESSVPb z%bmDlDw!0>J-)Re@~fnr!0tHi<{QY81X;HedO`p>Y`%2alsnLasStDt3v#6CsD_Y^ za^*dZJ8Nt*?gQ4?QKh%8kRoI#{2a*t$!r%ZKCs*(u3D+fdgXrPu+RraLsu33w5^PF|$T*lVH~sQvV+!EGi1~b;kJr-}c}Xn4Nt2tXwFs zbF9|i8=0+K&zesc39}0Hkd0SxIY6lDOQmyQHLux<+$CG+s%4e7&Lx8~60TYkV2=GB zJ64LmbfjIG>|yi_RU?tNM2|JYZtBbEDZ%jc0~y?`uQuGI)HX*-yw++yTpu$hr^;)B zU-cJ;5RL!?ND{x-Fz8?=l}n9!7x63 z=)&CQP;A+Pd@F51o z3r0w3C?<%yBWaNR;gv?Xb-#co)>|sGGC+U52p?-;Sqc@RCfSq!N*;uwZwN16+f_S3W5 z+*OV8kYVG&jG7vbxG|y6B(EMIqXMA|fw^#`6fP)WXc&Gm9T?9;Q6dnBepu$7ra5=X zxA#y^x2}N1PhBWjsyPP{Aj(~KvM$#&<(_+mo@a=*I5}DN z1<{|747!?4N_EGnx!{hm!@ve%>e_J+^9vz{P7N8H? zZfFOvNYhcA;Cm~DDU1v2skV8=90H)O2_V=(#YteQv~{#AFF1xl#GX{QS_qfmuY`pJ zCCi5)t^tP6A74CB8wcDEo)8yEb1B0P?&-TR`pd<(rxgUUdJ7wwvJ!_UzYlcl)xnAT za7BwTBi^r%3q(z2I}iav5mJQ8V$`G$t9}g0XSNUtC_nJgYb!E-_T~5LFZ7fK@*2z3 zFJDi(L5VefXD%{ex_;xkKG5iNFJoyWmJzb_vG6V=v{$#-kh%l;X;e~i8PofdA8zNd zNbGctGS2LHVh*FiF&VzW;%_gbza5ZFPMCP&Eu?AQp4cfe|6&@NKGx?2F~Ds7lmQX0 zUTuUbcov&D`@EP+F_XoigS${d;r3$pO2(xCD@|#TRzaDqa`K%sg#tNX7(SHt*zYCn zeDL8dh8n)451vVHps{+QJs)M{B`iZ=7P_r7MdOX`JqqFgwE2Q0h5@flvbrh<;jqxC zk#Zg5>ebUsccakm(*WVdfJPMbSiXDy#+ZKdC1P-@vOKhY^Os5?z9MHte8a*reUoK9 zxVGF?1*r7RhKD2OJ%d-Ko#M_zd%<7`mTgv0d`?F@t6n^tJkoAI5nS^>l!%T#4QMr- z>>|kILPS(7f%OuY#7W$p!V^IO9rb%@>al;_;Z1$tGS-|pLI+s2zeDoB#|MSphcxxg5uBRShKktO|-n_^s)O zGlN@k*R!s$DOJ?zozpfID>a9S_3cz-au*TRU^(MI zIGUhten&*FnS{Fui;PXAdw)7xT$2(yC|>WanFYg~N69-ruy~*z$E`#gSA*8f&cKD{ zI!%I(wmqXw6*XcQHb)$gpbJ4nQ;tb#mYEVInJ8e_andbL;TkN!y$^Ob0T@i&>%;mK zN_9T_UB(w${H*6OWR)>nI&a$|H_&0!ZdEu+DL)0gfr174Ba%-edW9b~=e|)08ssS) zr?1Bz0RnmL&P++RCv3rectkLWit_4KZ_DuM31RAtm^hfcfV>Z`&B~D)3qw%65&#;Z z6(rzNM3Sm$3>pSi9>HpyK*R>%nhFknrWpMdgyrH`ML)S2P%6VrK+f<^44#AnP@=36 zl4`606#3$fAuYc7q9)ve@|S`&N+Z`HR-D=$S2^;G!aKhK5JIWgaBTE`sF??;Bwo)5 zWP@qcvw}_PRT3gL-yoV2$@s^wTAP7E=7%wYOF)|Uq<3HIQQD}GB{CO%=?&%4K_)F= zBIj=*a_WnNk%Q~52*Cc#J?FU`^A1TsV`dEuETWJPr2L&W=r(6{Md^3}TMl)4Sj%?_ z)Q{&7shc^PfX_(S^j>gznv>dk<(vYGj0TG1`_<+%shbX5bAf6;8&08RPMtX#SV zNu((={v)}NJ!EzcEJSF{RZM$^CI|}p5j_H=qqHxKG{fP=C(ctw zcSQRI!!bGXnpc^ai=wAE9G8Kg7l5q>d$%gYB@#h;ibQJfm)IK8W7`nn#mnB&3J6K4 zh(~ol7L;oDG>=Ucc1LrB&_DqRSJ)iqy&|u~ei~r5IBDbX{X*f(_g5dR-lV|YTE`is z1oX=V1G(~ya5a;$+sZ|VLCcYwAcE!v^nHr6dMEkS!JgG@FI<03Ui?I4un2m=EuGza ze8@OdrdSuIz!gm>STO~$vZCrPg~W9m`W++`v?9O)Dn6PT47>1tHg1xP&CjliWY>*c zUxCc#ekP=G(`7If-E}_Gi;zw>a$`VHM5oG9pkNn&sM{ITeC+-Dev|c>xxi8T0Fc0} z&P(`rAg8?-0;%D6rVL^A!nD*Dmqo z4>;QeGaCc4e93)CgzaAkv=v4>XC6Gl zG}K^4Ncck=QftCYV*ptI!hwgPrvAU5>!y;9{js^GDD4w|Eqe<3S%Qq93N%A2B$1no zf2=6jXi~-|q9GgOzJvjt(IXKDLQo=D>?M4?18{A@(=Qs^=80|Fws~S3JGO1xwtd2r z(FT&QOopcl~;lBnwokEoYk?-sM-mNy#%c9#RzL3qSo9lXp_;5Fke&l)_j%2*2hseGHRe|a*G9R{Vo4{^xHu6&oCT`W z97}*7C790p>_p>@19>)fPZiyLDfeYkFr~8}ontB`OmNU8LZ{D#PLmq&Osx*;bVHi6 zXvJRWrgFo-07neRxMv^fL<$8^9Wz7d6ZPl^i z3BM^+zYgqg#&kx z`N0og7%!cn2L*G5CQ(pzp}jAc&@RzZ&{uc-g1_+-6=egqW6wsyU`4Bxsbo5S5r#7p za(H73B?h%m-GOTw>JWB6CSySS)t8_6oeCTW-l2Jb#eZBk0#70*`Zc2u83heO=ccWD zR8=e9mLKZX;Xw~7jS#|`gSj%Gfaju*pcH8+{ps6Zkq5UkVYRH5pvey}7#nmqDL5#i zOE^>6Qa_U{GM+>+XyDnpQ9bA7gwMn&Bxj-fiAIwXmb)N!!)XHAvZp%pBJPR=DG~=I(ScDx^(Y%dTl$`EMxc6X zr!0SWgVIAdZPmdIah)BqTf6i2BY9M3@?Xzr<(9K_{!}gfF=;DjN#1$%mwj)%n%`)G z`QXwjrMFtm5e#XQB8p9>No>WtG^57>U9KBU!LXAnZN@kU%^ zS)N1Rq0*V_r#q%yoJ^oygG!ApeWKPx%(Q3A+$bQ<$t&Fe{3*NNIP9{&>T}DFIKDyb z(`HEPpi~?TKD-DhJSfu=&6N1fF>oh$OfdaP<$Ll=5y49mEzM6uXERgTaLCA*|E`Mu zio>^a=SmG(G~EKaaDdTHUdzNFio+Doov&$z>!;&t_n%}!SsNui_>humLX?xHjD_)P zl>oVLSa`rr8J^u2bh){8@sApEsB(=$y}TU(To~Qu%3p?9$Q6O8FSGt;!;;|$SMXgdCg${rFL4OxzKlTPsmxF3M zTm>ZK@!BHO*nd_lzSEdDT6i9;9S~nWKN$xvMjOThW*WN&hPu@i1C?>}*?3@4Ku?y{ z`V?q0kn9u(v}&5ce0CRn)hnRvc|EKvA^Up2%KZ_5B^mI2=zv2}G~i-`wUh9c#3+!Q zL26+9HJ>V`Fn4S5=*NGO)7xMpH{(z~gIj=8+&5H4Mt zpAfrXu{C*a_WJhnKaur%r}Vc1i*?e7MdPYAW@unK+Ur^FMpRUT+t@6k#OKn*B^DFA z49ZUS#G!qS5ld?kH9e>2dfZ5ijCvZD9}B31?T8P7LbUy(LfEURHJuw@6lpb`$L^Zp zZX4Dld7^ajZ0EDt4upRFbzcUWym(Ecw32_~8feeN(7&O^=$2Vw~F;5^MOUUH1@nKVujctt<V$6R8x3_{Vg;xsG82^?WHoot>Qx(k#SRJ+ve4QZoE&P!gEa$D zFSV|S-Rf8eV|owKpP{@gEzF#huO2~nA&hkhCUw{?uEu0xeJXHb+>MEx*Vxmn^mcJ? zoaI10WPnV^b%!(>7{;8Tuy4o_t|hYc;p9##F;;5nQ#oo$X}Hq8>dS!8`3oE7s^pD6 z{0OSD=Ty!;!Cs-kd!5W*PbRq&qQ|zG`3ZleBFBA%FfhX>?~buD_WYza;X1%N%~i<` z*fZk%IxAT^BbA@&Kvt z(`J9`d7vrbcrvU`I0k`mA3|E*%=crjW?Fp0eyj_n(=!tDU~q_rh&hydny0+zYy7Zg zexX2jR~h9CtAO&1492=qBJHd^8fDB+s%90h0%^FH^wKyl^>gvfdPr6D+B66m>H^2& z>IZomiK)Vd^1VVCKhjU&u;pcCRs5Ip2G}b;(wC*%gYFK`7YPiHO@1$ZK1O~6rV0}7 zjrgb$zxaeaFz|8~6nvufQW^Z6Nh#|+F)j=~jzTbwIC`T{U&Q?ouEL?Qh27QMTIe== zn>ZGo5vxx0LN7wDy&pP>tK7Mm;u;gl;YQ z=bh%PuS5a|cQi2U--6?y*@NdCpueeV2+>hycg;;vOT##)F}=^HQ?#WA2LpE z)uX|h>Sw;7i4@h>64G*pWDs%5@o@H`4bS22ZLPNVf_z@?N>UGc;1vB?2 zl_k^Uz!OY6C+u3_YC_`Bar^#+7}-uvopSaD-Sfg{o(3x_;6ecfoC$9ayE1UJ7~)sI zC>S+y`VeppUO0-Ly)%V!(##aMv!b{5-Gcu#n>^GeB>h)kkeNE>;HsVx;C9@s{Sg~) zFI&~}6BTHJ9v&YYHYnak)N|e3KQOXMSm-mt4QH=~S#dYWMM5BhZ*s87p3zS5`+PVY zOI^I4?=BJ&t>L=(zz*qW@l3ys82;sYcQ0yh=_IMggM|hES%*u| zEE&2gVM*Kq7-9gfa2Wv<*MwZ+I7|*{bEE*wK=A`gNI5_Z1Sfzy2CIEaC@I@R$v<1d z%cp44B9=+q9(gUnMt<;Y(>7P86N#*;#W@t_{yflpt7Bf*rh z80%8Y)~z+-q!n@?1xfAL%y0lPv8i5_gkxGa)m(=5UgH)G*Oh~@kGp+z`9b8*-M_D6S>eY@?L3Hn`H&Oy4m;)i*-H!F#OpMq}Ki(Wu z(RNV~_9`RB)&aWD*0GM#FimS6K|7wwV9<^@ZRj(h#$@2#Ygn0kdb`M?ep zgLDu^TNUT7LFc4*bQXPCO>V1t!+K{n%0lzvZ>_b=$3%vPV!1gFDawQsc4jz|TqxYr z&#H#H>08I($~X_Q0W3)AoY|F3 z7MXOR`c>P4uQe=~WA)Wd%%V)VpxiXW)=tZ6>IslI8EzRUiWSxf$_<)q5KOc#t|&6J zKC|70;!a`GaV5DYC>Zov=+dk){5;d?d~I*&RZ;O+fry^g0stcn;glT;H~ z5>I%iTyBRFL}HRZWb1Tf2gA-7pP|)^q4h{J+J%$h_)u`rE(ki9iDrw(Y{+!t&1i{c zz7~X`SY%=%p-T*zY73?IQ?PlT(Oc|@3x02&5UYpyof;fIaMpHHe3ou;XBwq2Q^;ok zM2)3fL6eZ~ZZbR}3&l8x9fQ#mE)xXL=eU{_EkK|Yyv1!0HDi&lex~lOAGX`vtgYgv z&4Z4NpI#6$V33GyMXif2zsZACNB>3=kDRe+CpbL&SIx-2*lU4?BAU8m+?Hifjm9+h zVeul*(u?GazL;!+wdY1ON>aAey70q!kZbVAy%=xZwc^)k-`MUllF>nFI<=!zx$bEc z>BArG1Ws?`c@&S{_PH>72Aa%pz7+K}GM>aD3z-9}HZGiI_xEU$159xVK&tm|Vg*SY zdUFT&@z;rP=dq}0=Yh8H6jyW#ow^IV`OJw<2Si#`7p&I{|Fz-~8ZV+k)lL;Ob!2Cv zFc7&14aaCE$mhDtG$hVHJXzcVhC1VmSHRysl)-O}kk{fR>m)(!*}-qCA~`_Vp= zecyrR}ByfZ|zRytVI*{QsVELj7n1=xvCXD)B*$T zAw8PzytQi4pcL&!D~vQ4lafULN~axurvgRAAPsqh{vC`zl{7P^g{-kVNTry=|C$24i}(VJ3!CiS&g#sER2}rgJwvfMA`cj;~}CM@fRv8j`!R9y4m$@vpH3coBRM#!=&53RV6^1GQ)CFJAc zc~*Mo66U@1vS;=-ZEYzZAJH!0lvn_?bYa1g^+86JgQymUCI2K0(fu*A=Zr16KocU` z2zW%I%TdD2(J`mJ^sdDFf2psjE%>YFmX${;Q8<@EGa!^lkg$g*xUKx+GP&2_-a+>K z#mv%I>wlB*+^WV$j=8u5r=dh*Lf8AD zMmnxYqxW+b(guzH6~o<2SG%@bX96c{Bw`jXd1%Y6_MB#q68XkC57U%+@p+imd5rx- zI_XVA9Z&DZWheyY)4wCyqKhZZt1x|N5I`=DoU zk|Xa*JX2*#zDl~EIt2frjozr?V+|3zZ#~25VtEHrP;vM%{C3jKAEBTb6vKi7CBZ11XO4c0%yO{Q7M7m-9QRrqeit9xcZUNorLcBZZ!DnSFyNx zW}yPkC{Mw34uST--uv{$wo#yFh{yTB$tVA{llQR2&#PK}SrM}Np-a)zILcvC-;V1K z*>UOiF!+&}6j#8tcncG2YWph5!I9=&MCMi#j=*SF6C&xVg(bMHFIC$J6W)Tp34FP{ z&OThRV}BLVG)0mi(-ML)JbZQ1U9dNt6-Oy+W*jWrs7~u|z@S zlDXXQ5Fg6EUE>_rX>EkkElYEqq4F#O_yw9cjbgtPhr68tdX&D@dC;dtJcbQGXSQuL z&8GmEm3^u+SC^$mXLYc}t)6~Gf)`d)BTepvbeC~k2tIq?4S{U?$?LobLwHjs8$uIYk)k|zD<~cGdlnXSF&zDp?tD3@4f7tf}K5V@45uz<8;str{yv9d; zx@ZymAq?v_B~b>&Kp_5yrM(%k!R0Oq)fxp@8*w>VDKBFz$u)rBei@Sj6b(A>g9w#>yGq*CbLgYuMK>RqmT`%FhVEj< zx|VLSd?O6+P&;aHn|>CPw^QLo@6tZHcLT|rH<)1xTt9y%YX^3bvH0)oiX>4W>^)n~ zs8I#u-*&N+CZy9CF-%p2FQvn%f&0r@80iu|rSo4+CkE~vwfPNUX>vRW-#%WeC_Vd? z>_vtP{J`p$z;L4yoOPFN9V1C$kyIvwG-GFvH09y<(4;WtC4;blin&@w8?40=AtmST zQ+)IC~eJueQs~5PWqJ| zYK#ggyhr4Ir&&O6_HKaIxw5Kxtg6j#SRQ}BPbO#PI6b<3`9<2HJ|4c_ogP!&gKupxWAbxICNCD8Szk_*^cZ2r)ZQ`=Iw-vEK*91if!E4BFk`kr3z=NIUl z|MEDdxc*|hAzyp_#{1;I)RlXG67IJ0&C4~5EX04L>{Pi=!+qpa^Ben=XxrX;2b3KU z^0m3%jQf<9DR?}aT~}JUqHUgTe^h;`&c=Kt{x!e;ll6Jun6({6n#4?{X~V^LF|QG8 zS&tPcSX_bECC```B{&FFPl!Y_M{&j;Fj-jX>*ey0mz%WpOn=r27Dmn^>IDRt1!4-9 zl*T8S#wpf?F&b)@5mh;YXe zzO}A7l5lIhHzJ52CK~?sJgF&3=78Q%2={_i@`QH_1JbrmbwZ9lAc-llg~7TV5CDTv z--wiOPJ)+KWx{zY4lE3EDt}fM>Vw8@6rE{N)5wqOJpmE70SdUtk3ff8MYznO%{(2H zYQ`_j7)v`!$$0T@>D1~g{{gs!eM}T+agGTo2U}zt$cM^MwlFg=3nGLnLIDE8!b6D( zJ4k%>$K>Hf0|Hg!rB{}eq~;_~j2b8qq>cVd86QX)8iW-(5G@QN1Z9mcDf}IxerY%9SJ{VCJbH05Dyq)0mQ zE70E>XeZxv8oZYTxc^yw@o1JI!-tsh7Z!=XYMKnRqRp5tHDHiVPhNRbhhiz#r^4oG9jJXx>H#SqE^ZV|V!zbDp3|MH*LFOkWux7fZIp zZLQrreQp!f$raS|lh9vgd(Rv#)@<6O*8KUyeECYxHb`i~{ zn8dQ>oVLwcgGWpvek9Nl%z}HYJY;e2}5k!kN(oD`I#eG?%!Cjbo^`9Gzcm~~<%VCM7KCU$(Pva$eRugOo z_ODm20ed5pJP+_tL2m)t9PG;1vL#NLH&^Mu7~krh{SWzF2PZ?%^k%7$8ndDgfHcF~ zIQC(3g1|!U;NU}m^Wh~43pTQU~rwox*A=7B1ky906(2G05MrEVE&l!Sysa(>_N&25aeQl@Ak~5sxqq>gRA1M1cUh*A`FE;X!hsTuB&IbvhPQtdg;abaa$&POLA%TgRValm85++6A)w$gkPuwC z#J|>^rGXWc({61twPPoefh$DXbTRaG;RKo%2mi0l6>+O1a=F|9$WipUcXj$ zfVV#ExwzXiWd9((FO1RQH4ezXkwOh5dMR&G;+C}`z24h-4{Z~=Y8hPi4Ed+Q$+)C0 zCs8QM(@&C<58|^Ys(p|qF?ayS6!l;+Uaj0?{n#5K82s|};`c0uYDi3q+-P59f9lG3 zZ_~NxGqa}RX=LQ^k$`GChUuah;6!)$WlWEQJ`ZAyw+dDp)vyMewKYKNUa7-6`?xdo zi+E2v-!+TJ`-UwtsB9WcLVP?^d`PW?BA;j>90shE zKCsXlYM&-p1a?Uiq@u1uC^ey(g8zkZshfeGG1LLz&yEv$$*vmf0l|UE{qzKBkJ~|Q zBGBCBU(#78SSVQDBb6u~%yz!kB|;C&np$oX%17+#5@ox#L+P7;k1jIk{uWP00?|HP z(V~}$L|_Ul(#^Buhm)ih2yTqY)=?O{&v||+{@A~}uoe}8%cyS$6DSI)Or_jxCSn>H zb}%)+BKIddLI2qYS`0y{2k(TX>{51!xA^=+?HkQ)0@QYLxt5p#gDW|GFRA6=cmCoO zeNUN=O00h5uyL{tSncq?rGTY>WSBzt1V|gKEuk`S29C1nrDtr_7S_a->SVSw8ke%Y zS#qzOHs6h{L(@?z~jb%Ufar`=3^RIv6L*Ug} zEF+59X+DosEF&hp!!3h5lKG!WS8-u{t~6gQolxz2Uu8-eX# zH)elvk64cXvo#CX(fPzgq%ys1r1t~geN?MHk{|p}VQ*%;jQOjmWe*;!p|b%f9DfD+ zue#c4?QFPzQ`?DQ3m&|L~Li_nSp7Yq_%io{Hcjd9m@J& zJ7i(Fa&qMEy^e|oK}WgSx`%G}+oj+T1nE-5knlJVC(w2x(9y5F^1o-W+aw8!~g`Yj9(AqlI|h! zLsAVi1Lful9pxdNid}eZ1_I`SWR$0N%?FC15c^#pexo7)WD6A^1LZA*xZ98bQOPWm z+oHQ^#uTpFSObAPQ&ro_f&|Onuze>JmB8y9mj9JKZsggnZp#+0M>NatpPP`Uzj1@$ zd)@>9wPpA~6Ewfk@3_ki(x(YUE&f}yvorT(rU~0(ZhxErj%r=kT~h}t@+>i8xLfk2 zdd=fX=HIt}U}O^!t4I!XPHjxP$OY6)qOJryp}45fo)M>@gjlQ@?d&Z(B@{*q%Zu48KT%1eMY!s+E-KBhXHzBW z?mnC-b(qK@P)Bay-~k|fv}&^uJ$l6?=tUV`F zbqO6mlMKG=#bQ?wji5a6A8UwV*rmn;iG(yi!@^nj|7lXT-etg8?qFL*i&C1%)x|DG zbuP7ZiCCMJm-p1t3I(auBN`AqL+-z$NmWBMIf#OL{=4DJ4i0+51hl>vn|LQqA?N`v zBG0)#dGQH;u!Pu7(AD40)J_ROl(mIJww; zgzM)>&CYwsDadf%yYg3JxX)uN=WI`76b6*C_)(RRlw1X-oW*@l>y7rcL2$|-XJ&{7 z#=JPXNuSg)WSK~;2JOm`4RQ`+$hN?9ILM$*XV4;aw)+|B@2i9`VUButGG9G0|rldvtydqcN+W64hR$3K0qh}NK$o>g|J(mZk@fNVJRtd^= zFEHM);31i{%jB#RM5D8PobTE6Lr)AJ^T$t4?Q)(9kNhUaK~T5nU%8i4)OC7_79W0+ zuU4QAELyP$mi1RJc!TecUx-)!Gx8@#d0m;R#>QlCIV=EY3q|_3;nr?6=u_MxAgOwK zZ>n#7Zi3Jd@XDiPzu`DOMrDEH<+ov>3bw26pkPLg9-WMS63-}Q-gCv+U__0MB}TKr zdB-iZ8AGma(g{a^?q8&-bb@dluCC~YHCqZoxWX|CVuY8il5-(Y-aJ7BLvkD+H188v|4_I4{kW#NI29LiBB-1 zF<>SJY8t`;%oIH%qa+q;I7S*j=DS~M0!|m1w;p#BMNMbu%J<_Ov?Ujh$l%w2Bke!y zvas{)xmR^WnN=}!=y4$T!f;dvk=wkMK8#gJB5L5 zcy+ocrpr5V%UsmBQgT=D@DmbFfAv|^<9$5gQqZgY)l1E2&{n_g#CvZ!J_r= z<i3C``LD_cNxpC&8gq`XHqu;U5p-6mlV} zP#h@LAnqnr6S&$fz}n+}%sphkdxGvl(hR}oXARoRgQ28jq`K%@ zS%|FsX>Uq(eYdneANi4tKWF^fe!`IR^qk;lM_74XKrL$Bx}@Bnw=1e8;p*AL$*j(lW?7WjJO z@w~4n)eab%YsRNcCxug6>!(zL?%eK6@MEK-7omZXAngF?$fYw@?O|{AqQ%2j@@f|3 zxjZudVqZT1-)u~TB)(FJoIoe_!i`xI3vf>A!mUt~FbAeZtEYY)_< zYIWHYd(BnIdxgM(k&0jW16Zampco*^`GOa)iK3$cwDbAxHp5zIWgUGHoRv_^RS>?J zNy0ke?s+T_D=5ObQ|WiG+9LANtpkysWigdWs2G>cX6a>m{Lte~R~LhjJMc;{CyZ*; zx17OQopo=(LazyKIFG3g#NZ3eo7p3U7?NKBb$h>m`85QNOb@wDMOVgoy~cHfX{^DM z6S88U=hP79)Ofj$rDOQ1d3vw0;8pO!`%;XfpvKTmTcLIvy+H+ASY$NRpB@Ii);``MUj35Yo3KC%KNB@ z)zE~f4&JPoFHn-@nlhb3phFlX96}?8j$J1u2WkaCH1can<9tBeX@aHs%{%vul3Mr= z&k1;$KoQNk!SxA2qt1c7kw}M-H?(YbJ7noS;kw{eT!$J&SBlx;bvH35qAsCzepXG| ze~}8`LZ}(J(KJ@3=)`(lNc0Th7VtGsF@{SxuwPIIpWD?%5k+JCng^ymYWY_zAqGPq zZwzNiUczqdFL5rIiYyqrhJb&=?7jL_$V1K44ja-+dRyxpZ5WW-i5sz3Qoz#=J%elp zfVJ2xFqcCM_$3!peE5MDd}l*IJhw@6(Xt4GoD9?Y%*<` z!2s=*q?3Pq2r6VRdcG!8hebHctPLR~@O6ei7N!)O0q-!gdG+CdF7=Z_?@uUO4_3R1 z?q`Lp3j_KHIZZWSl#R)H%mxl~MO+sdv6-8@D8$){Po!>xO9v-h%s!-KOm?a!&x%zW ziHAzn*D;<>4BoYIC%NbYhWQI#Wd_9Jz2ew(~xfp^aqW=B1_2`Ac65^Hg zTvT5Wc*H&DcLVhAOtiVGV}%`RPQ%2(0-0aRneU#9QKRoOu+|jgEl9!Aw`0Bmw-*6q z1>-@V0eAv-urOv2cCXSc>bSDS^P|>H1W0`ATHi8|08phuBJGQ+%4nuYGYT#_%afDF zH(SK0fP)xX)L%2+u^ZCP8zu|7N_mdySrTHv)>T)rc)^3yj0e%UDR}p70s5zk#!J8-76^ z6gbN&*2dv<=Y{gTF7u>5Ax}^gq3Gg*m&AP&npJT|D19Ngl#bcoHq&CuASD z%{8M^Bv`c2pt30iXy3|pfeIs#$>+OS=#WQih%kV2wo>3_SEt?Q* z_`W_pRSa!`apddRX&o(Iv~5uz+r8(I(oOj)(Xd0dZ70yY!ru;6&K#h%eh%!^rmt|w zXV(8l;ysnu68!B^F1_+`iTMdU>$l5>dyU=lDU9-fK-y-9y|`MJQe|@YbiVubFNPU* zQ^}!sziY*Jl=KWiIL<-%Wq`AU?`s?=%FHj|MbY5>)1#WXZSk$0-~AoGBwAQ;Zj4Ku ziv00O1}*xjC-;J1FtcoM(6%?SpTFn8vUM9cVOsabvnMGpFeFt-wKaL=_wzb~A8g7# zP%-h*@`kS==#Z`lI6W%YJ3ON@SkI^YP)j?rLimuN0fkI5?~3m~*6TbGg{a>hw8y!v z+ou|Ex`9ts^IrL}7p&IpFzVng5gxpcy_|3mkqI!KG(*1m{)y`H*<2=lse zkI=DPUvS(Uy1j>(w~p*gP9%R$S%6QpZo}ypUT1oWhF)q6mCJc?gnR$LQDc_7MxJ7GRlRLs#f_ zN4ER%QlZv(#>kD0YD$LS;AepP`5Th#VaxYL2461MdgcstNzK9^WU}HPtxRSC6m;1J zdwTzfPP_v9>o!5Jog+z@b`a)5FYP&<>Z(vsKYIa;SDLG3itYrhp>mi5_w~7D-(?k9 zYq7xo+Bp$oJE$_C&_%Sl^=x37u`H?TT$4v5dCn<1C!lu_JkFwpGBX-3S@1>csH6Nf zci~yNxA`zB16_(aYT|SpFS%%xLU5Vdv}2h7`pd#rdSpqkFP|HkwrpKVR?#`3X-mghRy(?UFaDBmK;$X z4jO(nG5JywE~Rr~j@04A8dDS-X}${Sb@dRGr5vj{0dJu;y8){-D}Kkp1dI;l(q z4mHc0c$MT5x>QoU(F`U0rDTc)2Me z<7#{HY4KgCa!HrgX(~q-nzTT216I-79R>drxkI9$iKFgM+~b#=_ARC1W$i9b{FCpd zWc13b2Y&}F9l8jo1o*{1mxLm>g1+bDOU~?#w4dP3>FO)}>}!E*O`%;8FgI0F@ojCc zVjsrXcZQ3=*MPA*lYw8D8J0QYF${>p<_q&|=`SPB(&Oh_YjqNk3VXBOVdD?j9lQX&XGbhB zrtln7AM2*NDHXkS#u;H#P?6xz46?Gr@kfq& zeD^unWHrt!^{_?O7Z)1l=?Z%KYAkLD{$m~Y8NC(gdzSfkJDk|FPM8%}9lX}tOiH@*Vy9)RVjtfQ@ckn4W6 z7m4*PfRNV3wTIgWG8>C+++m%uQ_By-bb>JiZLAfBMelZqwq+MtV3=+K;pjXUO@wT4 z!c_<3GUg4ur?0P;4N_Y_>#Q4E@l$u~Ygb_^8ts{xUOa4iKrwpyeNhSEI##&4ScYbH z_77xkchmmse$$$aMVh69effzjkgT{#Ziv00m%AiVYNS?TVU+2n+_Hk@LoeEFzU@|0 zNODBVJuGq`Z4TUp!>$l|CrtF4nzjjEZcn{kf1COE?Xei8Xf*D)PK820ubH|`UZBI( zoT6!4{+eDG@9>-BTsQS zhaKGEF2B>sH{@?C21QT4#>?KJE$Wjq6>DL9#yZZs#o=0xp=*!3tmY$*t%Y-J0x)Ro zmnQiy*&?xek`JwUVPX^fHQEe`~G_hMoORGu0LAaoc?-1qAR%$|74*m>O z4=4L2HZ6=k#YztT(B6nk7NNv8K%IhnX#h;Al?pXp0x&NMO^BzG6I`r5FA6-mE zwWgsYTXt*#E4tv=jZ|Re36nNWT~*YbN2r9F%5ICMNj}=NNoRKIT3R$WtGX9DGL2_; zbA%!er7aa*B%!0AC;{VFQy+m*2hTQZRJ3$;8T8QpOZ@)W*cR*8jh(K5Zq>AVj*Xet&cXN&L zPN0Gp&W6i)#0-2X&MH?M+f3WPlcG99TUbZfT7&UXvG27aI^~yRMcJ_;=Kkn{k+0O_ zxVZU9V%lllP#^oNX(_qAf)%|Qdv*S$Jfpw;6Wkxr?lmZ09MS1w7_~??vC~^1M?O3c zKG8yGC};4?(<8&{9;;feLn!*_dAtl$KKGJETg;)m4fA&y* z4%Y?TKpnUnd1@k0f#bK*S;Q;dy14ix8Vb$(5;&9AWstQHTfG!Xn|9i_JQZ-`5#YoKCX zZslG-ESDtt`7OHEIy1}-B@WZ7KS%R)*e=TzQJ=I#g+86b>I;XX6EgqYH5W?!2SKfC zQ4wNKClX>h=X%sf^Q43qLPFcniWNFFB0EJ7bCja7T9PPBa9wWw%bdAIQfTHRCM7n{ zjRG!|%o3chPX`LPaY>g1MbeCYuAy~dx(}lh!Rh;mc-LZz=8ViTlc}rg*>(3_Btj** z$j~*-K;cd8Oq`qnriQlv)w4IUg6AY;B>b=M-yA<3W!?WKGqe96IxjDS$Pd4>rM;b~ zp|dHaC^s`BGb1A>BQp~hBim1G9wP?@BO?XX|K_p>PzwEsH6@g?v2ppC$k5pyK*-EW z&qSz0DQ9SGY3FS3WT8Vv#UN*I^8YVR5nylPVr=@~@)SkI32iKm0EPe$LMAqPMn)wnN#xY#+F{)6_vNB!^Xf6HTK;$ma|4?b3AW)7DBq%m=@|Hr&ctX%Aj|H;R~ z#liAFNBGRxVEVpF8+p?f>qBm5YOo?LTRZT+EFBNn>JW{2zQw%xwR;7FH%s zmj5v?6DRwR!Ti7HC9= zA39)SV(0w-((`{=^?$GV$2cu*Oabse2Cic1Y5HR?49fQQ&V)a=n^2iS%FfK5@c(%T ze)^)nc^QS7#TXgIIYn7TSbmf)A}r3r&dJ3kBF@Dn%qAwn#?Q;l&LqyvD8eDc$;`~k xB*MkT#xBOmC?v$hA|@s*{J&=8Xcr4iqs1kOMJ3=A3XFCOLnB^QRabvEUI4@MJGB4+ literal 0 HcmV?d00001 diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..acaf56c --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,27 @@ +.. chromo documentation master file, created by + sphinx-quickstart on Thu Sep 17 12:55:50 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to chromo's documentation! +================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + Polymer Models + + Field Theoretic Treatment of Interactions + + Brownian Dynamics Simulation + + References + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst new file mode 100644 index 0000000..46ee1b7 --- /dev/null +++ b/doc/source/poly_models.rst @@ -0,0 +1,186 @@ +.. _poly_models: + +Polymer Models +============== + +Polymer chain model: shearable, stretchable wormlike chain +---------------------------------------------------------- + +We consider a polymer with :math:`n_{b}` number of beads. +We consider the shearable, stretchable wormlike chain potential, given by + +.. math:: + \beta E_{\mathrm{elas}} = \sum_{n=0}^{n_{b}-2} + \left[ + \frac{\epsilon_{\mathrm{b}}}{2 \Delta} \left| \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + + \frac{\epsilon_{\mathrm{\parallel}}}{2 \Delta} \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right)^{2} + + \frac{\epsilon_{\mathrm{\perp}}}{2 \Delta} \left| \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + \right], + +where :math:`\Delta \vec{r}^{(n)} = \vec{r}^{(n+1)} - \vec{r}^{(n)}` is the bond vector, +:math:`\Delta \vec{r}_{\perp}^{(n)} = \Delta \vec{r}^{(n)} - (\Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)}) \vec{t}_{3}^{(n)}` +is the perpendicular component of the bond vector to the tangent vector. + + + + +Polymer chain model: hearable, stretchable wormlike chain with twist +-------------------------------------------------------------------- + +We consider a closed ring polymer, where the :math:`n_{b}` bead is the same as the zeroth bead. +We consider the shearable, stretchable wormlike chain potential with twist, given by + +.. math:: + \beta E_{\mathrm{elas}} = \sum_{n=0}^{n_{b}-1} + \left[ + \frac{\epsilon_{\mathrm{b}}}{2 \Delta} \left| \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + + \frac{\epsilon_{\mathrm{\parallel}}}{2 \Delta} \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right)^{2} + + \frac{\epsilon_{\mathrm{\perp}}}{2 \Delta} \left| \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + + \frac{\epsilon_{\mathrm{t}}}{2 \Delta} \left( \omega^{(n)} \right)^{2} + \right], + +where :math:`\Delta \vec{r}^{(n)} = \vec{r}^{(n+1)} - \vec{r}^{(n)}` is the bond vector, +:math:`\Delta \vec{r}_{\perp}^{(n)} = \Delta \vec{r}^{(n)} - (\Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)}) \vec{t}_{3}^{(n)}` is the +perpendicular component of the bond vector to the tangent vector. + +The twist angle :math:`\omega^{(n)}` gives the +local twist deformation of the chain. +Geometrically, this is defined by the relationship + +.. math:: + \left( 1 + \vec{t}_{3}^{(n)} \cdot \vec{t}_{3}^{(n+1)} \right) \cos \Omega^{(n)} & = & + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} \\ + \left( 1 + \vec{t}_{3}^{(n)} \cdot \vec{t}_{3}^{(n+1)} \right) \sin \Omega^{(n)} & = & + \vec{t}_{2}^{(n)} \cdot \vec{t}_{1}^{(n+1)} - + \vec{t}_{1}^{(n)} \cdot \vec{t}_{2}^{(n+1)} + +where :math:`\omega^{(n)} = \Omega^{(n)} + 2 \pi m^{(n)}`, and :math:`m^{(n)}` gives the number of additional integer turns +of twist within the :math:`n`th segment. +We write a differential change in :math:`\omega^{(n)}` as + +.. math:: + \delta \omega^{(n)} & = & + \frac{\vec{t}_{1}^{(n+1)} \cdot \delta \vec{t}_{2}^{(n)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} + } - + \frac{\vec{t}_{2}^{(n+1)} \cdot \delta \vec{t}_{1}^{(n)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} + } + \nonumber \\ + & & + + \frac{\vec{t}_{2}^{(n)} \cdot \delta \vec{t}_{1}^{(n+1)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} + } - + \frac{\vec{t}_{1}^{(n)} \cdot \delta \vec{t}_{2}^{(n+1)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} + } \nonumber \\ + & & + - \left( + \frac{\vec{t}_{2}^{(n)} \cdot \vec{t}_{1}^{(n+1)} - \vec{t}_{1}^{(n)} \cdot \vec{t}_{2}^{(n+1)} } + {\vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} } + \right) + \left( + \frac{ + \vec{t}_{3}^{(n)} \cdot \delta \vec{t}_{3}^{(n+1)} + + \vec{t}_{3}^{(n+1)} \cdot \delta \vec{t}_{3}^{(n)} + }{1 + \vec{t}_{3}^{(n)} \cdot \vec{t}_{3}^{(n+1)} } + \right) + + +With this development, we write the torque vectors as + +.. math:: + \vec{\tau}_{1}^{(n)} & = & \frac{\epsilon_{t}}{\Delta} \omega^{(n)} + \left( + \frac{\vec{t}_{2}^{(n+1)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)}} + \right) + - + \frac{\epsilon_{t}}{\Delta} \omega^{(n-1)} + \left( + \frac{\vec{t}_{2}^{(n-1)}}{ + \vec{t}_{1}^{(n-1)} \cdot \vec{t}_{1}^{(n)} + + \vec{t}_{2}^{(n-1)} \cdot \vec{t}_{2}^{(n)}} + \right) + \\ + \vec{\tau}_{2}^{(n)} & = & - \frac{\epsilon_{t}}{\Delta} \omega^{(n)} + \left( + \frac{\vec{t}_{1}^{(n+1)}}{ + \vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)}} + \right) + + + \frac{\epsilon_{t}}{\Delta} \omega^{(n-1)} + \left( + \frac{\vec{t}_{1}^{(n-1)} }{ + \vec{t}_{1}^{(n-1)} \cdot \vec{t}_{1}^{(n)} + + \vec{t}_{2}^{(n-1)} \cdot \vec{t}_{2}^{(n)}} + \right) \\ + \vec{\tau}_{3}^{(n)} & = & + \vec{\tau}_{b}^{(n)} - + \vec{\tau}_{b}^{(n-1)} - \eta \left[ + (\Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)}) \vec{\tau}_{b}^{(n)} + + ( \vec{\tau}_{b}^{(n)} \cdot \vec{t}_{3}^{(n)} ) \Delta \vec{r}^{(n)} + \right] + \nonumber \\ + & & + - \frac{\epsilon_{\parallel}}{\Delta} + \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right) \Delta \vec{r}^{(n)} + + \frac{\epsilon_{\perp}}{\Delta} + (\Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} ) \Delta \vec{r}_{\perp}^{(n)} + \nonumber \\ + & & + +\frac{\epsilon_{t}}{\Delta} \omega^{(n)} + \left( + \frac{\vec{t}_{2}^{(n)} \cdot \vec{t}_{1}^{(n+1)} - \vec{t}_{1}^{(n)} \cdot \vec{t}_{2}^{(n+1)} } + {\vec{t}_{1}^{(n)} \cdot \vec{t}_{1}^{(n+1)} + + \vec{t}_{2}^{(n)} \cdot \vec{t}_{2}^{(n+1)} } + \right) + \frac{ + \vec{t}_{3}^{(n+1)}}{1 + \vec{t}_{3}^{(n)} \cdot \vec{t}_{3}^{(n+1)} } \nonumber \\ + & & + + + \frac{\epsilon_{t}}{\Delta} \omega^{(n-1)} + \left( + \frac{\vec{t}_{2}^{(n-1)} \cdot \vec{t}_{1}^{(n)} - \vec{t}_{1}^{(n-1)} \cdot \vec{t}_{2}^{(n)} } + {\vec{t}_{1}^{(n-1)} \cdot \vec{t}_{1}^{(n)} + + \vec{t}_{2}^{(n-1)} \cdot \vec{t}_{2}^{(n)} } + \right) + \frac{ + \vec{t}_{3}^{(n-1)}}{1 + \vec{t}_{3}^{(n-1)} \cdot \vec{t}_{3}^{(n)} } + +where + + +.. math:: + \vec{\tau}_{b}^{(n)} = + \frac{\epsilon_{b}}{\Delta} \left( + \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} + \right) + +The force on the :math:`n`th bead is given by + +.. math:: + \vec{f}^{(n)} & = & + -\eta \vec{\tau}_{b}^{(n)} + \eta ( \vec{\tau}_{b}^{(n)} \cdot \vec{t}_{3}^{(n)} ) \vec{t}_{3}^{(n)} + +\eta \vec{\tau}_{b}^{(n-1)} - \eta ( \vec{\tau}_{b}^{(n-1)} \cdot \vec{t}_{3}^{(n-1)} ) \vec{t}_{3}^{(n-1)} + \nonumber \\ + & & + + \frac{\epsilon_{\parallel}}{\Delta} + \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right) \vec{t}_{3}^{(n)} + - \frac{\epsilon_{\parallel}}{\Delta} + \left( \Delta \vec{r}^{(n-1)} \cdot \vec{t}_{3}^{(n-1)} - \Delta \gamma \right) \vec{t}_{3}^{(n-1)} + \nonumber \\ + & & + + \frac{\epsilon_{\perp}}{\Delta} + \Delta \vec{r}_{\perp}^{(n)} + - \frac{\epsilon_{\perp}}{\Delta} + \Delta \vec{r}_{\perp}^{(n-1)} + diff --git a/doc/source/references.rst b/doc/source/references.rst new file mode 100644 index 0000000..1a35691 --- /dev/null +++ b/doc/source/references.rst @@ -0,0 +1,40 @@ +.. _references: + + +References +========== + +.. Spakowitz Lab references + +.. [Spakowitz2004] + Spakowitz, Andrew J., and Zhen-Gang Wang. "Exact results for a semiflexible polymer chain in an aligning field." Macromolecules 37.15 (2004): 5814-5823. + +.. [Spakowitz2005] + Spakowitz, Andrew J., and Zhen-Gang Wang. "End-to-end distance vector distribution with fixed end orientations for the wormlike chain model." Physical Review E 72.4 (2005): 041802. + +.. [Spakowitz2006] + Spakowitz, A. J. "Wormlike chain statistics with twist and fixed ends." EPL (Europhysics Letters) 73.5 (2006): 684. + +.. [Mehraeen2008] + Mehraeen, Shafigh, et al. "End-to-end distribution for a wormlike chain in arbitrary dimensions." Physical Review E 77.6 (2008): 061803. + +.. Simulation methodologies + +.. [Pike2009a] + Detcheverry, François A., et al. "Monte Carlo simulation of coarse grain polymeric systems." Physical review letters 102.19 (2009): 197801. + +.. [Pike2009b] + Pike, Darin Q., et al. "Theoretically informed coarse grain simulations of polymeric systems." The Journal of chemical physics 131.8 (2009): 084903. + +.. Wormlike Chain references + +.. [Kratky1949] + Kratky, Otto, and Günther Porod. "Röntgenuntersuchung gelöster fadenmoleküle." Recueil des Travaux Chimiques des Pays‐Bas 68.12 (1949): 1106-1122. + +.. [Yamakawa1997] + Yamakawa, Hiromi, and Takenao Yoshizaki. Helical wormlike chains in polymer solutions. Vol. 1. Berlin: Springer, 1997. + +.. Mathematics references + +.. [Arfken1999] + Arfken, George B., and Hans J. Weber. "Mathematical methods for physicists." (1999): 165-169. diff --git a/notes/chromo-derive.log b/notes/chromo-derive.log index 801f624..63c5952 100644 --- a/notes/chromo-derive.log +++ b/notes/chromo-derive.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) (preloaded format=pdflatex 2019.5.8) 3 AUG 2020 16:42 +This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) (preloaded format=pdflatex 2019.5.8) 17 SEP 2020 13:17 entering extended mode restricted \write18 enabled. file:line:error style messages enabled. @@ -357,7 +357,7 @@ File: figures/weight.pdf Graphic file (type pdf) Package pdftex.def Info: figures/weight.pdf used on input line 60. (pdftex.def) Requested size: 281.85587pt x 140.93474pt. LaTeX Font Info: Font shape `OT1/ptm/bx/n' in size <14.4> not available -(Font) Font shape `OT1/ptm/b/n' tried instead on input line 88. +(Font) Font shape `OT1/ptm/b/n' tried instead on input line 90. [2 <./figures/weight.pdf>] (./chromo-derive.bbl) [3] (./chromo-derive.aux) ) @@ -379,7 +379,7 @@ texmf-dist/fonts/type1/urw/symbol/usyr.pfb> -Output written on chromo-derive.pdf (3 pages, 188127 bytes). +Output written on chromo-derive.pdf (3 pages, 189721 bytes). PDF statistics: 64 PDF objects out of 1000 (max. 8388607) 44 compressed objects within 1 object stream diff --git a/notes/chromo-derive.pdf b/notes/chromo-derive.pdf index 3a59cb556933c289a2cc9ffda4000f2ea7b9ef2d..2bf797407b8a74b172489a2be377696da5b463e1 100644 GIT binary patch delta 19490 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≺LEN<^qB3F`#K(^F&f%r1qs6-G0W(#2 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 AHvj+t diff --git a/notes/chromo-derive.synctex.gz b/notes/chromo-derive.synctex.gz index d3714b85f4bc9ee47f6bbe394c4d50abe60e4898..6ac7a59b1c463124f80de6e1828df08f6d2da773 100644 GIT binary patch literal 15802 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 Date: Thu, 17 Sep 2020 15:59:33 -0700 Subject: [PATCH 06/15] API edits --- doc/source/poly_models.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst index 46ee1b7..deb2a10 100644 --- a/doc/source/poly_models.rst +++ b/doc/source/poly_models.rst @@ -24,7 +24,7 @@ is the perpendicular component of the bond vector to the tangent vector. -Polymer chain model: hearable, stretchable wormlike chain with twist +Polymer chain model: shearable, stretchable wormlike chain with twist -------------------------------------------------------------------- We consider a closed ring polymer, where the :math:`n_{b}` bead is the same as the zeroth bead. From b7ec3149b62b9260460be0463aa2f82e3cdb3989 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Fri, 18 Sep 2020 07:00:08 -0700 Subject: [PATCH 07/15] Modified the polymer models --- doc/source/bd_sim.rst | 1 - doc/source/poly_models.rst | 73 +++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/doc/source/bd_sim.rst b/doc/source/bd_sim.rst index 3c25322..2d16313 100644 --- a/doc/source/bd_sim.rst +++ b/doc/source/bd_sim.rst @@ -105,4 +105,3 @@ With this development, we now write the Langevin equations as \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) - \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) \right] \vec{t}_{2}^{(n)} - diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst index deb2a10..7d37871 100644 --- a/doc/source/poly_models.rst +++ b/doc/source/poly_models.rst @@ -3,14 +3,68 @@ Polymer Models ============== -Polymer chain model: shearable, stretchable wormlike chain +We introduce the polymer models that can be used in the chromo simulation. +These models are designed to capture different physical effects. +They are all based on a common representation of the +chain as a discrete set of beads. +However, each model uses a subset of the geometric variables in their +calculation of energy, force, and torque, and the simulation automatically +adjusts the underlying calculations based on the model. +Here, we define the general chain representation that includes the most +complete geometric variables for the chain, and each polymer model utilizes +a subset of these variables (defined for each model below). +Each model also has the option of creating a linear or ring polymer, +which simply requires the model to add a bond between the first bead and the +last bead of the chain. + +We consider a polymer with :math:`n_{b}` number of beads in a single chain. +The polymer chain is represented by the +bead positions +:math:`\vec{r}^{(0)}, \vec{r}^{(1)}, \ldots, \vec{r}^{(n_{b}-1)}` +and orientations +:math:`\vec{t}_{i}^{(0)}, \vec{t}_{i}^{(1)}, \ldots, \vec{t}_{i}^{(n_{b}-1)}` +where :math:`i = 1, 2, 3`. +Since the orientation triad forms an orthonormal basis, the dynamics must maintain the following conditions: + +.. math:: + \vec{t}_{i}^{(n)} \cdot \vec{t}_{j}^{(n)} = \delta_{ij} + +Each model represents a chain whose total length is :math:`L`, so +the chain is discretized into segments of length +:math:`\Delta = L/n_{b}`. + + +Polymer chain model A: flexible Gaussian chain +-------------------------------------------- + +The flexible Gaussian chain captures the behavior of a flexible polymer chain that +is representative of a Gaussian random walk in the absence of additional interactions. +The chain is defined by the bead positions :math:`\vec{r}^{(n)}`, and the +bead orientations are not utilized in this model. + +We define the polymer energy function + +.. math:: + \beta E_{\mathrm{poly}} = \sum_{n=0}^{n_{b}-2} + \frac{3}{\Delta b} \left( \vec{r}^{(n+1)} - \vec{r}^{(n)} \right)^{2} + +where we define :math:`\beta = 1/(k_{B}T)`, and the Kuhn length +:math:`b` defines the statistical segment length of the polymer chain. +This energy definition is valid for a linear chain. +However, the ring representation only requires the upper limit of the +summation to be changed to :math:`n_{b} - 1`, and we note that +the condition :math:`\vec{r}^{(n_{b})} = \vec{r}^{(0)}` connects the +chain ends into a ring + + + +Polymer chain model B: shearable, stretchable wormlike chain ---------------------------------------------------------- -We consider a polymer with :math:`n_{b}` number of beads. We consider the shearable, stretchable wormlike chain potential, given by .. math:: - \beta E_{\mathrm{elas}} = \sum_{n=0}^{n_{b}-2} + \beta E_{\mathrm{poly}} = \sum_{n=0}^{n_{b}-2} \left[ \frac{\epsilon_{\mathrm{b}}}{2 \Delta} \left| \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + \frac{\epsilon_{\mathrm{\parallel}}}{2 \Delta} \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right)^{2} + @@ -24,14 +78,14 @@ is the perpendicular component of the bond vector to the tangent vector. -Polymer chain model: shearable, stretchable wormlike chain with twist +Polymer chain model C: shearable, stretchable wormlike chain with twist -------------------------------------------------------------------- We consider a closed ring polymer, where the :math:`n_{b}` bead is the same as the zeroth bead. We consider the shearable, stretchable wormlike chain potential with twist, given by .. math:: - \beta E_{\mathrm{elas}} = \sum_{n=0}^{n_{b}-1} + \beta E_{\mathrm{poly}} = \sum_{n=0}^{n_{b}-1} \left[ \frac{\epsilon_{\mathrm{b}}}{2 \Delta} \left| \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} \right|^{2} + \frac{\epsilon_{\mathrm{\parallel}}}{2 \Delta} \left( \Delta \vec{r}^{(n)} \cdot \vec{t}_{3}^{(n)} - \Delta \gamma \right)^{2} + @@ -55,8 +109,10 @@ Geometrically, this is defined by the relationship \vec{t}_{2}^{(n)} \cdot \vec{t}_{1}^{(n+1)} - \vec{t}_{1}^{(n)} \cdot \vec{t}_{2}^{(n+1)} -where :math:`\omega^{(n)} = \Omega^{(n)} + 2 \pi m^{(n)}`, and :math:`m^{(n)}` gives the number of additional integer turns -of twist within the :math:`n`th segment. +where :math:`\omega^{(n)} = \Omega^{(n)} + 2 \pi m^{(n)}`, +and :math:`m^{(n)}` gives the number of additional integer turns +of twist within the +nth segment. We write a differential change in :math:`\omega^{(n)}` as .. math:: @@ -158,14 +214,13 @@ With this development, we write the torque vectors as where - .. math:: \vec{\tau}_{b}^{(n)} = \frac{\epsilon_{b}}{\Delta} \left( \vec{t}_{3}^{(n+1)} - \vec{t}_{3}^{(n)} - \eta \Delta \vec{r}_{\perp}^{(n)} \right) -The force on the :math:`n`th bead is given by +The force on the nth bead is given by .. math:: \vec{f}^{(n)} & = & From 693de9053f2fe6356b130be865a5d275c5bfbf4c Mon Sep 17 00:00:00 2001 From: ajspakow Date: Fri, 18 Sep 2020 11:30:16 -0700 Subject: [PATCH 08/15] Added pages for mc_sim and code_structure --- doc/source/bd_sim.rst | 7 +++++++ doc/source/code_structure.rst | 7 +++++++ doc/source/index.rst | 6 +++++- doc/source/mc_sim.rst | 6 ++++++ doc/source/poly_models.rst | 18 +++++++++++++----- doc/source/references.rst | 3 +++ 6 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 doc/source/code_structure.rst create mode 100644 doc/source/mc_sim.rst diff --git a/doc/source/bd_sim.rst b/doc/source/bd_sim.rst index 2d16313..a8238cd 100644 --- a/doc/source/bd_sim.rst +++ b/doc/source/bd_sim.rst @@ -105,3 +105,10 @@ With this development, we now write the Langevin equations as \vec{t}_{2}^{(n)} \cdot \left( \vec{\tau}_{E,3}^{(n)} + \vec{\tau}_{B,3}^{(n)} \right) - \vec{t}_{3}^{(n)} \cdot \left( \vec{\tau}_{E,2}^{(n)} + \vec{\tau}_{B,2}^{(n)} \right) \right] \vec{t}_{2}^{(n)} + + +Brownian dynamics simulations with constrained bond lengths +----------------------------------------------------------- + +Overview of bond constraints +Ref [Hinch1994]_ \ No newline at end of file diff --git a/doc/source/code_structure.rst b/doc/source/code_structure.rst new file mode 100644 index 0000000..c474a9c --- /dev/null +++ b/doc/source/code_structure.rst @@ -0,0 +1,7 @@ +.. _code_structure: + +Code Overview and Structure +=========================== + +We provide an overview of the 'chromo' code structure and the individual classes and modules that +are responsible for the individual simulation capabilities. diff --git a/doc/source/index.rst b/doc/source/index.rst index acaf56c..b75edab 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -10,11 +10,15 @@ Welcome to chromo's documentation! :maxdepth: 2 :caption: Contents: + Code Overview and Structure + Polymer Models Field Theoretic Treatment of Interactions - Brownian Dynamics Simulation + Monte Carlo Simulations + + Brownian Dynamics Simulations References diff --git a/doc/source/mc_sim.rst b/doc/source/mc_sim.rst new file mode 100644 index 0000000..4a71e74 --- /dev/null +++ b/doc/source/mc_sim.rst @@ -0,0 +1,6 @@ +.. _mc_sim: + +Monte Carlo Simulations +======================= + + diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst index 7d37871..94cb53c 100644 --- a/doc/source/poly_models.rst +++ b/doc/source/poly_models.rst @@ -29,10 +29,14 @@ Since the orientation triad forms an orthonormal basis, the dynamics must mainta .. math:: \vec{t}_{i}^{(n)} \cdot \vec{t}_{j}^{(n)} = \delta_{ij} -Each model represents a chain whose total length is :math:`L`, so -the chain is discretized into segments of length -:math:`\Delta = L/n_{b}`. - +Each model represents a chain whose total length is :math:`L`, +For linear polymers, the chain is discretized into segments of length +:math:`\Delta = L/(n_{b}-1)`. This implies that the end-to-end +vector is given by :math:`\vec{R} = \vec{r}^{(n_{b}-1)} - \vec{r}^{(0)}`. +For ring polymers, the chain is discretized into segments of length +:math:`\Delta = L/n_{b}`, which includes the bond between the last +bead at :math:`\vec{r}^{(n_{b} - 1)}` and the first bead at +:math:`\vec{r}^{(0)}`. Polymer chain model A: flexible Gaussian chain -------------------------------------------- @@ -54,7 +58,11 @@ This energy definition is valid for a linear chain. However, the ring representation only requires the upper limit of the summation to be changed to :math:`n_{b} - 1`, and we note that the condition :math:`\vec{r}^{(n_{b})} = \vec{r}^{(0)}` connects the -chain ends into a ring +chain ends into a ring. +In this model, the bead orientations :math:`\vec{t}_{i}^{(n)}` do not +contribute to the energy and are not evolved in the simulation. + + diff --git a/doc/source/references.rst b/doc/source/references.rst index 1a35691..154c251 100644 --- a/doc/source/references.rst +++ b/doc/source/references.rst @@ -26,6 +26,9 @@ References .. [Pike2009b] Pike, Darin Q., et al. "Theoretically informed coarse grain simulations of polymeric systems." The Journal of chemical physics 131.8 (2009): 084903. +.. [Hinch1994] + Hinch, E. J. "Brownian motion with stiff bonds and rigid constraints." Journal of Fluid Mechanics 271 (1994): 219-234. + .. Wormlike Chain references .. [Kratky1949] From 0565de11399a396204b8cbb707cac40691db55a5 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Fri, 18 Sep 2020 12:42:11 -0700 Subject: [PATCH 09/15] Updated assignments --- doc/source/code_structure.rst | 2 ++ doc/source/mc_sim.rst | 1 + 2 files changed, 3 insertions(+) diff --git a/doc/source/code_structure.rst b/doc/source/code_structure.rst index c474a9c..fc3c3c9 100644 --- a/doc/source/code_structure.rst +++ b/doc/source/code_structure.rst @@ -5,3 +5,5 @@ Code Overview and Structure We provide an overview of the 'chromo' code structure and the individual classes and modules that are responsible for the individual simulation capabilities. + +9/18/20 - Bruno will update this page with a code map and discussion \ No newline at end of file diff --git a/doc/source/mc_sim.rst b/doc/source/mc_sim.rst index 4a71e74..91932cf 100644 --- a/doc/source/mc_sim.rst +++ b/doc/source/mc_sim.rst @@ -3,4 +3,5 @@ Monte Carlo Simulations ======================= +9/18/20 - Joe will update this page with an overview of the Monte Methodology (with schematic of moves and methods) From d2f35d29472a70b2e635b8319c6d0a426efb1b31 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Sat, 19 Sep 2020 15:26:13 -0700 Subject: [PATCH 10/15] Updated polymer models page --- doc/source/poly_models.rst | 75 +++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst index 94cb53c..5587770 100644 --- a/doc/source/poly_models.rst +++ b/doc/source/poly_models.rst @@ -29,7 +29,7 @@ Since the orientation triad forms an orthonormal basis, the dynamics must mainta .. math:: \vec{t}_{i}^{(n)} \cdot \vec{t}_{j}^{(n)} = \delta_{ij} -Each model represents a chain whose total length is :math:`L`, +Each model represents a chain whose total length is :math:`L`. For linear polymers, the chain is discretized into segments of length :math:`\Delta = L/(n_{b}-1)`. This implies that the end-to-end vector is given by :math:`\vec{R} = \vec{r}^{(n_{b}-1)} - \vec{r}^{(0)}`. @@ -39,7 +39,7 @@ bead at :math:`\vec{r}^{(n_{b} - 1)}` and the first bead at :math:`\vec{r}^{(0)}`. Polymer chain model A: flexible Gaussian chain --------------------------------------------- +---------------------------------------------- The flexible Gaussian chain captures the behavior of a flexible polymer chain that is representative of a Gaussian random walk in the absence of additional interactions. @@ -50,7 +50,7 @@ We define the polymer energy function .. math:: \beta E_{\mathrm{poly}} = \sum_{n=0}^{n_{b}-2} - \frac{3}{\Delta b} \left( \vec{r}^{(n+1)} - \vec{r}^{(n)} \right)^{2} + \frac{3}{2 \Delta b} \left( \vec{r}^{(n+1)} - \vec{r}^{(n)} \right)^{2} where we define :math:`\beta = 1/(k_{B}T)`, and the Kuhn length :math:`b` defines the statistical segment length of the polymer chain. @@ -62,12 +62,77 @@ chain ends into a ring. In this model, the bead orientations :math:`\vec{t}_{i}^{(n)}` do not contribute to the energy and are not evolved in the simulation. +From the polymer energy, we determine the force on the nth bead +is determined from :math:`\vec{f}^{(n)} = - \frac{\partial \beta E}{\partial \vec{r}^{(n)}}`, +where we scale the force by the thermal energy :math:`k_{B}T`. +This results in the force on the nth bead to be given as +.. math:: + \vec{f}^{(n)} = \frac{3}{\Delta b} \left( \vec{r}^{(n+1)} + - 2 \vec{r}^{(n)} + \vec{r}^{(n-1)} \right) + +for all beads within the interior of the chain. +This expression also applies to the end beads :math:`n=0` and +:math:`n=n_{b}-1` for a ring polymer, if we note that +:math:`\vec{r}^{(-1)} = \vec{r}^{(n_{b}-1)}` and +:math:`\vec{r}^{(n_{b})} = \vec{r}^{(0)}`. + +For the ends of a linear chain, the end-bead forces are given by + +.. math:: + \vec{f}^{(0)} & = & \frac{3}{\Delta b} \left( + \vec{r}^{(1)} + - \vec{r}^{(0)} + \right) \\ + \vec{f}^{(n_{b}-1)} & = & - \frac{3}{\Delta b} \left( + \vec{r}^{(n_{b}-1)} + - \vec{r}^{(n_{b}-2)} + \right) + +Initialization of the flexible Gaussian chain in the absence of additional interactions +(e.g. excluded-volume interactions or confinement) +is performed by selecting the bond vectors from a Gaussian distribution with +a variance that is given by + +.. math:: + \langle + \left( + \vec{r}^{(n+1)} - \vec{r}^{(n)} + \right) + \left( + \vec{r}^{(n'+1)} - \vec{r}^{(n')} + \right) + \rangle = \frac{\Delta b}{3} \delta_{nn'} \mathbf{I} +which leads to a mean-square end-to-end distance +.. math:: + \langle + \vec{R}^{2} + \rangle = + \sum_{n=0}^{n_{b}-2} + \sum_{n'=0}^{n_{b}-2} + \langle + \left( + \vec{r}^{(n+1)} - \vec{r}^{(n)} + \right) \cdot + \left( + \vec{r}^{(n'+1)} - \vec{r}^{(n')} + \right) + \rangle + = \sum_{n=0}^{n_{b}-2} + \sum_{n'=0}^{n_{b}-2} + \Delta b \delta_{nn'} + = \Delta b (n_{b} - 1) + = L b + +which is consistent with the solution for a Gaussian random +walk polymer with length :math:`L = N b`, +where :math:`N` is the number of Kuhn lengths in the +chain. Polymer chain model B: shearable, stretchable wormlike chain ----------------------------------------------------------- +------------------------------------------------------------ We consider the shearable, stretchable wormlike chain potential, given by @@ -87,7 +152,7 @@ is the perpendicular component of the bond vector to the tangent vector. Polymer chain model C: shearable, stretchable wormlike chain with twist --------------------------------------------------------------------- +----------------------------------------------------------------------- We consider a closed ring polymer, where the :math:`n_{b}` bead is the same as the zeroth bead. We consider the shearable, stretchable wormlike chain potential with twist, given by From 65c99dec3f4df71cfc57999d1b1a9737b914d1d9 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Fri, 23 Oct 2020 16:42:42 -0700 Subject: [PATCH 11/15] Andy's initial documentation --- doc/source/bd_sim.rst | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/doc/source/bd_sim.rst b/doc/source/bd_sim.rst index a8238cd..2a15804 100644 --- a/doc/source/bd_sim.rst +++ b/doc/source/bd_sim.rst @@ -3,6 +3,61 @@ Brownian Dynamics Simulations ============================= +Langevin equation for translation +--------------------------------- + +We consider a discrete chain of :math:`n_{b}` beads with positions :math:`\vec{r}^{(n)}`, +where the bead index :math:`n` runs from 0 to :math:`n_{b}-1`. +We consider a general potential energy :math:`E = E( \{ \vec{r} \} )`, where :math:`\{ \vec{r} \}` indicates +the full set of positions. +We define the potential forces on the beads to be + +.. math:: + \vec{f}_{E}^{(n)} = - \frac{\partial E}{\partial \vec{r}^{(n)}} + +The Langevin equation for the bead positions is given by + +.. math:: + \xi_{r} \frac{\partial \vec{r}^{(n)}}{\partial t} = \vec{f}_{E}^{(n)} + \vec{f}_{B}^{(n)} + +The Brownian force :math:`\vec{f}_{B}^{(n)}` is governed by the fluctuation dissipation theorem, +which states that :math:`\vec{f}_{B}^{(n)}` is a +Gaussian-distributed random force +that satisfies + +.. math:: + \langle \vec{f}_{B}^{(n)}(t) \rangle & = & 0, \\ + \langle \vec{f}_{B}^{(n)}(t) \vec{f}_{B}^{(n')}(t') \rangle + & = & + 2 k_{B} T \xi \delta (t - t') \delta_{nn'} \mathbf{I}. + +This stochastic differential equation is numerically integrated by +discretizing time in discrete time steps :math:`\delta t`. +Thus, the discrete time at the :math:`j`th time step is +given by :math:`t_{j} = \delta t (j-1)`, where :math:`t_{0} = 0`. +Based on this time discretization, we numerically integrate the Langevin +equation as + +.. math:: + \vec{r}^{(n)}_{j+1} = + \vec{r}^{(n)}_{j} + + \frac{\delta t}{\xi_{r}} \left( + \vec{f}_{E_{j}}^{(n)} + \vec{f}_{B_{j}}^{(n)} + \right) + +which suggests an explicit integration algorithm. + +The fluctuation dissipation for the discrete time + +.. math:: + \langle \vec{f}_{B_{j}}^{(n)} \rangle & = & 0, \\ + \langle \vec{f}_{B_{j}}^{(n)} \vec{f}_{B_{j'}}^{(n')} \rangle + & = & + \frac{2 k_{B} T \xi}{\delta t} \delta_{jj'} \delta_{nn'} \mathbf{I}. + +Thus, the value of :math:`\langle \vec{f}_{B_{j}}^{(n)}` is selected from a Gaussian distribution +with variance :math:`\frac{2 k_{B} T \xi}{\delta t}`. + Langevin equation for translation and rotation ---------------------------------------------- From 22a96e2c222a35df34a2d328fb96f786a269c1ac Mon Sep 17 00:00:00 2001 From: ajspakow Date: Sat, 24 Oct 2020 06:40:15 -0700 Subject: [PATCH 12/15] bd_sim doc additions --- doc/source/bd_sim.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/bd_sim.rst b/doc/source/bd_sim.rst index 2a15804..01a69ab 100644 --- a/doc/source/bd_sim.rst +++ b/doc/source/bd_sim.rst @@ -55,7 +55,7 @@ The fluctuation dissipation for the discrete time & = & \frac{2 k_{B} T \xi}{\delta t} \delta_{jj'} \delta_{nn'} \mathbf{I}. -Thus, the value of :math:`\langle \vec{f}_{B_{j}}^{(n)}` is selected from a Gaussian distribution +Thus, the value of :math:`\vec{f}_{B_{j}}^{(n)}` is selected from a Gaussian distribution with variance :math:`\frac{2 k_{B} T \xi}{\delta t}`. Langevin equation for translation and rotation From 445d412c5b2562e131d7027ab9559e5bb17add20 Mon Sep 17 00:00:00 2001 From: ajspakow Date: Tue, 27 Apr 2021 09:25:48 -0700 Subject: [PATCH 13/15] Added image --- chromo/image.py | 171 +++++++++++++++++++++++++++++++++++++ doc/source/poly_models.rst | 20 +++++ 2 files changed, 191 insertions(+) create mode 100644 chromo/image.py diff --git a/chromo/image.py b/chromo/image.py new file mode 100644 index 0000000..c7ec6f4 --- /dev/null +++ b/chromo/image.py @@ -0,0 +1,171 @@ +r""" +Imaging module - Generate image files from simulations for PyMol imaging + +Notes +----- + +""" + + +import numpy as np + + +def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limit_n = False, n_max = 100000, + max_method = 'mid_slice', add_nucleus = False, filename='r_poly.pdb', ring=False): + r""" + + Parameters + ---------- + r_poly : (num_beads, 3) float + Conformation of the chain subjected to active-Brownian forces + filename : str + File name to write the pdb file + ring : bool + Boolean to close the polymer into a ring + + Returns + ------- + + """ + + # Open the file + f = open(filename, 'w') + + atomname1 = "A1" # Chain atom type + resname = "SSN" # Type of residue (UNKnown/Single Stranded Nucleotide) + chain = "A" # Chain identifier + resnum = 1 + numresidues = len(r_poly[:, 0]) + descrip = "Pseudo atom representation of DNA" + chemicalname = "Body and ribbon spatial coordinates" + if len(meth_seq) == 0: + image_meth_seq = False + else: + image_meth_seq = True + + # Determine the bead indices to reduce the total represented to n_max if limit_n True + + if n_max >= numresidues: + limit_n = False + + if limit_n: + if max_method == 'mid_slice': + ind_save, connect_left, connect_right = find_ind_mid_slice(r_poly, n_max, ring) + else: + ind_save, connect_left, connect_right = find_ind_total(r_poly, ring) + + # Write the preamble to the pymol file + + f.write('HET %3s %1s%4d %5d %-38s\n' % (resname, chain, resnum, numresidues, descrip)) + f.write('HETNAM %3s %-50s\n' % (resname, chemicalname)) + f.write('FORMUL 1 %3s C20 N20 P21\n' % (resname)) + + # Write the conformation to the pymol file + + count = 0 + for ind in range(numresidues): + if ind_save[ind] == 1: + if image_meth_seq: + atomname = 'A' + str(int(meth_seq[ind])) + else: + atomname = atomname1 + f.write('ATOM%7d %4s %3s %1s %8.3f%8.3f%8.3f%6.2f%6.2f C\n' % + (count + 1, atomname, resname, chain, r_poly[ind, 0], r_poly[ind, 1], r_poly[ind, 2], 1.00, 1.00)) + count += 1 + numresidues_save = count + + # Add a nucleus bead to the pymol file + + atomname = 'AN' + chain = 'B' + r_com = np.mean(r_poly, axis = 0) + if add_nucleus: + f.write('ATOM%7d %4s %3s %1s %8.3f%8.3f%8.3f%6.2f%6.2f C\n' % + (count + 1, atomname, resname, chain, r_com[0], r_com[1], r_com[2], 1.00, 1.00)) + + # Define the connectivity in the chain + + count = 0 + for ind in range(numresidues): + if ind_save[ind] == 1: + if ind == 0: + ind_left = numresidues_save - 1 + else: + ind_left = count - 1 + if ind == numresidues - 1: + ind_right = 0 + else: + ind_right = count + 1 + + if connect_left[ind] == 1 and connect_right[ind] == 1: + f.write('CONECT%5d%5d%5d\n' % (count + 1, ind_left + 1, ind_right + 1)) + elif connect_left[ind] == 1 and connect_right[ind] == 0: + f.write('CONECT%5d%5d\n' % (count + 1, ind_left + 1)) + elif connect_left[ind] == 0 and connect_right[ind] == 1: + f.write('CONECT%5d%5d\n' % (count + 1, ind_right + 1)) +# elif connect_left[ind] == 0 and connect_right[ind] == 0: +# f.write('CONECT%5d\n' % (count + 1)) + count += 1 + + # Close the file + f.write('END') + f.close() + + return + + +def find_ind_mid_slice(r_poly, n_max, ring): + r""" + + """ + + # Find the value of the x-coordinate and sort the beads according to distance from mean + x_ave = np.mean(r_poly[:, 0]) + delta_x = r_poly[:, 0] - x_ave + ind_sort = np.argsort(np.abs(delta_x)) + + # Select the first n_max beads based on distance from the mean + ind_save = np.zeros(len(r_poly[:, 0])) + connect_left = np.zeros(len(r_poly[:, 0])) + connect_right = np.zeros(len(r_poly[:, 0])) + + for ind in range(n_max): + ind_save[ind_sort[ind]] = 1 + + # Determine whether adjacent beads are saved to define connections + for ind in range(n_max): + if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] - 1] == 1): + connect_left[ind_sort[ind]] = 1 + if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] + 1] == 1): + connect_right[ind_sort[ind]] = 1 + + # Remove the end connections if ring is false + if not ring: + connect_left[0] = 0 + + if not ring: + connect_right[-1] = 0 + + return ind_save, connect_left, connect_right + + +def find_ind_total(r_poly, ring): + r""" + + """ + + ind_save = np.ones(len(r_poly[:, 0])) + connect_left = np.ones(len(r_poly[:, 0])) + connect_right = np.ones(len(r_poly[:, 0])) + + if ring: + connect_left[0] = 1 + else: + connect_left[0] = 0 + + if ring: + connect_right[-1] = 1 + else: + connect_right[-1] = 0 + + return ind_save, connect_left, connect_right diff --git a/doc/source/poly_models.rst b/doc/source/poly_models.rst index 5587770..9077869 100644 --- a/doc/source/poly_models.rst +++ b/doc/source/poly_models.rst @@ -38,6 +38,26 @@ For ring polymers, the chain is discretized into segments of length bead at :math:`\vec{r}^{(n_{b} - 1)}` and the first bead at :math:`\vec{r}^{(0)}`. + +.. table:: + :widths: 30 30 30 30 30 + :align: center + + +-----------------+--------------+------------------+-------------------+-------------------+ + | model code | 'track_norm' | 'bond_contraint' | 'ring' | 'link_constraint' | + +=================+==============+==================+===================+===================+ + | 'gauss_chain' | False | False | True/False | False | + +-----------------+--------------+------------------+-------------------+-------------------+ + | 'wlc' | False | True | True/False | False | + +-----------------+--------------+------------------+-------------------+-------------------+ + | 'sswlc' | False | False | True/False | False | + +-----------------+--------------+------------------+-------------------+-------------------+ + | 'twlc' | True | True | True/False | True/False | + +-----------------+--------------+------------------+-------------------+-------------------+ + | 'tsswlc' | True | False | True/False | True/False | + +-----------------+--------------+------------------+-------------------+-------------------+ + + Polymer chain model A: flexible Gaussian chain ---------------------------------------------- From ace3a69eb066d7cc8227700d3fb9495ae9af0e2d Mon Sep 17 00:00:00 2001 From: ajspakow Date: Tue, 27 Apr 2021 17:50:47 -0700 Subject: [PATCH 14/15] Update image module --- chromo/image.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/chromo/image.py b/chromo/image.py index c7ec6f4..0d5184f 100644 --- a/chromo/image.py +++ b/chromo/image.py @@ -136,8 +136,12 @@ def find_ind_mid_slice(r_poly, n_max, ring): for ind in range(n_max): if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] - 1] == 1): connect_left[ind_sort[ind]] = 1 - if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] + 1] == 1): - connect_right[ind_sort[ind]] = 1 + if ind_sort[ind] == (len(r_poly[:, 0]) - 1): + if (ind_save[ind_sort[ind]] == 1) and (ind_save[0] == 1): + connect_right[ind_sort[ind]] = 1 + else: + if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] + 1] == 1): + connect_right[ind_sort[ind]] = 1 # Remove the end connections if ring is false if not ring: From b8e098a9bcf4b66e641a1407600084a16024d13e Mon Sep 17 00:00:00 2001 From: ajspakow Date: Thu, 29 Apr 2021 20:10:46 -0700 Subject: [PATCH 15/15] Image module updated --- chromo/image.py | 92 ++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/chromo/image.py b/chromo/image.py index 0d5184f..948932f 100644 --- a/chromo/image.py +++ b/chromo/image.py @@ -11,13 +11,20 @@ def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limit_n = False, n_max = 100000, - max_method = 'mid_slice', add_nucleus = False, filename='r_poly.pdb', ring=False): + max_method = 'mid_slice', ind_save = np.array([]), + add_com = False, filename='r_poly.pdb', ring=False): r""" Parameters ---------- r_poly : (num_beads, 3) float Conformation of the chain subjected to active-Brownian forces + meth_seq : (num_beads) int + Epigenetic sequence (0 = No tails methylated, 1 = 1 tail methylated, 2 = 2 tails methylated) + hp1_seq : (num_beads) int + Number of tails with HP1 bound + limit_n : Boolean + filename : str File name to write the pdb file ring : bool @@ -25,6 +32,7 @@ def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limi Returns ------- + none """ @@ -45,14 +53,16 @@ def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limi # Determine the bead indices to reduce the total represented to n_max if limit_n True - if n_max >= numresidues: - limit_n = False - - if limit_n: - if max_method == 'mid_slice': - ind_save, connect_left, connect_right = find_ind_mid_slice(r_poly, n_max, ring) + if not ind_save.size == 0: + connect_left, connect_right = find_connect(ind_save, ring) else: - ind_save, connect_left, connect_right = find_ind_total(r_poly, ring) + if n_max >= numresidues: + limit_n = False + if limit_n: + if max_method == 'mid_slice': + ind_save, connect_left, connect_right = find_ind_mid_slice(r_poly, n_max, ring) + else: + ind_save, connect_left, connect_right = find_ind_total(r_poly, ring) # Write the preamble to the pymol file @@ -79,7 +89,7 @@ def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limi atomname = 'AN' chain = 'B' r_com = np.mean(r_poly, axis = 0) - if add_nucleus: + if add_com: f.write('ATOM%7d %4s %3s %1s %8.3f%8.3f%8.3f%6.2f%6.2f C\n' % (count + 1, atomname, resname, chain, r_com[0], r_com[1], r_com[2], 1.00, 1.00)) @@ -103,8 +113,8 @@ def gen_pymol_file(r_poly, meth_seq = np.array([]), hp1_seq = np.array([]), limi f.write('CONECT%5d%5d\n' % (count + 1, ind_left + 1)) elif connect_left[ind] == 0 and connect_right[ind] == 1: f.write('CONECT%5d%5d\n' % (count + 1, ind_right + 1)) -# elif connect_left[ind] == 0 and connect_right[ind] == 0: -# f.write('CONECT%5d\n' % (count + 1)) + elif connect_left[ind] == 0 and connect_right[ind] == 0: + f.write('CONECT%5d\n' % (count + 1)) count += 1 # Close the file @@ -122,33 +132,17 @@ def find_ind_mid_slice(r_poly, n_max, ring): # Find the value of the x-coordinate and sort the beads according to distance from mean x_ave = np.mean(r_poly[:, 0]) delta_x = r_poly[:, 0] - x_ave - ind_sort = np.argsort(np.abs(delta_x)) +# ind_sort = np.argsort(np.abs(delta_x)) + ind_sort = np.argsort(-delta_x) # Select the first n_max beads based on distance from the mean ind_save = np.zeros(len(r_poly[:, 0])) - connect_left = np.zeros(len(r_poly[:, 0])) - connect_right = np.zeros(len(r_poly[:, 0])) for ind in range(n_max): ind_save[ind_sort[ind]] = 1 # Determine whether adjacent beads are saved to define connections - for ind in range(n_max): - if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] - 1] == 1): - connect_left[ind_sort[ind]] = 1 - if ind_sort[ind] == (len(r_poly[:, 0]) - 1): - if (ind_save[ind_sort[ind]] == 1) and (ind_save[0] == 1): - connect_right[ind_sort[ind]] = 1 - else: - if (ind_save[ind_sort[ind]] == 1) and (ind_save[ind_sort[ind] + 1] == 1): - connect_right[ind_sort[ind]] = 1 - - # Remove the end connections if ring is false - if not ring: - connect_left[0] = 0 - - if not ring: - connect_right[-1] = 0 + connect_left, connect_right = find_connect(ind_save, ring) return ind_save, connect_left, connect_right @@ -159,17 +153,37 @@ def find_ind_total(r_poly, ring): """ ind_save = np.ones(len(r_poly[:, 0])) - connect_left = np.ones(len(r_poly[:, 0])) - connect_right = np.ones(len(r_poly[:, 0])) + connect_left, connect_right = find_connect(ind_save, ring) - if ring: - connect_left[0] = 1 - else: + return ind_save, connect_left, connect_right + + +def find_connect(ind_save, ring): + r""" + + + """ + connect_left = np.zeros(len(ind_save)) + connect_right = np.zeros(len(ind_save)) + + for ind in range(len(ind_save)): + if ind_save[ind] * ind_save[ind - 1] == 1: + connect_left[ind] = 1 + + if ind == (len(ind_save) - 1): + if ind_save[ind] * ind_save[0] == 1: + connect_right[ind] = 1 + else: + if ind_save[ind] * ind_save[ind + 1] == 1: + connect_right[ind] = 1 + + # Remove end connection if ring False + + if not ring: connect_left[0] = 0 - if ring: - connect_right[-1] = 1 - else: + if not ring: connect_right[-1] = 0 - return ind_save, connect_left, connect_right + return connect_left, connect_right +