#!/usr/bin/env python

# This library contains functions for creating either an InstaCorr
# (IC) or Graph View (GV) driver script for the AP results directory.
#
auth = 'PA Taylor'
#ver = 2.0 
# [June 25, 2023] merged from earlier versions of script writing
ver = 2.1
# [June 10, 2025] remove the '-no1D' opt, so we can pick ideal time series
#
#########################################################################


import os, copy
import sys
import glob
import json
import subprocess

from afnipy import lib_apqc_tcsh       as lat

# ========================================================================
# some simple mappings of names and abbrevs

DICT_proc_type = {
    'IC' : 'InstaCorr',
    'GV' : 'GraphView',
}

LIST_input_type = ['pbrun', 'errts']

##########################################################################

# some utility bits

# check valid proc_type: IC, GV, etc.
def is_valid_proc_type( proc_type, do_warn=1, do_exit=0 ):
    if proc_type in DICT_proc_type.keys() : 
        return True
    else: 
        if do_warn :
            print('+* WARN: unrecognized proc_type:', proc_type)
        if do_exit :
            sys.exit(3)
        return False

# check valid input_type: errts, pbrun, etc.
def is_valid_input_type( input_type, do_warn=1, do_exit=0 ):
    if input_type in LIST_input_type : 
        return True
    else: 
        if do_warn :
            print('+* WARN: unrecognized input_type:', input_type)
        if do_exit :
            sys.exit(3)
        return False

# single check for validity
def is_valid_proc_and_input(proc_type, input_type, do_warn=1 ):
    val = is_valid_input_type(input_type, do_warn=do_warn) 
    val = val and is_valid_proc_type(proc_type, do_warn=do_warn) 
    return val 

# check if ap_ssdict entered (needed sometimes here)
def is_valid_ap_ssdict( ap_ssdict, do_warn=1, do_exit=0 ):
    if ap_ssdict == None :
        if do_warn :
            print('+* WARN: no ap_ssdict entered as arg')
        if do_exit :
            sys.exit(3)
        return False
    return True

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

def make_scriptname( proc_type, input_type):
    """Give a name to the script, depending on whether the proc_type is IC
or GV, and whether the input_type is pbrun or errts

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'

input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
scriptname : str
    name of script to create

"""
    
    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    scriptname = 'run_'
    scriptname+= DICT_proc_type[proc_type].lower() + '_'
    scriptname+= input_type
    scriptname+= '.tcsh'

    return scriptname 

def make_script_text_intro(proc_type, input_type):
    """Make the top descriptive comment in the script, depending on
whether the proc_type is IC or GV.

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text descriptive str

"""
    
    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = '''#!/bin/tcsh

# This script was created by the afni_proc.py quality control (APQC)
# generator.  
#
# Its purpose is to facilitate investigating the properties of time 
# series data, using the AFNI GUI's {proc_type} functionality.'''

    if input_type == 'pbrun' :
        otxt+= '''
#
# In this script, one *must* provide 2 command line args: 
# + a pb label (pb00, pb01, etc.), 
# + a run number (r01, r02, r03, etc.).'''

    otxt+= '''
#
# Additionally, one *can* add three numbers on the command line
# to represent the starting location (RAI coordinate notation) of the 
# initial seed.'''

    if proc_type == 'IC' :
        otxt+= '''
#
# Using InstaCorr:
# As described in the popup help, once the GUI is open and InstaCorr
# has been set up, users should just need to hold down the Ctrl+Shift
# keys and then left-click and move the mouse around (dragging or
# re-clicking).  Watch the correlation patterns to that seed location
# change, and this often provides an excellent way to understand the
# data.'''

    otxt+= '''
#
# ver = {ver}
# -------------------------------------------------------------------------

'''.format(ver=ver, proc_type=proc_type)

    return otxt

def make_script_text_input_label(proc_type, input_type):
    """Make the part of the script getting inputs and creating the label.

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text descriptive str

"""

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = '''
# ----- Get inputs and create label
'''

    if input_type == 'pbrun' :
        otxt+= '''
set pb  = "$1"
set run = "$2"

if ( "${run}" == "" ) then
    echo "** Exiting: this program requires 2 cmd line args to run:"
    echo "   + a pb label (pb00, pb01, etc.)"
    echo "   + a run number (r01, r02, r03, etc.)."
    echo "   Additionally, you can then put 3 numbers as an initial"
    echo "   seed location coordinate"
    exit 1
endif

set label = "${pb} ${run}"

# possible starting seed coordinate (in RAI notation)
set xcoor = "$3"
set ycoor = "$4"
set zcoor = "$5"
'''
    elif input_type == 'errts' :
        otxt+= '''
# possible starting seed coordinate (in RAI notation)
set xcoor = "$1"
set ycoor = "$2"
set zcoor = "$3"

set label = 'errts (residuals)'
'''

    return otxt

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

