Difference between revisions of "CSEP 1 STEPCoulombQuickFix"

From SCECpedia
Jump to navigationJump to search
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
[[CSEP_Working_Group|CSEP Working Group Home Page]]<br>
 
== Introduction ==
 
== Introduction ==
  
RFC002 discusses the issues observed with the STEPCoulomb model in the CSEP New Zealand testing center. CSEP provides a computational infrastructure to perform and evaluate both prospective and  
+
RFC002 discusses the issues observed with the STEPCoulomb model in the CSEP New Zealand testing center. CSEP provides a computational infrastructure to perform and evaluate both prospective and retrospective earthquake forecasting experiments. In regards to a retrospective forecasting experiment, it was observed that the STEPCoulomb model installed in CSEP did not produce the expected output. This behavior was observed for the Darfield Experiment -- a retrospective forecasting experiment of the 2010 Christchurch Earthquake sequence addressing the information gained by including a physics-based component of the forecast.  
retrospective earthquake forecasting experiments. In regards to a retrospective forecasting experiment, it was observed that the STEPCoulomb model installed in CSEP did not produce the expected output for the Darfield Experiment -- a forecasting experiment of the 2010 Christchurch Earthquake sequence.  
 
  
 
The STEPCoulomb model represents a hybrid model consisting of a statistical STEP model and a physics-based Coulomb stress model. The executable that computes the STEP forecast obtains a  
 
The STEPCoulomb model represents a hybrid model consisting of a statistical STEP model and a physics-based Coulomb stress model. The executable that computes the STEP forecast obtains a  
 
Coulomb mask based on available slip models, and uses the information contained from the Coulomb stress model to provide physical constraints to the statistical STEP (short-term earthquake prediction)  
 
Coulomb mask based on available slip models, and uses the information contained from the Coulomb stress model to provide physical constraints to the statistical STEP (short-term earthquake prediction)  
 
forecast. The STEPCoulomb forecast should produce two forecast outputs: (1) STEP forecast, and (2) STEPCoulomb forecast, which can be compared to determine the pairwise efficacy of the two  
 
