import warnings
from qiskit import QuantumRegister, ClassicalRegister
from qiskit import QuantumCircuit, execute, Aer, transpile, IBMQ, assemble
from qiskit.tools.monitor import job_monitor
from qiskit.circuit.library import QFT
from qiskit.visualization import plot_bloch_multivector, plot_histogram, array_to_latex
warnings.filterwarnings("ignore", category=DeprecationWarning)
import numpy as np
import pandas as pd
import math
from math import sqrt
from scipy.stats import chi2_contingency, ttest_ind, chisquare, ttest_rel, normaltest

from statsmodels.stats.proportion import proportions_ztest
from statsmodels.stats.weightstats import ztest

pi = np.pi

def flip_endian(dict):
    newdict = {}
    for key in list(dict):
        newdict[key[::-1]] = dict.pop(key)
    return newdict

def set_measure_x(circuit, n):
    for num in range(n):
        circuit.h(num)

def set_measure_y(circuit, n):
    for num in range(n):
        circuit.sdg(num)
        circuit.h(num)

def qft_rotations(circuit, n):
    #if qubit amount is 0, then do nothing and return
    if n == 0:
        #set it to measure the x axis
        set_measure_x(qc, 2)
        qc.measure_all()
        return circuit
    n -= 1
    circuit.h(n)
    for qubit in range(n):
        circuit.cp(pi/2**(n-qubit), qubit, n)
    return qft_rotations(circuit, n)

backend = Aer.get_backend('aer_simulator') 
qc = QuantumCircuit(2)
qc.x(0)
circ = qft_rotations(qc,2)#call the recursive qft method
print(circ)
#set it to measure the x axis
set_measure_x(qc, 2)

job = execute(qc, backend, shots=100000)#run the circuit 1000000 times
print(flip_endian(job.result().get_counts()))#return the result counts

def measure_z(circuit, qubit_indexes):
    cBitIndex = 0
    for index in qubit_indexes:
        # print(index)
        circuit.measure(index, cBitIndex)
        cBitIndex+=1
    return circuit

def measure_x(circuit, qubitIndexes):
    cBitIndex = 0
    for index in qubitIndexes:
        circuit.h(index)
        circuit.measure(index, cBitIndex)
        cBitIndex+=1
    return circuit

def measure_y(circuit, qubit_indexes):
    cBitIndex = 0
    for index in qubit_indexes:
        circuit.sdg(index)
        circuit.h(index)
        circuit.measure(index, cBitIndex)
        cBitIndex+=1
    return circuit

qc1 = QuantumCircuit(2,2)
qc1.h(0)
qc1.cnot(0,1)
qc1.measure(0,0)
qc1.measure(1,1)
# print(qc1)

qc2 = QuantumCircuit(2,2)
qc2.x(0)
qc2.h(0)
qc2.cnot(0,1)
# qc2.swap(0,1)
qc2.measure(0,1)
qc2.measure(1,0)
# qc2.measure_all()
# print(qc2)

backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute([qc1, qc2], backend_sim, shots=10)
result_sim = job_sim.result()
counts1 = result_sim.get_memory(qc1,memory=True)
counts2 = result_sim.get_memory(qc2,memory=True)
print(counts1, counts2)

qc3 = QuantumCircuit(2,2)
qc3.h(1)
qc3.h(0)
qubits_to_assert = [0,1]
yQuantumCircuit = measure_y(qc3.copy(), qubits_to_assert)
xQuantumCircuit = measure_x(qc3.copy(), qubits_to_assert)
zQuantumCircuit = measure_z(qc3, qubits_to_assert)

yJob = execute(yQuantumCircuit, backend, shots=20, memory=True)
yMemory = yJob.result().get_memory()
yCounts = yJob.result().get_counts()
print(type(yMemory))

def qft_dagger(qc, n):
    for j in range(n):
        for m in range(j):
            qc.cp(math.pi/float(2**(j-m)), m, j)
        qc.h(j)
    return qc

q = QuantumCircuit(2)

# qc.x(0)
q.x(0)
q.x(1)
q.measure_all()
print(q)
qft_rotations(q,2)
q2 = qft_dagger(q,2)# #call the recursive qft method