def make_script_text_main_dset(proc_type, input_type, ap_ssdict=None):
    """Make the part of the script getting main input ulay dset (and
ic_dset for IC case).

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'
ap_ssdict : dict
    some functionality chains require having the ap_ssdict from APQC

Returns
-------
otxt : str
    text

    """

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = '''
# ----- find main dset(s)
'''

    if input_type == 'pbrun' :
        otxt+= '''
set all_dset = `find . -maxdepth 1 -name "${pb}.*.${run}.*.HEAD" \\
                      | cut -b3- | sort`

if ( ${#all_dset} == 0 ) then
    echo "** Exiting: could not find dset: ${pb}.*.${run}.*.HEAD"
    exit 1
else if ( ${#all_dset} == 1 ) then
    echo "++ Found ulay dset: ${all_dset}"
else
    echo "++ Note: found multiple (${#all_dset}) dsets: ${pb}.*.${run}.*.HEAD"
    echo "   Assuming this is ME-FMRI"
endif
'''

        # navigate fact we might have ME-FMRI here
        idx = -1
        if is_valid_ap_ssdict( ap_ssdict ) :
            ldep = ['reg_echo']
            if lat.check_dep(ap_ssdict, ldep) :
                idx = int(ap_ssdict['reg_echo'])
                otxt+= '''

# Set index from reg_echo uvar (looks like using ME-FMRI)
set idx = {idx}
set dset_ulay = "${{all_dset[$idx]}}"
'''.format(idx=idx)
        
        # essentially alternatives to previous nested case
        if idx < 0 :
            otxt+= '''

# Set index to be 'middle' dset (is just first if N=1)
set idx = `echo "scale=0; (${#all_dset}+1)/2" | bc`
set dset_ulay = "${all_dset[$idx]}"
'''

        if proc_type == 'IC' :
            otxt+= '''
set ic_dset   = "${dset_ulay}"
'''

    elif input_type == 'errts' :
        # here, specific files have to be searched for
        if proc_type == 'IC' :
            qqq = is_valid_ap_ssdict( ap_ssdict, do_exit=1 )
            uvar, ttt = make_apqc_ic_ulay( ap_ssdict )
            otxt+= ttt
            if proc_type == 'IC' :
                uvar, uuu = make_apqc_ic_dset( ap_ssdict )
                otxt+= uuu
        elif proc_type == 'GV' :
            otxt+= '''
set dset_ulay = {}
'''.format(ap_ssdict['errts_dset'])


    return otxt

        
def make_apqc_ic_ulay( ap_ssdict ):
    """Decide which 3D or 4D dataset should be the underlay in the APQC
run_instacorr* script.  This just involves going through a list of
possible items, in order.

Parameters
----------
ap_ssdict : dict
            the dictionary of 'uvar' elements for a given subject

Return
------
ouvar : str
            the uvar of the chosen dset
otxt  : str
            the tcsh-syntax string that sets the variable with the
            chosen uvar's value.
"""

    # default return, if error exiting
    BAD_RETURN = "", ""

    # list of uvars, in decreasing order of preference
    list_ldep = ['final_anat', 'vr_base_dset', 'errts_dset']

    # initialize
    ouvar = ''
    otxt  = """set dset_ulay = """

    for ldep in list_ldep:
        if lat.check_dep(ap_ssdict, [ldep]) :
            ouvar = ldep
            otxt += '''"{}"'''.format(ap_ssdict[ldep])
            break
    otxt+= """\n"""

    return ouvar, otxt

def make_apqc_ic_dset( ap_ssdict ):
    """Decide which 4D dataset should be used to generate the correlations
in the APQC run_instacorr* script.  This just involves going
through a list of possible items, in order.

Parameters
----------
ap_ssdict : dict
            the dictionary of 'uvar' elements for a given subject

Return
------
ouvar : str
            the uvar of the chosen dset
otxt  : str
            the tcsh-syntax string that sets the variable with the
            chosen uvar's value.
"""

    # default return, if error exiting
    BAD_RETURN = "", ""

    # list of uvars, in decreasing order of preference
    # [PT: Jun 18, 2025] now, if errts_blur exists, it will get priority
    # as the dset for IC, bc it has only been created if it should be used
    list_ldep = ['errts_blur', 'errts_dset']

    # initialize
    ouvar = ''
    otxt  = """set ic_dset   = """

    for ldep in list_ldep:
        if lat.check_dep(ap_ssdict, [ldep]) :
            ouvar = ldep
            otxt += '''"{}"'''.format(ap_ssdict[ldep])
            break
    otxt+= """\n"""

    return ouvar, otxt

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

