From c9d22836a399adf5ab2b39fb0cd9013c866cfd0f Mon Sep 17 00:00:00 2001
From: Evan Goetz <evan.goetz@ligo.org>
Date: Thu, 19 Dec 2024 13:38:07 -0800
Subject: [PATCH] Update lalpulsar_MakeSFTDAG and Fscan with improved workflow

---
 lalpulsar/.gitignore                          |   1 +
 lalpulsar/bin/Fscan/spec_avg.c                |   4 +-
 lalpulsar/bin/Fscan/spec_avg_long.c           |   4 +-
 lalpulsar/bin/Fscan/spec_coherence.c          |   8 +-
 lalpulsar/bin/MakeData/Makefile.am            |   1 +
 .../bin/MakeData/lalpulsar_MakeSFTDAG.py      |  83 +++++++-
 lalpulsar/bin/MakeData/lalpulsar_MoveSFTs.py  | 201 ++++++++++++++++++
 lalpulsar/bin/MakeData/testMakeSFTDAG.sh      |  57 ++---
 lalpulsar/bin/MakeData/testMakeSFTDAG.tar.gz  |   4 +-
 9 files changed, 303 insertions(+), 60 deletions(-)
 create mode 100644 lalpulsar/bin/MakeData/lalpulsar_MoveSFTs.py

diff --git a/lalpulsar/.gitignore b/lalpulsar/.gitignore
index 9658609c80..729ef596ce 100644
--- a/lalpulsar/.gitignore
+++ b/lalpulsar/.gitignore
@@ -66,6 +66,7 @@ bin/MakeData/lalpulsar_MakeSFTDAG
 bin/MakeData/lalpulsar_MakeSFTs
 bin/MakeData/lalpulsar_Makefakedata_v4
 bin/MakeData/lalpulsar_Makefakedata_v5
+bin/MakeData/lalpulsar_MoveSFTs
 bin/MakeData/makeMultiChFrame
 bin/PiecewiseSearch/lalpulsar_PiecewiseSearch
 bin/PiecewiseSearch/lalpulsar_PiecewiseSearchTemplateBank
