def mean_std_to_distribution_params(distribution, mu, std=1.0):

    if np.any(std <= 0.0):
        raise_value_error("Standard deviation std = " + str(std) + " <= 0!")

    std_check = {
        "exponential": lambda mu: mu,
        "poisson": lambda mu: np.sqrt(mu),
        "chisquare": lambda mu: np.sqrt(2.0 * mu),
        "bernoulli": lambda mu: np.sqrt(mu * (1.0 - mu))
    }
    if np.in1d(distribution,
               ["exponential", "poisson", "chisquare", "bernoulli"]):
        std_check = std_check[distribution](mu)
        if std != std_check:
            msg = "\nmu = " + str(mu) + "\nstd = " + str(
                std) + "\nstd should be = " + str(std_check)
            warning(
                msg +
                "\nStandard deviation constraint not satisfied for distribution "
                + distribution + "!)")

    p = distrib_dict[distribution]["from_mu_std"](mu, std)

    if distrib_dict[distribution]["constraint"](p):
        return p

    else:
        for key, val in p.iteritems():
            logger.info("\n" + str(key) + ": " + str(val))
        raise_value_error("\nDistribution parameters'constraints " +
                          distrib_dict[distribution]["constraint_str"] +
                          " is not met!")
Exemple #2
0
 def read_t1(self, path):
     if os.path.isfile(path):
         tvb_t1 = structural.StructuralMRI.from_file(path)
         return tvb_t1.array_data
     else:
         warning("\nNo Structural MRI file found at path " + path + "!")
         return []
Exemple #3
0
    def write_to_h5(self, folder_name, file_name):
        """
        Store H5Model object to a hdf5 file
        """
        final_path, overwrite = change_filename_or_overwrite(
            folder_name, file_name)
        # final_path = ensure_unique_file(folder_name, file_name)

        if overwrite:
            try:
                os.remove(final_path)
            except:
                warning("\nFile to overwrite not found!")

        logger.info("Writing %s at: %s" % (self, final_path))

        h5_file = h5py.File(final_path, 'a', libver='latest')

        for attribute, field in self.datasets_dict.iteritems():
            h5_file.create_dataset("/" + attribute, data=field)

        for meta, val in self.metadata_dict.iteritems():
            h5_file.attrs.create(meta, val)

        h5_file.close()
def write_sensors(labels,
                  locations,
                  folder=os.path.dirname(PATIENT_VIRTUAL_HEAD),
                  file_name=None,
                  logger=logger):
    """
    Store Sensors in a file to be shared by multiple patient virtualizations (heads)
    """
    if file_name is None:
        file_name = "SensorsSEEG_" + str(len(labels)) + ".h5"

    path, overwrite = change_filename_or_overwrite(folder, file_name)

    if overwrite:
        try:
            os.remove(path)
        except:
            warning("\nFile to overwrite not found!")

    logger.info("Writing Sensors at:\n" + path)
    h5_file = h5py.File(path, 'a', libver='latest')

    write_metadata({
        KEY_TYPE: "SeegSensors",
        KEY_SENSORS: len(labels)
    }, h5_file, KEY_DATE, KEY_VERSION)
    h5_file.create_dataset("/labels", data=labels)
    h5_file.create_dataset("/locations", data=locations)
    h5_file.close()
Exemple #5
0
 def read_volume_mapping(self, path):
     if os.path.isfile(path):
         tvb_vm = region_mapping.RegionVolumeMapping.from_file(path)
         return tvb_vm.array_data
     else:
         warning("\nNo Volume Mapping file found at path " + path + "!")
         return []
Exemple #6
0
 def read_cortical_surface(self, path):
     if os.path.isfile(path):
         tvb_srf = surfaces.CorticalSurface.from_file(path)
         return Surface(tvb_srf.vertices, tvb_srf.triangles,
                        tvb_srf.vertex_normals, tvb_srf.triangle_normals)
     else:
         warning("\nNo Cortical Surface file found at path " + path + "!")
         return []
Exemple #7
0
 def read_projection(self, path, s_type):
     if os.path.isfile(path):
         if s_type == Sensors.TYPE_EEG:
             tvb_prj = projections.ProjectionSurfaceEEG.from_file(path)
         elif s_type == Sensors.TYPE_MEG:
             tvb_prj = projections.ProjectionSurfaceMEG.from_file(path)
         else:
             tvb_prj = projections.ProjectionSurfaceSEEG.from_file(path)
         return tvb_prj.projection_data
     else:
         warning("\nNo Projection Matrix file found at path " + path + "!")
         return []
 def read_cortical_surface(self, h5_path):
     if os.path.isfile(h5_path):
         self.logger.info("Reading Surface from " + h5_path)
         h5_file = h5py.File(h5_path, 'r', libver='latest')
         vertices = h5_file['/vertices'][()]
         triangles = h5_file['/triangles'][()]
         vertex_normals = h5_file['/vertex_normals'][()]
         h5_file.close()
         return Surface(vertices, triangles, vertex_normals)
     else:
         warning("\nNo Cortical Surface file found at path " + h5_path +
                 "!")
         return []
Exemple #9
0
 def read_sensors(self, path, s_type):
     if os.path.isfile(path):
         if s_type == Sensors.TYPE_EEG:
             tvb_sensors = sensors.SensorsEEG.from_file(path)
         elif s_type == Sensors.TYPE_MEG:
             tvb_sensors = sensors.SensorsMEG.from_file(path)
         else:
             tvb_sensors = sensors.SensorsInternal.from_file(path)
         return Sensors(tvb_sensors.labels, tvb_sensors.locations,
                        tvb_sensors.orientations, s_type)
     else:
         warning("\nNo Sensor file found at path " + path + "!")
         return []
    def read_sensors(self, h5_path, s_type):
        if os.path.isfile(h5_path):
            self.logger.info("Reading Sensors from: " + h5_path)
            h5_file = h5py.File(h5_path, 'r', libver='latest')

            labels = h5_file['/labels'][()]
            locations = h5_file['/locations'][()]

            h5_file.close()
            return Sensors(labels, locations, s_type=s_type)
        else:
            warning("\nNo Sensor file found at path " + h5_path + "!")
            return None
 def __init__(self,
              number_of_regions,
              x0_values=X0_DEF,
              e_values=E_DEF,
              yc=YC_DEF,
              Iext1=I_EXT1_DEF,
              Iext2=I_EXT2_DEF,
              K=K_DEF,
              a=A_DEF,
              b=B_DEF,
              d=D_DEF,
              slope=SLOPE_DEF,
              s=S_DEF,
              gamma=GAMMA_DEF,
              zmode=numpy.array("lin"),
              x1eq_mode="optimize"):
     self.number_of_regions = number_of_regions
     self.x0_values = x0_values * numpy.ones(
         (self.number_of_regions, ), dtype=numpy.float32)
     self.yc = yc
     self.Iext1 = Iext1
     self.Iext2 = Iext2
     self.a = a
     self.b = b
     self.d = d
     self.slope = slope
     self.s = s
     self.gamma = gamma
     self.zmode = zmode
     self.x1eq_mode = x1eq_mode
     if len(ensure_list(K)) == 1:
         self.K_unscaled = numpy.array(K) * numpy.ones(
             (self.number_of_regions, ), dtype=numpy.float32)
     elif len(ensure_list(K)) == self.number_of_regions:
         self.K_unscaled = numpy.array(K)
     else:
         warning(
             "The length of input global coupling K is neither 1 nor equal to the number of regions!"
             +
             "\nSetting model_configuration_service.K_unscaled = K_DEF for all regions"
         )
     self.K = None
     self._normalize_global_coupling()
     self.e_values = e_values * numpy.ones(
         (self.number_of_regions, ), dtype=numpy.float32)
     self.x0cr = 0.0
     self.rx0 = 0.0
     self._compute_critical_x0_scaling()
Exemple #12
0
 def read_sensors_projections(self, root_folder, conn, sensor_files,
                              s_type):
     sensors_dict = {}
     for sensor_file in ensure_list(sensor_files):
         sensor = self.read_sensors(
             os.path.join(root_folder, sensor_file[0]), s_type)
         if isinstance(sensor, Sensors):
             projection = self.read_projection(
                 os.path.join(root_folder, sensor_file[1]), s_type)
             if projection == []:
                 warning(
                     "Calculating projection matrix based solely on euclidean distance!"
                 )
                 projection = sensor.calculate_projection(conn)
             sensors_dict[sensor] = projection
     return sensors_dict