def make_script_text_load_dset(proc_type, input_type, ap_ssdict=None):
    """Make the part of the script loading dsets

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'
ap_ssdict : dict
    some functionality chains require having the ap_ssdict from APQC

Returns
-------
otxt : str
    text

    """

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = ''

    if input_type == 'pbrun' :
        # search for vlines and radcor first
        otxt+= '''
# ----- find associated vline file, if exists
set dset_vline = ""
set dir_vline  = `find . -maxdepth 1 -type d        \\
                      -name "vlines.${pb}.*"        \\
                      | cut -b3- | sort`
if ( ${#dir_vline} == 1 ) then
    set dset_vline  = `find ./${dir_vline} -maxdepth 1 -type f        \\
                           -name "var.1.*${run}*"                     \\
                           | cut -b3- | sort`
endif

# ----- find associated radcor file, if exists
set dset_radcor = ""
set dir_radcor  = `find . -maxdepth 1 -type d       \\
                     -name "radcor.${pb}.*"         \\
                     | cut -b3- | sort`
if ( ${#dir_radcor} == 1 ) then
    set dset_radcor  = `find ./${dir_radcor} -maxdepth 1 -type f     \\
                            -name "radcor.*.${run}*HEAD"             \\
                            | cut -b3- | sort`
endif
'''

        if proc_type == 'IC' :
            # load across runs for a pb, and don't forget the IC dset itself
            otxt+= '''
# ----- make ordered list of dsets to load
set all_load  = ( "${all_dset}" "${ic_dset}"        \\
                   ${pb}.*HEAD                      \\
                   ${dset_vline} ${dset_radcor}     \\
                   *.HEAD *.nii* )
'''
        elif proc_type == 'GV' :
            # load across runs for a pb
            otxt+= '''
# ----- make ordered list of dsets to load
set all_load  = ( "${all_dset}"                     \\
                   ${pb}.*HEAD                      \\
                   ${dset_vline} ${dset_radcor}     \\
                   *.HEAD *.nii* )
'''

    elif input_type == 'errts' :
        # no radcor or vlines
        qqq = is_valid_ap_ssdict( ap_ssdict, do_exit=1 )
        otxt+= '''
# ----- make list of dsets to load
'''
        otxt+= make_apqc_errts_all_load( proc_type, ap_ssdict )


    return otxt


def make_apqc_errts_all_load( proc_type, ap_ssdict, skip_uvars=None ):
    """All results directory dsets get loaded in, to be available to be
used.  We build the list order so that the most useful to explore with
InstaCorr are first, and then everything follows in alphabetical
order.  This just involves going through a list of possible items, in
order.

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
ap_ssdict : dict
            the dictionary of 'uvar' elements for a given subject
skip_uvars: list
            list of uvars to skip (because they might already be 
            set as $dset_ulay and/or $ic_dset).

Return
------
otxt  : str
            the tcsh-syntax string that sets the variable with the
            chosen uvar's value.

"""

    # default return, if error exiting
    BAD_RETURN = ""

    # list of uvars, in decreasing order of preference
    list_ldep = ['anat_final', 'vr_base_dset', 
                 'errts_dset', 'mask_dset']

    # initialize
    otxt = """\n"""
    if proc_type == 'IC' :
        otxt+= """set all_load  = ( "${dset_ulay}" "${ic_dset}" """
        otxt+= ' '*20 
    elif proc_type == 'GV' :
        otxt+= """set all_load  = ( "${dset_ulay}" """
        otxt+= ' '*28 
    otxt+= """\\\n"""
    # indentation index for below
    nindent = otxt.index('(') + 2
    nfinal  = otxt.index('\\') - 1

    # add corr_brain, and vert align COL char
    line = '''{}corr_brain*HEAD'''.format(' '*nindent)
    npad = nfinal - len(line)
    if npad > 0 :
        line+= ' '*npad
    line+= '''\\\n'''
    otxt+= line

    for ldep in list_ldep:
        if lat.check_dep(ap_ssdict, [ldep]) :
            if skip_uvars and not(ldep in skip_uvars) :
                line = '''{}"{}" '''.format(' '*nindent, ap_ssdict[ldep])
                npad = nfinal - len(line)
                if npad > 0 :
                    line+= ' '*npad
                line+= '''\\\n'''
                otxt+= line
    
    otxt+= """{}all_runs.*.HEAD *.HEAD *.nii* )""".format(' '*nindent)
    otxt+= """\n"""

    return otxt

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

