import time, sys
import matplotlib.pyplot as plt
from astropy.io import fits
from astropy.cosmology import WMAP9
import pandas as pd
from scipy.stats import truncnorm
import numpy as np

from sedpy.observate import load_filters
from prospect import prospect_args
from prospect.fitting import fit_model
from prospect.io import write_results as writer
import sedpy

# --------------
# Load LEGA-C data
# --------------

objid = 172669
df_legac = pd.read_csv("/home/cwoodrum/Documents/LEGA-C/LEGAC_internalDR3.cat", sep=r"\s+", comment="#")
df_uvista = pd.read_csv("/home/cwoodrum/Documents/LEGA-C/UVISTA_final_v4.1.cat", sep=r"\s+", comment="#")

work_df_legac = df_legac[df_legac['id'] == objid]
work_df_uvista = df_uvista[df_uvista['id'] == objid]

obj_red = float(work_df_legac['z_spec'].values)
path_spec = "/home/cwoodrum/Documents/LEGA-C/spec1d/legac_M" + str(int(work_df_legac['mask'].values)) + "_v3.6_spec1d_" + str(objid) + ".fits"
path_err = "/home/cwoodrum/Documents/LEGA-C/spec1d/legac_M" + str(int(work_df_legac['mask'].values)) + "_v3.6_wht1d_" + str(objid) + ".fits"

def zp25_mags(flux_filter):
    return -2.5*np.log10(flux_filter) + 25

def mags_to_maggies(mags):
    return 10**(-0.4*mags)

def aper_to_tot(flux_aperture, flux_Ks_total, flux_Ks):
    flux_total = flux_aperture * (flux_Ks_total/flux_Ks)
    return flux_total

def phot_ready(df, phot_name, ephot_name):
    band = df[phot_name].values
    eband = df[ephot_name].values
    band_tot = aper_to_tot(band, df['Ks_tot'].values, df['Ks'].values)
    eband_tot = aper_to_tot(eband, df['eKs_tot'].values, df['eKs'].values)
    band_mags = zp25_mags(band_tot)
    eband_mags = zp25_mags(eband_tot)
    band_maggies = mags_to_maggies(band_mags)
    eband_maggies = mags_to_maggies(eband_mags)
    return band_maggies, eband_maggies

def phot_maggies(df):
    filternames = ["UVISTA_Ks", "UVISTA_H", "UVISTA_J", "UVISTA_Y",
                   "IB427.SuprimeCam", "IB464.SuprimeCam", "IB484.SuprimeCam", "IB505.SuprimeCam",
                   "IB527.SuprimeCam", "IB574.SuprimeCam", "IB624.SuprimeCam", "IB679.SuprimeCam",
                   "IB709.SuprimeCam", "IB738.SuprimeCam", "IB767.SuprimeCam", "IB827.SuprimeCam",
                   "spitzer_irac_ch1", "spitzer_irac_ch2",
                   "spitzer_irac_ch3", "spitzer_irac_ch4", #"spitzer_mips_24",
                   "galex_FUV", "galex_NUV",
                   "u_megaprime_sagem",
                   "B_subaru", "V_subaru", "g_subaru", "r_subaru", "i_subaru", "z_subaru"]

    Ks_maggies, eKs_maggies = phot_ready(df, 'Ks', 'eKs')
    H_maggies, eH_maggies = phot_ready(df, 'H', 'eH')
    J_maggies, eJ_maggies = phot_ready(df, 'J', 'eJ')
    Y_maggies, eY_maggies = phot_ready(df, 'Y', 'eY')

    IB427_maggies, eIB427_maggies = phot_ready(df, 'IB427', 'eIB427')
    IB464_maggies, eIB464_maggies = phot_ready(df, 'IB464', 'eIB464')
    IA484_maggies, eIA484_maggies = phot_ready(df, 'IA484', 'eIA484')
    IB505_maggies, eIB505_maggies = phot_ready(df, 'IB505', 'eIB505')
    IA527_maggies, eIA527_maggies = phot_ready(df, 'IA527', 'eIA527')
    IB574_maggies, eIB574_maggies = phot_ready(df, 'IB574', 'eIB574')
    IA624_maggies, eIA624_maggies = phot_ready(df, 'IA624', 'eIA624')
    IA679_maggies, eIA679_maggies = phot_ready(df, 'IA679', 'eIA679')
    IB709_maggies, eIB709_maggies = phot_ready(df, 'IB709', 'eIB709')
    IA738_maggies, eIA738_maggies = phot_ready(df, 'IA738', 'eIA738')
    IA767_maggies, eIA767_maggies = phot_ready(df, 'IA767', 'eIA767')
    IB827_maggies, eIB827_maggies = phot_ready(df, 'IB827', 'eIB827')

    ch1_maggies, ech1_maggies = phot_ready(df, 'ch1', 'ech1')
    ch2_maggies, ech2_maggies = phot_ready(df, 'ch2', 'ech2')
    ch3_maggies, ech3_maggies = phot_ready(df, 'ch3', 'ech3')
    ch4_maggies, ech4_maggies = phot_ready(df, 'ch4', 'ech4')
    #mips24_maggies, emips24_maggies = phot_ready(df, 'mips24', 'emips24')

    fuv_maggies, efuv_maggies = phot_ready(df, 'fuv', 'efuv')
    nuv_maggies, enuv_maggies = phot_ready(df, 'nuv', 'enuv')
    u_maggies, eu_maggies = phot_ready(df, 'u', 'eu')

    B_maggies, eB_maggies = phot_ready(df, 'B', 'eB')
    V_maggies, eV_maggies = phot_ready(df, 'V', 'eV')
    gp_maggies, egp_maggies = phot_ready(df, 'gp', 'egp')
    rp_maggies, erp_maggies = phot_ready(df, 'rp', 'erp')
    ip_maggies, eip_maggies = phot_ready(df, 'ip', 'eip')
    zp_maggies, ezp_maggies = phot_ready(df, 'zp', 'ezp')

    maggies = [Ks_maggies, H_maggies, J_maggies, Y_maggies,
                IB427_maggies, IB464_maggies, IA484_maggies, IB505_maggies,
                IA527_maggies, IB574_maggies, IA624_maggies, IA679_maggies,
                IB709_maggies, IA738_maggies, IA767_maggies, IB827_maggies,
               ch1_maggies, ch2_maggies, ch3_maggies, ch4_maggies, #mips24_maggies,
               fuv_maggies, nuv_maggies, u_maggies,
                B_maggies, V_maggies, gp_maggies, rp_maggies, ip_maggies, zp_maggies]

    emaggies = [eKs_maggies, eH_maggies, eJ_maggies, eY_maggies,
                eIB427_maggies, eIB464_maggies, eIA484_maggies, eIB505_maggies,
                eIA527_maggies, eIB574_maggies, eIA624_maggies, eIA679_maggies,
                eIB709_maggies, eIA738_maggies, eIA767_maggies, eIB827_maggies,
                ech1_maggies, ech2_maggies, ech3_maggies, ech4_maggies, #emips24_maggies,
                efuv_maggies, enuv_maggies, eu_maggies,
                eB_maggies, eV_maggies, egp_maggies, erp_maggies, eip_maggies, ezp_maggies]
    maggies = np.concatenate(maggies, axis=0)
    emaggies = np.concatenate(emaggies, axis=0)
    return maggies, emaggies

def prospector_wl_flux(spec_name, err_name):
    fluxes = fits.open(spec_name)[0].data
    invfluxvars = fits.open(err_name)[0].data
    fluxerrs = np.sqrt(1./invfluxvars)

    wav0 = fits.open(spec_name)[0].header["CRVAL1"]
    dwav = 0.6
    wl = np.arange(wav0, wav0+0.6*fluxes.shape[0], dwav)

    flux = np.array(fluxes)*1e-19
    flux_err = np.array(fluxerrs)*1e-19

    mask = (flux_err != 0) & (flux != 0) & (wl > 6500) & (wl < 9000) & np.isfinite(flux_err) & (wl > (1.0 + obj_red) * 3550)

    wl_good = wl[mask]
    flux_good = flux[mask]
    flux_err_good = flux_err[mask]

    lam2_c = (wl_good*wl_good)/2.99792e18
    fl_nu = lam2_c*flux_good
    fl_jansky = fl_nu*1e23
    fl_maggies = fl_jansky/3631
    fl_err = lam2_c*flux_err_good*1e23
    fl_err_maggies = fl_err/3631

    return wl_good, fl_maggies, fl_err_maggies

# --------------
# RUN_PARAMS
# When running as a script with argparsing, these are ignored.  Kept here for backwards compatibility.
# --------------

run_params = {'verbose':True,
              'debug':False,
              #'outfile':'demo_galphot',
              'nofork':True,
              # dynesty Fitter parameters
              'nested_bound': 'multi', # bounding method
              'nested_sample': 'rwalk', # sampling method
              'nested_walks': 50,
              'nested_nlive_init': 200,
              'nested_nlive_batch': 200,
              'nested_bootstrap': 0,
              'nested_dlogz_init': 0.01,
              'nested_weight_kwargs': {"pfrac": 1.0},
              'nested_stop_kwargs': {"post_thresh": 0.1},
              # Obs data parameters
#              'objid':0,
#              'phottable': 'demo_photometry.dat',
              'luminosity_distance': None,  # in Mpc
              }

# --------------
# Model Definition
# --------------

def build_model(fixed_metallicity=None, luminosity_distance=None, **extras):
    """Construct a model.  This method defines a number of parameter
    specification dictionaries and uses them to initialize a
    `models.sedmodel.SedModel` object.
    :param object_redshift:
        If given, given the model redshift to this value.
    :param add_dust: (optional, default: False)
        Switch to add (fixed) parameters relevant for dust emission.
    :param add_neb: (optional, default: False)
        Switch to add (fixed) parameters relevant for nebular emission, and
        turn nebular emission on.
    :param luminosity_distance: (optional)
        If present, add a `"lumdist"` parameter to the model, and set it's
        value (in Mpc) to this.  This allows one to decouple redshift from
        distance, and fit, e.g., absolute magnitudes (by setting
        luminosity_distance to 1e-5 (10pc))
    """
    from prospect.models.templates import TemplateLibrary, adjust_continuity_agebins
    from prospect.models import priors, sedmodel, transforms

    model_params = TemplateLibrary['continuity_sfh']

    ### BASIC PARAMETERS ###

    model_params["imf_type"] = {'N': 1,
                                'isfree': False,
                                'init': 1, #1=Chabrier
                                'prior': None}

    model_params['zred'] = {'N': 1,
                                'isfree': True,
                                'init': obj_red,
                                "prior": priors.TopHat(mini=obj_red-0.05, maxi=obj_red+0.05)}

    model_params['add_igm_absorption'] = {'N': 1,
                                'isfree': False,
                                'init': 1,
                                'units': None,
                                'prior': None}

    model_params['add_agb_dust_model'] = {'N': 1,
                                'isfree': False,
                                'init': 1,
                                'units': None,
                                'prior': None}

    # model_params['pmetals'] = {'N': 1,
    #                             'isfree': False,
    #                             'init': -99,
    #                             'units': '',
    #                             'prior': priors.TopHat(mini=-3, maxi=-1)}

    ### SFH ###

    tuniv = WMAP9.age(obj_red).value
    model_params = adjust_continuity_agebins(model_params, tuniv=tuniv, nbins=7)

    ### DUST ABSORPTION ###

    model_params['dust_type'] = {'N': 1,
                            'isfree': False,
                            'init': 4, #4=Kriek & Conroy
                            'units': 'index',
                            'prior': None}

    model_params['dust1'] = {'N': 1,
                            'isfree': False,
                            'depends_on': transforms.dustratio_to_dust1,
                            'init': 0.,
                            'units': 'optical depth towards young stars'}

    model_params['dust_ratio'] = {'N': 1,
                            'isfree': True,
                            'init': 1.0,
                            'init_disp': 0.8,
                            'disp_floor': 0.8,
                            'units': 'ratio of birth-cloud to diffuse dust',
                            'prior': priors.ClippedNormal(mini=0.0, maxi=2.0, mean=1.0, sigma=0.3)}

    model_params['dust2'] = {'N': 1,
                            'isfree': True,
                            'init': 1.0,
                            'init_disp': 0.25,
                            'disp_floor': 0.15,
                            'units': 'optical depth at 5500AA',
                            'prior': priors.ClippedNormal(mini=0.0, maxi=4.0, mean=0.3, sigma=1)}

    model_params['dust_index'] = {'N': 1,
                            'isfree': True,
                            'init': 0.0,
                            'init_disp': 0.25,
                            'disp_floor': 0.15,
                            'units': 'power-law multiplication of Calzetti',
                            'prior': priors.TopHat(mini=-2.0, maxi=0.5)}

    ### DUST EMISSION ###

    model_params.update(TemplateLibrary["dust_emission"])

    ### NEBULAR EMISSION ###

    model_params['add_neb_emission'] = {'N': 1,
                            'isfree': False,
                            'init': True,
                            'prior': None}

    model_params['add_neb_continuum'] = {'N': 1,
                            'isfree': False,
                            'init': True,
                            'prior': None}

    model_params['gas_logz'] = {'N': 1,
                            'isfree': True,
                            'init': 0.0,
                            'units': r'log Z/Z_\odot',
                            'prior': priors.TopHat(mini=-2.0, maxi=0.5)}

    model_params['gas_logu'] = {'N': 1,
                            'isfree': True,
                            'init': -1.0,
                            'units': '',
                            'prior': priors.TopHat(mini=-4.0, maxi=-1.0)}

    ### CALIBRATION ###
    model_params['polyorder'] = {'N': 1,
                            'init': 10,
                            'isfree': False}

    model_params['spec_norm'] = {'N': 1,
                            'init': 1.0,
                            'isfree': True,
                            'prior': priors.Normal(sigma=0.2, mean=1.0),
                            'units': 'f_true/f_obs'}

    model_params['spec_jitter'] = {"N": 1,
                            "isfree": True,
                            "init": 1.0,
                            "prior": priors.TopHat(mini=0., maxi=4.0)}

    model_params['f_outlier_spec'] = {"N": 1,
                            "isfree": True,
                            "init": 0.01,
                            "prior": priors.TopHat(mini=1e-5, maxi=0.5)}

    model_params['nsigma_outlier_spec'] = {"N": 1,
                            "isfree": False,
                            "init": 5.0}

    ### SMOOTHING ###

    model_params.update(TemplateLibrary["spectral_smoothing"])
    model_params["sigma_smooth"]["prior"] = priors.TopHat(mini=150, maxi=250)

    # Now instantiate the model using this new dictionary of parameter specifications
    model = sedmodel.SedModel(model_params)

    return model