Exemple #13
0
    def prepare_epileptor_model_for_json(self, no_regions=88):
        epileptor_params_list = []

        warning("No of regions is " + str(no_regions))
        for idx in xrange(no_regions):
            epileptor_params_list.append(
                EpileptorParams(self.model.a[idx], self.model.b[idx],
                                self.model.c[idx], self.model.d[idx],
                                self.model.aa[idx], self.model.r[idx],
                                self.model.Kvf[idx], self.model.Kf[idx],
                                self.model.Ks[idx], self.model.tau[idx],
                                self.model.Iext[idx], self.model.Iext2[idx],
                                self.model.slope[idx], self.model.x0[idx],
                                self.model.tt[idx]))

        return epileptor_params_list
Exemple #14
0
    def launch_simulation(self, n_report_blocks=0):
        opts = "java -Dncsa.hdf.hdf5lib.H5.hdf5lib=" + os.path.join(LIB_PATH, HDF5_LIB) + " " + \
               "-Djava.library.path=" + LIB_PATH + " " + "-cp" + " " + JAR_PATH + " " + \
               JAVA_MAIN_SIM + " " + os.path.abspath(self.json_config_path) + " " + os.path.abspath(self.head_path)

        try:
            status = subprocess.call(opts, shell=True)
            print(status)

        except:
            status = False
            warning("Something went wrong with this simulation...")

        time, data = read_ts(os.path.join(self.head_path, "full-configuration",
                                          "ts.h5"),
                             data="data")
        return time, data, status
Exemple #15
0
    def run_pse(self, connectivity_matrix, grid_mode=False, **kwargs):

        results = []
        execution_status = []

        loop_tenth = 1
        for iloop in range(self.n_loops):

            params = self.pse_params[iloop, :]

            if iloop == 0 or iloop + 1 >= loop_tenth * self.n_loops / 10.0:
                print "\nExecuting loop " + str(iloop + 1) + " of " + str(
                    self.n_loops)
                if iloop > 0:
                    loop_tenth += 1
            # print "\nParameters:"
            # for ii in range(len(params)):
            #      print self.params_paths[ii] + "[" + str(self.params_indices[ii]) + "] = " + str(params[ii])

            status = False
            output = None

            try:
                status, output = self.run_fun(self.pse_object,
                                              connectivity_matrix,
                                              self.params_paths, params,
                                              self.params_indices,
                                              self.out_fun, **kwargs)

            except:
                pass

            if not status:
                warning("\nExecution of loop " + str(iloop) + " failed!")

            results.append(output)
            execution_status.append(status)

        if grid_mode:
            results = np.reshape(np.array(results, dtype="O"),
                                 tuple(self.n_params_vals))
            execution_status = np.reshape(np.array(execution_status),
                                          tuple(self.n_params_vals))

        return results, execution_status
    def launch_simulation(self, n_report_blocks=1):

        self.simTVB._configure_history(
            initial_conditions=self.simTVB.initial_conditions)

        status = True

        if n_report_blocks < 2:
            try:
                tavg_time, tavg_data = self.simTVB.run()[0]

            except Exception, error_message:
                status = False
                warning("Something went wrong with this simulation...:" +
                        "\n" + error_message)
                return None, None, status

            return tavg_time, tavg_data, status
    def __init__(self,
                 n_samples=10,
                 n_outputs=1,
                 sampler="uniform",
                 trunc_limits={},
                 sampling_module="numpy",
                 random_seed=None,
                 **kwargs):

        super(StochasticSamplingService, self).__init__(n_samples, n_outputs)

        self.random_seed = random_seed
        self.params = kwargs
        self._list_params()
        self.trunc_limits = trunc_limits
        sampling_module = sampling_module.lower()

        self.sampler = sampler

        if len(self.trunc_limits) > 0:

            self.trunc_limits = dicts_of_lists(self.trunc_limits,
                                               self.n_outputs)

            # We use inverse transform sampling for truncated distributions...

            if sampling_module is not "scipy":
                warning("\nSelecting scipy module for truncated distributions")

            self.sampling_module = "scipy.stats." + sampler + " inverse transform sampling"

        elif sampling_module == "scipy":
            self.sampling_module = "scipy.stats." + self.sampler + ".rvs"

        elif sampling_module == "numpy":
            self.sampling_module = "numpy.random." + self.sampler

        elif sampling_module == "salib":
            self.sampling_module = "SALib.sample." + self.sampler + ".sample"

        else:
            raise_value_error("Sampler module " + str(sampling_module) +
                              " is not recognized!")
def write_epileptogenicity_hypothesis(ep_vector,
                                      folder_path=PATIENT_VIRTUAL_HEAD,
                                      folder_name=None,
                                      file_name=None,
                                      logger=logger):
    """
    Store X0 values to be used when launching simulations
    """

    if file_name is None:
        file_name = "ep"

    if folder_name is None:
        folder_name = file_name

    path, overwrite = change_filename_or_overwrite(
        os.path.join(folder_path, folder_name), file_name + ".h5")

    if overwrite:
        try:
            os.remove(path)
        except:
            warning("\nFile to overwrite not found!")

    os.makedirs(os.path.dirname(path))

    logger.info("Writing an Epileptogenicity at:\n" + path)

    h5_file = h5py.File(path, 'a', libver='latest')

    write_metadata(
        {
            KEY_TYPE: "EpileptogenicityModel",
            KEY_NODES: ep_vector.shape[0]
        }, h5_file, KEY_DATE, KEY_VERSION)
    h5_file.create_dataset("/values", data=ep_vector)
    h5_file.close()
    def _compute_jacobian(self, model_configuration):

        # Check if any of the equilibria are in the supercritical regime (beyond the separatrix) and set it right before
        # the bifurcation.
        zEQ = model_configuration.zEQ
        temp = model_configuration.x1EQ > X1_EQ_CR_DEF - 10**(-3)
        if temp.any():
            correction_value = X1_EQ_CR_DEF - 10**(-3)
            warning(
                "Equibria x1EQ[" + str(numpy.where(temp)[0]) + "]  = " +
                str(model_configuration.x1EQ[temp]) +
                "\nwere corrected for LSA to value: X1_EQ_CR_DEF - 10 ** (-3) = "
                + str(correction_value) + " to be sub-critical!")
            model_configuration.x1EQ[temp] = correction_value
            i_temp = numpy.ones(model_configuration.x1EQ.shape)
            zEQ[temp] = calc_eq_z(model_configuration.x1EQ[temp],
                                  model_configuration.yc * i_temp[temp],
                                  model_configuration.Iext1 * i_temp[temp],
                                  "2d", 0.0,
                                  model_configuration.slope * i_temp[temp],
                                  model_configuration.a * i_temp[temp],
                                  model_configuration.b * i_temp[temp],
                                  model_configuration.d * i_temp[temp])

        fz_jacobian = calc_fz_jac_square_taylor(
            model_configuration.zEQ, model_configuration.yc,
            model_configuration.Iext1, model_configuration.K,
            model_configuration.connectivity_matrix, model_configuration.a,
            model_configuration.b, model_configuration.d)

        if numpy.any([
                numpy.any(numpy.isnan(fz_jacobian.flatten())),
                numpy.any(numpy.isinf(fz_jacobian.flatten()))
        ]):
            raise_value_error("nan or inf values in dfz")

        return fz_jacobian