diff --git a/lalpulsar/bin/Fscan/spec_avg.c b/lalpulsar/bin/Fscan/spec_avg.c
index 02c9973e99..11f4ce9a73 100644
--- a/lalpulsar/bin/Fscan/spec_avg.c
+++ b/lalpulsar/bin/Fscan/spec_avg.c
@@ -103,9 +103,9 @@ int main( int argc, char **argv )
   // unless --allow_skipping is true
   if ( errnum != 0 ) {
     if ( allow_skipping ) {
-      LogPrintf( LOG_CRITICAL, "No SFTs were found, exiting without error due to --allow_skipping=true\n" );
+      LogPrintf( LOG_CRITICAL, "No SFTs were found, exiting with code %d due to --allow_skipping=true\n", XLAL_EUSR0 );
       XLALDestroyUserVars();
-      exit( 0 );
+      exit( XLAL_EUSR0 );
     } else {
       XLAL_ERROR_MAIN( errnum );
     }
diff --git a/lalpulsar/bin/Fscan/spec_avg_long.c b/lalpulsar/bin/Fscan/spec_avg_long.c
index 1456b49d4b..197112c07c 100644
--- a/lalpulsar/bin/Fscan/spec_avg_long.c
+++ b/lalpulsar/bin/Fscan/spec_avg_long.c
@@ -145,9 +145,9 @@ int main( int argc, char **argv )
   // unless --allow_skipping is true
   if ( errnum != 0 ) {
     if ( allow_skipping ) {
-      LogPrintf( LOG_CRITICAL, "No SFTs were found, exiting without error due to --allow_skipping=true\n" );
+      LogPrintf( LOG_CRITICAL, "No SFTs were found, exiting with code %d due to --allow_skipping=true\n", XLAL_EUSR0 );
       XLALDestroyUserVars();
-      exit( 0 );
+      exit( XLAL_EUSR0 );
     } else {
       XLAL_ERROR_MAIN( errnum );
     }
diff --git a/lalpulsar/bin/Fscan/spec_coherence.c b/lalpulsar/bin/Fscan/spec_coherence.c
index 5fca28e360..3d59f8558b 100644
--- a/lalpulsar/bin/Fscan/spec_coherence.c
+++ b/lalpulsar/bin/Fscan/spec_coherence.c
@@ -93,7 +93,7 @@ int main( int argc, char **argv )
   /* Ensure that some SFTs were found given the start and end time and IFO constraints unless --allow_skipping is true */
   if ( errnumA != 0 || errnumB != 0 ) {
     if ( errnumA != 0 && allow_skipping ) {
-      LogPrintf( LOG_CRITICAL, "Channel A %s found no SFTs, exiting without error due to --allow_skipping=true\n", SFTpattA );
+      LogPrintf( LOG_CRITICAL, "Channel A %s found no SFTs, exiting with code %d due to --allow_skipping=true\n", SFTpattA, XLAL_EUSR0 );
       if ( catalog_a != NULL ) {
         XLALDestroySFTCatalog( catalog_a );
       }
@@ -101,12 +101,12 @@ int main( int argc, char **argv )
         XLALDestroySFTCatalog( catalog_b );
       }
       XLALDestroyUserVars();
-      exit( 0 );
+      exit( XLAL_EUSR0 );
     } else if ( errnumA != 0 ) {
       XLAL_ERROR_MAIN( errnumA );
     }
     if ( errnumB != 0 && allow_skipping ) {
-      LogPrintf( LOG_CRITICAL, "Channel B %s found no SFTs, exiting without error due to --allow_skipping=true\n", SFTpattB );
+      LogPrintf( LOG_CRITICAL, "Channel B %s found no SFTs, exiting with code %d due to --allow_skipping=true\n", SFTpattB, XLAL_EUSR0 );
       if ( catalog_a != NULL ) {
         XLALDestroySFTCatalog( catalog_a );
       }
@@ -114,7 +114,7 @@ int main( int argc, char **argv )
         XLALDestroySFTCatalog( catalog_b );
       }
       XLALDestroyUserVars();
-      exit( 0 );
+      exit( XLAL_EUSR0 );
     } else if ( errnumB != 0 ) {
       XLAL_ERROR_MAIN( errnumB );
     }
diff --git a/lalpulsar/bin/MakeData/Makefile.am b/lalpulsar/bin/MakeData/Makefile.am
index 2e61e4f6f8..4531b582c8 100644
--- a/lalpulsar/bin/MakeData/Makefile.am
+++ b/lalpulsar/bin/MakeData/Makefile.am
@@ -58,6 +58,7 @@ if HAVE_PYTHON
 pybin_scripts = \
 	lalpulsar_CopyPublicSFTs \
 	lalpulsar_MakeSFTDAG \
+	lalpulsar_MoveSFTs \
 	$(END_OF_LIST)
 
 endif
diff --git a/lalpulsar/bin/MakeData/lalpulsar_MakeSFTDAG.py b/lalpulsar/bin/MakeData/lalpulsar_MakeSFTDAG.py
index 3c578ae524..58cc5cba52 100644
--- a/lalpulsar/bin/MakeData/lalpulsar_MakeSFTDAG.py
+++ b/lalpulsar/bin/MakeData/lalpulsar_MakeSFTDAG.py
@@ -85,6 +85,8 @@ __date__ = git_version.date
 #               rate
 # 10/2024  eag; Modify workflow for version 3 SFTs and HTCondor file transfer
 #               workflow
+# 12/2024  eag; Modify workflow to use lalpulsar_MoveSFTs script instead of
+#               remapping files
 
 
 def sft_name_from_vars(
@@ -207,24 +209,23 @@ def writeToDag(dagFID, nodeCount, startTimeThisNode, endTimeThisNode, site, args
         else:
             sft_start += args.time_baseline
         sft_end = sft_start + args.time_baseline
-    # condor needs this to be a comma separated list
-    outputfiles = ",".join(outputfiles)
-    # condor needs this to be a semi-colon separated list (why?!)
-    remap = ";".join(remap)
 
     # gw_data_find job
     if not args.cache_file:
         dagFID.write(f"JOB {datafind} {Path(dagFID.name).parent / 'datafind.sub'}\n")
         dagFID.write(f"RETRY {datafind} 1\n")
         dagFID.write(
-            f'VARS {datafind} gpsstarttime="{startTimeDatafind}" gpsendtime="{endTimeDatafind}" observatory="{site}" inputdatatype="{args.input_data_type}" tagstring="{tagStringOut}"\n'
+            f'VARS {datafind} gpsstarttime="{startTimeDatafind}" '
+            f'gpsendtime="{endTimeDatafind}" observatory="{site}" '
+            f'inputdatatype="{args.input_data_type}" tagstring="{tagStringOut}"\n'
         )
 
     # MakeSFT job
     dagFID.write(f"JOB {MakeSFTs} {Path(dagFID.name).parent / 'MakeSFTs.sub'}\n")
     dagFID.write(f"RETRY {MakeSFTs} 1\n")
     dagFID.write(
-        f'VARS {MakeSFTs} argList="{argStr}" cachefile="{cacheFile}" outputfiles="{outputfiles}" remapfiles="{remap}" tagstring="{tagStringOut}"\n'
+        f'VARS {MakeSFTs} argList="{argStr}" cachefile="{cacheFile}" '
+        f'tagstring="{tagStringOut}"\n'
     )
     if not args.cache_file:
         dagFID.write(f"PARENT {datafind} CHILD {MakeSFTs}\n")
@@ -506,6 +507,20 @@ parser.add_argument(
           MAKESFTS_PATH env variable or system default (in that \
           order)",
 )
+parser.add_argument(
+    "--movesfts-path",
+    type=Path,
+    help="string specifying the lalpulsar_MoveSFTs executable, \
+          or a path to it; if not set, will use \
+          MOVESFTS_PATH env variable or system default (in that \
+          order)",
+)
+parser.add_argument(
+    "--no-validate",
+    dest="validate",
+    action="store_false",
+    help="do not validate created SFTs",
+)
 parser.add_argument(
     "-Y",
     "--request-memory",
@@ -662,7 +677,7 @@ if len(args.channel_name) > 1 and args.observing_run == 0:
         "--observing-kind and --observing-revision"
     )
 
-# Set the data find executable and lalpulsar_MakeSFTs executable
+# Set executables for gw_data_find, lalpulsar_MakeSFTs, and lalpulsar_MoveSFTs
 dataFindExe = "gw_data_find"
 if args.datafind_path:
     if args.datafind_path.is_file():
@@ -685,6 +700,17 @@ elif "MAKESFTS_PATH" in os.environ:
 else:
     makeSFTsExe = Path("@LALSUITE_BINDIR@") / makeSFTsExe
 
+moveSFTsExe = "lalpulsar_MoveSFTs"
+if args.movesfts_path:
+    if args.movesfts_path.is_file():
+        moveSFTsExe = args.movesfts_path
+    else:
+        moveSFTsExe = args.movesfts_path / moveSFTsExe
+elif "MOVESFTS_PATH" in os.environ:
+    moveSFTsExe = Path("$ENV(MOVESFTS_PATH)") / moveSFTsExe
+else:
+    moveSFTsExe = Path("@LALSUITE_BINDIR@") / moveSFTsExe
+
 # try and make a directory to store the cache files and job logs
 try:
     args.log_path.mkdir()
@@ -787,6 +813,7 @@ path_to_dag_file = args.dag_file.parent
 dag_filename = args.dag_file.name
 datafind_sub = path_to_dag_file / "datafind.sub"
 makesfts_sub = path_to_dag_file / "MakeSFTs.sub"
+movesfts_sub = path_to_dag_file / "MoveSFTs.sub"
 
 # create datafind.sub
 if not args.cache_file:
@@ -833,13 +860,32 @@ with open(makesfts_sub, "w") as MakeSFTsFID:
     MakeSFTsFID.write("RequestCpus = 1\n")
     MakeSFTsFID.write("should_transfer_files = yes\n")
     MakeSFTsFID.write("transfer_input_files = $(cachefile)\n")
-    MakeSFTsFID.write("transfer_output_files = $(outputfiles)\n")
-    # condor needs transfer_output_remaps to be in quotes (why?!)
-    MakeSFTsFID.write('transfer_output_remaps = "$(remapfiles)"\n')
     if "MAKESFTS_PATH" in os.environ and not args.makesfts_path:
         MakeSFTsFID.write("getenv = MAKESFTS_PATH\n")
     MakeSFTsFID.write("queue 1\n")
 
+# create MoveSFTs.sub
+with open(movesfts_sub, "w") as MoveSFTsFID:
+    MoveSFTsLogFile = f"{args.log_path}/MoveSFTs_{dag_filename}.log"
+    MoveSFTsFID.write("universe = local\n")
+    MoveSFTsFID.write(f"executable = {moveSFTsExe}\n")
+    MoveSFTsFID.write("arguments = ")
+    if not args.validate:
+        MoveSFTsFID.write("$(opts) ")
+    MoveSFTsFID.write("-s $(sourcedirectory) -c $(channels) -d $(destdirectory)\n")
+    MoveSFTsFID.write(f"accounting_group = {args.accounting_group}\n")
+    MoveSFTsFID.write(f"accounting_group_user = {args.accounting_group_user}\n")
+    MoveSFTsFID.write(f"log = {MoveSFTsLogFile}\n")
+    MoveSFTsFID.write(f"error = {args.log_path}/MoveSFTs.err\n")
+    MoveSFTsFID.write(f"output = {args.log_path}/MoveSFTs.out\n")
+    MoveSFTsFID.write("notification = never\n")
+    MoveSFTsFID.write(f"request_memory = 1GB\n")
+    MoveSFTsFID.write(f"request_disk = 10MB\n")
+    MoveSFTsFID.write("RequestCpus = 1\n")
+    if "MOVESFTS_PATH" in os.environ and not args.movesfts_path:
+        MoveSFTsFID.write("getenv = MOVESFTS_PATH\n")
+    MoveSFTsFID.write("queue 1\n")
+
 # create the DAG file with the jobs to run
 with open(args.dag_file, "w") as dagFID:
     startTimeAllNodes = None
@@ -1043,6 +1089,23 @@ with open(args.dag_file, "w") as dagFID:
                 )
         # END while (endTimeAllNodes < args.analysis_end_time)
     # END for seg in segList
+
+    # Write the move SFTs job to the DAG
+    # Move SFTs
+    dagFID.write(f"JOB MoveSFTs {Path(dagFID.name).parent / 'MoveSFTs.sub'}\n")
+    dagFID.write(f"RETRY MoveSFTs 1\n")
+    dagFID.write(f"VARS MoveSFTs ")
+    if not args.validate:
+        dagFID.write('opts="--no-validate" ')
+    dagFID.write(
+        f'sourcedirectory="." '
+        f"channels=\"{' '.join(args.channel_name)}\" "
+        f"destdirectory=\"{' '.join([str(p) for p in args.output_sft_path])}\"\n"
+    )
+    dagFID.write(
+        f"PARENT {' '.join([f'MakeSFTs_{n}' for n in range(1, nodeCount+1)])} CHILD MoveSFTs\n"
+    )
+
 # Close the DAG file
 
 # Update actual end time of the last job and print out the times all jobs will run on:
diff --git a/lalpulsar/bin/MakeData/lalpulsar_MoveSFTs.py b/lalpulsar/bin/MakeData/lalpulsar_MoveSFTs.py
new file mode 100644
index 0000000000..cef15cd50d
--- /dev/null
+++ b/lalpulsar/bin/MakeData/lalpulsar_MoveSFTs.py
@@ -0,0 +1,201 @@
+##python
+# Copyright (C) 2024 Evan Goetz
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with with program; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301  USA
+
+## \file
+## \ingroup lalpulsar_bin_SFTTools
+"""Move SFTs between directories."""
+
+import argparse
+import os
+import sys
+import time
+import shutil
+from contextlib import contextmanager
+from concurrent.futures import ProcessPoolExecutor, as_completed
+from tqdm import tqdm
+
+from lal import LALERRORBIT, LALWARNINGBIT, LALINFOBIT, LALTRACEBIT
+from lal import GetDebugLevel, ClobberDebugLevel
+
+from lalpulsar import git_version
+from lalpulsar import ValidateSFTFile, SFTErrorMessage
+
+__author__ = "Evan Goetz <evan.goetz@ligo.org>"
+__credits__ = "Karl Wette <karl.wette@ligo.org>"
+__version__ = git_version.id
+__date__ = git_version.date
+
+
+@contextmanager
+def silence_xlal_error_messages():
+    saveDebugLevel = GetDebugLevel()
+    silentDebugLevel = saveDebugLevel & ~(
+        LALERRORBIT | LALWARNINGBIT | LALINFOBIT | LALTRACEBIT
+    )
+    ClobberDebugLevel(silentDebugLevel)
+    try:
+        yield None
+    finally:
+        ClobberDebugLevel(saveDebugLevel)
+
+
+def parse_command_line():
+    # parse command line
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument(
+        "-p", "--processes", type=int, default=1, help="number of moving processes"
+    )
+    parser.add_argument(
+        "-n",
+        "--no-validate",
+        dest="validate",
+        action="store_false",
+        help="do not validate destination SFTs",
+    )
+    parser.add_argument(
+        "-s", "--source-directory", type=str, help="SFT source directory"
+    )
+    parser.add_argument(
+        "-c",
+        "--channels",
+        type=str,
+        nargs="+",
+        help="Channel names (must be the same number as " "--dest-directory arguments)",
+    )
+    parser.add_argument(
+        "-d",
+        "--dest-directory",
+        type=str,
+        nargs="+",
+        help="SFT destination directory (must be the same "
+        "number as --channels arguments)",
+    )
+    args = parser.parse_args()
+
+    # check arguments
+    if args.processes <= 0:
+        parser.error("--processes must be strictly positive")
+    if not os.path.isdir(args.source_directory):
+        parser.error("source_directory is not a directory")
+    if len(args.channels) != len(args.dest_directory):
+        parser.error(
+            "Number of channel arguments must equal number of " "directory arguments"
+        )
+
+    return args
+
+
+def find_SFT_files(source_directory, channel, dest_directory):
+    # find SFT files for a specific channel and return the source-destiation tuple
+    src_dest_paths = []
+
+    # channel format in filename
+    chan = channel.split(":")[1].replace("-", "").replace("_", "")
+
+    # find source SFT files
+    for src_root, _, src_files in os.walk(source_directory):
+        for src_file in src_files:
+            if src_file.endswith(".sft") and chan in src_file:
+                src_path = os.path.join(src_root, src_file)
+                _, src_name = os.path.split(src_path)
+
+                # build SFT destination path
+                dest_path = os.path.join(dest_directory, src_name)
+
+                # add to outputs
+                src_dest_paths.append((src_path, dest_path))
+
+    return src_dest_paths
+
+
+def make_dest_dirs(dest_dirs):
+    # make destination SFT directories
+    print(f"{__file__}: making {len(dest_dirs)} directories ...", flush=True)
+    for dest_dir in dest_dirs:
+        os.makedirs(dest_dir, exist_ok=True)
+    print(f"{__file__}: making {len(dest_dirs)} directories ... done\n", flush=True)
+
+
+def move_SFT_file(src_path, dest_path, validate):
+    # move SFT with a temporary extension
+    tmp_dest_path = dest_path + "_TO_BE_VALIDATED"
+    shutil.move(src_path, tmp_dest_path)
+
+    # validate SFT if requested
+    if validate:
+        with silence_xlal_error_messages() as _:
+            validate_errorcode = ValidateSFTFile(tmp_dest_path)
+        if validate_errorcode != 0:
+            validate_errorstr = SFTErrorMessage(validate_errorcode)
+            return (tmp_dest_path, validate_errorstr)
+
+    # move destination SFT to final location
+    os.rename(tmp_dest_path, dest_path)
+
+    return None
+
+
+def move_all_SFT_files(src_dest_paths, validate, processes):
+    validate_errors = []
+
+    # create executor
+    print(f"{__file__}: copying {len(src_dest_paths)} SFTs ...", flush=True)
+    with ProcessPoolExecutor(max_workers=args.processes) as executor:
+        # submit tasks
+        pool = [
+            executor.submit(move_SFT_file, src_path, dest_path, validate)
+            for src_path, dest_path in src_dest_paths
+        ]
+
+        # collect tasks
+        for task in tqdm(as_completed(pool), total=len(pool)):
+            validate_error = task.result()
+            if validate_error is not None:
+                validate_errors.append(validate_error)
+
+    print("")
+
+    # show any validation errors
+    if validate_errors:
+        print(
+            f"{__file__}: failed to validate {len(validate_errors)} SFTs after copying:",
+            flush=True,
+        )
+        for tmp_dest_path, validate_errorstr in validate_errors:
+            print(f"  {tmp_dest_path}\n    {validate_errorstr}", flush=True)
+        sys.exit(1)
+
+    print(f"{__file__}: copying {len(src_dest_paths)} SFTs ... done\n", flush=True)
+
+
+if __name__ == "__main__":
+    args = parse_command_line()
+
+    dest_dirs = set()
+    src_dest_paths = []
+    for idx, c in enumerate(args.channels):
+        src_dest = find_SFT_files(args.source_directory, c, args.dest_directory[idx])
+
+        dest_dirs.add(args.dest_directory[idx])
+        src_dest_paths.extend(src_dest)
+
+    make_dest_dirs(dest_dirs)
+
+    move_all_SFT_files(src_dest_paths, args.validate, args.processes)
+
+    print(f"{__file__}: DONE", flush=True)
diff --git a/lalpulsar/bin/MakeData/testMakeSFTDAG.sh b/lalpulsar/bin/MakeData/testMakeSFTDAG.sh
index 9a11e39727..d3362359c8 100644
--- a/lalpulsar/bin/MakeData/testMakeSFTDAG.sh
+++ b/lalpulsar/bin/MakeData/testMakeSFTDAG.sh
@@ -115,13 +115,10 @@ unittest public_SFTs \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w hann -P 0.5 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest public_SFTs \
     "-O 4 -K DEV -R 1" \
-    "-w hann -P 0.5" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft1_half_overlap}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft2_half_overlap}-${Tsft}.sft"
+    "-w hann -P 0.5"
 
 ## two SFTs per job
 unittest two_SFTs_per_job \
