From 5d2d7f8197a80a9615ba1bf9ade7279e85aecda4 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Mon, 4 Nov 2019 22:04:07 +0100 Subject: [PATCH 1/9] change default ephemerides to look for to DE405 -consistent with current defaults in lalapps --- pyfstat/helper_functions.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pyfstat/helper_functions.py b/pyfstat/helper_functions.py index 8943b3d..915ba6f 100644 --- a/pyfstat/helper_functions.py +++ b/pyfstat/helper_functions.py @@ -146,15 +146,16 @@ def get_ephemeris_files(): earth_ephem = None sun_ephem = None elif env_var in list(os.environ.keys()): - earth_ephem = os.path.join(os.environ[env_var], "earth00-40-DE421.dat.gz") - sun_ephem = os.path.join(os.environ[env_var], "sun00-40-DE421.dat.gz") + ephem_version = "DE405" + earth_ephem = os.path.join(os.environ[env_var], "earth00-40-{:s}.dat.gz".format(ephem_version)) + sun_ephem = os.path.join(os.environ[env_var], "sun00-40-{:s}.dat.gz".format(ephem_version)) if not (os.path.isfile(earth_ephem) and os.path.isfile(sun_ephem)): - earth_ephem = os.path.join(os.environ[env_var], "earth00-19-DE421.dat.gz") - sun_ephem = os.path.join(os.environ[env_var], "sun00-19-DE421.dat.gz") + earth_ephem = os.path.join(os.environ[env_var], "earth00-19-{:s}.dat.gz".format(ephem_version)) + sun_ephem = os.path.join(os.environ[env_var], "sun00-19-{:s}.dat.gz".format(ephem_version)) if not (os.path.isfile(earth_ephem) and os.path.isfile(sun_ephem)): logging.warning( - "No [earth/sun]00-[19/40]-DE421 ephemerides " - "found in the " + os.environ[env_var] + " directory. " + please + "Default [earth/sun]00-[19/40]-"+ephem_version+" ephemerides " + "not found in the " + os.environ[env_var] + " directory. " + please ) earth_ephem = None sun_ephem = None -- GitLab From 59f8d6f4e3bd26959a4aced5c742f38abc931bcd Mon Sep 17 00:00:00 2001 From: David Keitel Date: Mon, 4 Nov 2019 22:35:31 +0100 Subject: [PATCH 2/9] Writer.run_makefakedata: pass through ephemeride file choices --- pyfstat/make_sfts.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index 8ef6b1f..1b77bfa 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -350,6 +350,10 @@ transientTau = {:10.0f}\n""" cl_mfd.append("--Tsft={}".format(self.Tsft)) if self.h0 != 0: cl_mfd.append('--injectionSources="{}"'.format(self.config_file_name)) + if self.earth_ephem is not None: + cl_mfd.append('--ephemEarth="{}"'.format(self.earth_ephem)) + if self.sun_ephem is not None: + cl_mfd.append('--ephemSun="{}"'.format(self.sun_ephem)) cl_mfd = " ".join(cl_mfd) -- GitLab From 62dffe7a87a53bb01431f9be343f87f30b88f4ed Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 15:09:45 +0000 Subject: [PATCH 3/9] make_sfts.py: more ephemeris handling fixes -add missing self.set_ephemeris_files() call to GlitchWriter.__init__() -also write out to CLA in FrequencyModulatedArtifactWriter.run_makefakedata_v4() -use getattr for safety --- pyfstat/make_sfts.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index 1b77bfa..fdf0d28 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -350,10 +350,12 @@ transientTau = {:10.0f}\n""" cl_mfd.append("--Tsft={}".format(self.Tsft)) if self.h0 != 0: cl_mfd.append('--injectionSources="{}"'.format(self.config_file_name)) - if self.earth_ephem is not None: - cl_mfd.append('--ephemEarth="{}"'.format(self.earth_ephem)) - if self.sun_ephem is not None: - cl_mfd.append('--ephemSun="{}"'.format(self.sun_ephem)) + earth_ephem = getattr(self, "earth_ephem", None) + sun_ephem = getattr(self, "sun_ephem", None) + if earth_ephem is not None: + cl_mfd.append('--ephemEarth="{}"'.format(earth_ephem)) + if sun_ephem is not None: + cl_mfd.append('--ephemSun="{}"'.format(sun_ephem)) cl_mfd = " ".join(cl_mfd) @@ -439,6 +441,7 @@ class GlitchWriter(Writer): see `lalapps_Makefakedata_v5 --help` for help with the other paramaters """ + self.set_ephemeris_files() self.basic_setup() self.calculate_fmin_Band() @@ -758,6 +761,12 @@ class FrequencyModulatedArtifactWriter(Writer): cl_mfd.append("--h0={}".format(h0)) cl_mfd.append("--cosi={}".format(self.cosi)) cl_mfd.append("--lineFeature=TRUE") + earth_ephem = getattr(self, "earth_ephem", None) + sun_ephem = getattr(self, "sun_ephem", None) + if earth_ephem is not None: + cl_mfd.append('--ephemEarth="{}"'.format(earth_ephem)) + if sun_ephem is not None: + cl_mfd.append('--ephemSun="{}"'.format(sun_ephem)) cl_mfd = " ".join(cl_mfd) helper_functions.run_commandline(cl_mfd, log_level=10) -- GitLab From 2149448cd7fa670c174bd9a45d881d29583cd7ba Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 15:11:47 +0000 Subject: [PATCH 4/9] BaseSearchClass.set_ephemeris_files(): if given custom files, actually save them --- pyfstat/core.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfstat/core.py b/pyfstat/core.py index d2fb2a1..914022e 100755 --- a/pyfstat/core.py +++ b/pyfstat/core.py @@ -345,7 +345,8 @@ class BaseSearchClass(object): Paths of the two files containing positions of Earth and Sun, respectively at evenly spaced times, as passed to CreateFstatInput - Note: If not manually set, default values in ~/.pyfstat are used + Note: If not manually set, default values from get_ephemeris_files() + are used (looking in ~/.pyfstat or $LALPULSAR_DATADIR) """ @@ -353,8 +354,12 @@ class BaseSearchClass(object): if earth_ephem is None: self.earth_ephem = earth_ephem_default + else: + self.earth_ephem = earth_ephem if sun_ephem is None: self.sun_ephem = sun_ephem_default + else: + self.sun_ephem = sun_ephem class ComputeFstat(BaseSearchClass): -- GitLab From 69c31083c9a04b392daea3ef26b19dbfb37b1e91 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 15:22:40 +0000 Subject: [PATCH 5/9] pass ephemerides through to PredictFstat --- pyfstat/core.py | 7 +++++++ pyfstat/make_sfts.py | 2 ++ 2 files changed, 9 insertions(+) diff --git a/pyfstat/core.py b/pyfstat/core.py index 914022e..6a27867 100755 --- a/pyfstat/core.py +++ b/pyfstat/core.py @@ -159,6 +159,8 @@ def predict_fstat( IFOs=None, assumeSqrtSX=None, tempory_filename="fs.tmp", + earth_ephem=None, + sun_ephem=None, **kwargs ): """ Wrapper to lalapps_PredictFstat @@ -201,6 +203,11 @@ def predict_fstat( cl_pfs.append("--maxStartTime={}".format(int(maxStartTime))) cl_pfs.append("--outputFstat={}".format(tempory_filename)) + if earth_ephem is not None: + cl_pfs.append("--ephemEarth='{}'".format(earth_ephem)) + if sun_ephem is not None: + cl_pfs.append("--ephemSun='{}'".format(sun_ephem)) + cl_pfs = " ".join(cl_pfs) helper_functions.run_commandline(cl_pfs) d = read_par(filename=tempory_filename) diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index fdf0d28..9ad3149 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -377,6 +377,8 @@ transientTau = {:10.0f}\n""" self.detectors, self.sqrtSX, tempory_filename="{}.tmp".format(self.label), + earth_ephem=self.earth_ephem, + sun_ephem=self.sun_ephem ) # detectors OR IFO? return twoF_expected -- GitLab From fcf6c3079a201d530556004491b58794fc9ec655 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 16:13:57 +0000 Subject: [PATCH 6/9] Writer.check_cached_data_okay_to_use(): fix comparing new commandline against old SFT header -this used to require exact string match, but SFT header can for some reason have the CLAs reordered (e.g. when ephemerides are involved) -introduce new helper function match_commandlines() and do proper unordered set comparison -also comment out log info about cff content checking, which wasn't actually implemented! --- pyfstat/helper_functions.py | 13 +++++++++++++ pyfstat/make_sfts.py | 22 +++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/pyfstat/helper_functions.py b/pyfstat/helper_functions.py index 915ba6f..80c023d 100644 --- a/pyfstat/helper_functions.py +++ b/pyfstat/helper_functions.py @@ -369,3 +369,16 @@ def twoFDMoffThreshold( return twoFDMoffthreshold_below_threshold else: return 10 ** (prefactor * np.log10(twoFon - offset)) + + +def match_commandlines(cl1, cl2, be_strict_about_full_executable_path=False): + """ Check if two commandlines match element-by-element, regardless of order """ + cl1s = cl1.split(" ") + cl2s = cl2.split(" ") + # first item will be the executable name + # by default be generous here and do not worry about full paths + if not be_strict_about_full_executable_path: + cl1s[0] = os.path.basename(cl1s[0]) + cl2s[0] = os.path.basename(cl2s[0]) + unmatched = np.setxor1d(cl1s,cl2s) + return len(unmatched)==0 diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index 9ad3149..4a7dca9 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -281,15 +281,23 @@ transientTau = {:10.0f}\n""" self.config_file_name, self.sftfilepath ) ) - logging.info("Checking contents of cff file") + #logging.info("Checking contents of cff file") # FIXME: check doesn't seem to exist...? + #if not XXX: + #logging.info("Contents unmatched") + #return False + logging.info("Checking commandline against existing SFT header") cl_dump = "lalapps_SFTdumpheader {} | head -n 20".format(self.sftfilepath) output = helper_functions.run_commandline(cl_dump) - found = [True for line in output.split("\n") if line[-len(cl_mfd) :] == cl_mfd] - if any(found): - logging.info("Contents matched, use old sft file") + header_lines_lalapps = [line for line in output.split("\n") if "lalapps" in line] + if len(header_lines_lalapps)==0: + logging.info("Could not obtain comparison commandline from old SFT header") + return False + cl_old = header_lines_lalapps[0] + if helper_functions.match_commandlines(cl_old,cl_mfd): + logging.info("Commandline matched with old SFT header, use old sft file") return True else: - logging.info("Contents unmatched, create new sft file") + logging.info("Commandlines unmatched, create new sft file") return False def check_if_cff_file_needs_rewritting(self, content): @@ -358,8 +366,8 @@ transientTau = {:10.0f}\n""" cl_mfd.append('--ephemSun="{}"'.format(sun_ephem)) cl_mfd = " ".join(cl_mfd) - - if self.check_cached_data_okay_to_use(cl_mfd) is False: + check_ok = self.check_cached_data_okay_to_use(cl_mfd) + if check_ok is False: helper_functions.run_commandline(cl_mfd) def predict_fstat(self): -- GitLab From 0e9d656ba2f900c488d1851c4f140860b88c29c6 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 16:54:55 +0000 Subject: [PATCH 7/9] Writer: clean up logic in check_cached_data_okay_to_use() -make clearer when and why we test the .cff file -also improve logging output in this function and in check_if_cff_file_needs_rewritting() -test_makefakedata_usecached: add a call to make_cff() in 2nd run as an extra check --- pyfstat/make_sfts.py | 70 ++++++++++++++++++++++++-------------------- tests.py | 4 +++ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index 4a7dca9..6cdc245 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -259,46 +259,51 @@ transientTau = {:10.0f}\n""" def check_cached_data_okay_to_use(self, cl_mfd): """ Check if cached data exists and, if it does, if it can be used """ - getmtime = os.path.getmtime + need_new = "Will create new SFT file." + logging.info("Checking if cached data good to reuse...") if os.path.isfile(self.sftfilepath) is False: - logging.info("No SFT file matching {} found".format(self.sftfilepath)) + logging.info("No SFT file matching {} found. {}".format(self.sftfilepath, need_new)) return False else: - logging.info("Matching SFT file found") - - if getmtime(self.sftfilepath) < getmtime(self.config_file_name): - logging.info( - ( - "The config file {} has been modified since the sft file {} " - + "was created" - ).format(self.config_file_name, self.sftfilepath) - ) - return False + logging.info("OK: Matching SFT file found.") + + if "injectionSources" in cl_mfd: + if os.path.isfile(self.config_file_name): + if os.path.getmtime(self.sftfilepath) < os.path.getmtime(self.config_file_name): + logging.info( + ( + "The config file {} has been modified since the SFT file {} " + + "was created. {}" + ).format(self.config_file_name, self.sftfilepath, need_new) + ) + return False + else: + logging.info( + "OK: The config file {} is older than the SFT file {}".format( + self.config_file_name, self.sftfilepath) + # NOTE: at this point we assume it's safe to re-use, since + # check_if_cff_file_needs_rewritting() + # should have already been called before + ) + else: + raise RuntimeError("Commandline requires file '{}' but it is missing.".format(self.config_file_name)) - logging.info( - "The config file {} is older than the sft file {}".format( - self.config_file_name, self.sftfilepath - ) - ) - #logging.info("Checking contents of cff file") # FIXME: check doesn't seem to exist...? - #if not XXX: - #logging.info("Contents unmatched") - #return False - logging.info("Checking commandline against existing SFT header") + logging.info("Checking new commandline against existing SFT header...") cl_dump = "lalapps_SFTdumpheader {} | head -n 20".format(self.sftfilepath) output = helper_functions.run_commandline(cl_dump) header_lines_lalapps = [line for line in output.split("\n") if "lalapps" in line] if len(header_lines_lalapps)==0: - logging.info("Could not obtain comparison commandline from old SFT header") + logging.info("Could not obtain comparison commandline from old SFT header. "+need_new) return False cl_old = header_lines_lalapps[0] - if helper_functions.match_commandlines(cl_old,cl_mfd): - logging.info("Commandline matched with old SFT header, use old sft file") - return True - else: - logging.info("Commandlines unmatched, create new sft file") + if not helper_functions.match_commandlines(cl_old,cl_mfd): + logging.info("Commandlines unmatched. "+need_new) return False + else: + logging.info("OK: Commandline matched with old SFT header.") + logging.info("Looks like cached data matches current options, will re-use it!") + return True def check_if_cff_file_needs_rewritting(self, content): """ Check if the .cff file has changed @@ -306,24 +311,25 @@ transientTau = {:10.0f}\n""" Returns True if the file should be overwritten - where possible avoid overwriting to allow cached data to be used """ + logging.info("Checking if we can re-use injection config file...") if os.path.isfile(self.config_file_name) is False: - logging.info("No config file {} found".format(self.config_file_name)) + logging.info("No config file {} found.".format(self.config_file_name)) return True else: - logging.info("Config file {} already exists".format(self.config_file_name)) + logging.info("Config file {} already exists.".format(self.config_file_name)) with open(self.config_file_name, "r") as f: file_content = f.read() if file_content == content: logging.info( - "File contents match, no update of {} required".format( + "File contents match, no update of {} required.".format( self.config_file_name ) ) return False else: logging.info( - "File contents unmatched, updating {}".format(self.config_file_name) + "File contents unmatched, updating {}.".format(self.config_file_name) ) return True diff --git a/tests.py b/tests.py index a793f04..2b826b4 100644 --- a/tests.py +++ b/tests.py @@ -80,12 +80,16 @@ class Writer(Test): Writer = pyfstat.Writer(self.label, outdir=self.outdir, duration=3600) if os.path.isfile(Writer.sftfilepath): os.remove(Writer.sftfilepath) + # first run: make everything from scratch Writer.make_cff() Writer.run_makefakedata() time_first = os.path.getmtime(Writer.sftfilepath) + # second run: should re-use .cff and .sft + Writer.make_cff() Writer.run_makefakedata() time_second = os.path.getmtime(Writer.sftfilepath) self.assertTrue(time_first == time_second) + # third run: touch the .cff to force regeneration time.sleep(1) # make sure timestamp is actually different! os.system("touch {}".format(Writer.config_file_name)) Writer.run_makefakedata() -- GitLab From 2a2e469af6ed51d596dae86fb8c43f0c888afc69 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Tue, 5 Nov 2019 09:16:07 -0800 Subject: [PATCH 8/9] black style fixes to preceding set of ephem-handling commits --- pyfstat/helper_functions.py | 22 +++++++++++++------- pyfstat/make_sfts.py | 40 ++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/pyfstat/helper_functions.py b/pyfstat/helper_functions.py index 80c023d..bddaa9b 100644 --- a/pyfstat/helper_functions.py +++ b/pyfstat/helper_functions.py @@ -147,14 +147,22 @@ def get_ephemeris_files(): sun_ephem = None elif env_var in list(os.environ.keys()): ephem_version = "DE405" - earth_ephem = os.path.join(os.environ[env_var], "earth00-40-{:s}.dat.gz".format(ephem_version)) - sun_ephem = os.path.join(os.environ[env_var], "sun00-40-{:s}.dat.gz".format(ephem_version)) + earth_ephem = os.path.join( + os.environ[env_var], "earth00-40-{:s}.dat.gz".format(ephem_version) + ) + sun_ephem = os.path.join( + os.environ[env_var], "sun00-40-{:s}.dat.gz".format(ephem_version) + ) if not (os.path.isfile(earth_ephem) and os.path.isfile(sun_ephem)): - earth_ephem = os.path.join(os.environ[env_var], "earth00-19-{:s}.dat.gz".format(ephem_version)) - sun_ephem = os.path.join(os.environ[env_var], "sun00-19-{:s}.dat.gz".format(ephem_version)) + earth_ephem = os.path.join( + os.environ[env_var], "earth00-19-{:s}.dat.gz".format(ephem_version) + ) + sun_ephem = os.path.join( + os.environ[env_var], "sun00-19-{:s}.dat.gz".format(ephem_version) + ) if not (os.path.isfile(earth_ephem) and os.path.isfile(sun_ephem)): logging.warning( - "Default [earth/sun]00-[19/40]-"+ephem_version+" ephemerides " + "Default [earth/sun]00-[19/40]-" + ephem_version + " ephemerides " "not found in the " + os.environ[env_var] + " directory. " + please ) earth_ephem = None @@ -380,5 +388,5 @@ def match_commandlines(cl1, cl2, be_strict_about_full_executable_path=False): if not be_strict_about_full_executable_path: cl1s[0] = os.path.basename(cl1s[0]) cl2s[0] = os.path.basename(cl2s[0]) - unmatched = np.setxor1d(cl1s,cl2s) - return len(unmatched)==0 + unmatched = np.setxor1d(cl1s, cl2s) + return len(unmatched) == 0 diff --git a/pyfstat/make_sfts.py b/pyfstat/make_sfts.py index 6cdc245..913c7e2 100644 --- a/pyfstat/make_sfts.py +++ b/pyfstat/make_sfts.py @@ -263,14 +263,18 @@ transientTau = {:10.0f}\n""" logging.info("Checking if cached data good to reuse...") if os.path.isfile(self.sftfilepath) is False: - logging.info("No SFT file matching {} found. {}".format(self.sftfilepath, need_new)) + logging.info( + "No SFT file matching {} found. {}".format(self.sftfilepath, need_new) + ) return False else: logging.info("OK: Matching SFT file found.") if "injectionSources" in cl_mfd: if os.path.isfile(self.config_file_name): - if os.path.getmtime(self.sftfilepath) < os.path.getmtime(self.config_file_name): + if os.path.getmtime(self.sftfilepath) < os.path.getmtime( + self.config_file_name + ): logging.info( ( "The config file {} has been modified since the SFT file {} " @@ -281,24 +285,34 @@ transientTau = {:10.0f}\n""" else: logging.info( "OK: The config file {} is older than the SFT file {}".format( - self.config_file_name, self.sftfilepath) + self.config_file_name, self.sftfilepath + ) + ) # NOTE: at this point we assume it's safe to re-use, since # check_if_cff_file_needs_rewritting() # should have already been called before - ) else: - raise RuntimeError("Commandline requires file '{}' but it is missing.".format(self.config_file_name)) + raise RuntimeError( + "Commandline requires file '{}' but it is missing.".format( + self.config_file_name + ) + ) logging.info("Checking new commandline against existing SFT header...") cl_dump = "lalapps_SFTdumpheader {} | head -n 20".format(self.sftfilepath) output = helper_functions.run_commandline(cl_dump) - header_lines_lalapps = [line for line in output.split("\n") if "lalapps" in line] - if len(header_lines_lalapps)==0: - logging.info("Could not obtain comparison commandline from old SFT header. "+need_new) + header_lines_lalapps = [ + line for line in output.split("\n") if "lalapps" in line + ] + if len(header_lines_lalapps) == 0: + logging.info( + "Could not obtain comparison commandline from old SFT header. " + + need_new + ) return False cl_old = header_lines_lalapps[0] - if not helper_functions.match_commandlines(cl_old,cl_mfd): - logging.info("Commandlines unmatched. "+need_new) + if not helper_functions.match_commandlines(cl_old, cl_mfd): + logging.info("Commandlines unmatched. " + need_new) return False else: logging.info("OK: Commandline matched with old SFT header.") @@ -329,7 +343,9 @@ transientTau = {:10.0f}\n""" return False else: logging.info( - "File contents unmatched, updating {}.".format(self.config_file_name) + "File contents unmatched, updating {}.".format( + self.config_file_name + ) ) return True @@ -392,7 +408,7 @@ transientTau = {:10.0f}\n""" self.sqrtSX, tempory_filename="{}.tmp".format(self.label), earth_ephem=self.earth_ephem, - sun_ephem=self.sun_ephem + sun_ephem=self.sun_ephem, ) # detectors OR IFO? return twoF_expected -- GitLab From f94ea43b20540f8cc42ee8ae110a046160378229 Mon Sep 17 00:00:00 2001 From: David Keitel Date: Wed, 6 Nov 2019 11:42:44 +0100 Subject: [PATCH 9/9] Update ephemerides instructions in README.md --- README.md | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 18eade3..d84e5cf 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,10 @@ we have a number of scripts demonstrating different use cases. ## Installation -### `python` installation -The scripts are written in `python 2.7+` and therefore require a working -`python` installation. While many systems come with a system wide python +### python installation +This package works best with `python3.5+`, +with higher versions to be required soon. +While many systems come with a system wide python installation, it can often be easier to manage a user-specific python installation. This way one does not require root access to install or remove modules. One method to do this, is to use the `conda` system, either through @@ -82,7 +83,7 @@ $ ./configure --prefix=${HOME}/lalsuite-install --disable-all-lal --enable-lalpu ``` -### `pyfstat` installation +### PyFstat installation The module and associated scripts can be installed system wide (or to the currently active venv), assuming you are in the source directory, via @@ -97,14 +98,37 @@ $ python -c 'import pyfstat' if no error message is output, then you have installed `pyfstat`. Note that the module will be installed to whichever python executable you call it from. -### Ephemeris installation - -The scripts require paths to earth and sun ephemeris files in order to use the -`lalpulsar.ComputeFstat` module. This should be automatically picked up from -the $LALPULSAR_DATADIR environment variable, defaulting to the -00-40-DE421 ephemerides or 00-19-DE421 as a backup. -Alternatively, these can either be manually specified when initialising -each search (as one of the arguments), or simply by placing a file +### Ephemerides installation + +PyFstat requires paths to earth and sun ephemerides files +in order to use the `lalpulsar.ComputeFstat` module and various `lalapps` tools. + +If you have done `pip install lalsuite`, +you need to manually download at least these two files: +* [earth00-40-DE405.dat.gz](https://git.ligo.org/lscsoft/lalsuite/raw/master/lalpulsar/src/earth00-40-DE405.dat.gz) +* [sun00-40-DE405.dat.gz](https://git.ligo.org/lscsoft/lalsuite/raw/master/lalpulsar/src/sun00-40-DE405.dat.gz) + +(Other ephemerides versions exist, but these should be sufficient for most applications.) +You then need to tell PyFstat where to find these files, +by either setting an environment variable $LALPULSAR_DATADIR +or by creating a `~/.pyfstat.conf` file as described further below. +If you are working with a virtual environment, +you should be able to get a full working ephemerides installation with these commands: +``` +mkdir $VIRTUAL_ENV/share/lalpulsar +wget https://git.ligo.org/lscsoft/lalsuite/raw/master/lalpulsar/src/earth00-40-DE405.dat.gz -P $VIRTUAL_ENV/share/lalpulsar +wget https://git.ligo.org/lscsoft/lalsuite/raw/master/lalpulsar/src/sun00-40-DE405.dat.gz -P $VIRTUAL_ENV/share/lalpulsar +echo 'export LALPULSAR_DATADIR=$VIRTUAL_ENV/share/lalpulsar' >> ${VIRTUAL_ENV}/bin/activate +deactivate +source path/to/venv/bin/activate +``` + +If instead you have built and installed lalsuite from source, +and set your path up properly through something like +`source $MYLALPATH/etc/lalsuite-user-env.sh`, +then the ephemerides path should be automatically picked up from +the $LALPULSAR_DATADIR environment variable. +Alternatively, you can place a file `~/.pyfstat.conf` into your home directory which looks like ``` @@ -113,6 +137,9 @@ sun_ephem = '/home//lalsuite-install/share/lalpulsar/sun00-19-DE421.dat.gz ``` Paths set in this way will take precedence over the environment variable. +Finally, you can manually specify ephemerides files when initialising +each PyFstat search (as one of the arguments). + ### Contributors * Greg Ashton -- GitLab