def make_script_text_coors_params(proc_type, input_type):
    """Make the part of the script, about coordinates and other possible
params like seed radius (for IC).

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text

    """

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = '''
# ----- finalize remaining parameters
'''

    otxt+= '''
if ( "${zcoor}" != "" ) then
    set coord = ( "${xcoor}" "${ycoor}" "${zcoor}" )
else
    set coord = `3dinfo -dc3 "${dset_ulay}"`
endif
'''
    if proc_type == 'IC' :
        otxt+= '''
set voxvol      = `3dinfo -voxvol "${ic_dset}"`
set ic_seedrad  = `echo "${voxvol}"                                      \\
                        | awk '{printf "%0.2f",(2*($1)^0.3334);}'`
echo "++ seedcorr radius: ${ic_seedrad}"
'''

        if input_type == 'errts' :
            otxt+= '''
set ic_blur = 0
'''
        elif input_type == 'pbrun' :
            otxt+= '''
# apply blur in IC if pb is not 'blur' or 'scale' block
set bind = `echo "${ic_dset}" | awk '{print index($0, "blur")}'`
set sind = `echo "${ic_dset}" | awk '{print index($0, "scale")}'`
if ( ${bind} || ${sind} ) then
    echo "++ Apply no blur for 'blur' or 'scale' blocks"
    set ic_blur = 0
else
    set ic_blur = `echo "${voxvol}"                                      \\
                        | awk '{printf "%0.2f",(1.5*($1)^0.3334);}'`
endif
'''

        otxt+= '''echo "++ blurring radius: ${ic_blur}"
'''

    return otxt

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

def make_script_text_env_vars(proc_type, input_type):
    """Make the part of the script, env vars.

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text

    """

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = '''
# ===========================================================================
'''

    otxt+= '''
# General GUI parameters set by default
setenv AFNI_ENVIRON_WARNINGS    NO
setenv AFNI_THRESH_INIT_EXPON   0
setenv AFNI_NOSPLASH            YES
setenv AFNI_SPLASH_MELT         NO
setenv AFNI_STARTUP_WARNINGS    NO
setenv AFNI_NIFTI_TYPE_WARN     NO
setenv AFNI_NO_OBLIQUE_WARNING  YES
setenv AFNI_COMPRESSOR          NONE
setenv AFNI_NEVER_SAY_GOODBYE   YES
setenv AFNI_MOTD_CHECK          NO
setenv AFNI_VERSION_CHECK       NO
setenv AFNI_IMAGE_DATASETS      NO
setenv AFNI_NO_ADOPTION_WARNING YES
setenv AFNI_FLASH_VIEWSWITCH    NO
setenv AFNI_SKIP_TCSV_SCAN      YES
'''

    if proc_type == 'IC' :
        otxt+= '''
# GUI params, set here for speed, perhaps 
setenv AFNI_DEFAULT_OPACITY    7
setenv AFNI_THRESH_AUTO        NO
'''
        if input_type == 'errts' :
            otxt+='''setenv AFNI_FUNC_BOXED         YES
'''
        elif input_type == 'pbruns' :
            otxt+='''setenv AFNI_FUNC_BOXED         NO
'''

    if proc_type == 'GV' :
        otxt+= '''
# graph specific parameters (faster to do here than with driving)
setenv AFNI_graph_width     800  # initial width of graph window
setenv AFNI_graph_height    500  # initial height of graph window
setenv AFNI_graph_matrix    5    # initial number of sub-graphs
'''

    return otxt

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