@@ -129,13 +126,10 @@ unittest two_SFTs_per_job \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w hann -P 0.5 -m 2 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest two_SFTs_per_job \
     "-O 4 -K DEV -R 1" \
-    "-w hann -P 0.5" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft1_half_overlap}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft2_half_overlap}-${Tsft}.sft"
+    "-w hann -P 0.5"
 
 ## two channels
 unittest two_channels \
@@ -143,16 +137,10 @@ unittest two_channels \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p dir1 dir2 \
     -N ${chan1} ${chan2} -F ${fmin} -B ${Band} -w hann -P 0.5 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest two_channels \
     "-O 4 -K DEV -R 1" \
-    "-w hann -P 0.5" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft1_half_overlap}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WHANN-${seg2_sft2_half_overlap}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan2sft}+WHANN-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan2sft}+WHANN-${seg2_sft1_half_overlap}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan2sft}+WHANN-${seg2_sft2_half_overlap}-${Tsft}.sft"
+    "-w hann -P 0.5"
 
 ## private SFTs
 unittest private_SFTs \
@@ -160,13 +148,10 @@ unittest private_SFTs \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w hann -P 0.5 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest private_SFTs \
     "-O 0 -X private" \
-    "-w hann -P 0.5" \
-    "H-1_H1_${Tsft}SFT_private-${seg1_sft1}-1800.sft" \
-    "H-1_H1_${Tsft}SFT_private-${seg2_sft1_half_overlap}-1800.sft" \
-    "H-1_H1_${Tsft}SFT_private-${seg2_sft2_half_overlap}-1800.sft"
+    "-w hann -P 0.5"
 
 ## frame cache file
 unittest frame_cache_file \