Exemple #20
0
def build_hierarchical_object_recursively(obj,
                                          key,
                                          value,
                                          children_dict=class_dict):

    if isinstance(obj, dict):
        set_field = lambda obj, key, value: obj.update({key: value})
        get_field = lambda obj, key: obj.get(key, None)

    elif isinstance(obj, list):
        set_field = lambda obj, key, value: set_list_item_by_reference_safely(
            int(key), value, obj)
        get_field = lambda obj, key: get_list_or_tuple_item_safely(obj, key)

    else:
        set_field = lambda obj, attribute, value: setattr(
            obj, attribute, value)
        get_field = lambda obj, attribute: getattr(obj, attribute, None)

    # Check whether value is an inf, nan, None, bool, or empty list/dict/tuple/str value
    try:
        bool_inf_nan_empty_value = bool_inf_nan_empty.get(
            value, "skip_bool_inf_nan_empty_value")
        if bool_inf_nan_empty_value != "skip_bool_inf_nan_empty_value":
            set_field(obj, key, bool_inf_nan_empty_value)
            return
    except:
        pass

    child_object = get_field(obj, key)
    if child_object is not None:
        set_field(obj, key, value)

    else:

        this_name = key.split('/', 1)[0]
        split_name = this_name.split('#')
        if len(split_name) == 2:
            name = split_name[0]
            class_name = split_name[1]
        else:
            class_name = ""
            name = this_name

        try:

            # value is not a container object, or it is an empty container object
            if this_name == key:
                # just assign it:
                if np.in1d(class_name, ["tuple", "list"]) and isinstance(
                        value, np.ndarray):
                    value = value.tolist()
                    if class_name == "tuple":
                        value = tuple(value)
                set_field(obj, name, value)
                return 1

            else:
                child_key = key.split('/', 1)[1]
                child_object = deepcopy(get_field(obj, name))
                # Check if it exists already:
                if child_object is None:
                    # and create it if not:
                    for class_type, class_instance in children_dict.iteritems(
                    ):
                        if class_name == class_type:
                            child_object = class_instance
                    if isinstance(child_object, (list, tuple)):
                        # if it is a list or tuple...
                        grandchild_name = child_key.split('/', 1)[0]
                        # but its own children names are not strings of integers:
                        if not (grandchild_name.isdigit()):
                            # convert to a dict
                            child_object = list_or_tuple_to_dict(child_object)
                        # if it is a tuple...
                        if isinstance(child_object, tuple):
                            # ...convert to list that is mutable
                            child_object = list(child_object)
                # If still not created, make a dict() by default:
                if child_object is None:
                    logger.warning(
                        "\n Child object " + str(name) +
                        " still not created! Creating an Ordereddict() by default!"
                    )
                    child_object = OrderedDict()
                # ...and continue to further specify it...
                children_dict.update(getattr(child_object, "children_dict",
                                             {}))
                build_hierarchical_object_recursively(child_object, child_key,
                                                      value, children_dict)
                if class_name == "tuple":
                    child_object = tuple(child_object)
                set_field(obj, name, child_object)
        except:
            warning("Failed to set attribute " + str(key) + " of object " +
                    obj.__class__.__name__ + "!")
def assert_equilibrium_point(epileptor_model, weights, equilibrium_point):

    n_dim = equilibrium_point.shape[0]

    if epileptor_model._ui_name == "EpileptorDP2D":
        # We use the opposite sign for K with respect to all epileptor models
        K = -epileptor_model.K
        dfun2 = calc_dfun(equilibrium_point[0].flatten(), equilibrium_point[1].flatten(),
                          epileptor_model.yc.flatten(), epileptor_model.Iext1.flatten(), epileptor_model.x0.flatten(),
                          K.flatten(), weights, model_vars=n_dim, zmode=epileptor_model.zmode,
                          slope=epileptor_model.slope.flatten(), a=epileptor_model.a.flatten(),
                          b=epileptor_model.b.flatten(), d=epileptor_model.d.flatten(),
                          tau1=epileptor_model.tau1, tau0=epileptor_model.tau0, output_mode="array")

    elif epileptor_model._ui_name == "EpileptorDP":
        # We use the opposite sign for K with respect to all epileptor models
        K = -epileptor_model.K
        #dfun_max_cr[2] = 10 ** -3
        dfun2 = calc_dfun(equilibrium_point[0].flatten(), equilibrium_point[2].flatten(),
                          epileptor_model.yc.flatten(), epileptor_model.Iext1.flatten(), epileptor_model.x0.flatten(),
                          K.flatten(), weights, model_vars=n_dim, zmode=epileptor_model.zmode,
                          y1=equilibrium_point[1].flatten(), x2=equilibrium_point[3].flatten(),
                          y2=equilibrium_point[4].flatten(), g=equilibrium_point[5].flatten(),
                          slope=epileptor_model.slope.flatten(), a=epileptor_model.a.flatten(),
                          b=epileptor_model.b.flatten(), d=epileptor_model.d.flatten(), s=epileptor_model.s.flatten(),
                          Iext2=epileptor_model.Iext2.flatten(), gamma=epileptor_model.gamma.flatten(),
                          tau1=epileptor_model.tau1, tau0=epileptor_model.tau0, tau2=epileptor_model.tau2,
                          output_mode="array")

    elif epileptor_model._ui_name == "EpileptorDPrealistic":
        # We use the opposite sign for K with respect to all epileptor models
        K = -epileptor_model.K
        #dfun_max_cr[2] = 10 ** -3
        dfun2 = calc_dfun(equilibrium_point[0].flatten(), equilibrium_point[2].flatten(),
                          epileptor_model.yc.flatten(), epileptor_model.Iext1.flatten(), epileptor_model.x0.flatten(),
                          K.flatten(), weights, model_vars=n_dim,
                          zmode=epileptor_model.zmode, pmode=epileptor_model.pmode,
                          y1=equilibrium_point[1].flatten(), x2=equilibrium_point[3].flatten(),
                          y2=equilibrium_point[4].flatten(), g=equilibrium_point[5].flatten(),
                          x0_var=equilibrium_point[6].flatten(), slope_var=equilibrium_point[7].flatten(),
                          Iext1_var=equilibrium_point[8].flatten(), Iext2_var=equilibrium_point[9].flatten(),
                          K_var=equilibrium_point[10].flatten(),
                          slope=epileptor_model.slope.flatten(), a=epileptor_model.a.flatten(),
                          b=epileptor_model.b.flatten(), d=epileptor_model.d.flatten(), s=epileptor_model.s.flatten(),
                          Iext2=epileptor_model.Iext2.flatten(), gamma=epileptor_model.gamma.flatten(),
                          tau1=epileptor_model.tau1, tau0=epileptor_model.tau0, tau2=epileptor_model.tau2,
                          output_mode="array")
    else:
        # all 6D models (tvb, custom)
        # dfun_max_cr[2] = 10 ** -3
        # We use the opposite sign for K with respect to all epileptor models
        K = -epileptor_model.Ks
        dfun2 = calc_dfun(equilibrium_point[0].flatten(), equilibrium_point[2].flatten(),
                          epileptor_model.c, epileptor_model.Iext, epileptor_model.x0,
                          K, weights, model_vars=n_dim,
                          y1=equilibrium_point[1].flatten(), x2=equilibrium_point[3].flatten(),
                          y2=equilibrium_point[4].flatten(), g=equilibrium_point[5].flatten(),
                          slope=epileptor_model.slope, a=epileptor_model.a, b=epileptor_model.b,
                          d=epileptor_model.d, s=epileptor_model.aa, Iext2=epileptor_model.Iext2,
                          tau1=epileptor_model.tt, tau0=1.0 / epileptor_model.r, tau2=epileptor_model.tau,
                          output_mode="array")

    if hasattr(epileptor_model, 'dfun'):
        # We use the opposite sign for K with respect to all epileptor models
        coupl = calc_coupling(equilibrium_point[0], -K, weights)
        coupl = numpy.expand_dims((numpy.c_[coupl, 0.0 * coupl]).T, 2)

        dfun = epileptor_model.dfun(numpy.expand_dims(equilibrium_point, 2).astype('float32'), coupl)
        dfun_max = numpy.max(numpy.abs(dfun.flatten()))
        dfun_max_cr = 10 ** -5 * numpy.ones(dfun_max.shape)

        max_dfun_diff = numpy.max(numpy.abs(dfun2.flatten() - dfun.flatten()))
        if numpy.any(max_dfun_diff > dfun_max_cr):
            warning("\nmodel dfun and calc_dfun functions do not return the same results!\n"
                    + "maximum difference = " + str(max_dfun_diff))
                  # + "\n" + "model dfun = " + str(dfun) + "\n"
                  # + "calc_dfun = " + str(dfun2))
    else:
        dfun_max = numpy.max(numpy.abs(dfun2.flatten()))
        dfun_max_cr = 10 ** -5 * numpy.ones(dfun_max.shape)

    if numpy.any(dfun_max > dfun_max_cr):
        # raise_value_error("Equilibrium point for initial condition not accurate enough!\n" \
        #                  + "max(dfun) = " + str(dfun_max))
        ##                  + "\n" + "model dfun = " + str(dfun))
        warning("\nEquilibrium point for initial condition not accurate enough!\n"
                 + "max(dfun) = " + str(dfun_max))
