def residual_quartic(param):
    '''Function which computes the residual (as sum of squares) comparing the
    ratio of expt to theoretical intensity ratio to the sensitivity  profile
    modelled as  a line, ( 1+ c1*x + c2*x**2 + c3*x**3 + c4*x**4 )

    param : T, c1, c2, c3, c4

    '''
    TK = param[0]

    sosD2 = compute_series_para.sumofstate_D2(TK)
    sosHD = compute_series_para.sumofstate_HD(TK)
    sosH2 = compute_series_para.sumofstate_H2(TK)

    computed_D2_o1s1 = compute_series_para.spectra_D2_o1s1(
        TK, OJ_D2, SJ_D2, sosD2)
    computed_D2_q1 = compute_series_para.D2_Q1(TK, QJ_D2, sosD2)

    computed_HD_o1s1 = compute_series_para.spectra_HD_o1s1(
        TK, OJ_HD, SJ_HD, sosHD)
    computed_HD_q1 = compute_series_para.HD_Q1(TK, QJ_HD, sosHD)

    computed_H2_o1 = compute_series_para.H2_O1(TK, OJ_H2, sosH2)
    computed_H2_q1 = compute_series_para.H2_Q1(TK, QJ_H2, sosH2)

    # --------------------------------------------------
    #   generate the matrix of ratios

    trueR_D2_o1s1 = gen_intensity_mat(computed_D2_o1s1, 2)
    expt_D2_o1s1 = gen_intensity_mat(dataD2_o1s1, 0)
    trueR_D2_q1 = gen_intensity_mat(computed_D2_q1, 2)
    expt_D2_q1 = gen_intensity_mat(dataD2_q1, 0)
    # --------------------------------------------------
    trueR_HD_o1s1 = gen_intensity_mat(computed_HD_o1s1, 2)
    expt_HD_o1s1 = gen_intensity_mat(dataHD_o1s1, 0)
    trueR_HD_q1 = gen_intensity_mat(computed_HD_q1, 2)
    expt_HD_q1 = gen_intensity_mat(dataHD_q1, 0)
    # --------------------------------------------------
    trueR_H2_o1 = gen_intensity_mat(computed_H2_o1, 2)
    expt_H2_o1 = gen_intensity_mat(dataH2_o1, 0)
    trueR_H2_q1 = gen_intensity_mat(computed_H2_q1, 2)
    expt_H2_q1 = gen_intensity_mat(dataH2_q1, 0)
    # --------------------------------------------------

    #   take ratio of expt to calculated

    I_D2_q1 = np.divide(expt_D2_q1, trueR_D2_q1)
    I_D2_o1s1 = np.divide(expt_D2_o1s1, trueR_D2_o1s1)

    I_HD_q1 = np.divide(expt_HD_q1, trueR_HD_q1)
    I_HD_o1s1 = np.divide(expt_HD_o1s1, trueR_HD_o1s1)

    I_H2_q1 = np.divide(expt_H2_q1, trueR_H2_q1)
    I_H2_o1 = np.divide(expt_H2_o1, trueR_H2_o1)

    #   remove redundant elements
    I_D2_q1 = clean_mat(I_D2_q1)
    I_HD_q1 = clean_mat(I_HD_q1)
    I_H2_q1 = clean_mat(I_H2_q1)

    I_D2_o1s1 = clean_mat(I_D2_o1s1)
    I_HD_o1s1 = clean_mat(I_HD_o1s1)
    I_H2_o1 = clean_mat(I_H2_o1)
    # --------------------------------------------------

    # generate sensitivity matrix using true data
    sD2_q1 = gen_s_quartic(computed_D2_q1, param)
    sHD_q1 = gen_s_quartic(computed_HD_q1, param)
    sH2_q1 = gen_s_quartic(computed_H2_q1, param)

    sD2_o1s1 = gen_s_quartic(computed_D2_o1s1, param)
    sHD_o1s1 = gen_s_quartic(computed_HD_o1s1, param)
    sH2_o1 = gen_s_quartic(computed_H2_o1, param)
    # --------------------------------------------------
    eD2_q1 = (np.multiply(1, I_D2_q1) - sD2_q1)
    eHD_q1 = (np.multiply(1, I_HD_q1) - sHD_q1)
    eH2_q1 = (np.multiply(1, I_H2_q1) - sH2_q1)

    eD2_o1s1 = (np.multiply(weight, I_D2_o1s1) - sD2_o1s1)
    eHD_o1s1 = (np.multiply(weight, I_HD_o1s1) - sHD_o1s1)
    eH2_o1 = (np.multiply(1, I_H2_o1) - sH2_o1)
    # --------------------------------------------------

    eD2_o1s1 = clean_mat(eD2_o1s1)
    eD2_q1 = clean_mat(eD2_q1)

    eHD_o1s1 = clean_mat(eHD_o1s1)
    eHD_q1 = clean_mat(eHD_q1)

    eH2_q1 = clean_mat(eH2_q1)
    eH2_o1 = clean_mat(eH2_o1)

    # --------------------------------------------------

    E = np.sum(np.abs(eD2_q1)) + np.sum(np.abs(eHD_q1)) \
        + np.sum(np.abs(eH2_q1)) + np.sum(np.abs(eD2_o1s1)) \
        + np.sum(np.abs(eHD_o1s1)) + + np.sum(np.abs(eH2_o1))

    return (E)
wMat_D2 = 1
wMat_HD = 1
wMat_H2 = 1

# checks for input done here

# generate calculated data for the entered J values

sosD2 = compute_series_para.sumofstate_D2(299)
sosHD = compute_series_para.sumofstate_HD(299)
sosH2 = compute_series_para.sumofstate_H2(299)

print(sosD2, sosHD, sosH2)

# ----------------------------------------
computed_D2_o1s1 = compute_series_para.spectra_D2_o1s1(299, OJ_D2, SJ_D2,
                                                       sosD2)
computed_D2_q1 = compute_series_para.D2_Q1(299, QJ_D2, sosD2)

computed_HD_o1s1 = compute_series_para.spectra_HD_o1s1(299, OJ_HD, SJ_HD,
                                                       sosHD)

computed_HD_q1 = compute_series_para.HD_Q1(299, QJ_HD, sosHD)

computed_H2_o1 = compute_series_para.H2_O1(299, OJ_H2, sosH2)
computed_H2_q1 = compute_series_para.H2_Q1(299, QJ_H2, sosH2)
# ----------------------------------------

# checks for dimension match done here
if (computed_D2_o1s1.shape[0] != dataD2_o1s1.shape[0]):
    print('D2 : Dimension of input data does not match with the calculated\
           spectra. Check input expt data or the J-indices entered.')