@@ -174,13 +159,11 @@ unittest frame_cache_file \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w hann -P 0.5 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath} -e ${cachepath}
+    -g ${segs} -J ${MSFTpath}  --movesfts-path=${MSFTpath} \
+    -e ${cachepath}
 greptest frame_cache_file \
     "-O 0 -X private" \
-    "-w hann -P 0.5" \
-    "H-1_H1_${Tsft}SFT_private-${seg1_sft1}-1800.sft" \
-    "H-1_H1_${Tsft}SFT_private-${seg2_sft1_half_overlap}-1800.sft" \
-    "H-1_H1_${Tsft}SFT_private-${seg2_sft2_half_overlap}-1800.sft"
+    "-w hann -P 0.5"
 
 ## default window
 unittest default_window \
@@ -188,12 +171,10 @@ unittest default_window \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest default_window \
     "-O 4 -K DEV -R 1" \
-    "-w tukey -r 0.001" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY5-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY5-${seg2_sft1_no_overlap}-${Tsft}.sft"
+    "-w tukey -r 0.001"
 
 ## Tukey window with parameter 0.001
 unittest Tukey_window \
@@ -201,12 +182,10 @@ unittest Tukey_window \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w tukey:0.001 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest Tukey_window \
     "-O 4 -K DEV -R 1" \