def calc_eq_x2(Iext2, y2eq=None, zeq=None, geq=None, x1eq=None, y1eq=None, Iext1=None, x2=0.0,
               slope=SLOPE_DEF, a=A_DEF, b=B_DEF, d=D_DEF, x1_neg=True, s=S_DEF, x2_neg=True):

    if geq is None:
        geq = calc_eq_g(x1eq)

    if zeq is None:
        zeq = calc_eq_z(x1eq, y1eq, Iext1, "6d", x2, slope, a, b, d, x1_neg)

    zeq, geq, Iext2, s = assert_arrays([zeq, geq, Iext2, s])

    shape = zeq.shape
    n = zeq.size

    zeq, geq, Iext2, s = assert_arrays([zeq, geq, Iext2, s], (n,))

    if SYMBOLIC_CALCULATIONS_FLAG:

        fx2y2, v = symbol_eqtn_fx2y2(n, x2_neg)[1:]
        fx2y2 = fx2y2.tolist()

        x2eq = []
        for iv in range(n):
            fx2y2[iv] = fx2y2[iv].subs([(v["z"][iv], zeq[iv]), (v["g"][iv], geq[iv]), (v["Iext2"][iv], Iext2[iv]),
                                      (v["s"][iv], s[iv]), (v["tau1"][iv], 1.0)])
            fx2y2[iv] = list(solveset(fx2y2[iv], v["x2"][iv], S.Reals))
            x2eq.append(numpy.min(numpy.array(fx2y2[iv], dtype=zeq.dtype)))

    else:

        # fx2 = tau1 * (-y2 + Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05)
        # if x2_neg = True, so that y2eq = 0.0:
        #   fx2 = tau1 * (Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05) =>
        #     0 = x2eq ** 3 - x2eq - (Iext2 + 2 * geq -0.3 * zeq + 1.05)
        # if x2_neg = False , so that y2eq = s*(x2+0.25):
        #   fx2 = tau1 * (-s * (x2 + 0.25) + Iext2 + 2 * g - x2 ** 3 + x2 - 0.3 * z + 1.05) =>
        #   fx2 = tau1 * (-0.25 * s  + Iext2 + 2 * g - x2 ** 3 + (1 - s) * x2 - 0.3 * z + 1.05 =>
        #     0 = x2eq ** 3 + (s - 1) * x2eq - (Iext2 + 2 * geq -0.3 * zeq - 0.25 * s + 1.05)

        # According to http://mathworld.wolfram.com/CubicFormula.html
        # and given that there is no square term (x2eq^2; "depressed cubic"), we write the equation in the form:
        # x^3 + 3 * Q * x -2 * R = 0
        Q = (-numpy.ones((n, ))/3.0)
        R = ((Iext2 + 2.0 * geq - 0.3 * zeq + 1.05) / 2)
        if y2eq is None:
            ss = numpy.where(x2_neg, 0.0, s)
            Q += ss / 3
            R -= 0.25 * ss / 2
        else:
            y2eq = (assert_arrays([y2eq], (n, )))
            R += y2eq / 2

        # Then the determinant is :
        # delta = Q^3 + R^2 =>
        delta = Q ** 3 + R ** 2
        # and S = cubic_root(R+sqrt(D), T = cubic_root(R-sqrt(D)
        delta_sq = numpy.sqrt(delta.astype("complex")).astype("complex")
        ST = [R + delta_sq, R - delta_sq]
        for ii in range(2):
            for iv in range(n):
                if numpy.imag(ST[ii][iv]) == 0.0:
                    ST[ii][iv] = numpy.sign(ST[ii][iv]) * numpy.power(numpy.abs(ST[ii][iv]), 1.0/3)
                else:
                    ST[ii][iv] = numpy.power(ST[ii][iv], 1.0 / 3)
        # and B = S+T, A = S-T
        B = ST[0]+ST[1]
        A = ST[0]-ST[1]
        # The roots then are:
        # x1 = -1/3 * a2 + B
        # x21 = -1/3 * a2 - 1/2 * B + 1/2 * sqrt(3) * A * j
        # x22 = -1/3 * a2 - 1/2 * B - 1/2 * sqrt(3) * A * j
        # where j = sqrt(-1)
        # But, in our case a2 = 0.0, so that:
        B2 = - 0.5 *B
        AA = (0.5 * numpy.sqrt(3.0) * A * 1j)
        sol = numpy.concatenate([[B.flatten()], [B2 + AA], [B2 - AA]]).T
        x2eq = []
        for ii in range(delta.size):
            temp = sol[ii, numpy.abs(numpy.imag(sol[ii])) < 10 ** (-6)]
            if temp.size == 0:
                raise_value_error("No real roots for x2eq_" + str(ii))
            else:
                x2eq.append(numpy.min(numpy.real(temp)))

        # zeq = zeq.flatten()
        # geq = geq.flatten()
        # Iext2 = Iext2.flatten()
        # x2eq = []
        # for ii in range(n):
        #
        #     if y2eq is None:
        #
        #         fx2 = lambda x2: calc_fx2(x2, y2=calc_eq_y2(x2, x2_neg=x2_neg), z=zeq[ii], g=geq[ii],
        #                                   Iext2=Iext2[ii], tau1=1.0)
        #
        #         jac = lambda x2: -3 * x2 ** 2 + 1.0 - numpy.where(x2_neg, 0.0, -s)
        #
        #     else:
        #
        #         fx2 = lambda x2: calc_fx2(x2, y2=0.0, z=zeq[ii], g=geq[ii], Iext2=Iext2[ii], tau1=1.0)
        #         jac = lambda x2: -3 * x2 ** 2 + 1.0
        #
        #     sol = root(fx2, -0.5, method='lm', jac=jac, tol=10 ** (-6), callback=None, options=None)
        #
        #     if sol.success:
        #
        #         if numpy.any([numpy.any(numpy.isnan(sol.x)), numpy.any(numpy.isinf(sol.x))]):
        #             raise_value_error("nan or inf values in solution x\n" + sol.message)
        #
        #         x2eq.append(numpy.min(numpy.real(numpy.array(sol.x))))
        #
        #     else:
        #         raise_value_error(sol.message)

    if numpy.array(x2_neg).size == 1:
        x2_neg = numpy.tile(x2_neg, (n, ))

    for iv in range(n):

        if x2_neg[iv] == False and x2eq[iv] < -0.25:
            warning("\nx2eq["+str(iv)+"] = " + str(x2eq[iv]) + " < -0.25, although x2_neg[" + str(iv)+"] = False!" +
                    "\n" + "Rerunning with x2_neg[" + str(iv)+"] = True...")
            temp, _ = calc_eq_x2(Iext2[iv], zeq=zeq[iv], geq=geq[iv], s=s[iv], x2_neg=True)
            if temp < -0.25:
                x2eq[iv] = temp
                x2_neg[iv] = True
            else:
                warning("\nThe value of x2eq returned after rerunning with x2_neg[" + str(iv)+"] = True, " +
                        "is " + str(temp) + ">= -0.25!" +
                        "\n" + "We will use the original x2eq!")

        if x2_neg[iv] == True and x2eq[iv] > -0.25:
            warning("\nx2eq["+str(iv)+"] = " + str(x2eq[iv]) + " > -0.25, although x2_neg[" + str(iv)+"] = True!" +
                    "\n" + "Rerunning with x2_neg[" + str(iv)+"] = False...")
            temp, _ = calc_eq_x2(Iext2[iv], zeq=zeq[iv], geq=geq[iv], s=s[iv], x2_neg=False)
            if temp > -0.25:
                x2eq[iv] = temp
                x2_neg[iv] = True
            else:
                warning("\nThe value of x2eq returned after rerunning with x2_neg[" + str(iv)+"] = False, " +
                        "is " + str(temp) + "=< -0.25!" +
                        "\n" + "We will use the original x2eq!")

    x2eq = numpy.reshape(x2eq, shape)

    return x2eq, x2_neg
from tvb_epilepsy.base.computations.calculations_utils import calc_x0, calc_fx1, calc_fx1z, calc_fy1, calc_fz, calc_fg,\
                                                  calc_coupling, calc_dfun, calc_fx1z_2d_x1neg_zpos_jac, calc_fx1z_diff

logger = initialize_logger(__name__)