# --------------
# Observational Data
# --------------

def build_obs(objid=objid, phottable=None,
             luminosity_distance=None, **kwargs):

    from prospect.utils.obsutils import fix_obs

    wl, flux, flux_err = prospector_wl_flux(path_spec, path_err)
    maggies, emaggies = phot_maggies(work_df_uvista)

    obs = {}
    filternames = ["UVISTA_Ks", "UVISTA_H", "UVISTA_J", "UVISTA_Y",
                   "IB427.SuprimeCam", "IB464.SuprimeCam", "IB484.SuprimeCam", "IB505.SuprimeCam",
                   "IB527.SuprimeCam", "IB574.SuprimeCam", "IB624.SuprimeCam", "IB679.SuprimeCam",
                   "IB709.SuprimeCam", "IB738.SuprimeCam", "IB767.SuprimeCam", "IB827.SuprimeCam",
                   "spitzer_irac_ch1", "spitzer_irac_ch2", "spitzer_irac_ch3", "spitzer_irac_ch4", #"spitzer_mips_24",
                   "galex_FUV", "galex_NUV",
                   "u_megaprime_sagem",
                   "B_subaru", "V_subaru", "g_subaru", "r_subaru", "i_subaru", "z_subaru",]
    obs['filters'] = load_filters(filternames)
    obs['maggies'] = maggies
    floor_phot = 0.05*obs['maggies']
    obs['maggies_unc'] = np.clip(emaggies, floor_phot, np.inf)
    obs['wavelength'] = wl
    obs['spectrum'] = flux
    floor_spec = 0.01*obs['spectrum']
    obs['unc'] = np.clip(flux_err, floor_spec, np.inf)
    obs['objid'] = objid

    obs = fix_obs(obs)
    return obs

# --------------
# SPS Object
# --------------

def build_sps(compute_vega_mags=False, **extras):
    from prospect.sources import FastStepBasis
    sps = FastStepBasis()
    return sps

# -----------------
# Noise Model
# ------------------

def build_noise(**extras):
    from prospect.likelihood import NoiseModel
    from prospect.likelihood.kernels import Uncorrelated
    jitter = Uncorrelated(parnames = ['spec_jitter'])
    spec_noise = NoiseModel(kernels=[jitter],metric_name='unc',weight_by=['unc'])
    return spec_noise, None

# -----------
# Everything
# ------------

def build_all(**kwargs):

    return (build_obs(**kwargs), build_model(**kwargs),
            build_sps(**kwargs), build_noise(**kwargs))

if __name__=='__main__':

    # - Parser with default arguments -
    parser = prospect_args.get_parser()
    # - Add custom arguments -
#    parser.add_argument('--object_redshift', type=float, default=zred,
#                        help=("Redshift for the model"))
    parser.add_argument('--add_neb', action="store_true",
                        help="If set, add nebular emission in the model (and mock).")
    parser.add_argument('--add_duste', action="store_true",
                        help="If set, add dust emission to the model.")
#    parser.add_argument('--luminosity_distance', type=float, default=1e-5,
#                        help=("Luminosity distance in Mpc. Defaults to 10pc "
#                              "(for case of absolute mags)"))
#    parser.add_argument('--phottable', type=str, default="demo_photometry.dat",
#                        help="Names of table from which to get photometry.")
    parser.add_argument('--objid', type=int, default=objid,
                    help="zero-index row number in the table to fit.")

    args = parser.parse_args()
    run_params = vars(args)
    obs, model, sps, noise = build_all(**run_params)

    #run_params["sps_libraries"] = sps.ssp.libraries
    run_params["param_file"] = __file__

    print(model)

    if args.debug:
        sys.exit()

    #hfile = setup_h5(model=model, obs=obs, **run_params)
    hfile = "{0}_{1}_mcmc.h5".format(args.outfile, int(time.time()))
    output = fit_model(obs, model, sps, noise, **run_params)

    writer.write_hdf5(hfile, run_params, model, obs,
                    output["sampling"][0], output["optimization"][0],
                    tsample=output["sampling"][1],
                    toptimize=output["optimization"][1])

    try:
        hfile.close()
    except(AttributeError):
        pass


import numpy as np

__all__ = [
  'cached_generator',
  'cached_generators',
  'metric'
]

class cached_generator(object):
  def __init__(self, gen):
    self.gen = gen
    self._data = None

  def __getitem__(self, item):
    if isinstance(item, slice):
      self(item.stop)
    else:
      self._cache(item)

    return tuple(x[item] for x in self._data)

  def samples(self, size):
    """
    Some generators are mixture generators that also
    return parameters along with the samples.
    This method always returns only samples.
    """
    return self(size)[0]

  def _cache(self, size):
    return tuple(x[:size] for x in self._data)

  def __call__(self, size):
    if self._data is None:
      result = self.gen(size)

      if isinstance(result, tuple):
        self._data = result
      else:
        self._data = (result, )

    while self._data[0].shape[0] < size:
      n = size - self._data[0].shape[0]

      result = self.gen(n)
      if not isinstance(result, tuple):
        result = (result, )

      self._data = tuple(
        np.concatenate([x, r], axis=0)
        for x, r in zip(self._data, result)
      )

    return self._cache(size)

def cached_generators(gen, gen_val=None):
  if gen_val is None:
    if isinstance(gen, cached_generator):
      raise ValueError('Can not use cached generator for training and validation!')

    gen_val = gen

  gen = gen if isinstance(gen, cached_generator) else cached_generator(gen)
  gen_val = gen_val if isinstance(gen_val, cached_generator) else cached_generator(gen_val)
  return gen, gen_val

### well, it is not metric, in a strict sense...
class metric(object):
  def __init__(self):
    pass

  def __call__(self, clf, gen_pos, gen_neg, gen_pos_val=None, gen_neg_val=None):
    raise NotImplementedError()


import json
import logging
import time
from collections import defaultdict
from copy import deepcopy
from enum import Enum
from functools import partial
from itertools import chain

from kademlia.config import Config
from kademlia.crypto import Crypto
from kademlia.exceptions import InvalidValueFormatException, UnauthorizedOperationException, InvalidSignException
from kademlia.utils import digest, compose, get_field, unpack, filtering_by

log = logging.getLogger(__name__)

class JsonSerializable(object):

    def to_json(self):
        json_dict = {}
        for k, v in self.__dict__.items():
            if '__' not in k:
                # Remove `_` from field name
                k = k[1:]
                if isinstance(v, JsonSerializable):
                    json_dict[k] = v.to_json()
                elif v is None or type(v) in [str, int, bool, dict, list]:
                    json_dict[k] = v
                elif isinstance(v, PersistMode):
                    json_dict[k] = v.value
                else:
                    json_dict[k] = str(v)

        return json_dict

class PublicKey(JsonSerializable):

    def __init__(self, hex_pub_key, exp_time=None):
        self.key = hex_pub_key
        self.exp_time = exp_time

    @property
    def key(self):
        return self._key

    @key.setter
    def key(self, base64_pub_key):
        check_pkey_type(base64_pub_key)
        self._key = base64_pub_key

    @property
    def exp_time(self):
        return self._exp_time

    @exp_time.setter
    def exp_time(self, exp_time):
        self._exp_time = exp_time

    @staticmethod
    def of_json(dct):
        assert 'exp_time' in dct
        assert 'key' in dct

        return PublicKey(dct['key'], dct['exp_time'])

class Authorization(JsonSerializable):

    def __init__(self, pub_key: PublicKey, sign):
        self.sign = sign
        self.pub_key = pub_key

    @property
    def pub_key(self):
        return self._pub_key

    @pub_key.setter
    def pub_key(self, value):
        self._pub_key = value

    @property
    def sign(self):
        return self._sign

    @sign.setter
    def sign(self, value):
        self._sign = value

    @staticmethod
    def of_json(dct):
        assert 'pub_key' in dct
        assert 'sign' in dct

        return Authorization(PublicKey.of_json(dct['pub_key']), dct['sign'])

class PersistMode(Enum):
    SECURED = 'SECURED'
    CONTROLLED = 'CONTROLLED'

    def __str__(self):
        return str(self.value)

class Value(JsonSerializable):

    def __init__(self, dkey: bytes, data: str, persist_mode: str, authorization: Authorization):
        self.__dkey = dkey
        self.authorization = authorization
        self.data = data
        self.persist_mode = persist_mode

    def __str__(self):
        return json.dumps(self.to_json())

    def __eq__(self, other):
        return self.to_json() == other.to_json()

    def __hash__(self):
        dval = digest(self.__dkey.hex() + self.data + str(self.authorization.pub_key.exp_time) + str(self.persist_mode))
        return int(dval.hex(), 16)

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, data):
        if isinstance(data, str) or data is None:
            self._data = data
        else:
            raise TypeError('Value must be of type int, float, bool, str, or bytes')

    @property
    def key(self):
        return self.__dkey

    @property
    def persist_mode(self):
        return self._persist_mode

    @persist_mode.setter
    def persist_mode(self, persist_mode):
        if persist_mode in (m.value for m in PersistMode):
            self._persist_mode = PersistMode(persist_mode)
        else:
            raise TypeError('Value persist mode MUST be "SECURED" or "CONTROLLED"')

    @property
    def authorization(self):
        return self._authorization

    @authorization.setter
    def authorization(self, authorization):
        assert type(authorization) is Authorization or \
               authorization is None
        self._authorization = authorization

    def is_valid(self):
        dval = digest(self.__dkey.hex() + self.data + str(self.authorization.pub_key.exp_time) + str(self.persist_mode))
        return Crypto.check_signature(dval, self.authorization.sign, self.authorization.pub_key.key)

    @staticmethod
    def of_json(key: bytes, dct: dict):
        check_value_json(dct)
        return Value(key, dct['data'], dct['persist_mode'], Authorization.of_json(dct['authorization']))

    @staticmethod
    def of_string(key: bytes, string: str):
        dct = json.loads(string)
        return Value.of_json(key, dct)

    @staticmethod
    def of_params(dkey: bytes, data: str, persist_mode: PersistMode, exp_time=None, priv_key=Config.NODE_PRIVATE_KEY,
                  pub_key=Config.NODE_PUBLIC_KEY):
        log.debug(f'Going to sign {data} with key: [{dkey.hex()}]')

        dval = digest(dkey.hex() + str(data) + str(exp_time) + str(persist_mode))
        signature = Crypto.get_signature(dval, priv_key).hex()
        log.debug(f'Successfully signed data with key: [{dkey.hex()}]')

        return Value(dkey, data, str(persist_mode), Authorization(PublicKey(pub_key, exp_time), signature))