backend = Aer.get_backend('aer_simulator') 
job = execute([q,q2], backend, shots=1000000)#run the circuit 1000000 times
counts = job.result().get_counts(q)
counts2 = job.result().get_counts(q2)
print(counts)#return the result counts
print(counts2)

def getDf(qc,qubits_to_assert,measurements_to_make,backend):

    ## classical register must be of same length as amount of qubits to assert
    ## if there is no classical register add them according to length of qubit list
    if (qc.num_clbits == 0):
        qc.add_register(ClassicalRegister(len(qubits_to_assert)))
    elif (len(qubits_to_assert) != 2):
        raise ValueError("QuantumCircuit classical register must be of length 2")

    ## divide measurements to make by 3 as we need to run measurements twice, one for x and one for y
    measurements_to_make = measurements_to_make // 3
    yQuantumCircuit = measure_y(qc.copy(), qubits_to_assert)
    xQuantumCircuit = measure_x(qc.copy(), qubits_to_assert)
    zQuantumCircuit = measure_z(qc, qubits_to_assert)

    yJob = execute(yQuantumCircuit, backend, shots=measurements_to_make, memory=True)
    yMemory = yJob.result().get_memory()
    yCounts = yJob.result().get_counts()
    # print("yCounts",yCounts)

        ## get x axis results
    xJob = execute(xQuantumCircuit, backend, shots=measurements_to_make, memory=True)
    xMemory = xJob.result().get_memory()
    xCounts = xJob.result().get_counts()
    # print("xCounts",xCounts)
    ## get z axis results
    zJob = execute(zQuantumCircuit, backend, shots=measurements_to_make, memory=True)
    zMemory = zJob.result().get_memory()
    zCounts = zJob.result().get_counts()
    # print("zCounts",zCounts)

    resDf = pd.DataFrame(columns=['0','1','+','i','-','-i'])
    # resDf = pd.DataFrame(columns=['zAxis','xAxis','yAxis'])
    classical_qubit_index = 1
    for qubit in qubits_to_assert:
        zero_amount, one_amount, plus_amount, i_amount, minus_amount, minus_i_amount = 0,0,0,0,0,0
        for experiment in xCounts:
            if (experiment[2-classical_qubit_index] == '0'):
                plus_amount += xCounts[experiment]
            else:
                minus_amount += xCounts[experiment]
        for experiment in yCounts:
            if (experiment[2-classical_qubit_index] == '0'):
                i_amount += yCounts[experiment]
            else:
                minus_i_amount += yCounts[experiment]
        for experiment in zCounts:
            if (experiment[2-classical_qubit_index] == '0'):
                zero_amount += zCounts[experiment]
            else:
                one_amount += zCounts[experiment]
        df = {'0':zero_amount, '1':one_amount,
              '+':plus_amount, 'i':i_amount,
              '-':minus_amount,'-i':minus_i_amount}
        # df = {'zAxis':zero_amount+one_amount,
        #       'xAxis':plus_amount+ minus_amount,
        #       'yAxis':i_amount+minus_i_amount}

        resDf = resDf.append(df, ignore_index = True)
        classical_qubit_index+=1

    resDf['+'] = resDf['+'].astype(int)
    resDf['i'] = resDf['i'].astype(int)
    resDf['-'] = resDf['-'].astype(int)
    resDf['-i'] = resDf['-i'].astype(int)
    resDf['0'] = resDf['0'].astype(int)
    resDf['1'] = resDf['1'].astype(int)
    # resDf['zAxis'] = resDf['zAxis'].astype(int)
    # resDf['xAxis'] = resDf['xAxis'].astype(int)
    # resDf['yAxis'] = resDf['yAxis'].astype(int)
    return resDf