def make_script_text_ic_params_cmd(input_type):
    """Make the part of the script, specifically for InstaCorr (so no
proc_type choice).

Parameters
----------
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text

"""

    if not(is_valid_input_type(input_type)) :  return ''

    if input_type == 'pbrun' :
        dpar = {
            'ic_polort' : '3' + ' '*20 + '# bc the data be unprocessed',
        }
    elif input_type == 'errts' :
        dpar = {
            'ic_polort' : '-1' + ' '*20 + '# bc the data be residuals',
        }

    otxt = '''
# ----- InstaCorr setup and cmd

# IC parameters
set ic_ignore   = 0
set ic_automask = no
set ic_despike  = no
set ic_bandpass = 0,99999
set ic_polort   = {ic_polort}
set ic_method   = P

# GUI visualization parameters
set pbar_sign   = "-"
set ncolors     = 99
set topval      = 0.6
set cbar        = "Reds_and_Blues_Inv"
set olay_alpha  = "Quadratic"
set thresh      = 0.3
set frange      = ${{topval}}
set crossh      = MULTI
set xh_gap      = -1
set OW          = "OPEN_WINDOW"

# port communication
set portnum = `afni -available_npb_quiet`

'''.format( **dpar )

    otxt+= '#' + '=' * 76

    otxt+= '''

afni -q  -no_detach                                                     \\
    -npb ${portnum}                                                     \\
    -com "SWITCH_UNDERLAY    ${dset_ulay}"                              \\
    -com "INSTACORR INIT                                                \\
                    DSET=${ic_dset}                                     \\
                  IGNORE=${ic_ignore}                                   \\
                    BLUR=${ic_blur}                                     \\
                AUTOMASK=${ic_automask}                                 \\
                 DESPIKE=${ic_despike}                                  \\
                BANDPASS=${ic_bandpass}                                 \\
                  POLORT=${ic_polort}                                   \\
                 SEEDRAD=${ic_seedrad}                                  \\
                  METHOD=${ic_method}"                                  \\
    -com "INSTACORR SET      ${coord} J"                                \\
    -com "SET_THRESHNEW      ${thresh}"                                 \\
    -com "SET_PBAR_ALL       ${pbar_sign}${ncolors} ${topval} ${cbar}"  \\
    -com "SET_FUNC_RANGE     ${frange}"                                 \\
    -com "SET_XHAIRS         ${crossh}"                                 \\
    -com "SET_XHAIR_GAP      ${xh_gap}"                                 \\
    -com "SET_FUNC_ALPHA     ${olay_alpha}"                             \\
    -com "$OW sagittalimage"                                            \\
    ${all_load:q}  &

sleep 1

set l = `prompt_popup -message \\
"   Run InstaCorr on AP results data:  ${label}  \\n\\n\\
\\n\\
InstaCorr calc using : ${ic_dset}\\n\\
Initial ulay dataset : ${ic_dset}\\n\\
         IC seed rad : ${ic_seedrad} mm\\n\\
         IC blur rad : ${ic_blur} mm\\n\\
         IC polort N : ${ic_polort}\\n\\
\\n\\
Wait briefly for initial correlation patterns to appear.  \\n\\
\\n\\
To use InstaCorr:\\n\\
+ Hold down Ctrl+Shift\\n\\
+ Left-click in the dataset\\n\\
+ Drag the cursor around.\\n\\
... and correlation patterns instantly update\\n\\
from each new seed location.\\n\\
\\n\\
To jump to particular coordinates:\\n\\
+ Right-click -> 'Jump to (xyz)' \\n\\
+ Enter 3 space-separated coords\\n\\
+ Right-click -> 'InstaCorr set'\\n\\
\\n\\'''

    if input_type == 'errts' :
        otxt+= '''
Alpha (transparent) thresholding is ON, and boxes have\\n\\
been placed around suprathreshold regions.\\n\\
\\n" \\
-b '          Done - Close AFNI GUI          '`
'''
    elif input_type == 'pbrun' :
        otxt+= '''
Alpha (transparent) thresholding is ON. To put boxes\\n\\
around suprathreshold regions, click 'B' above the   \\n\\
colorbar in the GUI.\\n\\
\\n" \\
-b '          Done - Close AFNI GUI          '`

'''

    otxt+= '''
if ("$l" != "1") then
    echo "+* Warn: InstaCorr guidance message failed to open"
endif

echo "++ Quiet talkers"
@Quiet_Talkers -quiet -npb_val ${portnum}

cat << EOF
===========================================
++ Goodbye, and thank you for InstaCorring.

EOF
exit 0
'''

    return otxt