if SYMBOLIC_CALCULATIONS_FLAG :

    try:
        from sympy import solve, solve_poly_system, solveset, S, lambdify
        from mpmath import re, im
        from tvb_epilepsy.base.computations.symbolic_utils import symbol_vars, symbol_eqtn_fx1z, symbol_eqtn_fx2y2, \
                                                                  symbol_eqtn_fx1z_diff

    except:
        warning("Unable to load sympy. Turning to scipy.optimization.")
        SYMBOLIC_CALCULATIONS_FLAG = False


def def_x1eq(X1_DEF, X1_EQ_CR_DEF, n_regions):
    #The default initial condition for x1 equilibrium search
    return (X1_EQ_CR_DEF + X1_DEF) / 2.0 * numpy.ones((1,n_regions), dtype='float32')


def def_x1lin(X1_DEF, X1_EQ_CR_DEF, n_regions):
    # The point of the linear Taylor expansion
    return (X1_EQ_CR_DEF + X1_DEF) / 2.0 * numpy.ones((1,n_regions), dtype='float32')


def calc_eq_x1(yc, Iext1, x0, K, w, a=A_DEF, b=B_DEF, d=D_DEF, zmode=numpy.array("lin"), model="6d"):
                    if not tavg is None:
                        tavg_time.append(tavg[0][0])
                        tavg_data.append(tavg[0][1])

                    if curr_time_step >= curr_block * block_length:
                        end_block = time.time()
                        # TODO: correct this part to print percentage of simulation at the same line by erasing previous
                        print_this = "\r" + "..." + str(100 * curr_time_step / sim_length) + "% done in " + \
                                     str(end_block - start) + " secs"
                        sys.stdout.write(print_this)
                        sys.stdout.flush()
                        curr_block += 1.0
            except Exception, error_message:
                status = False
                warning("Something went wrong with this simulation...:" +
                        "\n" + error_message)
                return None, None, status

            return numpy.array(tavg_time), numpy.array(tavg_data), status

    def _prepare_for_h5(self):

        attributes_dict = epileptor_model_attributes_dict[self.model._ui_name]
        for attr in attributes_dict:
            p = self.model.x0.shape
            field = getattr(self.model, attributes_dict[attr])
            if isinstance(field, (float, int, long, complex)) \
                    or (isinstance(field, (numpy.ndarray))
                        and numpy.all(str(field.dtype)[1] != numpy.array(["O", "S"])) and field.size == 1):
                setattr(self.model, attributes_dict[attr],
                        field * numpy.ones(p))