class ControlledValue(JsonSerializable):

    def __init__(self, dkey: bytes, values: list):
        self.__dkey = dkey
        self._values = {val.authorization.pub_key.key: val for val in values}

    def __str__(self):
        return json.dumps([val.to_json() for val in self.values])

    def to_json(self):
        return [val.to_json() for val in self.values]

    @property
    def values(self):
        return self._values.values()

    @values.setter
    def values(self, values):
        if all(map(lambda it: type(it) is Value and it.persist_mode is PersistMode.CONTROLLED, values)):
            self._values = {val.authorization.pub_key.key: val for val in values}
        else:
            raise TypeError('All values must be of type Value and persist mode CONTROLLED')

    @classmethod
    def empty(cls, dkey: bytes):
        return cls(dkey, list())

    # TODO: add creation time to value
    def add_value(self, value: Value):
        assert value.persist_mode is PersistMode.CONTROLLED and value.is_valid()
        n_pub_key = value.authorization.pub_key.key

        if n_pub_key in self._values.keys() and not is_new_value_valid(self.__dkey, self._values.get(n_pub_key), value):
            raise UnauthorizedOperationException()

        self._values[n_pub_key] = value

        return deepcopy(self)

    def is_valid(self):
        return all(map(lambda value: value.is_valid and value.persist_mode is PersistMode.CONTROLLED, self.values))

    @classmethod
    def of_json(cls, dkey: bytes, jsn: list):
        values = [Value.of_json(dkey, val_jsn) for val_jsn in jsn]
        if all(map(lambda it: it.persist_mode is PersistMode.CONTROLLED and it.is_valid(), values)):
            return ControlledValue(dkey, values)
        else:
            raise ValueError('All json values must have persist mode "CONTROLLED"')

    @staticmethod
    def of_string(dkey: bytes, json_string: str):
        return ControlledValue.of_json(dkey, json.loads(json_string))

    def merge(self, controller_value):
        if controller_value.is_valid():
            for value in controller_value:
                self.add_value(value)

class ValueFactory(object):

    @staticmethod
    def create_from_json(dkey, jsn):
        if isinstance(jsn, list):
            return ControlledValue.of_json(dkey, jsn)
        else:
            value = Value.of_json(dkey, jsn)
            if value.persist_mode is PersistMode.CONTROLLED:
                return ControlledValue(dkey, [value])
            elif value.persist_mode is PersistMode.SECURED:
                return value
            else:
                raise ValueError("Unknown persist mode")

    @staticmethod
    def create_from_string(dkey, string):
        try:
            return ValueFactory.create_from_json(dkey, json.loads(string))
        except Exception as ex:
            log.exception(ex)

    @staticmethod
    def create_from_value(value: Value):
        if value.persist_mode is PersistMode.SECURED:
            return value
        elif value.persist_mode is PersistMode.CONTROLLED:
            return ControlledValue(value.key, [value])
        else:
            raise ValueError("Unknown persist mode")

class NodeMessage(JsonSerializable):

    def __init__(self, dkey: bytes, data: str, authorization: Authorization):
        self.__dkey = dkey
        self.authorization = authorization
        self.data = data

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, data):
        self._data = data

    @property
    def authorization(self):
        return self._authorization

    @authorization.setter
    def authorization(self, authorization):
        assert type(authorization) is Authorization or \
               authorization is None
        self._authorization = authorization

    def is_valid(self):
        dval = digest(self.__dkey.hex() + self.data + str(self.authorization.pub_key.exp_time))
        pub_key = self.authorization.pub_key.key
        return Crypto.check_signature(dval, self.authorization.sign, pub_key)

    @staticmethod
    def of_params(dkey: bytes, data, exp_time=None, priv_key=Config.NODE_PRIVATE_KEY,
                  pub_key=Config.NODE_PUBLIC_KEY):
        log.debug(f'Going to sign {data} with key: [{dkey.hex()}]')

        if isinstance(data, Value) or isinstance(data, ControlledValue):
            data = str(data)

        dval = digest(dkey.hex() + str(data) + str(exp_time))
        signature = Crypto.get_signature(dval, priv_key).hex()
        log.debug(f'Successfully signed data with key: [{dkey.hex()}]')

        return NodeMessage(dkey, data, Authorization(PublicKey(pub_key, exp_time), signature))

def is_new_value_valid(dkey, stored_value: Value, new_value: Value):
    try:
        validate_authorization(dkey, new_value)
        return stored_value.authorization.pub_key.key == new_value.authorization.pub_key.key
    except Exception as ex:
        log.exception(ex)
        return False

def validate_authorization(dkey, value: Value):
    log.debug(f"Going to validate authorization for key {dkey.hex()}")
    sign = value.authorization.sign
    exp_time = value.authorization.pub_key.exp_time
    persist_mode = value.persist_mode
    data = value.data
    assert exp_time is None or exp_time > int(time.time())

    d_record = digest(dkey.hex() + str(data) + str(exp_time) + persist_mode.value)

    if not Crypto.check_signature(d_record, sign, value.authorization.pub_key.key):
        raise InvalidSignException(sign)

def check_value_json(dct: dict):
    auth = dct.get('authorization')
    p_mode = dct.get('persist_mode')
    data = dct.get('data')

    if not all((auth, p_mode, data)):
        raise InvalidValueFormatException(
            'Invalid value format, value MUST contain following keys: authorization, persist_mode, data')

    if p_mode not in (m.value for m in PersistMode):
        raise InvalidValueFormatException('Invalid value format, persist_mode MUST be set to "SECURED" or "CONTROLLED"')

# TODO: move to value responsibilities
def validate_secure_value(dkey, new_value: Value, stored_value: Value):
    if new_value.persist_mode != PersistMode.SECURED:
        raise UnauthorizedOperationException()
    if new_value.persist_mode != stored_value.persist_mode:
        raise UnauthorizedOperationException()
    if not is_new_value_valid(dkey, stored_value, new_value):
        raise UnauthorizedOperationException()

# TODO: move to value responsibilities
def validate_controlled_value(dkey, new_value: Value, stored_value: list):
    if new_value.persist_mode != PersistMode.CONTROLLED:
        raise UnauthorizedOperationException()
    controlled_value = {}
    nv_pub_key = new_value.authorization.pub_key.key
    for val in stored_value:
        controlled_value[val['authorization']['pub_key']['key']] = Value.of_json(dkey, val)
    if nv_pub_key in controlled_value.keys() and not is_new_value_valid(dkey, controlled_value.get(nv_pub_key), new_value):
            raise UnauthorizedOperationException()

def select_most_common_response(dkey, responses):
    from collections import Counter

    unpack_inner_object = compose(get_field('data'), unpack)
    json_to_value = to_value_with_key(dkey)

    if responses:
        if not isinstance(responses, list):
            responses = [responses]

        values = [unpack_inner_object(r) for r in responses]
        most_common_type = Counter(map(lambda it: type(it), values)).most_common(1)[0][0]
        values = list(filtering_by(most_common_type)(values))

        if most_common_type is list:

            pub_key_value = list(map(lambda x: (x.authorization.pub_key.key, x), map(json_to_value, chain(*values))))
            grouped = defaultdict(list)
            for el in pub_key_value:
                grouped[el[0]].append(el[1])

            result = ControlledValue(dkey, [Counter(key_values).most_common(1)[0][0] for key_values in grouped.values()])

        else:
            result = Counter(map(json_to_value, values)).most_common(1)[0][0]

        return result
    else:
        return None

def to_value_with_key(key):
    return partial(Value.of_json, key)

def check_pkey_type(hex_pub_key):
    assert type(hex_pub_key) is str


from People_class import *

class Staff(People):
    employee_id = 0

    def __init__(self, role, wage, first_name, last_name):
        super().__init__(first_name, last_name)
        self.role = role
        self.__wage = wage
        self.first_name = first_name
        self.last_name = last_name
        Staff.employee_id += 1

    def email(self):
        email_fname = self.first_name[0]
        return email_fname + '.' + self.last_name + ".@legendsrest.com"

    def get_wage(self):
        return self.__wage

# test
#staff_chief = Staff('id_1', 'chief', 50000, 'Babish', 'Long')
# staff_driver = Staff ('id_1', 'Delivery', 30000, 'Dhann', 'Tapatieto')
#
#print(staff_chief.staff_email)


import sys, atsp, multiprocessing as mp

#################
cores = 12  # how many threads you want to use? >=2
epoch = 50  # epoch takes more time but has better chance approaching to the best result.
regb = (0.3, 3)  # regularization_bound for atsp
initf = 20  # initial fitness for multiprocessing, more fitness takes more time but reaches closer to the best result
initc = None  # initial solution in an array format
#################

def addajob(bestres, sil_mod=True):
    global processes, epoch, initf

    def tsplib(init_sol):
        _atsp = atsp.SA(data, infinity=inf, regularization_bound=regb, initial_fitness=initf, initial_solution=init_sol, silent_mode=sil_mod)
        output.put(_atsp.solve())

    if epoch > 0:
        _job = mp.Process(target=tsplib, args=(bestres,))
        processes.append(_job)
        _job.start()
        epoch -= 1
        initf += 1

if len(sys.argv) == 2:
    with open(sys.argv[1], 'r') as fp:
        content = fp.read().split()
        idx = content.index('DIMENSION:') + 1
        n = int(content[idx])
        idx = content.index('EDGE_WEIGHT_FORMAT:') + 1
        flag = True
        if content[idx] != 'FULL_MATRIX':
            print('ATSP FILE MUST BE FULL MATRIX')
            flag = False
        idx = content.index('EDGE_WEIGHT_SECTION') + 1
        inf = int(content[idx])
        data = []
        for i in range(n):
            if len(content) > idx + n:
                data.append(list(map(int, content[idx:idx + n])))
            else:
                print('ATSP FILE FORMAT ERROR')
                flag = False
            idx += n

        if flag:
            res, processes = ([], float('inf')), []
            output = mp.Manager().Queue()
            addajob(initc, False)
            n = 2
            while processes:
                _job = processes.pop(0)
                _job.join()
                _candidate = output.get()
                if _candidate[1] and _candidate[1] < res[1]:
                    res = _candidate
                if epoch:
                    for _ in range(min(n, cores) - len(processes)):
                        addajob(res[0])
                n += 1
            print(' OPTIMIZED COST:', res[1])
            print(' '.join(map(str, res[0])))


# -*- coding:utf-8 -*-
import urllib2

__author__ = 'Eric'