# Completed but more testing required
## assert that qubits are equal
def assertEqual(backend, quantumCircuit1,quantumCircuit2, qubits_to_assert, measurements_to_make, experiments, alpha):
    ## needs to make at least 2 measurements, one for x axis, one for y axis
    ## realistically we need more for any statistical significance
    if (measurements_to_make < 2):
        raise ValueError("Must make at least 2 measurements")

    # makes sure qubits_to_assert is a list
    if (not isinstance(qubits_to_assert, list)):
        qubits_to_assert = [qubits_to_assert]

    measqc1 = measure_z(quantumCircuit1.copy(),qubits_to_assert)
    measqc2 = measure_z(quantumCircuit2.copy(),qubits_to_assert)
    # quantumCircuit1.measure()
    # quantumCircuit2.measure()
    job_sim = execute([measqc1, measqc2], backend, shots=100)
    result_sim = job_sim.result()
    counts1 = result_sim.get_counts(measqc1)
    print("c1:", counts1)
    counts2 = result_sim.get_counts(measqc2)
    print("c2:", counts2)
    dict3={k:[v] for k,v in counts2.items()}
    for k,v in counts1.items():
        dict3[k]= dict3[k] + [v] if k in dict3 else [v]

    print(dict3)
    # measurements=[]
    for k,v in dict3.items():
        if len(v) <= 1:
            raise(AssertionError("Measurements are not in the same states"))
        # measurements.append(v)
    
    q1Vals = []
    q2Vals = []

    # Get Df is a function I made to return a dataframe containing measurements for each each qubit across all axes and I use 5 such different measurements for my dataset
    for i in range(experiments):
        resDf1 = getDf(quantumCircuit1,qubits_to_assert,measurements_to_make,backend)
        # print("resdf 1:")
        # print(resDf1)
        q1Vals.extend(resDf1['1'].tolist()+resDf1['-'].tolist()+resDf1['-i'].tolist())
        
        resDf2 = getDf(quantumCircuit2,qubits_to_assert,measurements_to_make,backend)
        # print("resdf 2: ")
        # print(resDf2)
        q2Vals.extend(resDf2['1'].tolist()+resDf2['-'].tolist()+resDf2['-i'].tolist())
        # resDf1['1']
        # print(resDf1['1'].tolist())
        # q2Vals.extend([resDf1.at[1,'1'],resDf1.at[1,'-'],resDf1.at[1,'-i']])

        # zStat_z, zPvalue = proportions_ztest(count=[resDf1['1'][0],resDf2['1'][1]], nobs=[measurements_to_make, measurements_to_make],  alternative='two-sided')

    print("q1: ",q1Vals)
    print("q2: ",q2Vals)
    tTest, pValue = ttest_ind(q1Vals, q2Vals, alternative = 'two-sided') # Apply t test
    # zStat_z, zPvalue = proportions_ztest(count=[q1Vals,q2Vals], nobs=[measurements_to_make, measurements_to_make],  alternative='two-sided')
    print("stat: ",tTest ,"pValue: ", pValue)
    if pValue > alpha:
        print("The two qubits are equal (fail to reject null hypothesis) ")
    else:
        print("There is a significant difference between the two qubits (reject null hypothesis)")

qc = QuantumCircuit(2,2)
backend = Aer.get_backend('aer_simulator')
# qc.initialize([0, 1/np.sqrt(2), -1.j/np.sqrt(2), 0], qc.qubits)
qc.x(0)
qc.h(0)
# qc.h(1)
qc.cnot(0,1)
# qc.p(0.5*2*math.pi/100, 1)
# qc.h(1)
# qc.p(10*2*math.pi/100, 0)
# qc.p(20*2*math.pi/100, 1)
qc.measure(0,0)
qc.measure(1,1)
# qc.measure_all()

qc1 = QuantumCircuit(2,2)
# qc1.x(1)
qc1.h(0)
qc1.cnot(0,1)
# qc1.measure_all()
qc1.measure(0,0)
qc1.measure(1,1)


qc3 = QuantumCircuit(2,2)
qc3.x(0)
qc3.x(1)
qc4=qft_dagger(qc3,2)

# from qiskit.quantum_info import Operator

# Op1 = Operator(qc)
# Op2 = Operator(qc1)

# if Op1.equiv(Op2):
#     print("True")
# else:
#     print("False")
assertEqual(backend, qc1,qc2, [0,1], 30000, 30, 0.05)
# assertEntangled(backend,circ,[1,0],3000,10,0.05)