def main_fit_sim_hyplsa(stats_model_name="vep_original",
                        EMPIRICAL='',
                        times_on_off=[],
                        channel_lbls=[],
                        channel_inds=[]):

    # ------------------------------Model code--------------------------------------
    # Compile or load model:
    model_file = os.path.join(FOLDER_VEP_HOME,
                              stats_model_name + "_stan_model.pkl")
    if os.path.isfile(model_file):
        stats_model = pickle.load(open(model_file, 'rb'))
    else:
        # vep_original_DP
        if stats_model_name is "vep_dWt":
            model_path = os.path.join(STATISTICAL_MODELS_PATH, "vep_dWt.stan")
        elif stats_model_name is "vep_original_x0":
            model_path = os.path.join(STATISTICAL_MODELS_PATH,
                                      "vep_original_x0.stan")
        else:
            model_path = os.path.join(STATISTICAL_MODELS_PATH,
                                      "vep_original_DP.stan")
        stats_model = compile_model(model_stan_code_path=model_path)
        with open(model_file, 'wb') as f:
            pickle.dump(stats_model, f)

    # -------------------------------Reading data-----------------------------------

    data_folder = os.path.join(DATA_CUSTOM, 'Head')

    reader = Reader()

    logger.info("Reading from: " + data_folder)
    head = reader.read_head(data_folder,
                            seeg_sensors_files=[("SensorsInternal.h5", "")])

    # head.plot()

    if len(channel_inds) > 1:
        channel_inds, _ = get_bipolar_channels(channel_inds, channel_lbls)

    # --------------------------Hypothesis definition-----------------------------------

    n_samples = 100

    # # Manual definition of hypothesis...:
    # x0_indices = [20]
    # x0_values = [0.9]
    # e_indices = [70]
    # e_values = [0.9]
    # disease_values = x0_values + e_values
    # disease_indices = x0_indices + e_indices

    # ...or reading a custom file:
    ep_name = "ep_l_frontal_complex"
    # FOLDER_RES = os.path.join(data_folder, ep_name)
    from tvb_epilepsy.custom.readers_custom import CustomReader

    if not isinstance(reader, CustomReader):
        reader = CustomReader()
    disease_values = reader.read_epileptogenicity(data_folder, name=ep_name)
    disease_indices, = np.where(disease_values > np.min([X0_DEF, E_DEF]))
    disease_values = disease_values[disease_indices]
    inds = np.argsort(disease_values)
    disease_values = disease_values[inds]
    disease_indices = disease_indices[inds]
    x0_indices = [disease_indices[-1]]
    x0_values = [disease_values[-1]]
    e_indices = disease_indices[0:-1].tolist()
    e_values = disease_values[0:-1].tolist()
    disease_indices = list(disease_indices)

    n_x0 = len(x0_indices)
    n_e = len(e_indices)
    n_disease = len(disease_indices)
    all_regions_indices = np.array(range(head.number_of_regions))
    healthy_indices = np.delete(all_regions_indices, disease_indices).tolist()
    n_healthy = len(healthy_indices)

    # This is an example of Excitability Hypothesis:
    hyp_x0 = DiseaseHypothesis(
        head.connectivity.number_of_regions,
        excitability_hypothesis={tuple(disease_indices): disease_values},
        epileptogenicity_hypothesis={},
        connectivity_hypothesis={})

    # This is an example of Mixed Hypothesis:
    hyp_x0_E = DiseaseHypothesis(
        head.connectivity.number_of_regions,
        excitability_hypothesis={tuple(x0_indices): x0_values},
        epileptogenicity_hypothesis={tuple(e_indices): e_values},
        connectivity_hypothesis={})

    hyp_E = DiseaseHypothesis(
        head.connectivity.number_of_regions,
        excitability_hypothesis={},
        epileptogenicity_hypothesis={tuple(disease_indices): disease_values},
        connectivity_hypothesis={})

    hypos = (hyp_x0_E, hyp_x0, hyp_E)
    # --------------------------Simulation preparations-----------------------------------
    tau1 = 0.5
    # TODO: maybe use a custom Monitor class
    fs = 10 * 2048.0 * (
        2 * tau1
    )  # this is the simulation sampling rate that is necessary for the simulation to be stable
    time_length = 50.0 / tau1  # msecs, the final output nominal time length of the simulation
    report_every_n_monitor_steps = 100.0
    (dt, fsAVG, sim_length, monitor_period, n_report_blocks) = \
        set_time_scales(fs=fs, time_length=time_length, scale_fsavg=1,
                        report_every_n_monitor_steps=report_every_n_monitor_steps)

    # Choose model
    # Available models beyond the TVB Epileptor (they all encompass optional variations from the different papers):
    # EpileptorDP: similar to the TVB Epileptor + optional variations,
    # EpileptorDP2D: reduced 2D model, following Proix et all 2014 +optional variations,
    # EpleptorDPrealistic: starting from the TVB Epileptor + optional variations, but:
    #      -x0, Iext1, Iext2, slope and K become noisy state variables,
    #      -Iext2 and slope are coupled to z, g, or z*g in order for spikes to appear before seizure,
    #      -multiplicative correlated noise is also used
    # Optional variations:
    zmode = "lin"  # by default, or "sig" for the sigmoidal expression for the slow z variable in Proix et al. 2014
    pmode = "z"  # by default, "g" or "z*g" for the feedback coupling to Iext2 and slope for EpileptorDPrealistic

    model_name = "EpileptorDP2D"
    if model_name is "EpileptorDP2D":
        spectral_raster_plot = False
        trajectories_plot = True
    else:
        spectral_raster_plot = False  # "lfp"
        trajectories_plot = False
    # We don't want any time delays for the moment
    # head.connectivity.tract_lengths *= TIME_DELAYS_FLAG

    # --------------------------Hypothesis and LSA-----------------------------------

    for hyp in hypos:  #hypotheses:

        logger.info("\n\nRunning hypothesis: " + hyp.name)

        # hyp.write_to_h5(FOLDER_RES, hyp.name + ".h5")

        logger.info("\n\nCreating model configuration...")
        model_configuration_service = ModelConfigurationService(
            hyp.number_of_regions, K=10.0)
        # model_configuration_service.write_to_h5(FOLDER_RES, hyp.name + "_model_config_service.h5")

        if hyp.type == "Epileptogenicity":
            model_configuration = model_configuration_service. \
                configure_model_from_E_hypothesis(hyp, head.connectivity.normalized_weights)
        else:
            model_configuration = model_configuration_service. \
                configure_model_from_hypothesis(hyp, head.connectivity.normalized_weights)
        model_configuration.write_to_h5(FOLDER_RES,
                                        hyp.name + "_ModelConfig.h5")

        # Plot nullclines and equilibria of model configuration
        model_configuration_service.plot_nullclines_eq(
            model_configuration,
            head.connectivity.region_labels,
            special_idx=disease_indices,
            model="6d",
            zmode="lin",
            figure_name=hyp.name + "_Nullclines and equilibria")

        logger.info("\n\nRunning LSA...")
        lsa_service = LSAService(eigen_vectors_number=None,
                                 weighted_eigenvector_sum=True)
        lsa_hypothesis = lsa_service.run_lsa(hyp, model_configuration)

        lsa_hypothesis.write_to_h5(FOLDER_RES, lsa_hypothesis.name + "_LSA.h5")
        lsa_service.write_to_h5(FOLDER_RES,
                                lsa_hypothesis.name + "_LSAConfig.h5")

        lsa_service.plot_lsa(lsa_hypothesis, model_configuration,
                             head.connectivity.region_labels, None)

        # ------------------------------Simulation--------------------------------------
        logger.info("\n\nConfiguring simulation...")
        noise_intensity = 10**-2.8
        sim = setup_simulation_from_model_configuration(
            model_configuration,
            head.connectivity,
            dt,
            sim_length,
            monitor_period,
            model_name,
            zmode=np.array(zmode),
            pmode=np.array(pmode),
            noise_instance=None,
            noise_intensity=noise_intensity,
            monitor_expressions=None)
        sim.model.tau1 = tau1
        sim.model.tau0 = 30.0

        # Integrator and initial conditions initialization.
        # By default initial condition is set right on the equilibrium point.
        sim.config_simulation(initial_conditions=None)

        # convert_to_h5_model(sim.model).write_to_h5(FOLDER_RES, lsa_hypothesis.name + "_sim_model.h5")

        if os.path.isfile(EMPIRICAL):

            observation, time, fs = prepare_seeg_observable(EMPIRICAL,
                                                            times_on_off,
                                                            channel_lbls,
                                                            log_flag=True)
            vois_ts_dict = {"time": time, "signals": observation}
            #
            # prepare_seeg_observable(os.path.join(SEEG_data, 'SZ2_0001.edf'), [15.0, 40.0], channel_lbls)

            # prepare_seeg_observable(os.path.join(SEEG_data, 'SZ5_0001.edf'), [20.0, 45.0], channel_lbls)
        else:

            ts_file = os.path.join(FOLDER_VEP_HOME,
                                   lsa_hypothesis.name + "_ts.mat")
            if os.path.isfile(ts_file):
                logger.info("\n\nLoading previously simulated time series...")
                vois_ts_dict = loadmat(ts_file)
            else:
                logger.info("\n\nSimulating...")
                ttavg, tavg_data, status = sim.launch_simulation(
                    n_report_blocks)

                # convert_to_h5_model(sim.simulation_settings).write_to_h5(FOLDER_RES,
                #                                                          lsa_hypothesis.name + "_sim_settings.h5")

                if not status:
                    warning("\nSimulation failed!")

                else:

                    time = np.array(ttavg, dtype='float32').flatten()

                    output_sampling_time = np.mean(np.diff(time))
                    tavg_data = tavg_data[:, :, :, 0]

                    logger.info("\n\nSimulated signal return shape: %s",
                                tavg_data.shape)
                    logger.info("Time: %s - %s", time[0], time[-1])
                    logger.info("Values: %s - %s", tavg_data.min(),
                                tavg_data.max())

                    # Variables of interest in a dictionary:
                    vois_ts_dict = prepare_vois_ts_dict(
                        VOIS[model_name], tavg_data)
                    vois_ts_dict['time'] = time
                    vois_ts_dict['time_units'] = 'msec'

                    vois_ts_dict = compute_seeg_and_write_ts_h5_file(
                        FOLDER_RES,
                        lsa_hypothesis.name + "_ts.h5",
                        sim.model,
                        vois_ts_dict,
                        output_sampling_time,
                        time_length,
                        hpf_flag=True,
                        hpf_low=10.0,
                        hpf_high=512.0,
                        sensor_dicts_list=[head.sensorsSEEG])

                    # Plot results
                    plot_sim_results(sim.model,
                                     lsa_hypothesis.propagation_indices,
                                     lsa_hypothesis.name,
                                     head,
                                     vois_ts_dict,
                                     head.sensorsSEEG.keys(),
                                     hpf_flag=False,
                                     trajectories_plot=trajectories_plot,
                                     spectral_raster_plot=spectral_raster_plot,
                                     log_scale=True)

                    # Optionally save results in mat files
                    savemat(
                        os.path.join(FOLDER_RES,
                                     lsa_hypothesis.name + "_ts.mat"),
                        vois_ts_dict)

        # Get data and observation signals:
        data, active_regions = prepare_data_for_fitting_vep(
            stats_model_name,
            model_configuration,
            lsa_hypothesis,
            fsAVG,
            vois_ts_dict,
            sim.model,
            noise_intensity,
            active_regions=None,
            active_regions_th=0.1,
            euler_method=1,
            observation_model=1,
            channel_inds=channel_inds,
            mixing=head.sensorsSEEG.values()[0])
        savemat(
            os.path.join(FOLDER_RES, lsa_hypothesis.name + "_fit_data.mat"),
            data)

        # Fit and get estimates:
        est, fit = stanfit_model(stats_model,
                                 data,
                                 mode="optimizing",
                                 iter=30000)  #
        savemat(os.path.join(FOLDER_RES, lsa_hypothesis.name + "_fit_est.mat"),
                est)

        plot_fit_results(lsa_hypothesis.name,
                         head,
                         est,
                         data,
                         active_regions,
                         time=vois_ts_dict['time'],
                         seizure_indices=[0, 1],
                         trajectories_plot=True)

        # Reconfigure model after fitting:
        fit_model_configuration_service = ModelConfigurationService(
            hyp.number_of_regions, K=est['K'] * hyp.number_of_regions)

        x0_values_fit = fit_model_configuration_service._compute_x0_values_from_x0_model(
            est['x0'])
        disease_indices = active_regions.tolist()
        hyp_fit = DiseaseHypothesis(
            head.connectivity.number_of_regions,
            excitability_hypothesis={tuple(disease_indices): x0_values_fit},
            epileptogenicity_hypothesis={},
            connectivity_hypothesis={},
            name='fit_' + hyp_x0.name)

        connectivity_matrix_fit = np.array(
            model_configuration.connectivity_matrix)
        connectivity_matrix_fit[active_regions][:, active_regions] = est["FC"]
        model_configuration_fit = fit_model_configuration_service.configure_model_from_hypothesis(
            hyp_fit, connectivity_matrix_fit)
        model_configuration_fit.write_to_h5(FOLDER_RES,
                                            hyp_fit.name + "_ModelConfig.h5")

        # Plot nullclines and equilibria of model configuration
        model_configuration_service.plot_nullclines_eq(
            model_configuration_fit,
            head.connectivity.region_labels,
            special_idx=disease_indices,
            model="6d",
            zmode="lin",
            figure_name=hyp_fit.name + "_Nullclines and equilibria")

        print("Done!")
 def read_projection(self, path, s_type):
     warning("Custom projection matrix reading not implemented yet!")
     return []
 def read_t1(self, h5_path):
     if os.path.isfile(h5_path):
         return self._read_data_field(h5_path)
     else:
         warning("\nNo Structural MRI file found at path " + h5_path + "!")
         return []
 def read_volume_mapping(self, h5_path):
     if os.path.isfile(h5_path):
         return self._read_data_field(h5_path)
     else:
         warning("\nNo Volume Mapping file found at path " + h5_path + "!")
         return []
