# Demonstrates usage of py2jemris functionalities
# May be used for quick testing
# Gehua Tong
# May 18, 2020

from coil2xml import coil2xml
from seq2xml import seq2xml
from sim_jemris import sim_jemris
from pulseq_jemris_simulator import simulate_pulseq_jemris, create_and_save_phantom
from recon_jemris import recon_jemris
import phantom as pht
from pulseq_library import make_pulseq_irse, make_pulseq_se_oblique

import numpy as np
import matplotlib.pyplot as plt
from pypulseq.Sequence.sequence import Sequence
from scipy.io import loadmat, savemat


#from virtualscanner.core.constants import SERVER_SIM_BLOCH_PY2JEMRIS_PATH

import os
import h5py


utest_path = 'sim/utest_outputs'
sim_path = 'sim'


def utest_coil2xml():
    # Example on using coil2xml
    # Generate coil using B1 maps and plot
    # 4 channels with different B1 maps

    b1 = np.ones((32,32))
    XY = np.meshgrid(np.linspace(0,1,32), np.linspace(0,1,32))
    X = XY[0]
    Y = XY[1]

    # Define coil sensitivity maps (complex arrays, in general)
    b1_ch1 = np.sqrt(X**2 + Y**2)
    b1_ch2 = np.rot90(b1_ch1)
    b1_ch3 = np.rot90(b1_ch2)
    b1_ch4 = np.rot90(b1_ch3)

    coil2xml(b1maps=[b1_ch1, b1_ch2, b1_ch3, b1_ch4], fov=200, name='test_coil', out_folder=utest_path)

    # Generate sensmaps.h5 using JEMRIS command
    os.chdir(utest_path)
    print(os.system('dir'))
    out = os.system('jemris test_coil.xml')
    os.chdir('../..')
    print(out)


    # Load sensmaps.h5 and plot coil
    a = h5py.File(utest_path + '/sensmaps.h5', 'r')
    maps_magnitude = a['maps/magnitude']
    maps_phase = a['maps/phase']
    plt.figure(1)
    plt.title('Coil sensitivity maps')
    for u in range(4):
        plt.subplot(2,4,u+1)
        plt.gray()
        plt.imshow(maps_magnitude[f'0{u}'])
        plt.title(f'Magnitude Ch #{u+1}')
        plt.subplot(2,4,u+5)
        plt.gray()
        plt.imshow(maps_phase[f'0{u}'])
        plt.title(f'Phase Ch #{u+1}')
    plt.show()
    return

def utest_seq2xml():
    # Make a sequence
    seq = make_pulseq_irse(fov=0.256, n=16, thk=0.01, fa=15, tr=150, te=30, ti=10,
                           enc='xyz', slice_locs=None, write=False)

    # Convert to .xml format
    seq2xml(seq, seq_name='irse16_pulseq', out_folder=utest_path)



    # Use JEMRIS to generate sequence diagrams from .xml sequence
    os.chdir(utest_path)
    print(os.system('dir'))
    out = os.system(f'jemris -x -d id=1 -f irse16_pulseq irse16_pulseq.xml')
    print(out)
    os.chdir('../..')

    # Read sequence diagram and plot
    data = h5py.File(utest_path + '/irse16_pulseq.h5','r')
    diag = data['seqdiag']

    t = diag['T']
    gx = diag['GX']
    gy = diag['GY']
    gz = diag['GZ']
    rxp = diag['RXP']
    txm = diag['TXM']
    txp = diag['TXP']

    ylist = [txm, txp, gx, gy, gz, rxp]
    title_list = ['RF Tx magnitude', 'RF Tx phase', 'Gx', 'Gy', 'Gz', 'RF Rx phase']
    styles = ['r-', 'g-', 'k-', 'k-', 'k-', 'bx']
    plt.figure(1)
    for v in range(6):
        plt.subplot(6,1,v+1)
        plt.plot(t, ylist[v], styles[v])
        plt.title(title_list[v])
        plt.xlabel('Time')

    plt.show()


    return

def utest_sim_jemris():
    # Copy helping files in
    os.chdir(sim_path)
    out = os.system('copy uniform.xml utest_outputs')
    print(out)
    os.chdir('..')

    utest_phantom_output_h5()

    list_sim_orig = {'seq_xml': 'gre32.xml', 'pht_h5': 'cylindrical.h5', 'tx_xml':'uniform.xml',
                       'rx_xml': 'uniform.xml'}
    out = sim_jemris(list_sim_orig, working_folder = utest_path)
    os.chdir(utest_path)
    savemat('data32_orig.mat',out)
    print('Data is saved in py2jemris/sim/utest_outputs/data32_orig.mat')
    os.chdir('../..')
    return

def utest_pulseq_sim():
    # TODO this !
    # Demonstrates simulation pipeline using pulseq inputs

    # Define the same phantom
    phantom_info = {'fov': 0.256, 'N': 15, 'type': 'cylindrical', 'dim': 2, 'dir': 'z', 'loc': 0}
    sps =  'sim/utest_outputs/se_fov256mm_Nf15_Np15_TE50ms_TR200ms_FA90deg.seq'
    sim_name = 'utest_outputs'
    # Make sequence
    os.chdir(utest_path)
    make_pulseq_se_oblique(fov=0.256,n=15, thk=0.005, tr=0.2, te=0.05, fa=90,
                              enc='xyz', slice_locs=[0], write=True)


    os.chdir('../..')
    simulate_pulseq_jemris(seq_path=sps, phantom_info=phantom_info, sim_name=sim_name,
                           coil_fov=0.256)

    kk, im, images = recon_jemris(file='sim/' + sim_name + '/signals.h5', dims=[15, 15])

    savemat('sim/' + sim_name + '/utest_pulseq_sim_output.mat', {'images': images, 'kspace': kk, 'imspace': im})
    print('Simulation result is in py2jemris/sim/utest_outputs/utest_pulseq_sim_output.mat')

    # Plot results
    plt.figure(1)
    plt.gray()
    plt.imshow(np.squeeze(images))
    plt.show()

    return

def utest_phantom_output_h5():
    # Creates a virtual scanner phantom and save it as an .h5 file (per JEMRIS standard)
    phantom_info = {'fov': 0.256, 'N': 32, 'type': 'cylindrical', 'dim': 2, 'dir': 'z', 'loc': 0}
    create_and_save_phantom(phantom_info, out_folder=utest_path)
    return


if __name__ == '__main__':

    # Run all "utests"
    #utest_coil2xml() # Converts B1 map into .h5 and .xml files for JEMRIS
    #utest_phantom_output_h5() # Makes a virtual scanner phantom and converts it into .h5 format for JEMRIS
    #utest_seq2xml() # Makes a pypulseq sequence and converts it into .xml and .h5 files for JEMRIS
    #utest_sim_jemris() # Calls JEMRIS on command line using pre-made files
    utest_pulseq_sim() # Calls pipeline (INPUT: seq + phantom info + FOV ; OUTPUT: complex image space & k-space, images)