qc1 = QuantumCircuit(2,2)
qc1.x(0)
qc1.h(0)
qc1.cnot(0,1)
# qc1.h(1)
print(qc1)
# qc1.measure_z()
qc1.measure(0,0)
qc1.measure(1,1)
# qc1.copy()
job = execute(qc1,backend,shots=10000,memory=True)
counts = job.result().get_counts()
# counts2 = job.result().get_counts(c1)
print(counts)
# zQuantumCircuit1 = measure_z(qc1, qubits_to_assert)
# zJob1 = execute(zQuantumCircuit1,backend,shots=10000,memory=True)
# zCounts1=zJob1.result().get_counts()
# print("z1", zCounts1)
# xQuantumCircuit1 = measure_x(qc1, qubits_to_assert)
# xJob1 = execute(xQuantumCircuit1,backend,shots=10000,memory=True)
# xCounts1=xJob1.result().get_counts()
# print("x1", xCounts1)
# yQuantumCircuit1 = measure_y(qc1, qubits_to_assert)
# yJob1 = execute(yQuantumCircuit1,backend,shots=10000,memory=True)
# yCounts1=yJob1.result().get_counts()
# print("y1", yCounts1)

qc2 = QuantumCircuit(2,2)
qc2.x(1)
qc2.h(0)
qc2.cnot(1,0)
print(qc2)
# qc2.h(0)
qc2.measure(0,0)
qc2.measure(1,1)

job2 = execute(qc2,backend,shots=10000,memort=True)
counts2 = job2.result().get_counts()
print(counts2)

# zQuantumCircuit2 = measure_z(qc2, qubits_to_assert)
# zJob2 = execute(zQuantumCircuit2,backend,shots=10000,memory=True)
# zCounts2=zJob2.result().get_counts()
# print("z2",zCounts2)
# xQuantumCircuit2 = measure_x(qc2, qubits_to_assert)
# xJob2 = execute(xQuantumCircuit2,backend,shots=10000,memory=True)
# xCounts2=xJob2.result().get_counts()
# print("x2", xCounts2)
# yQuantumCircuit2 = measure_y(qc2, qubits_to_assert)
# yJob2 = execute(yQuantumCircuit2,backend,shots=10000,memory=True)
# yCounts2=yJob2.result().get_counts()
# print("y2", yCounts2)

# tempD = { k: [counts[k],counts2[k]] for k in counts}
# print(tempD)
# from collections import defaultdict
# dd = defaultdict(list)
# dics=[counts,counts2]
# for dic in dics:
#     for key,val in dic.items():
#         dd[key].append(val)

# print(dd)

dict3={k:[v] for k,v in counts2.items()}
for k,v in counts.items():
    dict3[k]= dict3[k] + [v] if k in dict3 else [v]

print(dict3)
measurements=[]
for k,v in dict3.items():
    if len(v) <= 1:
        raise(AssertionError("There exists key(s) with just 1 measurement"))
    measurements.append(v)
meas1 = measurements[0]
meas2 = measurements[1]
size = [10000,10000]
# testStat,pValue1 = proportions_ztest(meas1,size,alternative='two-sided')
# testStat,pValue2 = proportions_ztest(meas2,size,alternative='two-sided')
zStat_z, pValue1 = proportions_ztest(count=[meas1[0],meas1[1]],nobs=size, alternative='two-sided')
zStat_z, pValue2 = proportions_ztest(count=[meas2[0],meas2[1]],nobs=size, alternative='two-sided')
print(pValue1)
print(pValue2)
if pValue1 > 0.05 and pValue2 > 0.05:
    print("The two qubits are equal (fail to reject null hypothesis) ")
elif(pValue1<=0.05):
    print("There is a significant difference between the two qubits (reject null hypothesis)")
elif (pValue2 <= 0.05):
    print("There is a significant difference between the two qubits (reject null hypothesis)")