forecast. The STEPCoulomb forecast should produce two forecast outputs: (1) STEP forecast, and (2) STEPCoulomb forecast, which can be compared to determine the pairwise efficacy of the two  
forecasting models.
+
forecasting models.
  
 
This document is laid out as follows: [[#Problem Statement|Problem Statement]] provides a description of the problems as communicated by the science groups to SCEC IT; and [[#Proposed Solution|Proposed Solution]] provides an explanation of the proposed solution to the problem outlined in the problem statement. [[#Implemented Solution|Implemented Solution]] outlines the specific steps taken to solve the problem.
 
This document is laid out as follows: [[#Problem Statement|Problem Statement]] provides a description of the problems as communicated by the science groups to SCEC IT; and [[#Proposed Solution|Proposed Solution]] provides an explanation of the proposed solution to the problem outlined in the problem statement. [[#Implemented Solution|Implemented Solution]] outlines the specific steps taken to solve the problem.
Line 15: Line 15:
 
'''1. Overview'''
 
'''1. Overview'''
 
   
 
   
It was suspected the STEPCoulomb forecast, computed by the New Zealand CSEP testing center, did not produce the expected outputs. This issue affects an on-going manuscript review, so an urgent response is needed. The problem was confirmed by comparing the STEP forecast with the supposed STEPCoulomb forecast and determining that there were no differences between the forecasts. Computing differences between the two forecasts indicated that both files were identical. It is expected that the physics-based Coulomb stress model should influence the rates forecasted by the statistical STEP model.
+
It was suspected the STEPCoulomb forecast, computed by the New Zealand CSEP testing center, did not produce the intended outputs. This issue affects an on-going manuscript review, so an urgent response is needed. The problem was confirmed by comparing the STEP forecast with the supposed STEPCoulomb forecast and determining that there were no differences between the forecasts. Computing differences between the two forecasts indicated that both files were identical. It is expected that the physics-based Coulomb stress model should influence the rates forecasted by the statistical STEP model.
  
 
'''2. Detailed Explanation'''
 
'''2. Detailed Explanation'''
Line 98: Line 98:
 
     }
 
     }
 
We see that a FileWriter is created using the filepath of "RegionDefaults.outputCoulombRatePath" which is hard-coded to be "./coulombRates.txt." As seen by the "RegionDefaults.setCsepParams(...)" code listen above, this location is not overwritten by the CSEP generate input files. This indicates that the Coulomb Rates are not being correctly stored to the CSEP file system and are being overwritten with each subsequent run.
 
We see that a FileWriter is created using the filepath of "RegionDefaults.outputCoulombRatePath" which is hard-coded to be "./coulombRates.txt." As seen by the "RegionDefaults.setCsepParams(...)" code listen above, this location is not overwritten by the CSEP generate input files. This indicates that the Coulomb Rates are not being correctly stored to the CSEP file system and are being overwritten with each subsequent run.
 +
 +
In addition to the issues caused by the wrong variables names being used to represent the Coulomb rates output, two other problems are preventing the two codes from communicating below.
 +
1. The Coulomb mask was written out with 1 decimal precision preventing the alignment of the STEP and Farfalle grids.
 +
2. The date to apply the slip model was verified using "less-than" instead of "less-equal", so the code was ignoring the slip model on the first day.
 +
 +
These problems have been implemented and do not need reviewed. Specifics will be present within the Github repository https://github.com/SCECcode/CSEP/issues .
  
 
== Proposed Solution ==
 
== Proposed Solution ==
Line 110: Line 116:
 
This solution would only require changing the RegionDefaults.setCsepParams(...) method to read the CSEP command line argument to the correct variable "outputCoulombRatePath". We would also need to supply  configuring the pure STEP model as an additional model in the forecast group configuration. This would require likely more than twice the computational time, because the currently installed STEP model is written in Matlab. I am unsure how long the forecasts take to run in Matlab. However, this solution seems more in line with the CSEP philosophy.
 
This solution would only require changing the RegionDefaults.setCsepParams(...) method to read the CSEP command line argument to the correct variable "outputCoulombRatePath". We would also need to supply  configuring the pure STEP model as an additional model in the forecast group configuration. This would require likely more than twice the computational time, because the currently installed STEP model is written in Matlab. I am unsure how long the forecasts take to run in Matlab. However, this solution seems more in line with the CSEP philosophy.
  
To implement this solution elegantly in CSEP we will register a new model that represents the true STEPCoulomb model. This model will use a separate executable containing the proposed solution outlined in this document. The CSEP system will treat the two models independently, and allow evaluations to be computed between the two different forecast models.
+
To implement this solution elegantly in CSEP we will register a new model that represents the true STEPCoulomb model. This model will use a separate executable containing the proposed solution outlined in this document. The CSEP system will treat the two models independently, and allow evaluations to be computed using the standard CSEP methodology.
 +
 
 +
== Implemented Solution (Under review)==
 +
All changes made on Git branch wsavran/step-coulomb-rfc002. Branch has not yet been pushed to remote.
 +
 
 +
'''1. Modifications to step-aftershock'''
 +
git diff HEAD^ HEAD
 +
diff --git a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore
 +
new file mode 100644
 +
index 0000000..3f20248
 +
--- /dev/null
 +
+++ b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore
 +
@@ -0,0 +1,6 @@
 +
+/junk/
 +
+/scratch/
 +
+/Makefile
 +
+/log4j.properties
 +
+/org/
 +
+/resources/
 +
diff --git a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
 +
index 8943db8..37a3304 100644
 +
--- a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
 +
+++ b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
 +
@@ -401,7 +401,7 @@ public class RegionDefaults {
 +
                cubeFilePath = line;
 +
                line = fileLines.get(4);
 +
                logger.info("forecast output file " + line);
 +
-              outputAftershockRatePath = line;//OUTPUT_DIR + "/" +  props.getProperty("output.file.time.dep.rates", "TimeDepRates.txt");     
 +
+              outputCoulombRatePath = line;//OUTPUT_DIR + "/" +  props.getProperty("output.file.time.dep.rates", "TimeDepRates.txt");
 +
 
 +
                line = fileLines.get(5);
 +
                logger.info("background rate input file " + line);
 +
 
 +
This model must be compiled and be installed on the CSEP system where the reprocessing will occur.
 +
 +
'''2. Modifications to CSEP system'''
 +
 +
* We added the model src/SCECModels/NewZealand/STEPCoulombModel2.py to wrap the step-aftershock executable that writes out the true STEPCoulomb forecast.  The implementation is shown below:
 +
<pre>
 +
diff --git a/src/SCECModels/NewZealand/STEPCoulombModel2.py b/src/SCECModels/NewZealand/STEPCoulombModel2.py
 +
new file mode 100644
 +
index 0000000..e4ee35b
 +
--- /dev/null
 +
+++ b/src/SCECModels/NewZealand/STEPCoulombModel2.py
 +
@@ -0,0 +1,251 @@
 +
+"""
 +
+Module STEPCoulomb2Model
 +
+"""
 +
+
 +
+__version__ = "$Revision:$"
 +
+__revision__ = "$Id:$"
 +
+
 +
+import os, datetime
 +
+
 +
+import Environment, CSEPFile, CSEP, CSEPLogging
 +
+from Forecast import Forecast
 +
+from CSEPInputParams import CSEPInputParams
 +
+from cseprandom import CSEPRandom
 +
+from GeoNetNZDataSource import GeoNetNZDataSource, FOCAL_MECHANISM_PATH_ENV
 +
+from DataSourceFactory import DataSourceFactory
 +
+from SlipModels import SlipModels
 +
+
 +
+
 +
+#-------------------------------------------------------------------------------
 +
+#
 +
+# STEPCoulombModel2 forecast model for New Zealand.
 +
+#
 +
+# This class is a helper to invoke any of Sandy Steacy/Matt Gerstenberger
 +
+# forecasts models.
 +
+#
 +
+class STEPCoulombModel2(object):
 +
+
 +
+    # Static data of the class
 +
+    Type = 'STEPCOULOMB2'
 +
+
 +
+    # Center code path for the model
 +
+    Path = os.path.join(Forecast.CodePath,
 +
+                        'NewZealand',
 +
+                        'src',
 +
+                        'STEPCoulombModel')
 +
+
 +
+    __JavaPath = os.path.join(Path,
 +
+                              'OpenSHA')
 +
+
 +
+    # Coulumb file list option
 +
+    CoulombFileOption = 'CoulombFile'
 +
+
 +
+    # Coulumb file list option
 +
+    SlipModelFileListOption = 'slipModelList'
 +
+
 +
+    # Parameter file for the Coulomb model: to support multiple
 +
+    # geographical regions
 +
+    ParamFileOption = 'masterParameter'
 +
+    __backgroundFileOption = "backgroundFile"
 +
+
 +
+    # Default options for the model
 +
+    __defaultArgs = {ParamFileOption: os.path.join(Path,
 +
+                                                  "master_file_GNS.txt"),
 +
+                    SlipModelFileListOption: None,
 +
+                    __backgroundFileOption: "NZZeroRate05.dat"}
 +
+
 +
+    __CoulombExecutableFile = 'CSEPCoulomb'
 +
+
 +
+    __ifortVersionFile = 'ifort.version'
 +
+   
 +
+
 +
+    #--------------------------------------------------------------------
 +
+    #
 +
+    # Initialization.
 +
+    #
 +
+    # Input:
 +
+    #        args - Optional arguments for the model. Default is None.
 +
+    #
 +
+    def __init__ (self, args=None):
 +
+        """ Initialization for STEPCoulombModel2 class"""
 +
+       
 +
+        # Input arguments for the model were provided:
 +
+        self.__args = CSEPInputParams.parse(STEPCoulombModel2.__defaultArgs,
 +
+                                            args)
 +
+
 +
+        self.CoulombOutput = None
 +
+       
 +
+
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Write input parameter file for the model in following format:
 +
+    #
 +
+    # Coulomb part of the model:
 +
+    # InputParameterFile master_file_GNS_2.txt
 +
+    # PathToThePrograms /home/ajimenez/programs
 +
+    # ForecastStartingDate 20120520050600
 +
+    # Slipmodelfile slip_models.txt
 +
+    # MomentTensorFile GeoNet_CMT_solutions.csv
 +
+    #       
 +
+    def writeCoulombFile (self,
 +
+                          filename,
 +
+                          start_date,
 +
+                          local_dir):
 +
+        """ Format input parameter file for the model.
 +
+            Path to created input parameter file will be passed to the
 +
+            model's executable."""
 +
+
 +
+        fhandle = file(filename,
 +
+                      CSEPFile.Mode.WRITE)
 +
+
 +
+        line = "InputParameterFile %s\n" %self.__args[STEPCoulombModel2.ParamFileOption]
 +
+        fhandle.write(line)
 +
+       
 +
+        line = "PathToThePrograms %s/\n" %self.Path
 +
+        fhandle.write(line)
 +
+       
 +
+        line = "ForecastStartingDate %s\n" %start_date.strftime("%Y%m%d%H%M%S")
 +
+        fhandle.write(line)
 +
+
 +
+        slip_models_list = self.__args[STEPCoulombModel2.SlipModelFileListOption]
 +
+        if slip_models_list is None:
 +
+            # Identify slip model files for the run
 +
+            slip_models_list = SlipModels().files(local_dir,
 +
+                                                  start_date,
 +
+                                                  include_eventID=True)
 +
+       
 +
+        line = "Slipmodelfile %s\n" %slip_models_list
 +
+        fhandle.write(line)
 +
+
 +
+        data_path, data_file = os.path.split(DataSourceFactory().object(GeoNetNZDataSource.Type,
 +
+                                                                        isObjReference=True).RawFile)
 +
+       
 +
+        if FOCAL_MECHANISM_PATH_ENV in os.environ:
 +
+            data_path = os.environ[FOCAL_MECHANISM_PATH_ENV]
 +
+       
 +
+        line = "MomentTensorFile %s\n" %os.path.join(data_path,
 +
+                                                    GeoNetNZDataSource.ProcessedFocalMechanismFile)
 +
+        fhandle.write(line)
 +
+
 +
+        line = "Outputfile %s\n" %self.CoulombOutput
 +
+        fhandle.write(line)
 +
+
 +
+
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Write input parameter file for the model in following format:
 +
+    #
 +
+    # Coulomb part of the model:
 +
+    # InputParameterFile master_file_GNS_2.txt
 +
+    # PathToThePrograms /home/ajimenez/programs
 +
+    # ForecastStartingDate 20120520050600
 +
+    # Slipmodelfile slip_models.txt
 +
+    # MomentTensorFile GeoNet_CMT_solutions.csv
 +
+    #       
 +
+    def writeSTEPFile (self,
 +
+                      fhandle,
 +
+                      start_date,
 +
+                      num_days,
 +
+                      catalog_file,
 +
+                      result_forecast):
 +
+        """ Format input parameter file for the STEP part of the model.
 +
+            Path to created input parameter file will be passed to the
 +
+            model's executable."""
 +
+
 +
+
 +
+        result_path, result_file = os.path.split(result_forecast)
 +
+        self.CoulombOutput = os.path.join(result_path,
 +
+                                          "CoulombPart_" + result_file)
 +
+           
 +
+        # Start time of the data - to save on computations use later than
 +
+        # input catalog's start date
 +
+        line = "1 1 2010 0 0 0\n"
 +
+        fhandle.write(line)
 +
+
 +
+        # Test date and time
 +
+        line = "%s %s %s %s %s %s\n" \
 +
+              %(start_date.day,
 +
+                start_date.month,
 +
+                start_date.year,
 +
+                start_date.hour,
 +
+                start_date.minute,
 +
+                start_date.second)
 +
+        fhandle.write(line)
 +
+
 +
+        # Duration in days
 +
+        line = "%s\n" %int(num_days)
 +
+        fhandle.write(line)
 +
+
 +
+        # Path to the input catalog file
 +
+        fhandle.write(catalog_file + '\n')
 +
+
 +
+        # Path to the output forecast file
 +
+        fhandle.write(result_forecast + "\n")
 +
+
 +
+        # Path to the CSEP_background file
 +
+        fhandle.write(os.path.join(self.__JavaPath,
 +
+                                  self.__args[STEPCoulombModel2.__backgroundFileOption]) + "\n")
 +
+       
 +
+        fhandle.write(self.CoulombOutput + '\n')
 +
+
 +
+
 +
+    #--------------------------------------------------------------------
 +
+    #
 +
+    # Invoke the model to generate forecast.
 +
+    #
 +
+    # Input: None
 +
+    #       
 +
+    def invokeModel (self,
 +
+                    parameter_file,
 +
+                    step_parameter_file):
 +
+        """ Invoke model."""
 +
+
 +
+               
 +
+        command = "%s %s" %(os.path.join(STEPCoulombModel2.Path,
 +
+                                        STEPCoulombModel2.__CoulombExecutableFile),
 +
+                            parameter_file)
 +
+        Environment.invokeCommand(command)
 +
+       
 +
+        cwd = os.getcwd()
 +
+        os.chdir(os.path.join(STEPCoulombModel2.__JavaPath,
 +
+                              'build'))
 +
+
 +
+        try:
 +
+            # Model requests to change to the model installation directory
 +
+            # since it's using relative paths to locate other files
 +
+            __command = "java -Xms2048m -Xmx6144m -jar lib/step-aftershock_coul.jar 0 -f %s" %os.path.join(cwd,
 +
+                                                                                                      step_parameter_file)
 +
+
 +
+            Environment.invokeCommand(__command)
 +
+
 +
+        finally:
 +
+            # Go back to the directory
 +
+            os.chdir(cwd)
 +
+           
 +
+        # Return path to the Coulomb part of the model that needs to be
 +
+        # archived to avoid it's evaluation
 +
+        return self.CoulombOutput
 +
+       
 +
+
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Return commands that should be used to capture version of external
 +
+    # software packages the model is dependent on.
 +
+    #
 +
+    # Input: None.
 +
+    #
 +
+    # Output:
 +
+    #          String identifying the type
 +
+    #
 +
+    @staticmethod
 +
+    def externalSoftwareVersions ():
 +
+        """ Returns dictionary of command to determine external software
 +
+            version and flag if output of that command is redirected to the
 +
+            stderr (True) or not (False) (java -version, for example)."""
 +
+       
 +
+        version_file = CSEPFile.openFile(os.path.join(STEPCoulombModel2.Path,
 +
+                                                      STEPCoulombModel2.__ifortVersionFile))
 +
+
 +
+        return {"ifort --version" : version_file.read(),
 +
+                "java -version"  : True} # Java outputs info to stderr
 +
+
 +
</pre>
 +
The expected executable should be placed in ''STEPCoulombModel.__JavaPath/build/lib/step-aftershock_coul.jar'' directory on the CSEP image. This would be in addition to the current "STEPCoulombModel.__JavaPath/build/lib/step-aftershock.jar".
 +
 
 +
* We also added STEPCoulombOneDay2.py to be consistent with the CSEP implementation of the previous STEPCoulombOneDay model.
 +
<pre>
 +
diff --git a/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py b/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py
 +
new file mode 100644
 +
index 0000000..7222be6
 +
--- /dev/null
 +
+++ b/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py
 +
@@ -0,0 +1,146 @@
 +
+"""
 +
+Module STEPCoulombOneDayModel
 +
+"""
 +
+
 +
+__version__ = "$Revision$"
 +
+__revision__ = "$Id$"
 +
+
 +
+
 +
+import os
 +
+
 +
+import CSEPFile
 +
+from CSEPLogging import CSEPLogging
 +
+from Forecast import Forecast
 +
+from OneDayForecast import OneDayForecast
 +
+from ReproducibilityFiles import ReproducibilityFiles
 +
+from STEPCoulombModel2 import STEPCoulombModel2
 +
+
 +
+
 +
+#-------------------------------------------------------------------------------
 +
+#
 +
+# STEPCoulombOneDayModel one-day forecast model.
 +
+#
 +
+# This class is designed to invoke one-day STEPCoulombOneDayModel forecast model
 +
+# by Matt Gerstenberger and Sandy Steacy. It prepares input catalog data,
 +
+# formats control file with model parameters, identifies list of available
 +
+# Coulomb and slip models and provides it as an input to the model. It places
 +
+# forecast file under user specified directory.
 +
+#
 +
+class STEPCoulombOneDayModel2 (OneDayForecast, STEPCoulombModel2):
 +
+
 +
+    # Static data of the class
 +
+   
 +
+    # Keyword identifying type of the class (Hacky implementation)
 +
+    Type = STEPCoulombModel2.Type + OneDayForecast.Type
 +
+   
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Initialization.
 +
+    #
 +
+    # Input:
 +
+    #        dir_path - Directory to store forecast file to.
 +
+    #        args - Optional arguments for the model. Default is None.
 +
+    #
 +
+    def __init__ (self, dir_path, args = None):
 +
+        """ Initialization for STEPCoulombOneDayModel class"""
 +
+       
 +
+        OneDayForecast.__init__(self,
 +
+                                dir_path)
 +
+        STEPCoulombModel2.__init__(self,
 +
+                                  args)
 +
+       
 +
+        # Parameter file for the Coulomb part of the model
 +
+        self.CoulombParamFile = None
 +
+
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Return keyword identifying the model.
 +
+    #
 +
+    # Input: None.
 +
+    #
 +
+    # Output:
 +
+    #          String identifying the type
 +
+    #
 +
+    def type (self):
 +
+        """ Returns keyword identifying the forecast model type."""
 +
+       
 +
+        return STEPCoulombOneDayModel2.Type
 +
+   
 +
+   
 +
+    #---------------------------------------------------------------------------
 +
+    #
 +
+    # Write input parameter file for the model
 +
+    #       
 +
+    def writeParameterFile (self,
 +
+                            filename = None):
 +
+        """ Format input parameter file for the model.
 +
+            Path to created input parameter file will be passed to the
 +
+            model's executable."""
 +
+
 +
+        # Open STEPCoulomb param file
 +
+        fhandle = Forecast.writeParameterFile(self,
 +
+                                              filename)
 +
+       
 +
+        STEPCoulombModel2.writeSTEPFile(self,
 +
+                                      fhandle,
 +
+                                      self.start_date,
 +
+                                      self.numDays(self.start_date,
 +
+                                                    self.end_date),
 +
+                                      os.path.join(self.catalogDir,
 +
+                                                    self.inputCatalogFilename()),
 +
+                                      self.filename())
 +
+       
 +
+        fhandle.close()
 +
+
 +
+        # Write param file to invoke Coulomb part of the model first
 +
+        param_path, param_file = os.path.split(self.parameterFile)
 +
+       
 +
+        self.CoulombParamFile = os.path.join(param_path,
 +
+                                            "CoulombPart_" + param_file)
 +
+       
 +
+        # To avoid inheritance from two classes that are derived from the same
 +
+        # base "Forecast" class, use this "pass all values" approach
 +
+        STEPCoulombModel2.writeCoulombFile(self,
 +
+                                          self.CoulombParamFile,
 +
+                                          self.start_date,
 +
+                                          self.catalogDir)
 +
+
 +
+        # Register input parameters file for reproducibility
 +
+        info_msg = "Input parameters file used by Coulomb part of %s model \
 +
+to generate '%s' forecast file for %s." %(self.type(),
 +
+                                          self.rawFilename(),
 +
+                                          self.start_date.date())
 +
+
 +
+        # Record parameter file with reproducibility registry
 +
+        ReproducibilityFiles.add(self,
 +
+                                self.CoulombParamFile,
 +
+                                info_msg,
 +
+                                CSEPFile.Extension.ASCII)
 +
+
 +
+
 +
+    #--------------------------------------------------------------------
 +
+    #
 +
+    # Invoke the model to generate forecast.
 +
+    #
 +
+    # Input: None
 +
+    #       
 +
+    def run(self):
 +
+        """ Invoke model."""
 +
+
 +
+        coulomb_output = STEPCoulombModel2.invokeModel(self, self.CoulombParamFile, self.parameterFile)
 +
+       
 +
+        # Move Coulomb file to the archive directory - should not be
 +
+        # evaluated
 +
+        if self.archive is not None:
 +
+         
 +
+            # Move file to the archive directory to avoid it
 +
+            # in evaluation tests
 +
+            CSEPLogging.getLogger(STEPCoulombOneDayModel2.__name__).info("run(): moving %s to %s"
 +
+                                                                        %(coulomb_output,
 +
+                                                                          self.archive))
 +
+
 +
+            new_path = os.path.join(self.archive,
 +
+                                    os.path.basename(coulomb_output))
 +
+            os.renames(coulomb_output,
 +
+                      new_path)
 +
+       
 +
</pre>
 +
 
 +
* ForecastFactory XML File was updated to include the new file. See updates below:
 +
<pre>
 +
git diff HEAD^ src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml | cat
 +
diff --git a/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml b/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
 +
index a522dc5..fd5a138 100644
 +
--- a/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
 +
+++ b/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
 +
@@ -42,6 +42,7 @@
 +
    <module>CattaniaOneYearModel.CattaniaOneYearModel</module>
 +
   
 +
    <module>STEPCoulombOneDayModel.STEPCoulombOneDayModel</module>
 +
+  <module>STEPCoulombOneDayModel2.STEPCoulombOneDayModel2</module>
 +
    <module>STEPCoulombOneMonthModel.STEPCoulombOneMonthModel</module>
 +
    <module>STEPCoulombOneYearModel.STEPCoulombOneYearModel</module>
 +
</pre>
 +
 +
'''3. Reprocessing Specifics'''
  
== Implemented Solution ==
+
Verification phase: Use the 03 September 2010 and 04 September 2010 using the bestAvailable and bestAvailable+10days data sets.

Latest revision as of 18:21, 10 April 2018

CSEP Working Group Home Page

Introduction

RFC002 discusses the issues observed with the STEPCoulomb model in the CSEP New Zealand testing center. CSEP provides a computational infrastructure to perform and evaluate both prospective and retrospective earthquake forecasting experiments. In regards to a retrospective forecasting experiment, it was observed that the STEPCoulomb model installed in CSEP did not produce the expected output. This behavior was observed for the Darfield Experiment -- a retrospective forecasting experiment of the 2010 Christchurch Earthquake sequence addressing the information gained by including a physics-based component of the forecast.

The STEPCoulomb model represents a hybrid model consisting of a statistical STEP model and a physics-based Coulomb stress model. The executable that computes the STEP forecast obtains a Coulomb mask based on available slip models, and uses the information contained from the Coulomb stress model to provide physical constraints to the statistical STEP (short-term earthquake prediction) forecast. The STEPCoulomb forecast should produce two forecast outputs: (1) STEP forecast, and (2) STEPCoulomb forecast, which can be compared to determine the pairwise efficacy of the two forecasting models.

This document is laid out as follows: Problem Statement provides a description of the problems as communicated by the science groups to SCEC IT; and Proposed Solution provides an explanation of the proposed solution to the problem outlined in the problem statement. Implemented Solution outlines the specific steps taken to solve the problem.

Problem Statement

1. Overview

It was suspected the STEPCoulomb forecast, computed by the New Zealand CSEP testing center, did not produce the intended outputs. This issue affects an on-going manuscript review, so an urgent response is needed. The problem was confirmed by comparing the STEP forecast with the supposed STEPCoulomb forecast and determining that there were no differences between the forecasts. Computing differences between the two forecasts indicated that both files were identical. It is expected that the physics-based Coulomb stress model should influence the rates forecasted by the statistical STEP model.

2. Detailed Explanation

When invoking the STEPCoulomb model, CSEP makes sequential, external calls to two executables: (1) STEPCoulomb and (2) step-aftershock. In model (1), finite-fault slip models are used to produce bitwise masks based on Coulomb stress calculations. The masks produced by model (1) are meant to be read by model (2), and used to update the forecasted rates. To facilitate the interchange of these executables, CSEP creates 'CSEP-specific' input files to define the file paths for forecast files and associated metadata on the CSEP filesystem. For example, the file located at

/home/csep.canterbury/DarfieldExperiment/bestAvailableTC/batch/runs/csep/2015_11/20151109214739/pid_3368/scec.csep.STEPCOULOMBOneDay.CoulombPart_STEPCOULOMBOneDay_control.dat.1447165313.806906.1   

provides the CSEP-specific inputs to forecast model (1). An example input file for (2) can be found at:

/home/csep.canterbury/DarfieldExperiment/bestAvailableTC/batch/runs/csep/2015_11/20151109214739/pid_3368/scec.csep.STEPCOULOMBOneDay.STEPCOULOMBOneDay_control.dat.1447165313.743799.1

If we compare the contents of this input file with the source code of executable (2), we find that there is a bug which would produce the issue described in the overview section. The contents of the linked input file for exectuable (2) are shown below:

1 1 2010 0 0 0
29 11 2010 16 35 42
1
/home/csep/DarfieldExperiment/bestAvailableTC/batch/runs/csep/2015_11/20151109214739/pid_3368/OneDayModelInputCatalog.dat
/home/csep/DarfieldExperiment/bestAvailableTC/one-day-forecasts/forecasts/STEPCOULOMBOneDay_11_29_2010.16_35_42.dat
/home/csep/csep-install/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/NZZeroRate05.dat
/home/csep/DarfieldExperiment/bestAvailableTC/one-day-forecasts/forecasts/CoulombPart_STEPCOULOMBOneDay_11_29_2010.16_35_42.dat

The code below shows the RegionDefaults.setCsepParams(...) function that is responsible for reading the CSEP generate input file and overwriting the default parameters of the model.

  public static void setCsepParams(String filePath)
   throws FileNotFoundException, IOException
 {
   logger.info(">> setCsepParams filePath " + filePath);
   
   ArrayList<String> fileLines = FileUtils.loadFile(filePath);
   
   String line = (String)fileLines.get(0);
   logger.info("catalog start date " + line);
   EVENT_START_TIME = parseCsepTime2Cal(line);
   logger.info("EVENT_START_TIME " + dateformater.format(EVENT_START_TIME.getTime()));
   line = (String)fileLines.get(1);
   logger.info("catalog end date " + line);
   forecastStartTime = parseCsepTime2Cal(line);
   logger.info("forecastStartTime " + dateformater.format(forecastStartTime.getTime()));
   line = (String)fileLines.get(2);
   logger.info("forecast length " + line);
   forecastLengthDays = Integer.parseInt(line.trim());
   line = (String)fileLines.get(3);
   logger.info("catalog input file " + line);
   cubeFilePath = line;
   line = (String)fileLines.get(4);
   logger.info("forecast output file " + line);
   outputAftershockRatePath = line;
   
   line = (String)fileLines.get(5);
   logger.info("background rate input file " + line);
   BACKGROUND_RATES_FILE_NAME = line;
   
   line = (String)fileLines.get(6);
   logger.info("Coulomb input file " + line);
   coulombFilterPath = line;
 }

We see that the output file name is assigned to the variable outputAftershockRatePath which defines the output for the pure STEP forecast. For more details on this aspect, view the method STEP_main.saveRatesFile(...). It shows that outputAftershockRatePath defines the output file path of the pure STEP forecast. The Coulomb portion of the STEPCoulomb model is implemented in "ApplyCoulombFilter.applyFilter(...)". The IO portion of this method is shown below:

    try
   {
     FileWriter fr = new FileWriter(RegionDefaults.outputCoulombRatePath);
     bgRegionSize = bgLocList.size();
     for (int k = 0; k < bgRegionSize; k++)
     {
       Location bgLoc = bgLocList.getLocationAt(k);
       
       HypoMagFreqDistAtLoc bgDistAtLoc = bggrid.getHypoMagFreqDistAtLoc(k);
       if (bgDistAtLoc != null)
       {
         int numForecastMags = 1 + (int)((RegionDefaults.maxForecastMag - RegionDefaults.minForecastMag) / RegionDefaults.deltaForecastMag);
         for (int index = 0; index < numForecastMags; index++)
         {
           double mag = RegionDefaults.minForecastMag + index * RegionDefaults.deltaForecastMag;
           
           double wrate = bgDistAtLoc.getFirstMagFreqDist().getIncrRate(mag);
           if (wrate == 0.0D) {
             wrate = 1.0E-11D;
           }
           fr.write(locFormat.format(bgLoc.getLongitude() - RegionDefaults.gridSpacing / 2.0D) + "    " + locFormat.format(bgLoc.getLongitude() + RegionDefaults.gridSpacing / 2.0D) + "    " + locFormat.format(bgLoc.getLatitude() - RegionDefaults.gridSpacing / 2.0D) + "    " + locFormat.format(bgLoc.getLatitude() + RegionDefaults.gridSpacing / 2.0D) + "    " + RegionDefaults.MIN_Z + "    " + RegionDefaults.MAX_Z + "    " + magFormat.format(mag - RegionDefaults.deltaForecastMag / 2.0D) + "    " + magFormat.format(mag + RegionDefaults.deltaForecastMag / 2.0D) + "    " + wrate + "     1\n");
         }
       }
     }
     fr.close();
   }
   catch (IOException ee)
   {
     ee.printStackTrace();
   }

We see that a FileWriter is created using the filepath of "RegionDefaults.outputCoulombRatePath" which is hard-coded to be "./coulombRates.txt." As seen by the "RegionDefaults.setCsepParams(...)" code listen above, this location is not overwritten by the CSEP generate input files. This indicates that the Coulomb Rates are not being correctly stored to the CSEP file system and are being overwritten with each subsequent run.

In addition to the issues caused by the wrong variables names being used to represent the Coulomb rates output, two other problems are preventing the two codes from communicating below. 1. The Coulomb mask was written out with 1 decimal precision preventing the alignment of the STEP and Farfalle grids. 2. The date to apply the slip model was verified using "less-than" instead of "less-equal", so the code was ignoring the slip model on the first day.

These problems have been implemented and do not need reviewed. Specifics will be present within the Github repository https://github.com/SCECcode/CSEP/issues .

Proposed Solution

There are two potential ways to solve this problem. The decision depends on how we want CSEP to treat the individual forecasting models, and considerations with modifying the step-aftershock.jar executable.

1. Output two forecast models from step-aftershock

This solution would require modifying STEPCoulombModel.writeSTEPFile(...) in the CSEP generic source code to accept the additional argument required to write out the STEPCoulomb. This would also require modifying RegionDefaults.setCsepParams(...) in the step-aftershock source code to accept this argument. It's currently uncertain if CSEP will respond well to a model producing two independent forecast files. This is not a concern for computing the forecasts, but could cause issues if trying to run evalulations within CSEP. This solution seems to be the most straightforward.

[Favored] 2. Have STEPCoulomb output one forecast and run STEP to output the STEP only forecast

This solution would only require changing the RegionDefaults.setCsepParams(...) method to read the CSEP command line argument to the correct variable "outputCoulombRatePath". We would also need to supply configuring the pure STEP model as an additional model in the forecast group configuration. This would require likely more than twice the computational time, because the currently installed STEP model is written in Matlab. I am unsure how long the forecasts take to run in Matlab. However, this solution seems more in line with the CSEP philosophy.

To implement this solution elegantly in CSEP we will register a new model that represents the true STEPCoulomb model. This model will use a separate executable containing the proposed solution outlined in this document. The CSEP system will treat the two models independently, and allow evaluations to be computed using the standard CSEP methodology.

Implemented Solution (Under review)

All changes made on Git branch wsavran/step-coulomb-rfc002. Branch has not yet been pushed to remote.

1. Modifications to step-aftershock

git diff HEAD^ HEAD
diff --git a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore 
new file mode 100644
index 0000000..3f20248
--- /dev/null 
+++ b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/classes/.gitignore
@@ -0,0 +1,6 @@
+/junk/
+/scratch/
+/Makefile
+/log4j.properties
+/org/
+/resources/
diff --git a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
index 8943db8..37a3304 100644
--- a/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
+++ b/src/SCECModels/NewZealand/src/STEPCoulombModel/OpenSHA/src/org/opensha/step/calc/RegionDefaults.java
@@ -401,7 +401,7 @@ public class RegionDefaults {
                cubeFilePath = line;
                line = fileLines.get(4);
                logger.info("forecast output file " + line);
-               outputAftershockRatePath = line;//OUTPUT_DIR + "/" +  props.getProperty("output.file.time.dep.rates", "TimeDepRates.txt");      
+               outputCoulombRatePath = line;//OUTPUT_DIR + "/" +  props.getProperty("output.file.time.dep.rates", "TimeDepRates.txt"); 
 
               line = fileLines.get(5);
               logger.info("background rate input file " + line);

This model must be compiled and be installed on the CSEP system where the reprocessing will occur.

2. Modifications to CSEP system

  • We added the model src/SCECModels/NewZealand/STEPCoulombModel2.py to wrap the step-aftershock executable that writes out the true STEPCoulomb forecast. The implementation is shown below:
diff --git a/src/SCECModels/NewZealand/STEPCoulombModel2.py b/src/SCECModels/NewZealand/STEPCoulombModel2.py
new file mode 100644
index 0000000..e4ee35b
--- /dev/null
+++ b/src/SCECModels/NewZealand/STEPCoulombModel2.py
@@ -0,0 +1,251 @@
+"""
+Module STEPCoulomb2Model
+"""
+
+__version__ = "$Revision:$"
+__revision__ = "$Id:$"
+
+import os, datetime
+
+import Environment, CSEPFile, CSEP, CSEPLogging
+from Forecast import Forecast
+from CSEPInputParams import CSEPInputParams
+from cseprandom import CSEPRandom
+from GeoNetNZDataSource import GeoNetNZDataSource, FOCAL_MECHANISM_PATH_ENV
+from DataSourceFactory import DataSourceFactory
+from SlipModels import SlipModels
+
+
+#-------------------------------------------------------------------------------
+#
+# STEPCoulombModel2 forecast model for New Zealand.
+#
+# This class is a helper to invoke any of Sandy Steacy/Matt Gerstenberger
+# forecasts models.
+#
+class STEPCoulombModel2(object):
+
+    # Static data of the class
+    Type = 'STEPCOULOMB2'
+
+    # Center code path for the model
+    Path = os.path.join(Forecast.CodePath,
+                        'NewZealand',
+                        'src',
+                        'STEPCoulombModel')
+
+    __JavaPath = os.path.join(Path,
+                              'OpenSHA')
+
+    # Coulumb file list option
+    CoulombFileOption = 'CoulombFile'
+
+    # Coulumb file list option
+    SlipModelFileListOption = 'slipModelList'
+
+    # Parameter file for the Coulomb model: to support multiple 
+    # geographical regions
+    ParamFileOption = 'masterParameter'
+    __backgroundFileOption = "backgroundFile"
+
+    # Default options for the model
+    __defaultArgs = {ParamFileOption: os.path.join(Path,
+                                                   "master_file_GNS.txt"),
+                     SlipModelFileListOption: None,
+                     __backgroundFileOption: "NZZeroRate05.dat"}
+
+    __CoulombExecutableFile = 'CSEPCoulomb'
+
+    __ifortVersionFile = 'ifort.version'
+    
+
+    #--------------------------------------------------------------------
+    #
+    # Initialization.
+    #
+    # Input:
+    #        args - Optional arguments for the model. Default is None.
+    #
+    def __init__ (self, args=None):
+        """ Initialization for STEPCoulombModel2 class"""
+        
+        # Input arguments for the model were provided:
+        self.__args = CSEPInputParams.parse(STEPCoulombModel2.__defaultArgs, 
+                                            args)
+
+        self.CoulombOutput = None
+        
+
+    #---------------------------------------------------------------------------
+    #
+    # Write input parameter file for the model in following format:
+    # 
+    # Coulomb part of the model:
+    # InputParameterFile master_file_GNS_2.txt
+    # PathToThePrograms /home/ajimenez/programs
+    # ForecastStartingDate 20120520050600
+    # Slipmodelfile slip_models.txt
+    # MomentTensorFile GeoNet_CMT_solutions.csv
+    #        
+    def writeCoulombFile (self, 
+                          filename,
+                          start_date,
+                          local_dir):
+        """ Format input parameter file for the model.
+            Path to created input parameter file will be passed to the 
+            model's executable."""
+
+        fhandle = file(filename, 
+                       CSEPFile.Mode.WRITE)
+
+        line = "InputParameterFile %s\n" %self.__args[STEPCoulombModel2.ParamFileOption]
+        fhandle.write(line)
+        
+        line = "PathToThePrograms %s/\n" %self.Path
+        fhandle.write(line)
+        
+        line = "ForecastStartingDate %s\n" %start_date.strftime("%Y%m%d%H%M%S")
+        fhandle.write(line)
+
+        slip_models_list = self.__args[STEPCoulombModel2.SlipModelFileListOption]
+        if slip_models_list is None:
+            # Identify slip model files for the run
+            slip_models_list = SlipModels().files(local_dir,
+                                                  start_date,
+                                                  include_eventID=True)
+        
+        line = "Slipmodelfile %s\n" %slip_models_list
+        fhandle.write(line)
+
+        data_path, data_file = os.path.split(DataSourceFactory().object(GeoNetNZDataSource.Type, 
+                                                                        isObjReference=True).RawFile)
+        
+        if FOCAL_MECHANISM_PATH_ENV in os.environ:
+            data_path = os.environ[FOCAL_MECHANISM_PATH_ENV]
+        
+        line = "MomentTensorFile %s\n" %os.path.join(data_path,
+                                                     GeoNetNZDataSource.ProcessedFocalMechanismFile)
+        fhandle.write(line)
+
+        line = "Outputfile %s\n" %self.CoulombOutput
+        fhandle.write(line)
+
+
+    #---------------------------------------------------------------------------
+    #
+    # Write input parameter file for the model in following format:
+    # 
+    # Coulomb part of the model:
+    # InputParameterFile master_file_GNS_2.txt
+    # PathToThePrograms /home/ajimenez/programs
+    # ForecastStartingDate 20120520050600
+    # Slipmodelfile slip_models.txt
+    # MomentTensorFile GeoNet_CMT_solutions.csv
+    #        
+    def writeSTEPFile (self, 
+                       fhandle,
+                       start_date,
+                       num_days,
+                       catalog_file,
+                       result_forecast):
+        """ Format input parameter file for the STEP part of the model.
+            Path to created input parameter file will be passed to the 
+            model's executable."""
+
+
+        result_path, result_file = os.path.split(result_forecast)
+        self.CoulombOutput = os.path.join(result_path,
+                                          "CoulombPart_" + result_file)
+            
+        # Start time of the data - to save on computations use later than
+        # input catalog's start date
+        line = "1 1 2010 0 0 0\n"
+        fhandle.write(line)
+
+        # Test date and time 
+        line = "%s %s %s %s %s %s\n" \
+               %(start_date.day,
+                 start_date.month,
+                 start_date.year,
+                 start_date.hour,
+                 start_date.minute,
+                 start_date.second)
+        fhandle.write(line)
+
+        # Duration in days
+        line = "%s\n" %int(num_days)
+        fhandle.write(line)
+
+        # Path to the input catalog file
+        fhandle.write(catalog_file + '\n')
+
+        # Path to the output forecast file
+        fhandle.write(result_forecast + "\n")
+
+        # Path to the CSEP_background file
+        fhandle.write(os.path.join(self.__JavaPath,
+                                   self.__args[STEPCoulombModel2.__backgroundFileOption]) + "\n")
+        
+        fhandle.write(self.CoulombOutput + '\n')
+
+
+    #--------------------------------------------------------------------
+    #
+    # Invoke the model to generate forecast.
+    #
+    # Input: None
+    #        
+    def invokeModel (self, 
+                     parameter_file, 
+                     step_parameter_file):
+        """ Invoke model."""
+
+                
+        command = "%s %s" %(os.path.join(STEPCoulombModel2.Path,
+                                         STEPCoulombModel2.__CoulombExecutableFile),
+                            parameter_file)
+        Environment.invokeCommand(command)
+        
+        cwd = os.getcwd()
+        os.chdir(os.path.join(STEPCoulombModel2.__JavaPath,
+                              'build'))
+
+        try:
+            # Model requests to change to the model installation directory
+            # since it's using relative paths to locate other files
+            __command = "java -Xms2048m -Xmx6144m -jar lib/step-aftershock_coul.jar 0 -f %s" %os.path.join(cwd,
+                                                                                                      step_parameter_file)
+
+            Environment.invokeCommand(__command)
+
+        finally:
+            # Go back to the directory
+            os.chdir(cwd)
+            
+        # Return path to the Coulomb part of the model that needs to be 
+        # archived to avoid it's evaluation
+        return self.CoulombOutput
+        
+
+    #---------------------------------------------------------------------------
+    #
+    # Return commands that should be used to capture version of external
+    # software packages the model is dependent on. 
+    #
+    # Input: None.
+    #
+    # Output:
+    #           String identifying the type
+    #
+    @staticmethod
+    def externalSoftwareVersions ():
+        """ Returns dictionary of command to determine external software 
+            version and flag if output of that command is redirected to the
+            stderr (True) or not (False) (java -version, for example)."""
+        
+        version_file = CSEPFile.openFile(os.path.join(STEPCoulombModel2.Path,
+                                                      STEPCoulombModel2.__ifortVersionFile))
+
+        return {"ifort --version" : version_file.read(),
+                "java -version"   : True} # Java outputs info to stderr
+

The expected executable should be placed in STEPCoulombModel.__JavaPath/build/lib/step-aftershock_coul.jar directory on the CSEP image. This would be in addition to the current "STEPCoulombModel.__JavaPath/build/lib/step-aftershock.jar".

  • We also added STEPCoulombOneDay2.py to be consistent with the CSEP implementation of the previous STEPCoulombOneDay model.
diff --git a/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py b/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py
new file mode 100644
index 0000000..7222be6
--- /dev/null
+++ b/src/SCECModels/NewZealand/STEPCoulombOneDayModel2.py
@@ -0,0 +1,146 @@
+"""
+Module STEPCoulombOneDayModel
+"""
+
+__version__ = "$Revision$"
+__revision__ = "$Id$"
+
+
+import os
+
+import CSEPFile
+from CSEPLogging import CSEPLogging
+from Forecast import Forecast
+from OneDayForecast import OneDayForecast
+from ReproducibilityFiles import ReproducibilityFiles
+from STEPCoulombModel2 import STEPCoulombModel2
+
+
+#-------------------------------------------------------------------------------
+#
+# STEPCoulombOneDayModel one-day forecast model.
+#
+# This class is designed to invoke one-day STEPCoulombOneDayModel forecast model 
+# by Matt Gerstenberger and Sandy Steacy. It prepares input catalog data, 
+# formats control file with model parameters, identifies list of available 
+# Coulomb and slip models and provides it as an input to the model. It places 
+# forecast file under user specified directory.
+#
+class STEPCoulombOneDayModel2 (OneDayForecast, STEPCoulombModel2):
+
+    # Static data of the class
+    
+    # Keyword identifying type of the class (Hacky implementation)
+    Type = STEPCoulombModel2.Type + OneDayForecast.Type
+    
+    #---------------------------------------------------------------------------
+    #
+    # Initialization.
+    #
+    # Input: 
+    #        dir_path - Directory to store forecast file to.
+    #        args - Optional arguments for the model. Default is None.
+    # 
+    def __init__ (self, dir_path, args = None):
+        """ Initialization for STEPCoulombOneDayModel class"""
+        
+        OneDayForecast.__init__(self, 
+                                dir_path)
+        STEPCoulombModel2.__init__(self, 
+                                  args)
+        
+        # Parameter file for the Coulomb part of the model
+        self.CoulombParamFile = None
+
+    #---------------------------------------------------------------------------
+    #
+    # Return keyword identifying the model.
+    #
+    # Input: None.
+    #
+    # Output:
+    #           String identifying the type
+    #
+    def type (self):
+        """ Returns keyword identifying the forecast model type."""
+        
+        return STEPCoulombOneDayModel2.Type
+    
+    
+    #---------------------------------------------------------------------------
+    #
+    # Write input parameter file for the model
+    #        
+    def writeParameterFile (self, 
+                            filename = None):
+        """ Format input parameter file for the model.
+            Path to created input parameter file will be passed to the 
+            model's executable."""
+
+        # Open STEPCoulomb param file
+        fhandle = Forecast.writeParameterFile(self,
+                                              filename)
+        
+        STEPCoulombModel2.writeSTEPFile(self,
+                                       fhandle,
+                                       self.start_date,
+                                       self.numDays(self.start_date,
+                                                    self.end_date),
+                                       os.path.join(self.catalogDir,
+                                                    self.inputCatalogFilename()), 
+                                       self.filename())
+        
+        fhandle.close()
+
+        # Write param file to invoke Coulomb part of the model first
+        param_path, param_file = os.path.split(self.parameterFile)
+        
+        self.CoulombParamFile = os.path.join(param_path,
+                                             "CoulombPart_" + param_file)
+        
+        # To avoid inheritance from two classes that are derived from the same
+        # base "Forecast" class, use this "pass all values" approach
+        STEPCoulombModel2.writeCoulombFile(self,
+                                          self.CoulombParamFile,
+                                          self.start_date,
+                                          self.catalogDir)
+
+        # Register input parameters file for reproducibility
+        info_msg = "Input parameters file used by Coulomb part of %s model \
+to generate '%s' forecast file for %s." %(self.type(), 
+                                          self.rawFilename(), 
+                                          self.start_date.date())
+
+        # Record parameter file with reproducibility registry
+        ReproducibilityFiles.add(self,
+                                 self.CoulombParamFile, 
+                                 info_msg, 
+                                 CSEPFile.Extension.ASCII)
+
+
+    #--------------------------------------------------------------------
+    #
+    # Invoke the model to generate forecast.
+    #
+    # Input: None
+    #        
+    def run(self):
+        """ Invoke model."""
+
+        coulomb_output = STEPCoulombModel2.invokeModel(self, self.CoulombParamFile, self.parameterFile)
+        
+        # Move Coulomb file to the archive directory - should not be
+        # evaluated
+        if self.archive is not None:
+           
+            # Move file to the archive directory to avoid it
+            # in evaluation tests 
+            CSEPLogging.getLogger(STEPCoulombOneDayModel2.__name__).info("run(): moving %s to %s"
+                                                                        %(coulomb_output,
+                                                                          self.archive))
+
+            new_path = os.path.join(self.archive, 
+                                    os.path.basename(coulomb_output))
+            os.renames(coulomb_output, 
+                       new_path)
+        
  • ForecastFactory XML File was updated to include the new file. See updates below:
git diff HEAD^ src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml | cat
diff --git a/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml b/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
index a522dc5..fd5a138 100644
--- a/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
+++ b/src/SCECModels/NewZealand/DarfieldForecastFactory.init.xml
@@ -42,6 +42,7 @@
    <module>CattaniaOneYearModel.CattaniaOneYearModel</module>
    
    <module>STEPCoulombOneDayModel.STEPCoulombOneDayModel</module>
+   <module>STEPCoulombOneDayModel2.STEPCoulombOneDayModel2</module>
    <module>STEPCoulombOneMonthModel.STEPCoulombOneMonthModel</module>
    <module>STEPCoulombOneYearModel.STEPCoulombOneYearModel</module>

3. Reprocessing Specifics

Verification phase: Use the 03 September 2010 and 04 September 2010 using the bestAvailable and bestAvailable+10days data sets.