def make_script_text_gv_params_cmd(input_type):
    """Make the part of the script, specifically for GraphView (so no
proc_type choice).

Parameters
----------
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'

Returns
-------
otxt : str
    text

"""

    if not(is_valid_input_type(input_type)) :  return ''

    otxt = '''
# ----- GraphView setup and cmd

# GUI visualization parameters
set crossh      = MULTI
set xh_gap      = -1
set OW          = "OPEN_WINDOW"
set graxis      = "axial"

# port communication
set portnum = `afni -available_npb_quiet`

'''

    otxt+= '#' + '=' * 76

    otxt+= '''

afni -q  -no_detach                                                     \\
    -npb ${portnum}                                                     \\
    -com "SWITCH_UNDERLAY    ${dset_ulay}"                              \\
    -com "SET_DICOM_XYZ      ${coord}"                                  \\
    -com "SET_XHAIRS         ${crossh}"                                 \\
    -com "SET_XHAIR_GAP      ${xh_gap}"                                 \\
    -com "$OW sagittalimage"                                            \\
    -com "$OW ${graxis}graph"                                           \\
    ${all_load:q}  &

sleep 1

set l = `prompt_popup -message \\
"   View graphs+images of AP results data:  ${label}\\n\\n\\
\\n\\
Initial ulay dataset : ${dset_ulay[1]}\\n\\
Initial graph shown  : ${graxis}\\n\\
\\n\\
Some useful graph keyboard shortcuts:\\n\\
+ g/G = decrease/increase vertical grid spacing\\n\\
+ m/M = reduce/increase matrix size of sub-graphs by 1  \\n\\
+ v/V = 'video' scroll forward/backward in time\\n\\
+ spacebar = pause scrolling\\n\\
+ a/A = autoscale graphs once/always\\n\\
+ z/Z = change slice number down/up by 1\\n\\
+ -/+ = scale graphs down/up vertically\\n\\
+ S   = save view of graph to image file\\n\\
+ w   = write highlighted time series as *.1D text file  \\n\\
\\n" \\
-b '          Done - Close AFNI GUI          '`


if ("$l" != "1") then
    echo "+* Warn: AFNI Graph Viewer guidance message failed to open"
endif

@Quiet_Talkers -npb_val ${portnum}

cat << EOF
===========================================
++ Goodbye, and thank you for graph viewing.

EOF
exit 0
'''

    return otxt

# ========================================================================

def make_script_text_full(proc_type, input_type, ap_ssdict=None):
    """Make the full script for InstaCorr, GraphView, etc.  Basically go
through all functions to build pieces in order correctly.

Parameters
----------
proc_type : str
    one of an accepted list of processing types, which are currently:
    'IC', 'GV'
input_type : str
    one of an accepted list of input types, which are currently:
    'pbrun', 'errts'
ap_ssdict : dict
    some functionality chains (proc_type==IC) require having the
    ap_ssdict from APQC

Returns
-------
otxt : str
    text descriptive str

    """

    if not(is_valid_proc_and_input(proc_type, input_type)) :  return ''

    otxt = make_script_text_intro(proc_type, input_type)
    otxt+= make_script_text_input_label(proc_type, input_type)
    otxt+= make_script_text_main_dset(proc_type, input_type,
                                      ap_ssdict=ap_ssdict)
    otxt+= make_script_text_load_dset(proc_type, input_type,
                                      ap_ssdict=ap_ssdict)
    otxt+= make_script_text_coors_params(proc_type, input_type)
    otxt+= make_script_text_env_vars(proc_type, input_type)
    if proc_type == 'IC' :
        otxt+= make_script_text_ic_params_cmd(input_type)
    elif proc_type == 'GV' :
        otxt+= make_script_text_gv_params_cmd(input_type)

    return otxt


def write_apqc_icgv_script(proc_type, input_type, ap_ssdict, pname = '' ):
    """Write out the text file of the InstaCorr script.

Parameters
----------
pname : str
    optional path name to prepend to the default filename

Return
------
okay : int
    success or not of writing file: 0 = success, else = failure

    """

    # get text of script
    otext = make_script_text_full(proc_type, input_type, ap_ssdict)

    # write the text file in the results directory
    oname = make_scriptname( proc_type, input_type)
    if oname :
        if pname :    ofile = pname + '/' 
        else:         ofile = ''
        ofile+= oname
    else:
        print("** ERROR: could not write scriptname for:", proc_type, 
              input_type)
        sys.exit(7)

    fff = open(ofile, 'w')
    fff.write(otext)
    fff.close()
    
    # make executable, a la rcr
    try: code = eval('0o755')
    except: code = eval('0755')
    try:
        os.chmod(ofile, code)
    except:
        omsg = "failed: chmod {} {}".format(code, ofile)
        print(omsg)
        return 1

    msg = '''++ Done making (executable) {proc_type} {input_type} script: 
      {ofile}'''.format(proc_type=proc_type, input_type=input_type,
                        ofile=ofile)
    print( msg )

    return 0