# qcList = [qc1,qc2]
# index=0
# for i in qcList:
#     index+=1
#     measurements_to_make=30000
#     qubits_to_assert=[0,1]
#     measurements_to_make = measurements_to_make // 3
#     yQuantumCircuit = measure_y(i.copy(), qubits_to_assert)
#     xQuantumCircuit = measure_x(i.copy(), qubits_to_assert)
#     zQuantumCircuit = measure_z(i, qubits_to_assert)

#     yJob = execute(yQuantumCircuit, backend, shots=measurements_to_make, memory=True)
#     yMemory = yJob.result().get_memory()
#     yCounts = yJob.result().get_counts()
#     print("y counts for", index, yCounts)

#         ## get x axis results
#     xJob = execute(xQuantumCircuit, backend, shots=measurements_to_make, memory=True)
#     xMemory = xJob.result().get_memory()
#     xCounts = xJob.result().get_counts()
#     print("x counts for", index,xCounts)
#     ## get z axis results
#     zJob = execute(zQuantumCircuit, backend, shots=measurements_to_make, memory=True)
#     zMemory = zJob.result().get_memory()
#     zCounts = zJob.result().get_counts()
#     print("z counts for", index,zCounts)


# for i in range(5):
#     job_sim = execute([qc, qc1], backend_sim, shots=10000)
#     result_sim = job_sim.result()
#     counts1 = result_sim.get_counts(qc)
#     # print(counts1)
#     yo.extend(list(counts1.values()))
#     # print(yo)
#     counts2 = result_sim.get_counts(qc1)
#     print(counts2)
#     yo2.extend(list(counts2.values()))
#     # print(yo2)
#     # print(counts1, counts2)



qc1 = QuantumCircuit(2,2)
qc1.x(0)
qc1.h(0)
qc1.cnot(0,1)
# qc1.h(1)
print(qc1)
qc1.measure(0,0)
qc1.measure(1,1)

qc2 = QuantumCircuit(2,2)
# qc2.x(1)
qc2.h(0)
qc2.cnot(0,1)
print(qc2)
# qc2.h(0)
qc2.measure(0,0)
qc2.measure(1,1)

yo=[]
yo2=[]
for i in range(2):
    job_sim = execute([qc1.copy(), qc2.copy()], backend, shots=10000)
    result_sim = job_sim.result()
    counts1 = result_sim.get_counts(qc1)
    print(i,"c1:", counts1)
    counts2 = result_sim.get_counts(qc2)
    print(i,"c2:",counts2)
    dict3={k:[v] for k,v in counts2.items()}
    for k,v in counts1.items():
        dict3[k]= dict3[k] + [v] if k in dict3 else [v]

    print(dict3)
    measurements=[]
    for k,v in dict3.items():
        if len(v) <= 1:
            raise(AssertionError("There exists key(s) with just 1 measurement"))
        measurements.append(v)
    # print("meas",measurements)

    resDf1 = getDf(qc1,[0,1],30000,backend)
    print("resdf1:")
    print(resDf1)
    resDf2 = getDf(qc2,[0,1],30000,backend)
    print("resdf2:")
    print(resDf2)
    yo.extend(resDf1['1'].tolist()+resDf1['-'].tolist()+resDf1['-i'].tolist())
    yo2.extend(resDf2['1'].tolist()+resDf2['-'].tolist()+resDf2['-i'].tolist())
print("yo:",yo)
print("yo2:",yo2)

tTest, pValue = ttest_ind(yo, yo2, alternative = 'two-sided') # Apply t test
print("stat: ",tTest, "pValue: ", pValue)
if pValue > 0.05:
    print("The two qubits are equal (fail to reject null hypothesis) ")
else:
    print("There is a significant difference between the two qubits (reject null hypothesis)")

from qiskit.aqua.components.uncertainty_models import NormalDistribution

q = QuantumRegister(2)
c= ClassicalRegister(2)
qc2 = QuantumCircuit(q,c)
qc2.x(0)
qc2.h(0)
# qc2.h(0)
qc2.cnot(0,1)
normal = NormalDistribution(num_target_qubits=2,mu=0,sigma=1,low=-1,high=1)
normal.build(qc2,q)
print(qc2)
# qc2.h(0)
qc2.measure(0,0)
qc2.measure(1,1)