Exemple #29
0
def main_vep(test_write_read=False,
             pse_flag=PSE_FLAG,
             sa_pse_flag=SA_PSE_FLAG,
             sim_flag=SIM_FLAG):

    logger = initialize_logger(__name__)

    # -------------------------------Reading data-----------------------------------

    data_folder = os.path.join(DATA_CUSTOM, 'Head')

    reader = Reader()

    logger.info("Reading from: " + data_folder)
    head = reader.read_head(data_folder)

    head.plot()

    # --------------------------Hypothesis definition-----------------------------------

    n_samples = 100

    # # Manual definition of hypothesis...:
    # x0_indices = [20]
    # x0_values = [0.9]
    # e_indices = [70]
    # e_values = [0.9]
    # disease_values = x0_values + e_values
    # disease_indices = x0_indices + e_indices

    # ...or reading a custom file:
    ep_name = "ep_test1"
    #FOLDER_RES = os.path.join(data_folder, ep_name)
    from tvb_epilepsy.custom.readers_custom import CustomReader

    if not isinstance(reader, CustomReader):
        reader = CustomReader()
    disease_values = reader.read_epileptogenicity(data_folder, name=ep_name)
    disease_indices, = np.where(disease_values > np.min([X0_DEF, E_DEF]))
    disease_values = disease_values[disease_indices]
    if disease_values.size > 1:
        inds_split = np.ceil(disease_values.size * 1.0 / 2).astype("int")
        x0_indices = disease_indices[:inds_split].tolist()
        e_indices = disease_indices[inds_split:].tolist()
        x0_values = disease_values[:inds_split].tolist()
        e_values = disease_values[inds_split:].tolist()
    else:
        x0_indices = disease_indices.tolist()
        x0_values = disease_values.tolist()
        e_indices = []
        e_values = []
    disease_indices = list(disease_indices)

    n_x0 = len(x0_indices)
    n_e = len(e_indices)
    n_disease = len(disease_indices)
    all_regions_indices = np.array(range(head.number_of_regions))
    healthy_indices = np.delete(all_regions_indices, disease_indices).tolist()
    n_healthy = len(healthy_indices)

    # This is an example of Excitability Hypothesis:
    hyp_x0 = DiseaseHypothesis(
        head.connectivity.number_of_regions,
        excitability_hypothesis={tuple(disease_indices): disease_values},
        epileptogenicity_hypothesis={},
        connectivity_hypothesis={})

    # This is an example of Epileptogenicity Hypothesis:
    hyp_E = DiseaseHypothesis(
        head.connectivity.number_of_regions,
        excitability_hypothesis={},
        epileptogenicity_hypothesis={tuple(disease_indices): disease_values},
        connectivity_hypothesis={})

    if len(e_indices) > 0:
        # This is an example of x0_values mixed Excitability and Epileptogenicity Hypothesis:
        hyp_x0_E = DiseaseHypothesis(
            head.connectivity.number_of_regions,
            excitability_hypothesis={tuple(x0_indices): x0_values},
            epileptogenicity_hypothesis={tuple(e_indices): e_values},
            connectivity_hypothesis={})
        hypotheses = (hyp_x0, hyp_E, hyp_x0_E)
    else:
        hypotheses = (hyp_x0, hyp_E)

    # --------------------------Simulation preparations-----------------------------------

    # TODO: maybe use a custom Monitor class
    fs = 2048.0  # this is the simulation sampling rate that is necessary for the simulation to be stable
    time_length = 10000.0  # =100 secs, the final output nominal time length of the simulation
    report_every_n_monitor_steps = 100.0
    (dt, fsAVG, sim_length, monitor_period, n_report_blocks) = \
        set_time_scales(fs=fs, time_length=time_length, scale_fsavg=None,
                        report_every_n_monitor_steps=report_every_n_monitor_steps)

    # Choose model
    # Available models beyond the TVB Epileptor (they all encompass optional variations from the different papers):
    # EpileptorDP: similar to the TVB Epileptor + optional variations,
    # EpileptorDP2D: reduced 2D model, following Proix et all 2014 +optional variations,
    # EpleptorDPrealistic: starting from the TVB Epileptor + optional variations, but:
    #      -x0, Iext1, Iext2, slope and K become noisy state variables,
    #      -Iext2 and slope are coupled to z, g, or z*g in order for spikes to appear before seizure,
    #      -multiplicative correlated noise is also used
    # Optional variations:
    zmode = "lin"  # by default, or "sig" for the sigmoidal expression for the slow z variable in Proix et al. 2014
    pmode = "z"  # by default, "g" or "z*g" for the feedback coupling to Iext2 and slope for EpileptorDPrealistic

    model_name = "EpileptorDPrealistic"
    if model_name is "EpileptorDP2D":
        spectral_raster_plot = False
        trajectories_plot = True
    else:
        spectral_raster_plot = "lfp"
        trajectories_plot = False
    # We don't want any time delays for the moment
    # head.connectivity.tract_lengths *= TIME_DELAYS_FLAG

    # --------------------------Hypothesis and LSA-----------------------------------

    for hyp in hypotheses:

        logger.info("\n\nRunning hypothesis: " + hyp.name)

        # hyp.write_to_h5(FOLDER_RES, hyp.name + ".h5")

        logger.info("\n\nCreating model configuration...")
        model_configuration_service = ModelConfigurationService(
            hyp.number_of_regions)
        model_configuration_service.write_to_h5(
            FOLDER_RES, hyp.name + "_model_config_service.h5")
        if test_write_read:
            logger.info(
                "Written and read model configuration services are identical?: "
                + str(
                    assert_equal_objects(
                        model_configuration_service,
                        read_h5_model(
                            os.path.join(FOLDER_RES, hyp.name +
                                         "_model_config_service.h5")
                        ).convert_from_h5_model(
                            obj=deepcopy(model_configuration_service)),
                        logger=logger)))

        if hyp.type == "Epileptogenicity":
            model_configuration = model_configuration_service.\
                                            configure_model_from_E_hypothesis(hyp, head.connectivity.normalized_weights)
        else:
            model_configuration = model_configuration_service.\
                                              configure_model_from_hypothesis(hyp, head.connectivity.normalized_weights)
        model_configuration.write_to_h5(FOLDER_RES,
                                        hyp.name + "_ModelConfig.h5")
        if test_write_read:
            logger.info(
                "Written and read model configuration are identical?: " + str(
                    assert_equal_objects(
                        model_configuration,
                        read_h5_model(
                            os.path.join(
                                FOLDER_RES, hyp.name +
                                "_ModelConfig.h5")).convert_from_h5_model(
                                    obj=deepcopy(model_configuration)),
                        logger=logger)))

        # Plot nullclines and equilibria of model configuration
        model_configuration_service.plot_nullclines_eq(
            model_configuration,
            head.connectivity.region_labels,
            special_idx=disease_indices,
            model="6d",
            zmode="lin",
            figure_name=hyp.name + "_Nullclines and equilibria")

        logger.info("\n\nRunning LSA...")
        lsa_service = LSAService(eigen_vectors_number=None,
                                 weighted_eigenvector_sum=True)
        lsa_hypothesis = lsa_service.run_lsa(hyp, model_configuration)

        lsa_hypothesis.write_to_h5(FOLDER_RES, lsa_hypothesis.name + "_LSA.h5")
        lsa_service.write_to_h5(FOLDER_RES,
                                lsa_hypothesis.name + "_LSAConfig.h5")
        if test_write_read:

            hypothesis_template = DiseaseHypothesis(hyp.number_of_regions)

            logger.info("Written and read LSA services are identical?: " + str(
                assert_equal_objects(
                    lsa_service,
                    read_h5_model(
                        os.path.join(FOLDER_RES, lsa_hypothesis.name +
                                     "_LSAConfig.h5")).convert_from_h5_model(
                                         obj=deepcopy(lsa_service)),
                    logger=logger)))
            logger.info(
                "Written and read LSA hypotheses are identical (input object check)?: "
                + str(
                    assert_equal_objects(
                        lsa_hypothesis,
                        read_h5_model(
                            os.path.join(FOLDER_RES, lsa_hypothesis.name +
                                         "_LSA.h5")).convert_from_h5_model(
                                             obj=deepcopy(lsa_hypothesis),
                                             hypothesis=True),
                        logger=logger)))
            logger.info(
                "Written and read LSA hypotheses are identical (input template check)?: "
                + str(
                    assert_equal_objects(
                        lsa_hypothesis,
                        read_h5_model(
                            os.path.join(FOLDER_RES, lsa_hypothesis.name +
                                         "_LSA.h5")).convert_from_h5_model(
                                             obj=hypothesis_template,
                                             hypothesis=True),
                        logger=logger)))

        lsa_service.plot_lsa(lsa_hypothesis, model_configuration,
                             head.connectivity.region_labels, None)

        if pse_flag:
            #--------------Parameter Search Exploration (PSE)-------------------------------

            logger.info("\n\nRunning PSE LSA...")
            pse_results = pse_from_lsa_hypothesis(
                lsa_hypothesis,
                head.connectivity.normalized_weights,
                head.connectivity.region_labels,
                n_samples,
                half_range=0.1,
                global_coupling=[{
                    "indices": all_regions_indices
                }],
                healthy_regions_parameters=[{
                    "name": "x0_values",
                    "indices": healthy_indices
                }],
                model_configuration_service=model_configuration_service,
                lsa_service=lsa_service,
                logger=logger)[0]

            lsa_service.plot_lsa(lsa_hypothesis, model_configuration,
                                 head.connectivity.region_labels, pse_results)
            # , show_flag=True, save_flag=False

            convert_to_h5_model(pse_results).write_to_h5(
                FOLDER_RES, lsa_hypothesis.name + "_PSE_LSA_results.h5")
            if test_write_read:
                logger.info(
                    "Written and read sensitivity analysis parameter search results are identical?: "
                    + str(
                        assert_equal_objects(
                            pse_results,
                            read_h5_model(
                                os.path.join(
                                    FOLDER_RES, lsa_hypothesis.name +
                                    "_PSE_LSA_results.h5")
                            ).convert_from_h5_model(),
                            logger=logger)))

        if sa_pse_flag:
            # --------------Sensitivity Analysis Parameter Search Exploration (PSE)-------------------------------

            logger.info("\n\nrunning sensitivity analysis PSE LSA...")
            sa_results, pse_sa_results = \
                sensitivity_analysis_pse_from_lsa_hypothesis(lsa_hypothesis,
                                                         head.connectivity.normalized_weights,
                                                         head.connectivity.region_labels,
                                                         n_samples, method="sobol", half_range=0.1,
                                         global_coupling=[{"indices": all_regions_indices,
                                                     "bounds":[0.0, 2 * model_configuration_service.K_unscaled[ 0]]}],
                                         healthy_regions_parameters=[{"name": "x0_values", "indices": healthy_indices}],
                                         model_configuration_service=model_configuration_service,
                                         lsa_service=lsa_service, logger=logger)

            lsa_service.plot_lsa(lsa_hypothesis,
                                 model_configuration,
                                 head.connectivity.region_labels,
                                 pse_sa_results,
                                 title="SA PSE Hypothesis Overview")
            # , show_flag=True, save_flag=False

            convert_to_h5_model(pse_sa_results).write_to_h5(
                FOLDER_RES, lsa_hypothesis.name + "_SA_PSE_LSA_results.h5")
            convert_to_h5_model(sa_results).write_to_h5(
                FOLDER_RES, lsa_hypothesis.name + "_SA_LSA_results.h5")
            if test_write_read:
                logger.info(
                    "Written and read sensitivity analysis results are identical?: "
                    + str(
                        assert_equal_objects(
                            sa_results,
                            read_h5_model(
                                os.path.join(
                                    FOLDER_RES, lsa_hypothesis.name +
                                    "_SA_LSA_results.h5")
                            ).convert_from_h5_model(),
                            logger=logger)))
                logger.info(
                    "Written and read sensitivity analysis parameter search results are identical?: "
                    + str(
                        assert_equal_objects(
                            pse_sa_results,
                            read_h5_model(
                                os.path.join(
                                    FOLDER_RES, lsa_hypothesis.name +
                                    "_SA_PSE_LSA_results.h5")
                            ).convert_from_h5_model(),
                            logger=logger)))

        if sim_flag:
            # ------------------------------Simulation--------------------------------------
            logger.info("\n\nConfiguring simulation...")
            sim = setup_simulation_from_model_configuration(
                model_configuration,
                head.connectivity,
                dt,
                sim_length,
                monitor_period,
                model_name,
                zmode=np.array(zmode),
                pmode=np.array(pmode),
                noise_instance=None,
                noise_intensity=None,
                monitor_expressions=None)

            # Integrator and initial conditions initialization.
            # By default initial condition is set right on the equilibrium point.
            sim.config_simulation(initial_conditions=None)

            convert_to_h5_model(sim.model).write_to_h5(
                FOLDER_RES, lsa_hypothesis.name + "_sim_model.h5")

            logger.info("\n\nSimulating...")
            ttavg, tavg_data, status = sim.launch_simulation(n_report_blocks)

            convert_to_h5_model(sim.simulation_settings).write_to_h5(
                FOLDER_RES, lsa_hypothesis.name + "_sim_settings.h5")

            if test_write_read:
                logger.info(
                    "Written and read simulation settings are identical?: " +
                    str(
                        assert_equal_objects(
                            sim.simulation_settings,
                            read_h5_model(
                                os.path.join(
                                    FOLDER_RES, lsa_hypothesis.name +
                                    "_sim_settings.h5")).convert_from_h5_model(
                                        obj=deepcopy(sim.simulation_settings)),
                            logger=logger)))

            if not status:
                warning("\nSimulation failed!")

            else:

                time = np.array(ttavg, dtype='float32')

                output_sampling_time = np.mean(np.diff(time))
                tavg_data = tavg_data[:, :, :, 0]

                logger.info("\n\nSimulated signal return shape: %s",
                            tavg_data.shape)
                logger.info("Time: %s - %s", time[0], time[-1])
                logger.info("Values: %s - %s", tavg_data.min(),
                            tavg_data.max())

                # Variables of interest in a dictionary:
                vois_ts_dict = prepare_vois_ts_dict(VOIS[model_name],
                                                    tavg_data)
                vois_ts_dict['time'] = time
                vois_ts_dict['time_units'] = 'msec'

                vois_ts_dict = compute_seeg_and_write_ts_h5_file(
                    FOLDER_RES,
                    lsa_hypothesis.name + "_ts.h5",
                    sim.model,
                    vois_ts_dict,
                    output_sampling_time,
                    time_length,
                    hpf_flag=True,
                    hpf_low=10.0,
                    hpf_high=512.0,
                    sensor_dicts_list=[head.sensorsSEEG])

                # Plot results
                plot_sim_results(sim.model,
                                 lsa_hypothesis.propagation_indices,
                                 lsa_hypothesis.name,
                                 head,
                                 vois_ts_dict,
                                 head.sensorsSEEG.keys(),
                                 hpf_flag=True,
                                 trajectories_plot=trajectories_plot,
                                 spectral_raster_plot=spectral_raster_plot,
                                 log_scale=True)