-    "-w tukey -r 0.001" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY5-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY5-${seg2_sft1_no_overlap}-${Tsft}.sft"
+    "-w tukey -r 0.001"
 
 ## Tukey window with parameter 0.5
 unittest Tukey_window_2 \
@@ -214,12 +193,10 @@ unittest Tukey_window_2 \
     -f test.dag -G TEST -d H1_HOFT_C00 -k 7 -T ${Tsft} -p . \
     -N ${chan1} -F ${fmin} -B ${Band} -w tukey:0.5 -m 1 \
     -A ${acctgtag} -U ${acctgusr} \
-    -g ${segs} -J ${MSFTpath}
+    -g ${segs} -J ${MSFTpath} --movesfts-path=${MSFTpath}
 greptest Tukey_window_2 \
     "-O 4 -K DEV -R 1" \
-    "-w tukey -r 0.5" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY2500-${seg1_sft1}-${Tsft}.sft" \
-    "H-1_H1_${Tsft}SFT_O4DEV+R1+C${chan1sft}+WTKEY2500-${seg2_sft1_no_overlap}-${Tsft}.sft"
+    "-w tukey -r 0.5"
 
 if test -f testMakeSFTDAG.tar.gz; then
     echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
diff --git a/lalpulsar/bin/MakeData/testMakeSFTDAG.tar.gz b/lalpulsar/bin/MakeData/testMakeSFTDAG.tar.gz
index 1d47b3891e..9df9a7ddd6 100644
--- a/lalpulsar/bin/MakeData/testMakeSFTDAG.tar.gz
+++ b/lalpulsar/bin/MakeData/testMakeSFTDAG.tar.gz
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0e758a12826b87a0f62136efc672a9764e68d7cade9d42dbaab447769f8397c1
-size 3056
+oid sha256:fc8a5ae90195239e94846c2a7c87331b6fa29746e2b82f3c18bd6d928d59a7c9
+size 3347
-- 
GitLab