q1=[]
q2=[]
resDf2 = getDf(qc2,[0,1],10000,backend)
print("resdf2:")
print(resDf2)
job = execute(qc2,backend,shots=10000)
result = job.result()
counts1 = result.get_counts()
q1.extend(counts1.values())
print(q1)

# q1 = np.array([488, 488, 520, 508, 509, 521, 495, 495, 519, 529, 497, 522, 472, 472, 501, 509, 511, 480, 516, 516, 491, 513, 487, 493])
# q2 = np.array([498, 502, 475, 477, 497, 524, 492, 508, 511, 490, 533, 491, 482, 518, 500, 513, 506, 515, 484, 516, 488, 503, 499, 497])

# q1= np.array([4897, 4897, 4992, 4998, 4940, 5092, 5014, 5014, 4939, 5047, 4970, 4938, 5015, 5015, 4962, 4956, 5057, 4993, 5086, 5086, 4961, 5069, 4939, 4979, 4984, 4984, 4943, 4965, 5010, 4956])
# q2=  np.array([5098, 10000, 5075, 5044, 5087, 5081, 5013, 10000, 5011, 4948, 5042, 4944, 5043, 10000, 5002, 4980, 4991, 5015, 5003, 10000, 4933, 4961, 5037, 5024, 4997, 10000, 5044, 5019, 4989, 4966])

# q3 = np.array([483, 483, 508, 531, 469, 501, 517, 517, 492, 469, 531, 499, 492, 492, 486, 528, 505, 505, 508, 508, 514, 472, 495, 495, 501, 501, 498, 486, 522, 475, 499, 499, 502, 514, 478, 525, 513, 513, 508, 529, 487, 524, 487, 487, 492, 471, 513, 476])
# q4 = np.array([504, 496, 509, 484, 519, 501, 496, 504, 491, 516, 481, 499, 521, 479, 481, 507, 483, 507, 479, 521, 519, 493, 517, 493, 482, 518, 523, 506, 486, 502, 518, 482, 477, 494, 514, 498, 515, 485, 486, 468, 497, 488, 485, 515, 514, 532, 503, 512])

# q5 = np.array([5062, 5062, 4989, 4967, 4969, 5024, 4938, 4938, 5011, 5033, 5031, 4976, 5016, 5016, 4956, 4998, 5083, 5006, 4984, 4984, 5044, 5002, 4917, 4994, 4992, 4992, 4987, 4988, 4995, 5073, 5008, 5008, 5013, 5012, 5005, 4927, 5014, 5014, 4982, 5093, 5085, 4915, 4986, 4986, 5018, 4907, 4915, 5085, 5092, 5092, 5003, 4923, 5081, 5014, 4908, 4908, 4997, 5077, 4919, 4986])
# q6 = np.array([4994, 5006, 4907, 5012, 4982, 4988, 5006, 4994, 5093, 4988, 5018, 5012, 4988, 5012, 4988, 4965, 4962, 5033, 5012, 4988, 5012, 5035, 5038, 4967, 4979, 5021, 4976, 4978, 5042, 4976, 5021, 4979, 5024, 5022, 4958, 5024, 4801, 5199, 4953, 4971, 4968, 5083, 5199, 4801, 5047, 5029, 5032, 4917, 4961, 5039, 4986, 5018, 4961, 5030, 5039, 4961, 5014, 4982, 5039, 4970])

# #both normal
q1=np.array([4902, 5098, 4908, 5042, 5013, 4993, 5098, 4902, 5092, 4958, 4987, 5007, 5078, 4922, 4956, 4979, 4984, 4890, 4922, 5078, 5044, 5021, 5016, 5110, 4912, 5088, 5023, 5068, 5101, 5039, 5088, 4912, 4977, 4932, 4899, 4961, 5028, 4972, 5046, 5020, 5085, 4969, 4972, 5028, 4954, 4980, 4915, 5031, 5015, 4985, 4996, 4939, 5003, 5002, 4985, 5015, 5004, 5061, 4997, 4998])
q2=np.array([5011, 4989, 4981, 5002, 4984, 5010, 4989, 5011, 5019, 4998, 5016, 4990, 5023, 4977, 4960, 5011, 4944, 4914, 4977, 5023, 5040, 4989, 5056, 5086, 4944, 5056, 4946, 5034, 4984, 5071, 5056, 4944, 5054, 4966, 5016, 4929, 4983, 5017, 5108, 5099, 5097, 5112, 5017, 4983, 4892, 4901, 4903, 4888, 4995, 5005, 4976, 5001, 4909, 5075, 5005, 4995, 5024, 4999, 5091, 4925])