from tvb_epilepsy.base.model.model_configuration import ModelConfiguration
from tvb_epilepsy.base.computations.calculations_utils import calc_x0cr_r, calc_coupling, calc_x0, calc_fx1, \
                                                              calc_fx1_2d_taylor, calc_fz, calc_x0_val__to_model_x0, \
                                                              calc_model_x0_to_x0_val
from tvb_epilepsy.base.computations.equilibrium_computation import calc_eq_z, eq_x1_hypo_x0_linTaylor, \
                                                                  eq_x1_hypo_x0_optimize, def_x1lin, calc_eq_y1
from tvb_epilepsy.base.plot_utils import save_figure, check_show

try:
    #https://github.com/joferkington/mpldatacursor
    #pip install mpldatacursor
    #Not working with the MacosX graphic's backend
    from mpldatacursor import HighlightingDataCursor  #datacursor
    MOUSEHOOVER = True
except:
    warning(
        "\nNo mpldatacursor module found! MOUSEHOOVER will not be available.")
    MOUSEHOOVER = False

# NOTES:
# In the future all the related to model configuration parameters might be part of the disease hypothesis:
# yc=YC_DEF, Iext1=I_EXT1_DEF, K=K_DEF, a=A_DEF, b=B_DEF
# For now, we assume default values, or externally set

logger = initialize_logger(__name__)


class ModelConfigurationService(object):
    x1EQcr = X1_EQ_CR_DEF

    def __init__(self,
                 number_of_regions,