if __name__=="__main__":
    url="http://www.csdn.net"
    req=urllib2.Request(url)
    req.add_header('User-Agent', 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19')
    response=urllib2.urlopen(req)
    # 读取响应信息并解码
    html = response.read().decode('utf-8')
    # 打印信息
    print(html)


import configparser
from datetime import datetime

class ConfigData:

    def __init__(self):
        config = configparser.ConfigParser(allow_no_value=True)
        config.read("config.ini")
        self.seed_value = config.getint("Simulator", "seedvalue")
        self.max_round = config.getint("Simulator", "max_round")
        self.particle_random_order = config.getboolean("Simulator", "particle_random_order")
        self.visualization = config.getint("Simulator", "visualization")
        self.window_size_x = config.getint("Simulator", "window_size_x")
        self.window_size_y = config.getint("Simulator", "window_size_y")

        self.size_x = config.getfloat("World", "size_x")
        self.size_y = config.getfloat("World", "size_y")
        self.border = config.getboolean("World", "border")
        self.max_particles = config.getint("World", "max_particles")

        self.memory_limitation = config.getboolean("Matter", "memory_limitation")
        self.particle_mm_size = config.getint("Matter", "particle_mm_size")
        self.tile_mm_size = config.getint("Matter", "tile_mm_size")
        self.marker_mm_size = config.getint("Matter", "marker_mm_size")

        try:
            self.scenario = config.get("File", "scenario")
        except configparser.NoOptionError as noe:
            self.scenario = "init_scenario.py"

        try:
            self.solution = config.get("File", "solution")
        except configparser.NoOptionError as noe:
            self.solution = "solution.py"

        self.local_time = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')[:-1]
        self.multiple_sim = 0


from astropy.io import fits
import numpy as np
import astropy.units as u
import math
import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.interactive(True)

plt.clf()

def circle(data,ycenter,xcenter,rad):
    edgex=[]
    edgey=[]
    for i in range(np.shape(data)[0]):
        for j in range(np.shape(data)[1]):
            if (j-xcenter)**2+(i-ycenter)**2==rad**2:
                edgex.append(j)
                edgey.append(i)
    return np.vstack((edgex,edgey))

'''
source='DSi'
fnum=10
base=f'/blue/adamginsburg/d.jeff/SgrB2DSreorg/field{fnum}/CH3OH/{source}/'
home=base+'field10originals_z0_000186431_5-6mhzwidth_stdfixes/'
'''
source='SgrB2S'
fnum=1
#home='/blue/adamginsburg/d.jeff/SgrB2DSreorg/field10/CH3OH/DSi/OctReimage_z0_000186431_5-6mhzwidth_stdfixes/'
home="/blue/adamginsburg/d.jeff/SgrB2DSreorg/field1/CH3OH/SgrB2S/OctReimage_z0_0002306756533745274_5-6mhzwidth_stdfixes/"
texmap=home+"texmap_5transmask_3sigma_allspw_withnans_weighted.fits"

texmap=fits.open(texmap)
texmapdata=texmap[0].data*u.K

dGC=8.34*u.kpc#per Meng et al. 2019 https://www.aanda.org/articles/aa/pdf/2019/10/aa35920-19.pdf

cellsize=(np.abs(texmap[0].header['CDELT1']*u.deg)).to('arcsec')

pixtophysicalsize=(np.tan(cellsize)*dGC).to('AU')

print(pixtophysicalsize)

#texpeakpix=(36,43)#DSi hotspot
texpeakpix=(73,56)#SgrB2S hotspot
#x-1, y-1 from DS9

print(f'max: {texmapdata[texpeakpix[0],texpeakpix[1]]}')

r=12
#pixradius=math.ceil((0.08*u.pc/pixtophysicalsize).to(''))
r_phys=r*pixtophysicalsize.to('pc')
print(f'physical radius: {r_phys}')

xpixs=np.arange(texpeakpix[0],(texpeakpix[0]+r))

texinradius=[]
xinradius=[]
yinradius=[]
centrtopix=[]

for y in range(np.shape(texmapdata)[0]):
    for x in range(np.shape(texmapdata)[1]):
        if (y-texpeakpix[0])**2+(x-texpeakpix[1])**2 <= r**2:
            texinradius.append(texmapdata[y,x].value)
            xinradius.append(x)
            yinradius.append(y)
            centrtopix.append((np.sqrt((y-texpeakpix[0])**2+(x-texpeakpix[1])**2)*pixtophysicalsize).value)
        else:
            pass

plt.rcParams["figure.dpi"]=150

ax=plt.subplot(111)
plt.scatter(centrtopix,texinradius)
ax.set_xlabel('$d$ (AU)',fontsize=14)
ax.set_ylabel('$T_K$ (K)',fontsize=14)
ax.tick_params(size=14)
plt.tight_layout()

plt.show()
'''
edgepoints=circle(texmapdata,texpeakpix[0],texpeakpix[1],r)

plt.imshow(texmapdata.value,origin='lower',vmax=550,vmin=10)
plt.scatter(edgepoints[0],edgepoints[1],color='orange')
#plt.scatter(xinradius,yinradius,color='orange')
plt.show()
'''


from traversal import *

from log_file_handler import *

TABLE_NAME_COMPACTION_ANALYSIS = "compaction_analysis"

def create_data_table(conn):
    c = conn.cursor()

    c.execute("Drop Table if exists "+TABLE_NAME_COMPACTION_ANALYSIS)
    c.execute("CREATE TABLE "+TABLE_NAME_COMPACTION_ANALYSIS+" (bandwidth text, media text, cpu text, batch_size text" +
            #   ",IOPS INT, average_latency_ms REAL" +
              ",compaction_frequency INT, overall_compaction_latency INT" +
              ",overall_compaction_cpu_latency INT" +
              ",overall_input_record INT" +
              ",overall_output_record INT" +
              ",overall_redundant_record INT" +
              ")")
    conn.commit()

    print("table created")

def paint_for_one_column(column_name, df, color_map,bandwidth_group,cpu_group,batch_size_group):
    import plotly.express as px

    column_label = column_name.replace("_"," ")
    column_label = column_label.replace("overall","cumulative")
    column_label = column_label.replace("latency","latency (ms)")
    fig = px.bar(df, x="cpu", y=column_name, color="batch_size", barmode="group",
                 facet_col="bandwidth",
                 facet_row="media",
                 category_orders={
                     # "bandwidth":["400mb","800mb","1200mb","1600mb","2000mb","unlimited"]
                     "bandwidth": ['100mb','200mb','400mb'],
                     "cpu": ['4CPU','8CPU'],
                     "batch_size": ['16MB','32MB','64MB','128MB']
                 },
                 labels={"cpu": "", },
                 color_discrete_map=color_map
                 )
    fontsize = 20

    fig.update_layout(
        autosize=False,
        width=1600,
        height=900,
        font=dict(size=fontsize),
        plot_bgcolor='white',
    )
    fig.update_yaxes(automargin=True)
    fig.update_xaxes(showgrid=False)
    # fig.show()
    fig.write_image("image/"+column_name+".pdf")

if __name__ == '__main__':
    dirs = get_log_dirs()
    print("Directory Scanned")

    db_conn = sqlite3.connect('speed_info.db')

    create_data_table(db_conn)

    insert_sql_head = "INSERT INTO "+TABLE_NAME_COMPACTION_ANALYSIS+" VALUES"

    for dir in dirs:
        sql_data_row = get_row(dir)
        sql_sentence = insert_sql_head + "(" + sql_data_row + ")"
        db_conn.execute(sql_sentence)

    print("DB Loaded")

    cpu_group = [1, 4, 8, 12]
    cpu_group = [str(x) + "CPU" for x in cpu_group]
    bandwidth_group = ['400', '800', '1200', '1600', '2000']
    bandwidth_group = [x + "mb" for x in bandwidth_group]
#   size_color = {16: "rgb(66,106,199)", 32: "rgb(254,117,0)",
#              64: "rgb(165,165,165)", 128: "rgb(255,194,0)"}
    batch_size_to_color_map = {
        "16MB": "rgb(66,106,199)",
        "32MB": "rgb(254,117,0)",
        "64MB": "rgb(165,165,165)",
        "128MB": "rgb(255,194,0)"
    }
    media = "NVMeSSD"
    batch_size_group = ["16MB", "32MB", "64MB", "128MB"]

    df = pd.read_sql_query("SELECT * FROM "+TABLE_NAME_COMPACTION_ANALYSIS, db_conn)

    column_list = list(df.columns.values)[4:]

    for column in column_list:
        paint_for_one_column(column,df,batch_size_to_color_map,bandwidth_group,cpu_group,batch_size_group)


from django.db import transaction
from reversion.management.commands import BaseRevisionCommand

from ereqs_admin.revision_creation import create_revisions_for

class Command(BaseRevisionCommand):
    help = "Creates revision for a given app [and model]."""    # noqa

    def add_arguments(self, parser):
        parser.add_argument(
            'app_label',
            metavar='app_label',
            nargs='*',
            help="Optional app_label or app_label.model_name list.",
        )

    def handle(self, *app_labels, **options):
        with transaction.atomic():
            for model in self.get_models(options):
                create_revisions_for(model)


from django.shortcuts import render
from bruteforce.models import UserProfileInfo
from bruteforce.forms import UserForm,UserProfileInfoForm

# Create your views here.

def index(request):
    return render(request,'bruteforce/index.html')

def register(request):

    registered = False
    if request.method =='POST':
        user_form = UserForm(data = request.POST)
        profile_form = UserProfileInfoForm(data=request.POST)

        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            user.set_password(user.password)#hashing the password
            user.save()

            profile =profile_form.save(commit=False)
            profile.user =user #OneToOne
            if 'profile_pic' in request.FILES:
                profile.profile_pic = request.FILES['profile_pic'] #key defined in models
            profile.save()
            registered =True
        else:
            print(user_form.errors,profile_form.errors)

    else:
        user_form = UserForm()
        profile_form = UserProfileInfoForm()

    return render(request,'bruteforce/registration.html',{'user_form': user_form,
    'profile_form': profile_form,
    'registered':registered})


import sys

from fractions import gcd

def compute_generations(P, Q):
    generations = 0
    cd = gcd(P, Q)
    P, Q = P / cd, Q / cd
    while P < Q:
        if Q % 2:
            return -1
        Q /= 2
        generations += 1
        if generations > 40:
            return -1
    while Q != 1:
        if Q % 2:
            return -1
        Q /= 2
    return generations

def read_test_case():
    P, Q = sys.stdin.readline().strip().split("/")
    P, Q = int(P), int(Q)
    return P, Q

def format_answer(index, answer):
    if answer > -1:
        return "Case #%d: %d" % (index + 1, answer)
    else:
        return "Case #%d: impossible" % (index + 1,)

def display_results(answers):
    output_lines = []
    for index in range(len(answers)):
        output_line = format_answer(index, answers[index])
        output_lines.append(output_line)
    output = "\n".join(output_lines)
    with open("elf_out.txt", "w") as f:
        print("%s" % output, file=f)

def main():
    line = sys.stdin.readline()
    test_cases = int(line.strip())
    answers = []
    for _ in range(test_cases):
        P, Q = read_test_case()
        generations = compute_generations(P, Q)
        # print(flips)
        answers.append(generations)
    display_results(answers)

if __name__ == "__main__":
    main()


import xlrd
import xlwt
import os

def readiItemToList(sheet, cloum):  # 读取ip用以分析
    list = []
    for i in range(1, sheet.nrows):
        val = sheet.cell(i, cloum).value
        if (str(val) not in list):
            list.append(str(val))
    return list

def getDirFileName(file_dir):
    for root, dirs, files in os.walk(file_dir):
        # print(root) #当前目录路径
        # print(dirs) #当前路径下所有子目录
        return dirs, files

def fxdb(zcfxlist, ldxqlist, path, dirs):  # 分析数据库
    for i in dirs:
        dbname = str(i)
        filename = path + "\\" + dbname + "\\" + dbname + r".xlsx"
        print("\n\n\n\n正在检测文件：" + filename + "\n所包含数据库为：" + dbname)
        fofadb = xlrd.open_workbook(filename)
        dbsh = fofadb.sheet_by_index(0)
        dblist = readiItemToList(dbsh, 1)

        bl = 0  # 暴露工控数据库设备
        xl = 0  # 泄露工控设备数据量
        for j in dblist:
            print("正在检测数据库 " + dbname + " 主机 ：" + str(j))
            if (j in ldxqlist):
                bl = bl + 1
                xl = xl + 1
                print("主机 " + str(j) + " 数据可能泄露, 数据库类型为：" + dbname)
                continue
            if (j in zcfxlist):
                bl = bl + 1
                print("主机 " + str(j) + " 公网暴露, 数据库类型为：" + dbname)
        temp = [dbname, bl, xl]
        txtfile = path + "\\" + dbname + "\\" + dbname + r".txt"
        with open(txtfile, 'w') as f:
            f.write(r"----------数据库 " + dbname + " 暴露数据量：" + str(bl) + " ,可能泄露数据量：" + str(xl) + "-----------")
        print("----------数据库 " + dbname + " 暴露数据量：" + str(bl) + " ,可能泄露数据量：" + str(xl) + "-----------")

def main():
    # 威努特全量资产
    print("正在准备待分析数据..........")
    wntql = xlrd.open_workbook(r'C:\Users\ThinkPad\Desktop\新建文件夹\工作\信通院\数据分析专栏\月报\初步月报\资产分析_2019-08-31.xlsx')
    wntshzcfx = wntql.sheet_by_name(r"资产分析")
    wntshldxq = wntql.sheet_by_name(r"漏洞详情")

    print("正在读取威努特全量数据..........")
    zcfxlist = readiItemToList(wntshzcfx, 0)
    ldxqlist = readiItemToList(wntshldxq, 0)
    print("读取完毕，开始检测..............")

    # fofa数据库
    path = r"C:\Users\ThinkPad\Desktop\新建文件夹\工作\信通院\数据分析专栏\月报\初步月报\fofa数据库\excel\0829"
    dirs, files = getDirFileName(path)
    fxdb(zcfxlist, ldxqlist, path, dirs)

if __name__ == "__main__":
    main()


from collections import defaultdict
from unittest import mock

from ward import expect, fixture
from ward.fixtures import Fixture
from ward.models import Scope, SkipMarker
from ward.suite import Suite
from ward.testing import Test, skip, TestOutcome, TestResult, test, each

NUMBER_OF_TESTS = 5
FORCE_TEST_PATH = "path/of/test"

def testable_test(func):
    return test(
        "testable test description",
        _force_path=FORCE_TEST_PATH,
        _collect_into=defaultdict(list),
    )(func)

testable_test.path = FORCE_TEST_PATH

@fixture
def module():
    return "test_module"

@fixture
def fixture_b():
    def b():
        return 2

    return b

@fixture
def fixture_a(b=fixture_b):
    def a(b=b):
        return b * 2

    return a

@fixture
def fixtures(a=fixture_a, b=fixture_b):
    return {"fixture_a": Fixture(fn=a), "fixture_b": Fixture(fn=b)}

@fixture
def example_test(module=module, fixtures=fixtures):
    @fixture
    def f():
        return 123

    @testable_test
    def t(fix_a=f):
        return fix_a

    return Test(fn=t, module_name=module)

@fixture
def skipped_test(module=module):
    @testable_test
    def t():
        expect(1).equals(1)

    return Test(fn=t, module_name=module, marker=SkipMarker())

@fixture
def suite(example_test=example_test):
    return Suite(tests=[example_test] * NUMBER_OF_TESTS)

@test(
    f"Suite.num_tests returns {NUMBER_OF_TESTS}, when the suite has {NUMBER_OF_TESTS} tests"
)
def _(suite=suite):
    expect(suite.num_tests).equals(NUMBER_OF_TESTS)

@test(
    f"Suite.generate_test_runs generates {NUMBER_OF_TESTS} when suite has {NUMBER_OF_TESTS} tests"
)
def _(suite=suite):
    runs = suite.generate_test_runs()

    expect(list(runs)).has_length(NUMBER_OF_TESTS)

@test("Suite.generate_test_runs generates yields the expected test results")
def _(suite=suite):
    results = list(suite.generate_test_runs())
    expected = [
        TestResult(test=test, outcome=TestOutcome.PASS, error=None, message="")
        for test in suite.tests
    ]
    expect(results).equals(expected)

@test("Suite.generate_test_runs yields a FAIL TestResult on `assert False`")
def _(module=module):
    @testable_test
    def _():
        assert False

    t = Test(fn=_, module_name=module)
    failing_suite = Suite(tests=[t])

    results = failing_suite.generate_test_runs()
    result = next(results)

    expected_result = TestResult(
        test=t, outcome=TestOutcome.FAIL, error=mock.ANY, message=""
    )
    expect(result).equals(expected_result)
    expect(result.error).instance_of(AssertionError)

@test(
    "Suite.generate_test_runs yields a SKIP TestResult when test has @skip decorator "
)
def _(skipped=skipped_test, example=example_test):
    suite = Suite(tests=[example, skipped])

    test_runs = list(suite.generate_test_runs())
    expected_runs = [
        TestResult(example, TestOutcome.PASS, None, ""),
        TestResult(skipped, TestOutcome.SKIP, None, ""),
    ]

    expect(test_runs).equals(expected_runs)

@test("Suite.generate_test_runs fixture teardown code is ran in the expected order")
def _(module=module):
    events = []

    @fixture
    def fix_a():
        events.append(1)
        yield "a"
        events.append(3)

    @fixture
    def fix_b():
        events.append(2)
        return "b"

    @testable_test
    def my_test(fix_a=fix_a, fix_b=fix_b):
        expect(fix_a).equals("a")
        expect(fix_b).equals("b")

    suite = Suite(tests=[Test(fn=my_test, module_name=module)])

    # Exhaust the test runs generator
    list(suite.generate_test_runs())

    expect(events).equals([1, 2, 3])

@test("Suite.generate_test_runs tears down deep fixtures")
def _(module=module):
    events = []

    @fixture
    def fix_a():
        events.append(1)
        yield "a"
        events.append(4)

    @fixture
    def fix_b():
        events.append(2)
        return "b"

    @fixture
    def fix_c(fix_b=fix_b):
        events.append(3)
        yield "c"
        events.append(5)

    @testable_test
    def my_test(fix_a=fix_a, fix_c=fix_c):
        expect(fix_a).equals("a")
        expect(fix_c).equals("c")

    suite = Suite(tests=[Test(fn=my_test, module_name=module)])

    # Exhaust the test runs generator
    list(suite.generate_test_runs())

    expect(events).equals([1, 2, 3, 4, 5])

@test("Suite.generate_test_runs cached fixture isn't executed again")
def _(module=module):
    events = []

    @fixture
    def a():
        events.append(1)

    # Both of the fixtures below depend on 'a', but 'a' should only be executed once.
    @fixture
    def b(a=a):
        events.append(2)

    @fixture
    def c(a=a):
        events.append(3)

    @testable_test
    def test(b=b, c=c):
        pass

    suite = Suite(tests=[Test(fn=test, module_name=module)])

    list(suite.generate_test_runs())

    expect(events).equals([1, 2, 3])

@test("Suite.generate_test_runs correctly tears down module scoped fixtures")
def _():
    events = []

    @fixture(scope=Scope.Module)
    def a():
        events.append("resolve")
        yield "a"
        events.append("teardown")

    @testable_test
    def test1(a=a):
        events.append("test1")

    @testable_test
    def test2(a=a):
        events.append("test2")

    @testable_test
    def test3(a=a):
        events.append("test3")

    # For testing purposes we need to assign paths ourselves,
    # since our test functions are all defined at the same path
    test1.ward_meta.path = "module1"
    test2.ward_meta.path = "module2"
    test3.ward_meta.path = "module2"

    suite = Suite(
        tests=[
            Test(fn=test1, module_name="module1"),
            Test(fn=test2, module_name="module2"),
            Test(fn=test3, module_name="module2"),
        ]
    )

    list(suite.generate_test_runs())

    expect(events).equals(
        [
            "resolve",  # Resolve at start of module1
            "test1",
            "teardown",  # Teardown at end of module1
            "resolve",  # Resolve at start of module2
            "test2",
            "test3",
            "teardown",  # Teardown at end of module2
        ]
    )

@test("Suite.generate_test_runs resolves and tears down global fixtures once only")
def _():
    events = []

    @fixture(scope=Scope.Global)
    def a():
        events.append("resolve")
        yield "a"
        events.append("teardown")

    @testable_test
    def test1(a=a):
        events.append("test1")

    @testable_test
    def test2(a=a):
        events.append("test2")

    @testable_test
    def test3(a=a):
        events.append("test3")

    suite = Suite(
        tests=[
            Test(fn=test1, module_name="module1"),
            Test(fn=test2, module_name="module2"),
            Test(fn=test3, module_name="module2"),
        ]
    )

    list(suite.generate_test_runs())

    expect(events).equals(
        [
            "resolve",  # Resolve at start of run only
            "test1",
            "test2",
            "test3",
            "teardown",  # Teardown only at end of run
        ]
    )

@test("Suite.generate_test_runs resolves mixed scope fixtures correctly")
def _():
    events = []

    @fixture(scope=Scope.Global)
    def a():
        events.append("resolve a")
        yield "a"
        events.append("teardown a")

    @fixture(scope=Scope.Module)
    def b():
        events.append("resolve b")
        yield "b"
        events.append("teardown b")

    @fixture(scope=Scope.Test)
    def c():
        events.append("resolve c")
        yield "c"
        events.append("teardown c")

    @testable_test
    def test_1(a=a, b=b, c=c):
        events.append("test1")

    @testable_test
    def test_2(a=a, b=b, c=c):
        events.append("test2")

    @testable_test
    def test_3(a=a, b=b, c=c):
        events.append("test3")

    test_1.ward_meta.path = "module1"
    test_2.ward_meta.path = "module2"
    test_3.ward_meta.path = "module1"

    suite = Suite(
        tests=[
            # Module ordering is intentionally off here, to ensure correct
            # interaction between module-scope fixtures and random ordering
            Test(fn=test_1, module_name="module1"),
            Test(fn=test_2, module_name="module2"),
            Test(fn=test_3, module_name="module1"),
        ]
    )

    list(suite.generate_test_runs())

    expect(events).equals(
        [
            "resolve a",  # global fixture so resolved at start
            "resolve b",  # module fixture resolved at start of module1
            "resolve c",  # test fixture resolved at start of test1
            "test1",
            "teardown c",  # test fixture teardown at start of test1
            "resolve b",  # module fixture resolved at start of module2
            "resolve c",  # test fixture resolved at start of test2
            "test2",
            "teardown c",  # test fixture teardown at start of test2
            "teardown b",  # module fixture teardown at end of module2
            "resolve c",  # test fixture resolved at start of test3
            "test3",
            "teardown c",  # test fixture teardown at end of test3
            "teardown b",  # module fixture teardown at end of module1
            "teardown a",  # global fixtures are torn down at the very end
        ]
    )

@skip("TODO: Determine how this should behave")
@test(
    "Suite.generate_test_runs dependent fixtures of differing scopes behave correctly"
)
def _():
    pass

@test("Suite.generate_test_runs correctly tears down module scoped parameterised tests")
def _():
    events = []

    @fixture(scope=Scope.Module)
    def a():
        events.append("resolve a")
        yield "a"
        events.append("teardown a")

    @testable_test
    def test_1(a=each(a, "second", a)):
        events.append("running test")

    suite = Suite(
        tests=[
            Test(fn=test_1, module_name="module1"),
        ]
    )

    list(suite.generate_test_runs())

    # Ensure that each parameterised instance of the final test in the
    # module runs before the module-level teardown occurs.
    expect(events).equals([
        "resolve a",
        "running test",
        "running test",
        "running test",
        "teardown a",
    ])


import discord
import config
import summit
from datetime import datetime

client = discord.Client()
token = config.TOKEN
bot_id = 866789374031822910
channel_id = 866788357543952441

release_time = "22:28:57"
edition = 47
date = "28.07"
with open("participants.txt") as f:
    participants = [x.strip() for x in f.readlines()]

current_summit = summit.Summit(edition, date, participants)

print("Gonna post this message:")
print(current_summit.get_message())

def time_module():
    print("Waiting for the right time")
    while True:
        current_time = datetime.now().strftime("%H:%M:%S")  # hour %H min %M sec %S am:pm %p
        if current_time == release_time:  # enter the time you wish
            print("Time to post!")
            break

time_module()

@client.event
async def on_ready():
    brexit_summit_channel = client.get_channel(channel_id)
    await brexit_summit_channel.send(current_summit.get_message())

@client.event
async def on_message(message):
    brexit_summit_channel = client.get_channel(channel_id)
    if message.channel == brexit_summit_channel:

        if "deconfirmed" in message.content:
            print(message.author.name + " has deconfirmed")
            messages = await brexit_summit_channel.history(limit=300).flatten()
            bot_messages = [x for x in messages if x.author.id == bot_id and "BREXIT SUMMIT" in x.content]
            previous_message = bot_messages[0]
            no_of_participants = len(current_summit.participants)
            current_summit.remove_participant(message.author.name)
            if len(current_summit.participants) < no_of_participants:
                await previous_message.edit(content=current_summit.get_message())
                await brexit_summit_channel.send("Du wurdest entfernt, " + message.author.name + "!")

        elif "confirmed" in message.content:
            print(message.author.name + " has confirmed")
            messages = await brexit_summit_channel.history(limit=300).flatten()
            bot_messages = [x for x in messages if x.author.id == bot_id and "BREXIT SUMMIT" in x.content]
            previous_message = bot_messages[0]
            current_summit.new_participant(message.author.name)
            await previous_message.edit(content=current_summit.get_message())
            await brexit_summit_channel.send("Du bist drin, " + message.author.name + "!")

client.run(token)


import os
import re

from Bio import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio.Blast import NCBIXML
import Bio.Alphabet

import pandas as pd

def _read(filename, schema, seq_label='sequence', alphabet=None, **kwargs):
    """Use BioPython's sequence parsing module to convert any file format to
    a Pandas DataFrame.
    """
    # Check Alphabet if given
    if alphabet is None:
        alphabet = Bio.Alphabet.Alphabet()
    elif alphabet in ['dna', 'rna', 'protein', 'nucleotide']:
        alphabet = getattr(Bio.Alphabet, 'generic_{}'.format(alphabet))
    else:
        raise Exception("The alphabet is not recognized. Must be 'dna', 'rna', 'nucleotide', or 'protein'.")

    kwargs.update(alphabet=alphabet)

    # Prepare DataFrame fields.
    data = {'id':[], seq_label:[], 'description':[], 'name':[]}

    # Parse Fasta file.
    for i, s in enumerate(SeqIO.parse(filename, format=schema, **kwargs)):
        data['id'].append(s.id)
        data[seq_label].append(str(s.seq))
        data['description'].append(s.description)
        data['name'].append(s.name)

    # Port to DataFrame.
    return DataFrame(data)

def _write(dataframe, filename=None, schema='fasta', sequence_col='sequence', id_col='id', id_only=False, alphabet=None, **kwargs):
    """Write a PhyloPandas DataFrame to a sequence file.
    """
    # Check Alphabet if given
    if alphabet is None:
        alphabet = Bio.Alphabet.Alphabet()
    elif alphabet in ['dna', 'rna', 'protein', 'nucleotide']:
        alphabet = getattr(Bio.Alphabet, 'generic_{}'.format(alphabet))
    else:
        raise Exception("The alphabet is not recognized. Must be 'dna', 'rna', 'nucleotide', or 'protein'.")

    seq_records = []
    # Iterate through dataframe rows
    for i, row in dataframe.iterrows():
        seq = Seq(row[sequence_col], alphabet)
        # Create a SeqRecord and append to list.
        if id_only:
            record = SeqRecord(seq, id=row[id_col], name='', description='')
        else:
            record = SeqRecord(seq, id=row[id_col], name=row['name'], description=row['description'])
        seq_records.append(record)

    # Write to disk or return string
    if filename != None:
        SeqIO.write(seq_records, filename, format=schema, **kwargs)
    else:
        return "".join([s.format(schema) for s in seq_records])

def read_fasta(filename, **kwargs):
    """Read fasta format."""
    return _read(filename, schema='fasta', **kwargs)

def read_phylip(filename, **kwargs):
    """Read phylip format."""
    return _read(filename, schema='phylip', **kwargs)

def read_clustal(filename, **kwargs):
    """Read clustal format."""
    return _read(filename, schema='clustal', **kwargs)

def read_embl(filename, **kwargs):
    """Read the EMBL flat file format."""
    return _read(filename, schema='embl', **kwargs)

def read_nexus(filename, **kwargs):
    """Read the EMBL flat file format."""
    return _read(filename, schema='nexus', **kwargs)

def read_swiss(filename, **kwargs):
    """Read Swiss-Prot aka UniProt format."""
    return _read(filename, schema='nexus', **kwargs)

def read_blast_xml(filename, **kwargs):
    """Read BLAST XML format."""
    # Read file.
    with open(filename, 'r') as f:
        blast_record = NCBIXML.read(f)

    # Prepare DataFrame fields.
    data = {'accession':[],
        'hit_def':[],
        'hit_id':[],
        'title':[],
        'length':[],
        'e_value':[],
        'sequence':[]}

    # Get alignments from blast result.
    for i, s in enumerate(blast_record.alignments):
        data['accession'] = s.accession
        data['hit_def'] = s.hit_def
        data['hit_id'] = s.hit_id
        data['title'] = s.title
        data['length'] = s.length
        data['e_value'] = s.hsps[0].expect
        data['sequence'] = s.hsps[0].sbjct

    # Port to DataFrame.
    return DataFrame(data)

class DataFrame(pd.DataFrame):

    def to_fasta(self, filename=None, sequence_col='sequence', id_col='id', id_only=False):
        """Write to fasta format."""
        return _write(self, filename=filename, schema="fasta", id_col=id_col, id_only=id_only)

    def to_phylip(self, filename=None, sequence_col='sequence', id_col='id'):
        """Write to phylip format."""
        return _write(self, filename=filename, schema="phylip", id_col=id_col)

    def to_clustal(self, filename=None, sequence_col='sequence'):
        """Write to alignment format of Clustal X and Clustal W."""
        return _write(self, filename=filename, schema="clustal")

    def to_embl(self, alphabet, filename=None, sequence_col='sequence'):
        """Write to the EMBL flat file format."""
        return _write(self, alphabet=alphabet, filename=filename, schema="embl")

    def to_nexus(self, alphabet, filename=None, sequence_col='sequence'):
        """Write to the NEXUS multiple alignment format."""
        return _write(self, alphabet=alphabet, filename=filename, schema="nexus")

    def to_swiss(self, filename=None, sequence_col='sequence'):
        """Write Swiss-Prot aka UniProt format."""
        return _write(self, filename=filename, schema="swiss")


# -*- coding: utf-8 -*-
"""
Created on Tue Apr  2 22:12:38 2019

First part is the V2 analysis (not block-wise)

@author: Greta
"""

import pickle
from matplotlib import pyplot as plt
import os
import statistics
import numpy as np
from scipy import stats
import seaborn as sns
os.chdir('C:\\Users\\Greta\\Documents\\GitHub\\ClosedLoop\\Scripts\\')
from responseTime_func import findRTsBlocks
import random

saveDir = 'P:\\closed_loop_data\\beh_analysis\\'
os.chdir(saveDir)

plt.style.use('seaborn-pastel')

font = {'family' : 'sans-serif',
       'weight' : 1,
       'size'   : 12}

#%%
with open('Beh_subjID_07.pkl', "rb") as fin:
    sub07 = (pickle.load(fin))[0]
with open('Beh_subjID_08.pkl', "rb") as fin:
    sub08 = (pickle.load(fin))[0]
with open('Beh_subjID_11.pkl', "rb") as fin:
    sub11 = (pickle.load(fin))[0]
with open('Beh_subjID_13.pkl', "rb") as fin:
    sub13 = (pickle.load(fin))[0]
with open('Beh_subjID_14.pkl', "rb") as fin:
    sub14 = (pickle.load(fin))[0]
with open('Beh_subjID_15.pkl', "rb") as fin:
    sub15 = (pickle.load(fin))[0]
with open('Beh_subjID_16.pkl', "rb") as fin:
    sub16 = (pickle.load(fin))[0]
with open('Beh_subjID_17.pkl', "rb") as fin:
    sub17 = (pickle.load(fin))[0]
with open('Beh_subjID_18.pkl', "rb") as fin:
    sub18 = (pickle.load(fin))[0]
with open('Beh_subjID_19.pkl', "rb") as fin:
    sub19 = (pickle.load(fin))[0]
with open('Beh_subjID_21.pkl', "rb") as fin:
    sub21 = (pickle.load(fin))[0]
with open('Beh_subjID_22.pkl', "rb") as fin:
    sub22 = (pickle.load(fin))[0]
with open('Beh_subjID_23.pkl', "rb") as fin:
    sub23 = (pickle.load(fin))[0]
with open('Beh_subjID_25.pkl', "rb") as fin:
    sub25 = (pickle.load(fin))[0]
with open('Beh_subjID_27.pkl', "rb") as fin:
    sub27 = (pickle.load(fin))[0]
with open('Beh_subjID_30.pkl', "rb") as fin:
    sub30 = (pickle.load(fin))[0]
with open('Beh_subjID_31.pkl', "rb") as fin:
    sub31 = (pickle.load(fin))[0]
with open('Beh_subjID_32.pkl', "rb") as fin:
    sub32 = (pickle.load(fin))[0]
with open('Beh_subjID_33.pkl', "rb") as fin:
    sub33 = (pickle.load(fin))[0]
with open('Beh_subjID_34.pkl', "rb") as fin:
    sub34 = (pickle.load(fin))[0]

#%% Measures

def computeStats(subjID,expDay):

    with open('Beh_subjID_' + subjID + '.pkl', "rb") as fin:
        sub = (pickle.load(fin))[0]

    TP = sub['no_Inhibitions_nonlure_day_'+expDay]
    FN = sub['inhibitions_nonlure_day_'+expDay]

    TN = sub['inhibitions_lure_day_'+expDay]
    FP = sub['no_Inhibitions_lure_day_'+expDay]

    sensitivity = TP/(TP+FN)
    specificity = TN/(TN+FP)

    false_positive_rate = FP/(FP+TN)

    accuracy = (TP+TN)/(TP+TN+FP+FN)

    return sensitivity,specificity,false_positive_rate,accuracy

#%% Analyze 4 days
dayLst = ['1','3','4','5']

f07=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f07[count,:]=computeStats('07',day)
f08=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f08[count,:]=computeStats('08',day)
f11=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f11[count,:]=computeStats('11',day)
f13=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f13[count,:]=computeStats('13',day)
f14=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f14[count,:]=computeStats('14',day)
f15=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f15[count,:]=computeStats('15',day)
f16=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f16[count,:]=computeStats('16',day)
f17=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f17[count,:]=computeStats('17',day)
f18=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f18[count,:]=computeStats('18',day)
f19=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f19[count,:]=computeStats('19',day)
f21=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f21[count,:]=computeStats('21',day)
f22=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f22[count,:]=computeStats('22',day)
f23=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f23[count,:]=computeStats('23',day)
f24=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f24[count,:]=computeStats('24',day)
f25=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f25[count,:]=computeStats('25',day)
f26=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f26[count,:]=computeStats('26',day)
f27=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f27[count,:]=computeStats('27',day)
f30=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f30[count,:]=computeStats('30',day)
f31=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f31[count,:]=computeStats('31',day)
f32=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f32[count,:]=computeStats('32',day)
f33=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f33[count,:]=computeStats('33',day)
f34=np.zeros((4,4))
for count,day in enumerate(dayLst):
    f34[count,:]=computeStats('34',day)

#%%
sub_fb=[f07,f08,f11,f13,f14,f16,f19,f22,f26,f27,f30]
sub_c=[f15,f17,f18,f21,f23,f24,f25,f31,f32,f33,f34]

#%%
sen_feedback=np.asarray([f[:,0] for f in sub_fb])
sen_control=np.asarray([f[:,0] for f in sub_c])

spec_feedback=np.asarray([f[:,1] for f in sub_fb])
spec_control=np.asarray([f[:,1] for f in sub_c])

fpr_feedback=np.asarray([f[:,2] for f in sub_fb])
fpr_control=np.asarray([f[:,2] for f in sub_c])

acc_feedback=np.asarray([f[:,3] for f in sub_fb])
acc_control=np.asarray([f[:,3] for f in sub_c])

#%% Sensitivity
plt.figure(1)
plt.bar(1,np.mean(sen_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato',yerr=np.std(sen_feedback[:,0]))
plt.bar(2,np.mean(sen_feedback[:,1]),color=(0,0,0,0),edgecolor='brown',yerr=np.std(sen_feedback[:,1]))
plt.bar(3,np.mean(sen_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue',yerr=np.std(sen_control[:,0]))
plt.bar(4,np.mean(sen_control[:,1]),color=(0,0,0,0),edgecolor='navy',yerr=np.std(sen_control[:,1]))

plt.scatter(np.full(11,1),sen_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),sen_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),sen_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),sen_control[:,1],color='navy')

plt.ylabel('Response sensitivity')
plt.ylim([0.9,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Sensitivity')

# Connect lines
plt.figure(10)
plt.ylabel('Response sensitivity')
plt.ylim([0.9,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Sensitivity')

plt.bar(1,np.mean(sen_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato')
plt.bar(2,np.mean(sen_feedback[:,1]),color=(0,0,0,0),edgecolor='brown')
plt.bar(3,np.mean(sen_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue')
plt.bar(4,np.mean(sen_control[:,1]),color=(0,0,0,0),edgecolor='navy')

plt.scatter(np.full(11,1),sen_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),sen_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),sen_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),sen_control[:,1],color='navy')

for i in range(11):
    plt.plot([(np.full(11,1))[i],(np.full(11,2))[i]], [(sen_feedback[:,0])[i],(sen_feedback[:,1])[i]],color='gray')
    plt.plot([(np.full(11,3))[i],(np.full(11,4))[i]], [(sen_control[:,0])[i],(sen_control[:,1])[i]],color='gray')

# Day 4 and 5
#plt.figure(3)
#plt.bar(1,np.mean(sen_feedback[:,2]))
#plt.bar(2,np.mean(sen_feedback[:,3]))
#plt.bar(3,np.mean(sen_control[:,2]))
#plt.bar(4,np.mean(sen_control[:,3]))

#%% Specificity
plt.figure(2)
plt.bar(1,np.mean(spec_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato',yerr=np.std(spec_feedback[:,0]))
plt.bar(2,np.mean(spec_feedback[:,1]),color=(0,0,0,0),edgecolor='brown',yerr=np.std(spec_feedback[:,1]))
plt.bar(3,np.mean(spec_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue',yerr=np.std(spec_control[:,0]))
plt.bar(4,np.mean(spec_control[:,1]),color=(0,0,0,0),edgecolor='navy',yerr=np.std(spec_control[:,1]))

plt.scatter(np.full(11,1),spec_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),spec_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),spec_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),spec_control[:,1],color='navy')

plt.ylabel('Response specificity')
plt.ylim([0.4,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Specificity')

# Connect lines
plt.figure(12)
plt.bar(1,np.mean(spec_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato')
plt.bar(2,np.mean(spec_feedback[:,1]),color=(0,0,0,0),edgecolor='brown')
plt.bar(3,np.mean(spec_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue')
plt.bar(4,np.mean(spec_control[:,1]),color=(0,0,0,0),edgecolor='navy')

plt.scatter(np.full(11,1),spec_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),spec_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),spec_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),spec_control[:,1],color='navy')

plt.ylabel('Response specificity')
plt.ylim([0.4,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Specificity')

for i in range(11):
    plt.plot([(np.full(11,1))[i],(np.full(11,2))[i]], [(spec_feedback[:,0])[i],(spec_feedback[:,1])[i]],color='gray')
    plt.plot([(np.full(11,3))[i],(np.full(11,4))[i]], [(spec_control[:,0])[i],(spec_control[:,1])[i]],color='gray')

#%% FPR
plt.figure(3)
plt.bar(1,np.mean(fpr_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato',yerr=np.std(fpr_feedback[:,0]))
plt.bar(2,np.mean(fpr_feedback[:,1]),color=(0,0,0,0),edgecolor='brown',yerr=np.std(fpr_feedback[:,1]))
plt.bar(3,np.mean(fpr_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue',yerr=np.std(fpr_control[:,0]))
plt.bar(4,np.mean(fpr_control[:,1]),color=(0,0,0,0),edgecolor='navy',yerr=np.std(fpr_control[:,1]))

plt.scatter(np.full(11,1),fpr_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),fpr_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),fpr_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),fpr_control[:,1],color='navy')

plt.ylabel('False positive rate')
plt.ylim([0,0.6])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('FPR')

# Connect
plt.figure(13)
plt.bar(1,np.mean(fpr_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato')
plt.bar(2,np.mean(fpr_feedback[:,1]),color=(0,0,0,0),edgecolor='brown')
plt.bar(3,np.mean(fpr_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue')
plt.bar(4,np.mean(fpr_control[:,1]),color=(0,0,0,0),edgecolor='navy')

plt.scatter(np.full(11,1),fpr_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),fpr_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),fpr_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),fpr_control[:,1],color='navy')

plt.ylabel('False positive rate')
plt.ylim([0,0.6])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('FPR')

for i in range(11):
    plt.plot([(np.full(11,1))[i],(np.full(11,2))[i]], [(fpr_feedback[:,0])[i],(fpr_feedback[:,1])[i]],color='gray')
    plt.plot([(np.full(11,3))[i],(np.full(11,4))[i]], [(fpr_control[:,0])[i],(fpr_control[:,1])[i]],color='gray')

#%% Accuracy
plt.figure(4)
plt.bar(1,np.mean(acc_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato',yerr=np.std(acc_feedback[:,0]))
plt.bar(2,np.mean(acc_feedback[:,1]),color=(0,0,0,0),edgecolor='brown',yerr=np.std(acc_feedback[:,1]))
plt.bar(3,np.mean(acc_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue',yerr=np.std(acc_control[:,0]))
plt.bar(4,np.mean(acc_control[:,1]),color=(0,0,0,0),edgecolor='navy',yerr=np.std(acc_control[:,1]))

plt.scatter(np.full(11,1),acc_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),acc_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),acc_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),acc_control[:,1],color='navy')

plt.ylabel('Accuracy')
plt.ylim([0.9,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Accuracy')

# Connect
plt.figure(14)
plt.bar(1,np.mean(acc_feedback[:,0]),color=(0,0,0,0),edgecolor='tomato')
plt.bar(2,np.mean(acc_feedback[:,1]),color=(0,0,0,0),edgecolor='brown')
plt.bar(3,np.mean(acc_control[:,0]),color=(0,0,0,0),edgecolor='dodgerblue')
plt.bar(4,np.mean(acc_control[:,1]),color=(0,0,0,0),edgecolor='navy')

plt.scatter(np.full(11,1),acc_feedback[:,0],color='tomato')
plt.scatter(np.full(11,2),acc_feedback[:,1],color='brown')
plt.scatter(np.full(11,3),acc_control[:,0],color='dodgerblue')
plt.scatter(np.full(11,4),acc_control[:,1],color='navy')

plt.ylabel('Accuracy')
plt.ylim([0.9,1])
plt.xticks([1,2,3,4],['NF day1','NF day3', 'Control day1', 'Control day3'])
plt.title('Accuracy')

for i in range(11):
    plt.plot([(np.full(11,1))[i],(np.full(11,2))[i]], [(acc_feedback[:,0])[i],(acc_feedback[:,1])[i]],color='gray')
    plt.plot([(np.full(11,3))[i],(np.full(11,4))[i]], [(acc_control[:,0])[i],(acc_control[:,1])[i]],color='gray')

#%% T tests

# Sensitivity
diff_fb=np.mean(sen_feedback[:,1]-sen_feedback[:,0])
diff_c=np.mean(sen_control[:,1]-sen_control[:,0])

diff_fb_p=stats.ttest_rel(sen_feedback[:,0],sen_feedback[:,1])
diff_c_p=stats.ttest_rel(sen_control[:,0],sen_control[:,1])

# Acc
#diff_fb_acc=np.mean(acc_feedback[:,1]-acc_feedback[:,0])
#diff_c_acc=np.mean(acc_control[:,1]-acc_control[:,0])

p_acc_fb=stats.ttest_rel(acc_feedback[:,0],acc_feedback[:,1])
p_acc_c=stats.ttest_rel(acc_control[:,0],acc_control[:,1])

#%% Plots for RT surrounding lures
def extractRTs(subjID):

    with open('Beh_subjID_' + subjID + '.pkl', "rb") as fin:
        sub = (pickle.load(fin))[0]

    c1 = sub['surrounding_CR_Lst_day_1']
    c3 = sub['surrounding_CR_Lst_day_3']

    f1 = sub['surrounding_FR_Lst_day_1']
    f3 = sub['surrounding_FR_Lst_day_3']

    # Computing day 1 and 3 together
    c13m = [statistics.mean(k) for k in zip(c1, c3)]
    f13m = [statistics.mean(k) for k in zip(f1, f3)]

    # Computing day 1 and 3 separately

    return np.asarray(c1), np.asarray(c3), np.asarray(f1), np.asarray(f3), np.asarray(c13m), np.asarray(f13m)

all_RTs = np.zeros((22,6),dtype=np.ndarray)

sub_all = ['07','08','11','13','14','15','16','17','18','19','21','22','23','24','25','26','27','30','31','32','33','34']

for idx, subj in enumerate(sub_all):
    all_RTs[idx,:] = extractRTs(subj)

# Mean over c13m and f13m for all subjects
all_c1 = all_RTs[:,0]
all_c3 = all_RTs[:,1]
all_f1 = all_RTs[:,2]
all_f3 = all_RTs[:,3]

all_c13 = all_RTs[:,4]
all_f13 = all_RTs[:,5]
# Make into np arrays?
all_c1m = np.mean(all_c1)
all_c3m = np.mean(all_c3)
all_f1m = np.mean(all_f1)
all_f3m = np.mean(all_f3)
all_c13m = np.mean(all_c13)
all_f13m = np.mean(all_f13)

# Standard error of the mean for errorbars
c1_yerr=(np.std(all_c1))/np.sqrt(22)
c3_yerr=(np.std(all_c3))/np.sqrt(22)
f1_yerr=(np.std(all_f1))/np.sqrt(22)
f3_yerr=(np.std(all_f3))/np.sqrt(22)
c13_yerr=(np.std(all_c13))/np.sqrt(22)
f13_yerr=(np.std(all_f13))/np.sqrt(22)

#%% Plots
ticks = ['-3','-2','-1','lure','1','2','3']

# Both days
#plt.plot(all_c13m,color='green',)
#plt.plot(all_f13m,color='red')

plt.figure(5)
plt.errorbar(np.arange(0,7),all_c13m,yerr=c13_yerr,color='green')
plt.errorbar(np.arange(0,7),all_f13m,yerr=f13_yerr,color='red')
plt.title('Day 1 and 3 - all participants')
plt.xticks(np.arange(0,7,1),ticks)
plt.xlabel('Trials from lure')
plt.ylabel('RT (ms)')

# Day 1
plt.figure(6)
#plt.plot(all_c1m,color='green')
#plt.plot(all_f1m,color='red')
plt.errorbar(np.arange(0,7),all_c1m,yerr=c1_yerr,color='green')
plt.errorbar(np.arange(0,7),all_f1m,yerr=f1_yerr,color='red')
plt.title('Day 1, all participants')
plt.xticks(np.arange(0,7,1),ticks)
plt.xlabel('Trials from lure')
plt.ylabel('RT (ms)')

# Day 3
plt.figure(7)
#plt.plot(all_c3m,color='green')
#plt.plot(all_f3m,color='red')
plt.errorbar(np.arange(0,7),all_c3m,yerr=c3_yerr,color='green')
plt.errorbar(np.arange(0,7),all_f3m,yerr=f3_yerr,color='red')
plt.title('Day 3, all participants')
plt.xticks(np.arange(0,7,1),ticks)
plt.xlabel('Trials from lure')
plt.ylabel('RT (ms)')

#%% ################## V3 analysis ####################
def computeStatsBlocks(subjID):

    with open('BehV3_subjID_' + subjID + '.pkl', "rb") as fin:
        sub = (pickle.load(fin))[0]

    statsDay = np.zeros((5,8))

    statsBlock = np.zeros((4,16,5))
    statsBlock_day2 = np.zeros((48,5))

    idx_c = 0

    for idx, expDay in enumerate(['1','2','3','4','5']):

        # Load catFile
        catFile = 'P:\\closed_loop_data\\' + str(subjID) + '\\createIndices_'+subjID+'_day_'+expDay+'.csv'

        if subjID == '11' and expDay == '2':
            responseTimes = [np.nan]
            nKeypress = np.nan
        else:
            responseTimes = sub['responseTimes_day'+expDay]
            nKeypress = sub['TOTAL_keypress_day'+expDay]

        if subjID == '11' and expDay == '2':
            CI_lure, NI_lure, I_nlure, NI_nlure, lure_RT_mean, nonlure_RT_mean, RT_mean, nNaN = [np.nan]*8
        else:
            CI_lure, NI_lure, I_nlure, NI_nlure, lure_RT_mean, nonlure_RT_mean, RT_mean, nNaN = findRTsBlocks(catFile,responseTimes,block=False)

        # Compute stats (for visibility)
        TP = NI_nlure
        FP = NI_lure
        TN = CI_lure
        FN = I_nlure

        sensitivity = TP/(TP+FN)
        specificity = TN/(TN+FP)

        accuracy = (TP+TN)/(TP+TN+FP+FN)
#        accuracy_all = (TP+TN)/nKeypress # Out of all the keypresses that day

        statsDay[idx,:] = sensitivity, specificity, accuracy, lure_RT_mean, nonlure_RT_mean, RT_mean, nKeypress, nNaN

        # Block-wise
        for block in range(1,int(len(responseTimes)/50)+1):
            print(block)

            if subjID == '11' and expDay == '2':
                TN, FP, FN, TP, lure_RT_mean, nonlure_RT_mean, RT_mean, nNaN = [np.nan]*8
            else:
                TN, FP, FN, TP, lure_RT_mean, nonlure_RT_mean, RT_mean, nNaN = findRTsBlocks(catFile,responseTimes,block=block)

            sensitivity = TP/(TP+FN)
            specificity = TN/(TN+FP)

            accuracy = (TP+TN)/(TP+TN+FP+FN)

            if expDay == '2':
                statsBlock_day2[block-1,:] = sensitivity, specificity, accuracy, RT_mean, nNaN

            if expDay != '2':
                statsBlock[idx_c,block-1,:] = sensitivity, specificity, accuracy, RT_mean, nNaN

        if expDay != '2':
            idx_c += 1

    return statsDay, statsBlock, statsBlock_day2

#%%
# Test for subj 11
#statsDay11, statsBlock11, statsBlock_day211 = computeStatsBlocks('11')
#statsDay, statsBlock, statsBlock_day2 = computeStatsBlocks('07')

sub_all = ['07','08','11','13','14','15','16','17','18','19','21','22','23','24','25','26','27','30','31','32','33','34']

statsAll = {}

for idx,subjID in enumerate(sub_all):
    statsDay, statsBlock, statsBlock_day2 = computeStatsBlocks(subjID)

    statsAll[subjID] = statsBlock

# Mean response time per block, day 2
plt.plot(statsBlock_day2[:,3])

# Mean response time per block, day 1 and 3
plt.plot(statsBlock[0,:,3])
plt.plot(statsBlock[1,:,3])

# Sensitivity across blocks
plt.plot(statsBlock[0,:,0])
plt.plot(statsBlock[1,:,0])

# Accuracy across blocks
plt.plot(statsBlock[0,:,2])
plt.plot(statsBlock[1,:,2])

#%%
subjIDs_NF = ['07','08','11','13','14','16','19','22','26','27','30']
subjIDs_C = ['15','17','18','21','23','24','25','31','32','33','34']

def extractBehVal(day,wanted_measure):
    '''
    Day is
    1=0
    3=1

    for statsBlock

    and wanted_measure is
    0 = sens
    1 = spec
    2 = acc
    3 = RT mean
    4 = nNaN

    '''

    if day == 1:
        day_idx = 0
    if day == 3:
        day_idx = 1
    if day == 4:
        day_idx = 2

    if wanted_measure == 'sen':
        w_idx = 0
    if wanted_measure == 'spec':
        w_idx = 1
    if wanted_measure == 'acc':
        w_idx = 2
    if wanted_measure == 'rt':
        w_idx = 3
    if wanted_measure == 'nan':
        w_idx = 4

    subsAll = []
    subsNF = []
    subsC = []

    for key, value in statsAll.items():
        result = value[day_idx,:,w_idx]
        print(result.shape)
        subsAll.append(result)

        if key in subjIDs_NF:
            subsNF.append(result)
        if key in subjIDs_C:
            subsC.append(result)

    return subsAll, subsNF, subsC

#%% NOT block-wise, statsDay. Check whether this corresponds to the other (V2) beh measures.
os.chdir(saveDir)

statsDayAll = {}

for idx,subjID in enumerate(sub_all):
    statsDay, statsBlock, statsBlock_day2 = computeStatsBlocks(subjID)

    statsDayAll[subjID] = statsDay
#%%
def extractStatsDayAll(day_idx,wanted_measure):
    #sensitivity, specificity, accuracy, lure_RT_mean, nonlure_RT_mean, RT_mean, nKeypress, nNaN
    day_idx = day_idx-1

    if wanted_measure == 'sen':
        w_idx = 0
    if wanted_measure == 'spec':
        w_idx = 1
    if wanted_measure == 'acc':
        w_idx = 2
    if wanted_measure == 'rt_lure':
        w_idx = 3
    if wanted_measure == 'rt_nlure':
        w_idx = 4
    if wanted_measure == 'rt':
        w_idx = 5
    if wanted_measure == 'nkeypress':
        w_idx = 6
    if wanted_measure == 'nan':
        w_idx = 7

    subsAll = []
    subsNF = []
    subsC = []

    for key, value in statsDayAll.items():
#        print(value.shape)
        result = value[day_idx,w_idx]
#        print(result.shape)
        subsAll.append(result)

        if key in subjIDs_NF:
            subsNF.append(result)
        if key in subjIDs_C:
            subsC.append(result)

    return subsAll, subsNF, subsC
#%%
# Reality check
senAll_d1, senNF_d1, senC_d1 = extractStatsDayAll(1,'sen')
senAll_d3, senNF_d3, senC_d3 = extractStatsDayAll(3,'sen')

sen_feedback[:,0] # Sensitivity, feedback group, day1
sen_control[:,0]

sen_feedback[:,1]

# Checked 29April, legit. V2 and V3 analysis corresponds.

#%%
def make4Bars(wanted_measure,title,ylabel):
    '''
    Comparing day 1 and 3, NF and controls, using the statsDayAll structure and extract func.

    Connected lines bar plot

    '''
    all_d1, NF_d1, C_d1 = extractStatsDayAll(1,wanted_measure)
    all_d3, NF_d3, C_d3 = extractStatsDayAll(3,wanted_measure)

    print('NF mean day 1: ',round(np.mean(NF_d1),3))
    print('NF mean day 3: ',round(np.mean(NF_d3),3))
    print('C mean day 1: ',round(np.mean(C_d1),3))
    print('C mean day 3: ',round(np.mean(C_d3),3))

    y_min = np.min([np.min(all_d1),np.min(all_d3)])
    y_max = np.max([np.max(all_d1),np.max(all_d3)])

    # Connect lines
    plt.figure(random.randint(0,100))
    plt.ylabel(ylabel)
    plt.ylim([y_min-0.05,y_max+0.05])
#    plt.ylim([y_min-5,y_max+5])
    plt.xticks([1,2,3,4],['NF day 1','NF day 3', 'Control day 1', 'Control day 3'])
    plt.title(title)

    plt.bar(1,np.mean(NF_d1),color=(0,0,0,0),edgecolor='tomato')
    plt.bar(2,np.mean(NF_d3),color=(0,0,0,0),edgecolor='brown')
    plt.bar(3,np.mean(C_d1),color=(0,0,0,0),edgecolor='dodgerblue')
    plt.bar(4,np.mean(C_d3),color=(0,0,0,0),edgecolor='navy')

    plt.scatter(np.full(11,1),NF_d1,color='tomato')
    plt.scatter(np.full(11,2),NF_d3,color='brown')
    plt.scatter(np.full(11,3),C_d1,color='dodgerblue')
    plt.scatter(np.full(11,4),C_d3,color='navy')

    for i in range(11):
        plt.plot([(np.full(11,1))[i],(np.full(11,2))[i]], [(NF_d1)[i],(NF_d3)[i]],color='gray')
        plt.plot([(np.full(11,3))[i],(np.full(11,4))[i]], [(C_d1)[i],(C_d3)[i]],color='gray')

    t_fb = stats.ttest_rel(NF_d1,NF_d3)
    t_c = stats.ttest_rel(C_d1,C_d3)

    return plt, t_fb, t_c

def make2Bars(wanted_measure,title,ylabel):
    '''
    Comparing day 2, NF and controls, using the statsDayAll structure and extract func.
    '''

    all_d2, NF_d2, C_d2 = extractStatsDayAll(2,wanted_measure)

    print('NF mean day 2: ',round(np.nanmean(NF_d2),3))
    print('C mean day 2: ',round(np.mean(C_d2),3))

    y_min = np.nanmin(all_d2)
    y_max = np.nanmax(all_d2)

    # Connect lines
    plt.figure(random.randint(0,100))
    plt.ylabel(ylabel)
    plt.ylim([y_min-0.01,y_max+0.01])
#    plt.ylim([y_min-5,y_max+5])
    plt.xticks([1,2],['NF day 2','Control day 2'])
    plt.title(title)

    plt.bar(1,np.nanmean(NF_d2),color=(0,0,0,0),edgecolor='tomato')
    plt.bar(2,np.mean(C_d2),color=(0,0,0,0),edgecolor='dodgerblue')

    plt.scatter(np.full(11,1),NF_d2,color='tomato')
    plt.scatter(np.full(11,2),C_d2,color='dodgerblue')

    # Omit one subject from C?
    t = stats.ttest_ind(NF_d2,C_d2,nan_policy='omit')

    return plt, t, all_d2

#%%
pl, t_fb, t_c = make4Bars('rt','Overall response time','Response time (s)')
pl, t_fb, t_c = make4Bars('rt_lure','Response time for lures','Response time (s)')
pl, t_fb, t_c = make4Bars('rt_nlure','Response time for non lures','Response time (s)')
pl, t_fb, t_c = make4Bars('nkeypress','Number of total keypresses','Number keypresses')
pl, t_fb, t_c = make4Bars('nan','Number of total NaNs','Number ') # Not saved

pl, t_fb, t_c = make4Bars('sen','x','x')
pl, t_fb, t_c = make4Bars('spec','x','x')
pl, t_fb, t_c = make4Bars('acc','x','x')

#diff_fb_p=stats.ttest_rel(sen_feedback[:,0],sen_feedback[:,1])
#diff_c_p=stats.ttest_rel(sen_control[:,0],sen_control[:,1])

# Investigate day 2, using make2Bars and StatsDayAll (NOT block-wise)
pl, t, sen_all_d2 = make2Bars('sen','Sensitivity day 2','Sensitivity')
pl, t, acc_all_d2 = make2Bars('acc','Accuracy day 2','Accuracy')
pl, t, rt_all_d2 = make2Bars('rt','RT day 2','RT')
pl, t = make2Bars('nkeypress','Number of total keypresses','Number keypresses')

# Check whether this looks reasonable by checking one day 2 file manually. DONE.

#%% Is good decoding accuracy correlated with a good day 2 behavioral response?
# Omit 11
sen_all_d2_c = np.copy(sen_all_d2)
sen_all_d2_c = sen_all_d2_c[~np.isnan(sen_all_d2_c)]

# Acc
acc_all_d2_c = np.copy(acc_all_d2)
acc_all_d2_c = acc_all_d2_c[~np.isnan(acc_all_d2_c)]

# RT
rt_all_d2_c = np.copy(rt_all_d2)
rt_all_d2_c = rt_all_d2_c[~np.isnan(rt_all_d2_c)]

subsAll_c = np.copy(subsAll) # From EEG inv 18April
subsAll_c = np.delete(subsAll_c, 2)

plt.scatter(subsAll_c,sen_all_d2_c)
plt.ylabel('Sensitivity day 2')
plt.xlabel('Real time decoding accuracy, bias corrected')
plt.title('Sensitivity day 2 vs. RT decoding accuracy, N=21')

plt.scatter(subsAll_c,acc_all_d2_c)
plt.ylabel('Accuracy day 2')
plt.xlabel('Real time decoding accuracy, bias corrected')
plt.title('Accuracy day 2 vs. RT decoding accuracy, N=21')

# Plot RT vs decoding acc
plt.scatter(subsAll_c,rt_all_d2_c)
plt.ylabel('Response time day 2')
plt.xlabel('Real time decoding accuracy, bias corrected')
plt.title('Response time day 2 vs. RT decoding accuracy, N=21')

stats.linregress(acc_all_d2_c,subsAll_c)

np.corrcoef(sen_all_d2_c,subsAll_c)

stats.linregress(sen_all_d2_c,subsAll_c)

np.corrcoef(acc_all_d2_c,subsAll_c)

#%% Plot sensitivity block-wise, with individual lines for subjects, day1
subsAll, subsNF, subsC = extractBehVal(1,'sen')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(20)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Sensitivity across blocks, all participants, day 1')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 1')
plt.ylabel('Sensitivity')
plt.legend()

#%% sensitivity block-wise, with individual lines for subjects, day3
subsAll, subsNF, subsC = extractBehVal(3,'sen')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(21)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Sensitivity across blocks, all participants, day 3')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 3')
plt.ylabel('Sensitivity')
plt.legend()

#%% spec block-wise, with individual lines for subjects, day1
subsAll, subsNF, subsC = extractBehVal(1,'spec')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(23)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Specificity across blocks, all participants, day 1')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 1')
plt.ylabel('Specificity')
plt.legend()

#%% spec block-wise, with individual lines for subjects, day3
subsAll, subsNF, subsC = extractBehVal(3,'spec')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(24)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Specificity across blocks, all participants, day 3')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 3')
plt.ylabel('Specificity')
plt.legend()

#%% acc block-wise, with individual lines for subjects, day1
subsAll, subsNF, subsC = extractBehVal(1,'acc')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(23)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Accuracy across blocks, all participants, day 1')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 1')
plt.ylabel('Accuracy')
plt.legend()

#%% acc block-wise, with individual lines for subjects, day1
subsAll, subsNF, subsC = extractBehVal(3,'acc')

colorC = sns.color_palette("Blues",11)
colorNF = sns.color_palette("Reds",11)

# Plot NF subjects
plt.figure(23)
for j in range(len(subsNF)):
    plt.plot(subsNF[j],color=colorNF[j],linewidth=0.8)

plt.plot(np.mean(subsNF,axis=0),label='Mean NF group',color='red',linewidth=2.0)

# Plot C subjects
for i in range(len(subsC)):
    plt.plot(subsC[i],color=colorC[i],linewidth=0.8)

plt.plot(np.mean(subsC,axis=0),label='Mean control group',color='blue',linewidth=2.0)

plt.plot(np.mean(subsAll,axis=0),label='Mean all participants',color='black',linewidth=2.0)
plt.title('Accuracy across blocks, all participants, day 3')
plt.xticks(np.arange(0,16),[str(item) for item in np.arange(1,17)])
plt.xlabel('Block number, day 3')
plt.ylabel('Accuracy')
plt.legend()