# q9= np.array([5064, 5064, 4968, 5067, 5031, 5055, 4936, 4936, 5032, 4933, 4969, 4945, 4914, 4914, 5007, 5066, 5053, 5103, 5086, 5086, 4993, 4934, 4947, 4897, 4970, 4970, 5012, 5057, 4987, 5032, 5030, 5030, 4988, 4943, 5013, 4968, 5039, 5039, 4987, 5004, 4993, 5050, 4961, 4961, 5013, 4996, 5007, 4950, 5084, 5084, 5012, 5035, 4972, 4979, 4916, 4916, 4988, 4965, 5028, 5021])
# q10=  np.array([4967, 10000, 4950, 4979, 4892, 4925, 5033, 0, 5050, 5021, 5108, 5075, 4953, 10000, 5069, 4994, 5009, 4912, 5047, 0, 4931, 5006, 4991, 5088, 5004, 10000, 5087, 4976, 4996, 4976, 4996, 0, 4913, 5024, 5004, 5024, 4995, 10000, 5054, 4979, 4950, 4984, 5005, 0, 4946, 5021, 5050, 5016, 5013, 10000, 4956, 4991, 5071, 5011, 4987, 0, 5044, 5009, 4929, 4989])


# q11=np.array([4958, 4958, 5037, 5058, 4987, 5007, 5050, 5050, 4975, 4978, 5006, 5026, 4940, 4940, 5047, 4957, 4970, 4964, 5069, 5069, 4977, 5057, 4919, 4960, 5021, 5021, 5030, 4942, 4917, 4971])
resDf=pd.DataFrame(columns=['q1','q2'])
# df1=pd.DataFrame(columns=['q1'])
df1={'q1':q3,'q2':q4}
# df2=pd.DataFrame(columns=['q2'])
# df2={'q2':[1,2,3,4,5]}
resDf = resDf.append(df1,ignore_index=True)
# resDf = resDf.append(df2,ignore_index=True)
print(resDf)
from sklearn.preprocessing import PowerTransformer

# pt = PowerTransformer(method='yeo-johnson')
# pt2 = PowerTransformer(method='yeo-johnson')
# q11=q11.reshape(-1,1)
# pt2.fit(q11)
# transf2=pt2.transform(q11)
from scipy.stats import rankdata
n=len(q1)
newQ1 = (rankdata(q1)/(n+1))*2 -1
newQ1 = np.arctanh(newQ1)
# k2,p2 = normaltest(transf2)
k2,p2 = normaltest(newQ1)
print("lol:",p2)
# interpret
alpha = 0.05
if p2 > alpha:
    print('Sample looks Gaussian (fail to reject H0)')
else:
    print('Sample does not look Gaussian (reject H0)')

# q10=q10.reshape(-1,1)
# pt.fit(q10)
# transf1=pt.transform(q10)
# n=len(q2)
newQ2 = (rankdata(q2)/(n+1))*2 -1
newQ2 = np.arctanh(newQ2)
k1,p1 = normaltest(newQ2)
print("lol:",p1)

if p1 > alpha:
    print('Sample looks Gaussian (fail to reject H0)')
else:
    print('Sample does not look Gaussian (reject H0)')

ttest,pVal = ttest_ind(newQ1,newQ2,alternative='two-sided')
print("stat: ",tTest, "pValue: ", pValue)
if pVal > 0.05:
    print("The two qubits are equal (fail to reject null hypothesis) ")
else:
    print("There is a significant difference between the two qubits (reject null hypothesis)")
# qc1.x(0)
