diff --git a/ThirdParty/Ert/.gitignore b/ThirdParty/Ert/.gitignore index 43c43a690a..1ec65bb69b 100644 --- a/ThirdParty/Ert/.gitignore +++ b/ThirdParty/Ert/.gitignore @@ -22,4 +22,5 @@ devel/python/lib64 scratch.sparsebundle *.iml *.DS_Store +__ert_lib_path.py diff --git a/ThirdParty/Ert/.travis.yml b/ThirdParty/Ert/.travis.yml new file mode 100644 index 0000000000..e28b6c4420 --- /dev/null +++ b/ThirdParty/Ert/.travis.yml @@ -0,0 +1,38 @@ +language: python + +python: + - 2.7_with_system_site_packages + +compiler: + - gcc + +addons: + apt: + packages: + - liblapack-dev + - texlive-latex-base + - valgrind + - python-qt4 + - python-qt4-gl + +before_install: + - wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh + - chmod +x miniconda.sh + - ./miniconda.sh -b + - export PATH=/home/travis/miniconda/bin:$PATH + - conda update --yes conda + +install: + - conda install --yes numpy scipy matplotlib pandas pyopengl sphinx + +before_script: + - sudo apt-get install libplplot-dev + - sudo apt-get install python-tk + - mkdir build + - cd build + - echo "WORKFLOW_JOB_DIRECTORY ../devel/share/workflows/jobs/internal/config" > DEFAULT_SITE_CONFIG_FILE + - echo "WORKFLOW_JOB_DIRECTORY ../devel/share/workflows/jobs/internal-gui/config" >> DEFAULT_SITE_CONFIG_FILE + - echo "JOB_SCRIPT ../devel/share/bin/job_dispatch.py" >> DEFAULT_SITE_CONFIG_FILE + - cmake -DPYTHON_INSTALL_PREFIX=python -DBUILD_ERT=ON -DERT_BUILD_GUI=ON -DBUILD_ENS_PLOT=ON -DBUILD_TESTS=ON -DBUILD_APPLICATIONS=ON -DUSE_RUNPATH=ON -DBUILD_PYTHON=ON -DERT_USE_OPENMP=ON -DERT_DOC=ON -DSITE_CONFIG_FILE=DEFAULT_SITE_CONFIG_FILE ../devel + +script: make && ctest --output-on-failure -LE StatoilData diff --git a/ThirdParty/Ert/devel/CMakeLists.txt b/ThirdParty/Ert/devel/CMakeLists.txt index 49c1750621..b435f95919 100644 --- a/ThirdParty/Ert/devel/CMakeLists.txt +++ b/ThirdParty/Ert/devel/CMakeLists.txt @@ -22,7 +22,7 @@ option( BUILD_ENS_PLOT "Build small Eclipse plotting program - no" OFF) option( BUILD_TESTS "Should the tests be built" OFF) option( BUILD_APPLICATIONS "Should we build small utility applications" OFF) option( BUILD_ECL_SUMMARY "Build the commandline application ecl_summary" OFF) -option( BUILD_PYTHON "Run py_compile on the python wrappers" OFF) +option( BUILD_PYTHON "Run py_compile on the python wrappers" ON) option( BUILD_SHARED_LIBS "Build shared libraries" ON ) option( INSTALL_ERT "Should anything be installed when issuing make install?" ON) option( ERT_BUILD_GUI "Should the pyQt based gui be compiled and installed" OFF ) @@ -84,8 +84,8 @@ if (ERT_USE_OPENMP) endif() -include(cmake/ert_check.cmake) include(cmake/ert_find.cmake) +include(cmake/ert_check.cmake) include(cmake/Modules/UseMultiArch.cmake) include(cmake/ert_link.cmake) @@ -207,10 +207,14 @@ endif() if (BUILD_PYTHON) - include(cmake/python.cmake2) - add_subdirectory( python ) - if(ERT_DOC) - add_subdirectory( docs ) + if (ERT_WINDOWS) + message(STATUS "Python is not supported on Windows") + else() + include(cmake/python.cmake2) + add_subdirectory( python ) + if(ERT_DOC) + add_subdirectory( docs ) + endif() endif() endif() diff --git a/ThirdParty/Ert/devel/cmake/ert_check.cmake b/ThirdParty/Ert/devel/cmake/ert_check.cmake index 5950d216a1..24c03a1543 100644 --- a/ThirdParty/Ert/devel/cmake/ert_check.cmake +++ b/ThirdParty/Ert/devel/cmake/ert_check.cmake @@ -1,3 +1,5 @@ +include(CheckSymbolExists) + check_function_exists( fseeko HAVE_FSEEKO ) if (HAVE_HFSEEKO) add_definitions( -DHAVE_FSEEKO ) @@ -110,6 +112,17 @@ if (HAVE__USLEEP) add_definitions( -DHAVE__USLEEP ) endif() +check_symbol_exists(_tzname time.h HAVE_WINDOWS_TZNAME) +if (HAVE_WINDOWS_TZNAME) + add_definitions(-DHAVE_WINDOWS_TZNAME) +else() + check_symbol_exists(tzname time.h HAVE_TZNAME) + if (HAVE_TZNAME) + add_definitions(-DHAVE_TZNAME) + else() + message(FATAL_ERROR "Could not find tzname global variable") + endif() +endif() check_function_exists(pthread_yield_np HAVE_YIELD_NP) if (HAVE_YIELD_NP) @@ -122,6 +135,11 @@ if (HAVE_YIELD) endif() +check_function_exists(pthread_timedjoin_np HAVE_TIMEDJOIN) +if (HAVE_TIMEDJOIN) + add_definitions(-DHAVE_TIMEDJOIN) +endif() + # Checking based on compiling. Some of the code generates warnings, so we just cut down to bare-bone compiler flags. set( CMAKE_C_FLAGS_main ${CMAKE_C_FLAGS} ) diff --git a/ThirdParty/Ert/devel/cmake/ert_find.cmake b/ThirdParty/Ert/devel/cmake/ert_find.cmake index 801134ded0..c4d448d6df 100644 --- a/ThirdParty/Ert/devel/cmake/ert_find.cmake +++ b/ThirdParty/Ert/devel/cmake/ert_find.cmake @@ -2,7 +2,7 @@ set(NEED_LIBDL OFF) find_library( DL_LIBRARY NAMES dl ) find_path( DLFUNC_HEADER dlfcn.h ) if (DL_LIBRARY AND DLFUNC_HEADER) - set(CMAKE_REQUIRED_LIBRARIES dl) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) check_function_exists( dladdr HAVE_DLADDR ) if (HAVE_DLADDR) @@ -30,6 +30,7 @@ if (PTHREAD_LIBRARY) if (WITH_PTHREAD) add_definitions( -DWITH_PTHREAD ) endif() + set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} pthread) else() set( WITH_PTHREAD FALSE ) message("pthread library not found - pthread support will not be included") @@ -85,3 +86,7 @@ endif() if (ERT_WINDOWS) find_library( SHLWAPI_LIBRARY NAMES Shlwapi ) endif() + +if (UNIX) + set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m) +endif(UNIX) diff --git a/ThirdParty/Ert/devel/cmake/python.cmake2 b/ThirdParty/Ert/devel/cmake/python.cmake2 index 99991808e9..414b9bbd9d 100644 --- a/ThirdParty/Ert/devel/cmake/python.cmake2 +++ b/ThirdParty/Ert/devel/cmake/python.cmake2 @@ -8,7 +8,11 @@ function(add_python_package target package_path source_files install_package) foreach (file ${source_files} ) set( source_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} ) set( build_file ${PROJECT_BINARY_DIR}/${package_path}/${file} ) - set( install_file ${CMAKE_INSTALL_PREFIX}/${package_path}/${file} ) + if("$ENV{DESTDIR}" STREQUAL "") + set( install_file ${CMAKE_INSTALL_PREFIX}/${package_path}/${file} ) + else() + set( install_file $ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/${package_path}/${file} ) + endif() add_custom_command( OUTPUT ${build_file} diff --git a/ThirdParty/Ert/devel/debian/control b/ThirdParty/Ert/devel/debian/control index 8198d32937..763f72dc09 100644 --- a/ThirdParty/Ert/devel/debian/control +++ b/ThirdParty/Ert/devel/debian/control @@ -2,7 +2,7 @@ Source: ert.ecl Priority: extra Maintainer: Arne Morten Kvarving Build-Depends: debhelper (>= 8.0.0), cmake, liblapack-dev, libquadmath0, - iputils-ping, zlib1g-dev, git + iputils-ping, zlib1g-dev, git, python-dev Standards-Version: 3.9.2 Section: libs Homepage: http://ert.nr.no @@ -24,3 +24,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends} Description: The Ensemble based Reservoir Tool ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble of reservoir models. + +Package: python-ert.ecl +Section: python +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libert.ecl1 +Description: The Ensemble based Reservoir Tool - Python bindings + ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble + of reservoir models. diff --git a/ThirdParty/Ert/devel/debian/rules b/ThirdParty/Ert/devel/debian/rules index f73eb28cac..c816b38cd0 100644 --- a/ThirdParty/Ert/devel/debian/rules +++ b/ThirdParty/Ert/devel/debian/rules @@ -13,4 +13,4 @@ dh $@ override_dh_auto_configure: - dh_auto_configure -- -DBUILD_SHARED_LIBS=1 -DBUILD_ECL_SUMMARY=1 -DCMAKE_BUILD_TYPE=Release + DESTDIR=$$(pwd)/debian/tmp dh_auto_configure -- -DBUILD_SHARED_LIBS=1 -DBUILD_ECL_SUMMARY=1 -DCMAKE_BUILD_TYPE=Release diff --git a/ThirdParty/Ert/devel/docs/user/distributions/index.rst b/ThirdParty/Ert/devel/docs/user/distributions/index.rst new file mode 100644 index 0000000000..c1b8f9ea94 --- /dev/null +++ b/ThirdParty/Ert/devel/docs/user/distributions/index.rst @@ -0,0 +1,141 @@ +.. toctree:: + :maxdepth: 1 + +.. _prior_distributions: + +Prior distributions avaliable in ERT +==================================== + +The :ref:`GEN_KW ` keyword is typically used in sensitivy +studies and as parameters which are updated with the Ensemble Smoother +in a model updating project. In your configuration file the +:ref:`GEN_KW ` keyword is configured as: + +:: + + GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt + +The file ``my_priors.txt`` contains the names of the variables +you are considering, and specifies the distribution which should be +used for the initial sampling. + + +NORMAL +------ +To set a normal (Gaussian) prior, use the keyword NORMAL. It takes two +arguments, a mean value and a standard deviation. Thus, the following +example will assign a normal prior with mean 0 and standard deviation +1 to the variable VAR1: + +:: + + VAR1 NORMAL 0 1 + +LOGNORMAL +--------- +A stochastic variable is log normally distributed if the logarithm of +the variable is normally distributed. In other words, if X is normally +distributed, then Y = exp(X) is log normally distributed. + +A log normal prior is suited to model positive quanties with a heavy +tail (tendency to take large values). To set a log normal prior, use +the keyword LOGNORMAL. It takes two arguments, the mean and standard +deviation of the *logarithm* of the variable: + +:: + + VAR2 LOGNORMAL 0 + +TRUNCATED_NORMAL +----------------- + +This *TRUNCATED_NORMAL* distribution works as follows: + + 1. Draw random variable X ~ N(mu,std) + 2. Clamp X to the interval [min, max] + +This is **not** a proper truncated normal distribution; hence the +clamping to ``[min,max]` should be an exceptional event. To configure +this distribution for a situation with mean 1, standard deviation 0.25 +and hard limits 0 and 10: + +:: + + VAR3 TRUNCATED_NORMAL 1 0.25 0 10 + + +UNIFORM +------- + +A stochastic variable is uniformly distributed if has a constant +probability density on a closed interval. Thus, the uniform +distribution is completely characterized by it's minimum and maximum +value. To assign a uniform distribution to a variable, use the keyword +UNIFORM, which takes a minimum and a maximum value for a the +variable. Here is an example, which assigns a uniform distribution +between 0 and 1 to a variable ``VAR4``: + +:: + + VAR4 UNIFORM 0 1 + +It can be shown that among all distributions bounded below by a and +above by b, the uniform distribution with parameters a and b has the +maximal entropy (contains the least information). Thus, the uniform +distribution should be your preferred prior distribution for robust +modeling of bounded variables. + + +LOGUNIF +------- + +A stochastic variable is log uniformly distributed if it's logarithm +is uniformly distributed on the interval [a,b]. To assign a log +uniform distribution to a a variable, use the keyword LOGUNIF, which +takes a minimum and a maximum value for the output variable as +arguments. The example + +:: + + VAR5 LOGUNIF 0.00001 1 + +will give values in the range [0.00001,1] - with considerably more +weight towards the lower limit. The log uniform distribution is useful +when modeling a bounded positive variable who has most of it's +probability weight towards one of the bounds. + +CONST +----- + +The keyword CONST is used to assign a Dirac distribution to a +variable, i.e. set it to a constant value. Here is an example of use: + +:: + + CONST 1.0 + + + +Priors and transformations +========================== + +The Ensemble Smoother method, which ERT uses for updating of +parameters, works with normally distributed variables. So internally +in ERT the interplay between ``GEN_KW`` variables and updates is as +follows: + + 1. ERT samples a random variable ``x ~ N(0,1)`` - before outputing + to the forward model this is *transformed* to ``y ~ F(Y)`` where + the the distribution ``F(Y)`` is the correct prior distribution. + + 2. When the prior simulations are complete ERT calculates misfits + between simulated and observed values and *updates* the + parameters; hence the variables ``x`` now represent samples from + a posterior distribution which is Normal with mean and standard + deviation *different from (0,1)*. + +The transformation prescribed by ``F(y)`` still "works" - but it no +longer maps to a distribution in the same family as initially +specified by the prior. A consequence of this is that the update +process can *not* give you a posterior with updated parameters in the +same distribution family as the Prior. diff --git a/ThirdParty/Ert/devel/docs/user/index.rst b/ThirdParty/Ert/devel/docs/user/index.rst index 6fcb3255b6..8848329bc8 100644 --- a/ThirdParty/Ert/devel/docs/user/index.rst +++ b/ThirdParty/Ert/devel/docs/user/index.rst @@ -10,3 +10,5 @@ Contents: keywords/index workflows/index observations/index + distributions/index + localization/index diff --git a/ThirdParty/Ert/devel/docs/user/keywords/index.rst b/ThirdParty/Ert/devel/docs/user/keywords/index.rst index 17c5f28ce0..a7017fea43 100644 --- a/ThirdParty/Ert/devel/docs/user/keywords/index.rst +++ b/ThirdParty/Ert/devel/docs/user/keywords/index.rst @@ -767,22 +767,32 @@ The keywords in this section are used to define a parametrization of the ECLIPSE GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt - Here ID is an (arbitrary) unique string, my_template.txt is the name of a template file, my_eclipse_include.txt is the name of the file which is made for each member based on my_template.txt and my_priors.txt is a file containing a list of parametrized keywords and a prior distribution for each. Note that you must manually edit the ECLIPSE data file so that my_eclipse_include.txt is included. + Here ID is an (arbitrary) unique string, my_template.txt is + the name of a template file, my_eclipse_include.txt is the + name of the file which is made for each member based on + my_template.txt and my_priors.txt is a file containing a list + of parametrized keywords and a prior distribution for + each. Note that you must manually edit the ECLIPSE data file + so that my_eclipse_include.txt is included. - Let us consider an example where the GEN_KW parameter type is used to estimate pore volume multipliers. We would then declare a GEN_KW instance in the main enkf configuration file: + Let us consider an example where the GEN_KW parameter type is + used to estimate pore volume multipliers. We would then + declare a GEN_KW instance in the main enkf configuration file: :: GEN_KW PAR_MULTPV multpv_template.txt multpv.txt multpv_priors.txt - In the GRID or EDIT section of the ECLIPSE data file, we would insert the following include statement: + In the GRID or EDIT section of the ECLIPSE data file, we would + insert the following include statement: :: INCLUDE 'multpv.txt' / - The template file multpv_template.txt would contain some parametrized ECLIPSE statements: + The template file multpv_template.txt would contain some + parametrized ECLIPSE statements: :: @@ -798,24 +808,37 @@ The keywords in this section are used to define a parametrization of the ECLIPSE 300* / ENDBOX - Here, and will act as magic strings. Note that the '<' '>' must be present around the magic strings. In this case, the parameter configuration file multpv_priors.txt could look like this: + Here, and will act as magic + strings. Note that the '<' '>' must be present around the + magic strings. In this case, the parameter configuration file + multpv_priors.txt could look like this: :: MULTPV_BOX2 UNIFORM 0.98 1.03 MULTPV_BOX1 UNIFORM 0.85 1.00 - In general, the first keyword on each line in the parameter configuration file defines a key, which when found in the template file enclosed in '<' and '>', is replaced with a value. The rest of the line defines a prior distribution for the key. See Prior distributions available in enkf for a list of available prior distributions. + In general, the first keyword on each line in the parameter + configuration file defines a key, which when found in the + template file enclosed in '<' and '>', is replaced with a + value. The rest of the line defines a prior distribution for + the key. See Prior distributions available in enkf for a list + of available prior distributions. **Example: Using GEN_KW to estimate fault transmissibility multipliers** - Previously enkf supported a datatype MULTFLT for estimating fault transmissibility multipliers. This has now been depreceated, as the functionality can be easily achieved with the help of GEN_KW. In th enkf config file: + Previously enkf supported a datatype MULTFLT for estimating + fault transmissibility multipliers. This has now been + depreceated, as the functionality can be easily achieved with + the help of GEN_KW. In th enkf config file: :: GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt - Here MY-FAULTS is the (arbitrary) key assigned to the fault multiplers, MULTFLT.tmpl is the template file, which can look like this: + Here MY-FAULTS is the (arbitrary) key assigned to the fault + multiplers, MULTFLT.tmpl is the template file, which can look + like this: :: @@ -824,22 +847,38 @@ The keywords in this section are used to define a parametrization of the ECLIPSE 'FAULT2' / / - and finally the initial distribution of the parameters FAULT1 and FAULT2 are defined in the file MULTFLT.txt: + and finally the initial distribution of the parameters FAULT1 + and FAULT2 are defined in the file MULTFLT.txt: :: FAULT1 LOGUNIF 0.00001 0.1 FAULT2 UNIFORM 0.00 1.0 + The various prior distributions available for the ``GEN_KW`` + keyword are here :ref:`prior distributions available in ERT ` + + Loading GEN_KW values from an external file - The default use of the GEN_KW keyword is to let the ERT application sample random values for the elements in the GEN_KW instance, but it is also possible to tell ERT to load a precreated set of data files, this can for instance be used as a component in a experimental design based workflow. When using external files to initialize the GEN_KW instances you supply an extra keyword INIT_FILE:/path/to/priors/files%d which tells where the prior files are: + The default use of the GEN_KW keyword is to let the ERT + application sample random values for the elements in the + GEN_KW instance, but it is also possible to tell ERT to load a + precreated set of data files, this can for instance be used as + a component in a experimental design based workflow. When + using external files to initialize the GEN_KW instances you + supply an extra keyword ``INIT_FILE:/path/to/priors/files%d`` + which tells where the prior files are: :: GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt INIT_FILES:priors/multflt/faults%d - In the example above you must prepare files priors/multflt/faults0, priors/multflt/faults1, ... priors/multflt/faultsn which ert will load when you initialize the case. The format of the GEN_KW input files can be of two varieties: + In the example above you must prepare files + priors/multflt/faults0, priors/multflt/faults1, + ... priors/multflt/faultsn which ert will load when you + initialize the case. The format of the GEN_KW input files can + be of two varieties: 1. The files can be plain ASCII text files with a list of numbers: diff --git a/ThirdParty/Ert/devel/docs/user/localization/index.rst b/ThirdParty/Ert/devel/docs/user/localization/index.rst new file mode 100644 index 0000000000..2095e12856 --- /dev/null +++ b/ThirdParty/Ert/devel/docs/user/localization/index.rst @@ -0,0 +1,917 @@ + +Keywords for the local configuration file +========================================= + + + +General overview +---------------- + +To create a configuration for localization you must "program" your own +configuration file, this file is then loaded from the ert/enkf proper +application. The 'commands' available in the local_config programming +language are listed below. + +An alterative way to 'program' the local config commands is by writing a Python script, and invoking it from a workflow. +Not all the commands available from the local config programming are supported for Python scripting. + + +**Local config ERT script example:** + +:: + + from ert.enkf import ErtScript + from ert.enkf import LocalConfig + + class LocalConfigJob(ErtScript): + + + def run(self): + + ert = self.ert() + local_config = ert.getLocalConfig() + + # Add your local config commands here + dataset_multflt = local_config.createDataset("DATASET_MULTFLT") + ... + + # Write to file for debugging + local_config.writeLocalConfigFile("tmp/debug_local_config.txt") + + + +List of keywords +---------------- +=========================================================================================== =========================================================== ============================================================================================================================================== +Keyword name ERT script function Purpose +=========================================================================================== =========================================================== ============================================================================================================================================== +:ref:`CREATE_MINISTEP ` createMinistep Creates ministep +:ref:`CREATE_UPDATESTEP ` createUpdatestep Creates updatestep +:ref:`CREATE_DATASET ` createDataset Creates dataset +:ref:`COPY_DATASET ` copyDataset Deep copy of dataset +:ref:`CREATE_OBSSET ` createObsdata Creates observation set +:ref:`COPY_OBSSET ` copyObsdata Deep copy of observation set +:ref:`ATTACH_MINISTEP ` attachMinistep Attaches ministep to update step +:ref:`ATTACH_DATASET ` attachDataset Attaches dataset to mini step +:ref:`ATTACH_OBSSET ` attachObsset Attaches observation set to mini step +:ref:`ADD_DATA ` addNode Adds data node to dataset +:ref:`DEL_DATA ` del Deletes observation node from dataset +:ref:`ADD_OBS ` addNodeAndRange Adds observation node to observation set +:ref:`DEL_OBS ` del Deletes observation node from observation set +:ref:`DATASET_DEL_ALL_DATA ` clear Delete all the data keys from a dataset +:ref:`ACTIVE_LIST_ADD_DATA_INDEX ` addActiveIndex Adds data index to the list of active indices +:ref:`ACTIVE_LIST_ADD_OBS_INDEX ` addActiveIndex Adds observation index to the list of active indices +:ref:`ACTIVE_LIST_ADD_MANY_DATA_INDEX ` addActiveIndex Adds several data indices to the list of active indices +:ref:`ACTIVE_LIST_ADD_MANY_OBS_INDEX ` addActiveIndex Adds several observation indinces to the list of active indices +:ref:`INSTALL_DEFAULT_UPDATESTEP ` Installs default update step +:ref:`ADD_FIELD ` addField Adds field node to dataset +:ref:`LOAD_FILE ` EclGrid, EclInitFile, Loads eclipse file in restart format +:ref:`CREATE_ECLREGION ` EclRegion Creates a new region for use when defining active regions for fields +:ref:`ECLREGION_SELECT_ALL ` select_active Selects or deselects cells in a region +:ref:`ECLREGION_SELECT_VALUE_EQUAL ` select_equal Selects or deselects cells in a region equal to given value +:ref:`ECLREGION_SELECT_VALUE_LESS ` select_less Selects or deselects cells in a region equal less than a given value +:ref:`ECLREGION_SELECT_VALUE_MORE ` select_more Selects or deselects cells in a region equal greater than a given value +:ref:`ECLREGION_SELECT_BOX ` select_box Selects or deselects cells in a box +:ref:`ECLREGION_SELECT_SLICE ` select_islice, select_jslice, select_kslice Selects or deselects cells in a slice +:ref:`ECLREGION_SELECT_PLANE ` select_below_plane Selects or deselects cells in a half space defined by a plane +:ref:`ECLREGION_SELECT_IN_POLYGON ` select_inside_polygon Selects or deselects cells in region inside polygon +:ref:`CREATE_POLYGON ` :ref:`Example ` Creates a geo-polygon based on coordinate list +:ref:`LOAD_POLYGON ` :ref:`Example ` Loads polygon in Irap RMS format from file +:ref:`LOAD_SURFACE ` Loads surface in Irap RMS format from file +:ref:`CREATE_SURFACE_REGION ` Creates region to select or deselect parts of a surface +:ref:`SURFACE_REGION_SELECT_IN_POLYGON ` Creates region to select or deselect parts of a surface +:ref:`SURFACE_REGION_SELECT_LINE ` Selects or deselects parts of a surface in half space define by a line +:ref:`ADD_DATA_SURFACE ` Adds surface node to dataset with elements in a surface region +=========================================================================================== =========================================================== ============================================================================================================================================== + +.. ########################################################################################################### + +.. _create_updatestep: +.. topic:: CREATE_UPDATESTEP + + | This function will create a new updatestep with the name 'NAME_OF_UPDATESTEP'. Observe that you must add (at least) one ministep to the updatestep, otherwise it will not be able to do anything. + + + *Example:* + + :: + + -- Update step in time interval 0->1 + CREATE_UPDATESTEP UPDATESTEP_0_1 + + + *Example:* + + :: + + update_step_0_1 = local_config.createUpdatestep("UPDATESTEP_0_1") + + +.. ########################################################################################################### + + +.. _create_ministep: +.. topic:: CREATE_MINISTEP + + | This function will create a new ministep with the name 'NAME_OF_MINISTEP'. A given OBSSET can be attached to a given ministep.The ministep is then ready for adding data. Before the ministep can be used you must attach it to an updatestep with the ATTACH_MINISTEP command + + *Example:* + + :: + + -- Mini step 0 in update step 0->1 + CREATE_MINISTEP MINISTEP_0_1_0 + + *Example:* + + :: + + ministep_0_1_0 = local_config.createMinistep("MINISTEP_0_1_0") + + + +.. ########################################################################################################### + +.. _create_dataset: +.. topic:: CREATE_DATASET + + | This function will create a new dataset, i.e. a collection of enkf_nodes which should be updated together. Before you can actually use a dataset you must attach it to a ministep with the ATTACH_DATASET command. + + *Example:* + + :: + + -- Create a DATASET_MULTFLT dataset + CREATE_DATASET DATASET_MULTFLT + + *Example:* + + :: + + dataset_multflt = local_config.createDataset("DATASET_MULTFLT") + +.. ########################################################################################################### + +.. _copy_dataset: +.. topic:: COPY_DATASET + + | Will create a new local_obsset instance which is a copy of the 'SRC_OBSSET'; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other. + + + *Example:* + + :: + + -- Deep copy DATASET_MULTFLT dataset + COPY_DATASET DATASET_MULTFLT COPY_DATASET_MULTFLT + +.. ########################################################################################################### + +.. _create_obsset: +.. topic:: CREATE_OBSSET + + | This function will create an observation set, i.e. a collection of observation keys which will be used as the observations in one ministep. Before the obsset can be used it must be attached to a ministep with the ATTACH_OBSSET command. + + + *Example:* + + :: + + -- Create a OBS_WELL obsset + CREATE_OBSSET OBS_WELL + + *Example:* + + :: + + obsset_obs_well = local_config.createObsdata("OBS_WELL") + + +.. ########################################################################################################### + +.. _copy_obsset: +.. topic:: COPY_OBSSET + + | Will create a new local_obsset instance which is a copy of the 'SRC_OBSSET'; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other. + + + *Example:* + + :: + + -- Deep copy OBS_WELL observation set + COPY_OBSSET OBS_WELL COPY_OBS_WELL + +.. ########################################################################################################### + +.. _attach_ministep: +.. topic:: ATTACH_MINISTEP + + | This function will attach the ministep 'NAME_OF_MINISTEP' to the updatestep 'NAME_OF_UPDATESTEP'; one ministep can be attached to many updatesteps. + + *Example:* + + :: + + -- Attach MINISTEP_0_1_0 to UPDATESTEP_0_1 + ATTACH_MINISTEP UPDATESTEP_0_1 MINISTEP_0_1_0 + + *Example:* + + :: + + update_step_0_1.attachMinistep(ministep_0_1_0) + + +.. ########################################################################################################### + +.. _attach_dataset: +.. topic:: ATTACH_DATASET + + | Will attach the dataset 'NAME_OF_DATASET' to the ministep given by 'NAME_OF_MINISTEP'. + + *Example:* + + :: + + -- Attach DATASET_MULTFLT to MINISTEP_0_1_0 + ATTACH_MINISTEP MINISTEP_0_1_0 DATASET_MULTFLT + + *Example:* + + :: + + ministep_0_1_0.attachDataset(dataset_multflt) + + +.. ########################################################################################################### + +.. _attach_obsset: +.. topic:: ATTACH_OBSSET + + | Will attach the obsset 'NAME_OF_OBSSET' to the ministep given by 'NAME_OF_MINISTEP'. + + *Example:* + + :: + + -- Attach OBS_WELL to MINISTEP_0_1_0 + ATTACH_MINISTEP MINISTEP_0_1_0 OBS_WELL + + *Example:* + + :: + + ministep_0_1_0.attachObsset(obsset_obs_well) + + +.. ########################################################################################################### + +.. _add_data: +.. topic:: ADD_DATA + + | This function will install 'KEY' as one enkf node which should be updated in this dataset. If you do not manipulate the KEY further with the ACTIVE_LIST_ADD_DATA_INDEX function the KEY will be added as 'ALL_ACTIVE', i.e. all elements will be updated. + + + *Example:* + + :: + + -- Add data node to data set + ADD_DATA DATASET_MULTFLT MULTFLT + + *Example:* + + :: + + dataset_multflt.addNode("MULTFLT") + +.. ########################################################################################################### + +.. _del_data: +.. topic:: DEL_DATA + + | This function will delete the data 'KEY' from the dataset 'NAME_OF_DATASET'. + + + *Example:* + + :: + + -- Delete data node from data set + DEL_DATA DATASET_MULTFLT MULTFLT + + *Example:* + + :: + + del dataset_multflt["MULTFLT"] + + +.. ########################################################################################################### + +.. _add_obs: +.. topic:: ADD_OBS + + | This function will install the observation 'OBS_KEY' as an observation for this obsset - similarly to the ADD_DATA function. + + + *Example:* + + :: + + -- Add data node to observation set + ADD_OBS OBS_WELL WOPR:OBS_WELL + + *Example:* + + :: + + -- The obsset has a time range + obsset_obs_well.addNodeAndRange("WOPR:OBS_WELL", 0, 1) + + +.. ########################################################################################################### + +.. _del_obs: +.. topic:: DEL_OBS + + | This function will delete the obs 'OBS_KEY' from the obsset 'NAME_OF_OBSSET'. + + + *Example:* + + :: + + -- Delete data node from observation set + DEL_OBS OBS_WELL WOPR:OBS_WELL + + *Example:* + + :: + + del obsset_obs_well["WOPR:OBS_WELL"] + + +.. ########################################################################################################### + +.. _dataset_del_all_data: +.. topic:: DATASET_DEL_ALL_DATA + + | This function will delete all the data keys from the dataset 'NAME_OF_DATASET'. + + + *Example:* + + :: + + -- Delete all data nodes from DATASET_MULTFLT + DATASET_DEL_ALL_DATA DATASET_MULTFLT + + *Example:* + + :: + + dataset_multflt.clear() + +.. ########################################################################################################### + +.. _active_list_add_data_index: +.. topic:: ACTIVE_LIST_ADD_DATA_INDEX + + | This function will say that the data with name 'DATA_KEY' in dataset with name 'DATASTEP_NAME' should have the index 'INDEX' active. + + + *Example:* + + :: + + -- Add index 0 from data MULTFLT to dataset DATASET_MULTFLT + ACTIVE_LIST_ADD_DATA_INDEX DATASET_MULTFLT MULTFLT 0 + + *Example:* + + :: + + active_list = dataset_multflt.getActiveList("MULTFLT") + active_list.addActiveIndex(0); + +.. ########################################################################################################### + +.. _active_list_add_obs_index: +.. topic:: ACTIVE_LIST_ADD_OBS_INDEX + + | This function will say that the observation with name 'OBS_KEY' in obsset with name 'OBSSET_NAME' should have the index 'INDEX' active. + + + *Example:* + + :: + + -- Add index 0 from data WOPR:OBS_WELL to obsset OBS_WELL + ACTIVE_LIST_ADD_OBS_INDEX OBS_WELL WOPR:OBS_WELL 0 + + *Example:* + + :: + + active_list = obsset_obs_well.getActiveList("WOPR:OBS_WELL") + active_list.addActiveIndex(0); + +.. ########################################################################################################### + +.. _active_list_add_many_data_index: +.. topic:: ACTIVE_LIST_ADD_MANY_DATA_INDEX + + | This function is similar to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices. + + + *Example:* + + :: + + -- Add indices 0, 1 and 2 from data MULTFLT to dataset DATASET_MULTFLT + ACTIVE_LIST_ADD_MANY_DATA_INDEX DATASET_MULTFLT MULTFLT 0 1 2 + + +.. ########################################################################################################### + +.. _active_list_add_many_obs_index: +.. topic:: ACTIVE_LIST_ADD_MANY_OBS_INDEX + + | This function is similar to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices. + + + *Example:* + + :: + + -- Add index 0, 1 and 2 from data WOPR:OBS_WELL to obsset OBS_WELL + ACTIVE_LIST_ADD_MANY_OBS_INDEX OBS_WELL WOPR:OBS_WELL 0 1 2 + +.. ########################################################################################################### + + +.. _install_default_updatestep: +.. topic:: INSTALL_DEFAULT_UPDATESTEP + + | This function will install 'NAME_OF_UPDATESTEP' as the default updatestep which applies to all report steps where you have not explicitly set another updatestep with the INSTALL_UPDATESTEP function. + + + + *Example:* + + :: + + -- Install default update step + INSTALL_DEFAULT_UPDATESTEP ALL_ACTIVE + + + +.. ########################################################################################################### + +.. _add_field: +.. topic:: ADD_FIELD + + | This function will install the node with name 'FIELD_NAME' in the dataset 'DATASET_NAME'. It will in addition select all the (currently) active cells in the region 'ECLREGION_NAME' as active for this field/ministep combination. The ADD_FIELD command is actually a shortcut of: ADD_DATA DATASET FIELD_NAME; followed by: ACTIVE_LIST_ADD_MANY_DATA_INDEX + + + + *Example:* + + :: + + -- Add data node PORO to data set DATA_PORO activating indices in ECLREG_PORO + ADD_FIELD DATA_PORO PORO ECLREG_PORO + + *Example:* + + :: + + # Load Eclipse grid + ecl_grid = EclGrid("path/to/LOCAL.GRDECL") + + with open("path/to/LOCAL.GRDECL","r") as fileH: + local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL") + + # Define Eclipse region + eclreg_poro = EclRegion(ecl_grid, False) + eclreg_poro.select_more(local_kw, 1) + + # Create dataset and add field to dataset + data_poro = local_config.createDataset("DATA_PORO") + data_poro.addField("PORO", eclreg_poro) + + +.. ########################################################################################################### + +.. _load_file: +.. topic:: LOAD_FILE + + | This function will load an ECLIPSE file in restart format (i.e. restart file or INIT file), the keywords in this file can then subsequently be used in ECLREGION_SELECT_VALUE_XXX commands below. The 'KEY' argument is a string which will be used later when we refer to the content of this file + + + + + *Example:* + + :: + + -- Load Eclipse init file + LOAD_FILE REFINIT path/to/FULLMODEL.INIT + + *Example:* + + :: + + # Load Eclipse grid and init file + ecl_grid = EclGrid("path/to/FULLMODEL.GRDECL") + refinit_file = EclInitFile(grid , "path/to/somefile.init") + +.. ########################################################################################################### + +.. _create_eclregion: +.. topic:: CREATE_ECLREGION + + | This function will create a new region 'ECLREGION_NAME', which can subsequently be used when defining active regions for fields. The second argument, SELECT_ALL, is a boolean value. If this value is set to true the region will start with all cells selected, if set to false the region will start with no cells selected. + + + *Example:* + + :: + + -- New Eclipse region with all cells inactive + CREATE_ECLREGION ECL_REGION FALSE + + *Example:* + + :: + + # Define Eclipse region + eclreg_poro = EclRegion(ecl_grid, False) + +.. ########################################################################################################### + +.. _eclregion_select_all: +.. topic:: ECLREGION_SELECT_ALL + + | Will select all the cells in the region (or deselect if SELECT == FALSE). + + + + + + *Example:* + + :: + + -- Select cells in region + ECLREGION_SELECT_ALL ECL_REGION TRUE + + + *Example:* + + :: + + eclreg_poro.select_active() + + + + +.. ########################################################################################################### + +.. _eclregion_select_value_equal: +.. topic:: ECLREGION_SELECT_VALUE_EQUAL + + | This function will compare an ecl_kw instance loaded from file with a user supplied value, and select (or deselect) all cells which match this value. It is assumed that the ECLIPSE keyword is an INTEGER keyword, for float comparisons use the ECLREGION_SELECT_VALUE_LESS and ECLREGION_SELECT_VALUE_MORE functions. + + + + + + + *Example:* + + :: + + -- Select cells in region ECL_REGION equal to 0 + ECLREGION_SELECT_VALUE_EQUAL ECL_REGION ECL_REGION:LOCAL 0 TRUE + + + *Example:* + + :: + + # Load Eclipse grid + ecl_grid = EclGrid("path/to/LOCAL.GRDECL") + + with open("path/to/LOCAL.GRDECL","r") as fileH: + local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL", ecl_type= EclTypeEnum.ECL_INT_TYPE) + + # Define Eclipse region + eclreg_poro = EclRegion(ecl_grid, False) + eclreg_poro.select_equal(local_kw, 1) + print 'GRID LOADED%s' % ecl_grid + print ecl_grid.getDims() + print local_kw.header + + + +.. ########################################################################################################### + +.. _eclregion_select_value_less: +.. topic:: ECLREGION_SELECT_VALUE_LESS + + | This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical below the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL. + + + + + + *Example:* + + :: + + -- Select cells in region ECL_REGION less than 1 + ECLREGION_SELECT_VALUE_LESS ECL_REGION ECL_REGION:LOCAL 1 TRUE + + *Example:* + + :: + + eclreg_poro.select_less(local_kw, 1) + + +.. ########################################################################################################### + +.. _eclregion_select_value_more: +.. topic:: ECLREGION_SELECT_VALUE_MORE + + | This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical above the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL. + + + + + + *Example:* + + :: + + -- Select cells in region ECL_REGION greater than 0 + ECLREGION_SELECT_VALUE_MORE ECL_REGION ECL_REGION:LOCAL 0 TRUE + + *Example:* + + :: + + eclreg_poro.select_more(local_kw, 1) + +.. ########################################################################################################### + +.. _eclregion_select_box: +.. topic:: ECLREGION_SELECT_BOX + + | This function will select (or deselect) all the cells in the box defined by the six coordinates i1 i2 j1 j2 k1 k2. The coordinates are inclusive, and the counting starts at 1. + + + + + *Example:* + + :: + + -- Select cells in box [0,1] x [2,3] x [4,5] + ECLREGION_SELECT_BOX ECL_REGION 0 1 2 3 4 5 TRUE + + *Example:* + + :: + + eclreg_poro.select_box((0,2,4),(1,3,5)) + + + +.. ########################################################################################################### + +.. _eclregion_select_slice: +.. topic:: ECLREGION_SELECT_SLICE + + | This function will select a slice in the direction given by 'dir', which can 'x', 'y' or 'z'. Depending on the value of 'dir' the numbers n1 and n2 are interpreted as (i1 i2), (j1 j2) or (k1 k2) respectively. The numbers n1 and n2 are inclusice and the counting starts at 1. It is OK to use very high/low values to imply "the rest of the cells" in one direction. + + + + *Example:* + + :: + + -- Select layer from z=2 to z=3 + ECLREGION_SELECT_SLICE ECL_REGION z 2 3 TRUE + + *Example:* + + :: + + eclreg_poro.select_kslice(2,3) + + +.. ########################################################################################################### + +.. _eclregion_select_plane: +.. topic:: ECLREGION_SELECT_PLANE + + | Will select all points which have positive (sign > 0) distance to the plane defined by normal vector n = (nx,ny,nz) and point p = (px,py,pz). If sign < 0 all cells with negative distance to plane will be selected. + + + *Example:* + + :: + + -- Select half space defined by plane perpendicular to vector [1 1 1] + ECLREGION_SELECT_PLANE ECL_REGION 1 1 1 0 0 0 -1 TRUE + + *Example:* + + :: + + eclreg_poro.select_below_plane((1,1,1),(0,0,0)) + + +.. ########################################################################################################### + +.. _eclregion_select_in_polygon: +.. topic:: ECLREGION_SELECT_IN_POLYGON + + | Well select all the points which are inside the polygon with name 'POLYGON_NAME'. The polygon should have been created with command CREATE_POLYGON or loaded with command 'LOAD_POLYGON' first. + + + + + *Example:* + + :: + + -- Select region inside polygon in xy plane + ECLREGION_SELECT_IN_POLYGON POLYGON TRUE + + *Example:* + + :: + + polygon = [(0,0) , (0,1) , (1,0)] + eclreg_poro.select_inside_polygon(polygon) + +.. ########################################################################################################### + +.. _create_polygon: +.. topic:: CREATE_POLYGON + + | Will create a geo_polygon instance based on the coordinate list: (x1,y1), (x2,y2), (x3,y3), ... The polygon should not be explicitly closed - i.e. you should in general have (x1,y1) != (xn,yn). The polygon will be stored under the name 'POLYGON_NAME' - which should later be used when referring to the polygon in region select operations. + + + + *Example:* + + :: + + -- Create polygon in xy plane + CREATE_POLYGON POLYGON 0 0 0 1 1 0 TRUE + + *Example:* + + :: + + polygon = [(0,0) , (0,1) , (1,0)] + +.. ########################################################################################################### + +.. _load_polygon: +.. topic:: LOAD_POLYGON + + | Will load a polygon instance from the file 'FILENAME' - the file should be in irap RMS format. The polygon will be stored under the name 'POLYGON_NAME' which can then later be used to refer to the polygon for e.g. select operations. + + + + + + *Example:* + + :: + + -- Load polygon from RMS file + LOAD_POLYGON path/to/polygon.irap + + *Example:* + + :: + + polygon = [] + with open("polygon.ply","r") as fileH: + for line in fileH.readlines(): + tmp = line.split() + polygon.append( (float(tmp[0]) , float(tmp[1]))) + +.. ########################################################################################################### + +.. _load_surface: +.. topic:: LOAD_SURFACE + + | Will load an irap surface from file 'SURFACE_FILE'. The surface will be stored internally as 'SURFACE_NAME' - this function is mainly needed to have a base surface available for the CREATE_SURFACE_REGION command. + + + + + + + *Example:* + + :: + + -- Load Irap RMS surface from file + LOAD_SURFACE path/to/surface.irap + +.. ########################################################################################################### + +.. _create_surface_region: +.. topic:: CREATE_SURFACE_REGION + + | Will create a new surface region object which can be used to select and deselect parts of a surface. The region will be called 'REGION_NAME' and it will be based on the surface given by 'BASE_SURFACE'. 'PRESELECT' is a boolean 'TRUE' or 'FALSE' which determines whether the region is created with all points selected, or no points selected. + + + + *Example:* + + :: + + -- Create surface region in xy plane + CREATE_SURFACE_REGION SURF_REGION BASE_SURFACE TRUE + +.. ########################################################################################################### + +.. _surface_region_select_in_polygon: +.. topic:: SURFACE_REGION_SELECT_IN_POLYGON + + | Well select all the points which are inside the polygon with name 'POLYGON_NAME'. The polygon should have been created with command CREATE_POLYGON or loaded with command 'LOAD_POLYGON' first. + + + + + + + + *Example:* + + :: + + -- Select surface region inside polygon + SURFACE_REGION_SELECT_IN_POLYGON SURF_REGION TRIANGLE TRUE + + +.. ########################################################################################################### + +.. _surface_region_select_line: +.. topic:: SURFACE_REGION_SELECT_LINE + + | Well select|deselect all the points which are above|below the line: (x1,y1) -> (x2,y2). If SIGN is positive the select will apply to all points with a positive (right hand system) distance to the line; if SIGN is negative the selector will apply to all points with a negative distance to the line. + + + + + + + + + *Example:* + + :: + + -- Select surface region inside a half space defined by a line from [0,0] to [1,1] + SURFACE_REGION_SELECT_LINE SURF_REGION 0 0 1 1 -1 TRUE + +.. ########################################################################################################### + +.. _add_data_surface: +.. topic:: ADD_DATA_SURFACE + + | Will add the node 'SURFACE_NAME' (not one of the loaded surfaces, but an enkf_node object) to the dataset 'DATASET_NAME'. Only the elements in the region 'REGION_NAME' will be added. Typically SURFACE_REGION_SELECT_xxxx has been used first to build a suitable region selection. + + + + + + + + + + *Example:* + + :: + + -- Add EnKF node object to dataset DATA_MULTFLT, with elements in SURF_REGION from BASE_SURFACE + ADD_DATA_SURFACE DATA_MULTFLT BASE_SURFACE SURF_REGION + + + +.. ########################################################################################################### + + + diff --git a/ThirdParty/Ert/devel/libconfig/src/config_content_node.c b/ThirdParty/Ert/devel/libconfig/src/config_content_node.c index 5966a6120f..939b55cfe5 100644 --- a/ThirdParty/Ert/devel/libconfig/src/config_content_node.c +++ b/ThirdParty/Ert/devel/libconfig/src/config_content_node.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_content_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2012 Statoil ASA, Norway. + + The file 'config_content_node.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -30,7 +30,7 @@ #define CONFIG_CONTENT_NODE_ID 6752887 struct config_content_node_struct { UTIL_TYPE_ID_DECLARATION; - const config_schema_item_type * schema; + const config_schema_item_type * schema; stringlist_type * stringlist; /* The values which have been set. */ const config_path_elm_type * cwd; stringlist_type * string_storage; @@ -59,7 +59,7 @@ void config_content_node_add_value(config_content_node_type * node , const char void config_content_node_set(config_content_node_type * node , const stringlist_type * token_list) { int argc = stringlist_get_size( token_list ) - 1; - for (int iarg=0; iarg < argc; iarg++) + for (int iarg=0; iarg < argc; iarg++) config_content_node_add_value( node , stringlist_iget( token_list , iarg + 1)); } @@ -149,7 +149,7 @@ const char * config_content_node_iget_as_path(config_content_node_type * node , const char * config_value = config_content_node_iget(node , index); char * path_value = config_path_elm_alloc_path( node->cwd , config_value ); config_content_node_push_string( node , path_value ); - + return path_value; } } @@ -161,7 +161,7 @@ const char * config_content_node_iget_as_abspath( config_content_node_type * nod const char * config_value = config_content_node_iget(node , index); char * path_value = config_path_elm_alloc_abspath( node->cwd , config_value ); config_content_node_push_string( node , path_value ); - + return path_value; } } @@ -173,7 +173,7 @@ const char * config_content_node_iget_as_relpath( config_content_node_type * nod const char * config_value = config_content_node_iget(node , index); char * path_value = config_path_elm_alloc_relpath( node->cwd , config_value ); config_content_node_push_string( node , path_value ); - + return path_value; } } @@ -216,13 +216,13 @@ const config_path_elm_type * config_content_node_get_path_elm( const config_cont Which will be inserted in the opt_hash dictionary as : {"KEY1" : "VALUE1" , ... } Elements which do not conform to this syntax are - ignored. + ignored. */ - + void config_content_node_init_opt_hash( const config_content_node_type * node , hash_type * opt_hash , int elm_offset) { int i; - for (i = elm_offset; i < config_content_node_get_size( node ); i++) + for (i = elm_offset; i < config_content_node_get_size( node ); i++) hash_add_option( opt_hash , config_content_node_iget( node , i )); } diff --git a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_grid.h b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_grid.h index 3c89292906..a11c7e34d8 100644 --- a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_grid.h +++ b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_grid.h @@ -56,6 +56,10 @@ extern "C" { void ecl_grid_get_cell_corner_xyz1(const ecl_grid_type * grid , int global_index , int corner_nr , double * xpos , double * ypos , double * zpos ); void ecl_grid_get_corner_xyz(const ecl_grid_type * grid , int i , int j , int k, double * xpos , double * ypos , double * zpos ); + double ecl_grid_get_cell_dx1( const ecl_grid_type * grid , int global_index ); + double ecl_grid_get_cell_dx3( const ecl_grid_type * grid , int i , int j , int k); + double ecl_grid_get_cell_dy1( const ecl_grid_type * grid , int global_index ); + double ecl_grid_get_cell_dy3( const ecl_grid_type * grid , int i , int j , int k); double ecl_grid_get_cell_thickness3( const ecl_grid_type * grid , int i , int j , int k); double ecl_grid_get_cell_thickness1( const ecl_grid_type * grid , int global_index ); double ecl_grid_get_cdepth1(const ecl_grid_type * grid , int global_index); diff --git a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_sum_tstep.h b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_sum_tstep.h index c0f285e49f..ec5a6da2e7 100644 --- a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_sum_tstep.h +++ b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_sum_tstep.h @@ -52,7 +52,11 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type; void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio); void ecl_sum_tstep_iset( ecl_sum_tstep_type * tstep , int index , float value); void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node , float value); + void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_key , float value); + double ecl_sum_tstep_get_from_key( const ecl_sum_tstep_type * tstep , const char * gen_key); + bool ecl_sum_tstep_has_key(const ecl_sum_tstep_type * tstep , const char * gen_key); + bool ecl_sum_tstep_sim_time_equal( const ecl_sum_tstep_type * tstep1 , const ecl_sum_tstep_type * tstep2 ); UTIL_SAFE_CAST_HEADER( ecl_sum_tstep ); diff --git a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_util.h b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_util.h index df304122ab..9c2b0441c7 100644 --- a/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_util.h +++ b/ThirdParty/Ert/devel/libecl/include/ert/ecl/ecl_util.h @@ -42,20 +42,6 @@ typedef enum { ECL_OTHER_FILE = 0 , ECL_DATA_FILE = 512 } ecl_file_enum; -#define ECL_FILE_ENUM_DEFS {.value = 0 , .name="ECL_OTHER_FILE"}, \ -{.value = 1 , .name="ECL_RESTART_FILE"}, \ -{.value = 2 , .name="ECL_UNIFIED_RESTART_FILE"}, \ -{.value = 4 , .name="ECL_SUMMARY_FILE"}, \ -{.value = 8 , .name="ECL_UNIFIED_SUMMARY_FILE"}, \ -{.value = 16 , .name="ECL_SUMMARY_HEADER_FILE"}, \ -{.value = 32 , .name="ECL_GRID_FILE"}, \ -{.value = 64 , .name="ECL_EGRID_FILE"}, \ -{.value = 128 , .name="ECL_INIT_FILE"}, \ -{.value = 256 , .name="ECL_RFT_FILE"}, \ -{.value = 512 , .name="ECL_DATA_FILE"} -#define ECL_FILE_ENUM_SIZE 11 - - /* This enum enumerates the four different ways summary and restart information diff --git a/ThirdParty/Ert/devel/libecl/include/ert/ecl/layer.h b/ThirdParty/Ert/devel/libecl/include/ert/ecl/layer.h index fae3e71479..639d418c51 100644 --- a/ThirdParty/Ert/devel/libecl/include/ert/ecl/layer.h +++ b/ThirdParty/Ert/devel/libecl/include/ert/ecl/layer.h @@ -78,6 +78,7 @@ extern "C" { void layer_update_active( layer_type * layer , const ecl_grid_type * grid , int k); void layer_cells_equal( const layer_type * layer , int value , int_vector_type * i_list , int_vector_type * j_list); + int layer_count_equal( const layer_type * layer , int value ); UTIL_IS_INSTANCE_HEADER( layer ); UTIL_SAFE_CAST_HEADER( layer ); diff --git a/ThirdParty/Ert/devel/libecl/src/ecl_file.c b/ThirdParty/Ert/devel/libecl/src/ecl_file.c index 4894d490fa..8e91a857f4 100644 --- a/ThirdParty/Ert/devel/libecl/src/ecl_file.c +++ b/ThirdParty/Ert/devel/libecl/src/ecl_file.c @@ -742,11 +742,6 @@ void ecl_file_fprintf_kw_list( const ecl_file_type * ecl_file , FILE * stream ) file_map_fprintf_kw_list( ecl_file->active_map , stream ); } -#ifdef HAVE_FORK -const char * ecl_file_enum_iget( int index , int * value) { - return util_enum_iget( index , ECL_FILE_ENUM_SIZE , (const util_enum_element_type []) { ECL_FILE_ENUM_DEFS } , value); -} -#endif /*****************************************************************/ diff --git a/ThirdParty/Ert/devel/libecl/src/ecl_grid.c b/ThirdParty/Ert/devel/libecl/src/ecl_grid.c index 9edcf66382..0f41998c79 100644 --- a/ThirdParty/Ert/devel/libecl/src/ecl_grid.c +++ b/ThirdParty/Ert/devel/libecl/src/ecl_grid.c @@ -639,6 +639,7 @@ struct ecl_grid_struct { but in cases with skewed cells this has proved numerically challenging. */ bool is_metric; + int eclipse_version; }; @@ -1338,6 +1339,7 @@ static ecl_grid_type * ecl_grid_alloc_empty(ecl_grid_type * global_grid , int du grid->parent_grid = NULL; grid->children = hash_alloc(); grid->coarse_cells = vector_alloc_new(); + grid->eclipse_version = 0; return grid; } @@ -2283,8 +2285,12 @@ static void ecl_grid_init_nnc_cells( ecl_grid_type * grid1, ecl_grid_type * grid */ static void ecl_grid_init_nnc(ecl_grid_type * main_grid, ecl_file_type * ecl_file) { int num_nnchead_kw = ecl_file_get_num_named_kw( ecl_file , NNCHEAD_KW ); - int i; + + if(num_nnchead_kw > 0 && main_grid->eclipse_version == 2015){ + return; //Eclipse 2015 has an error with nnc. + } + for (i = 0; i < num_nnchead_kw; i++) { ecl_file_push_block(ecl_file); /* <---------------------------------------------------------------- */ ecl_file_select_block(ecl_file , NNCHEAD_KW , i); @@ -2366,11 +2372,15 @@ static ecl_grid_type * ecl_grid_alloc_EGRID__( ecl_grid_type * main_grid , const ecl_kw_type * actnum_kw = NULL; ecl_kw_type * mapaxes_kw = NULL; int dualp_flag; + int eclipse_version; if (grid_nr == 0) { ecl_kw_type * filehead_kw = ecl_file_iget_named_kw( ecl_file , FILEHEAD_KW , grid_nr); dualp_flag = ecl_kw_iget_int( filehead_kw , FILEHEAD_DUALP_INDEX ); - } else + eclipse_version = ecl_kw_iget_int( filehead_kw, FILEHEAD_YEAR_INDEX); + } else{ dualp_flag = main_grid->dualp_flag; + eclipse_version = main_grid->eclipse_version; + } /** If ACTNUM is not present - that is is interpreted as - all active. */ @@ -2399,6 +2409,7 @@ static ecl_grid_type * ecl_grid_alloc_EGRID__( ecl_grid_type * main_grid , const corsnum_kw ); if (ECL_GRID_MAINGRID_LGR_NR != grid_nr) ecl_grid_set_lgr_name_EGRID(ecl_grid , ecl_file , grid_nr); + ecl_grid->eclipse_version = eclipse_version; return ecl_grid; } } @@ -4311,21 +4322,44 @@ double ecl_grid_get_cell_thickness3( const ecl_grid_type * grid , int i , int j +double ecl_grid_get_cell_dx1( const ecl_grid_type * grid , int global_index ) { + fprintf(stderr , "** WARNING: The ecl_grid_get_cell_dx1() function is only a stub returning -1.\n"); + fprintf(stderr , " If you need a correct value for cell dx you must rebuild a new ert version.\n"); + return -1; +} + + +double ecl_grid_get_cell_dx3( const ecl_grid_type * grid , int i , int j , int k) { + const int global_index = ecl_grid_get_global_index3(grid , i,j,k); + return ecl_grid_get_cell_dx1( grid , global_index ); +} + + +double ecl_grid_get_cell_dy1( const ecl_grid_type * grid , int global_index ) { + fprintf(stderr , "** WARNING: The ecl_grid_get_cell_dy1() function is only a stub returning -1.\n"); + fprintf(stderr , " If you need a correct value for cell dy you must update rebuild a new ert version.\n"); + return -1; +} + + +double ecl_grid_get_cell_dy3( const ecl_grid_type * grid , int i , int j , int k) { + const int global_index = ecl_grid_get_global_index3(grid , i,j,k); + return ecl_grid_get_cell_dy1( grid , global_index ); +} + + const nnc_info_type * ecl_grid_get_cell_nnc_info1( const ecl_grid_type * grid , int global_index) { const ecl_cell_type * cell = ecl_grid_get_cell( grid , global_index); return cell->nnc_info; } - - const nnc_info_type * ecl_grid_get_cell_nnc_info3( const ecl_grid_type * grid , int i , int j , int k) { const int global_index = ecl_grid_get_global_index3(grid , i,j,k); return ecl_grid_get_cell_nnc_info1(grid, global_index); } - /*****************************************************************/ /* Functions to query whether a cell is active or not. */ diff --git a/ThirdParty/Ert/devel/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/devel/libecl/src/ecl_rsthead.c index bb3505afdb..0bdb6dd374 100644 --- a/ThirdParty/Ert/devel/libecl/src/ecl_rsthead.c +++ b/ThirdParty/Ert/devel/libecl/src/ecl_rsthead.c @@ -46,6 +46,7 @@ double ecl_rsthead_get_sim_days( const ecl_rsthead_type * header ) { ecl_rsthead_type * ecl_rsthead_ialloc( const ecl_file_type * rst_file , int occurence) { if (ecl_file_get_num_named_kw( rst_file , INTEHEAD_KW) > occurence) { const ecl_kw_type * intehead_kw = ecl_file_iget_named_kw( rst_file , INTEHEAD_KW , occurence); + const ecl_kw_type * doubhead_kw = ecl_file_iget_named_kw( rst_file , DOUBHEAD_KW , occurence); ecl_rsthead_type * rsthead = util_malloc( sizeof * rsthead ); @@ -79,12 +80,7 @@ ecl_rsthead_type * ecl_rsthead_ialloc( const ecl_file_type * rst_file , int occu // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - - if (ecl_file_get_num_named_kw(rst_file, DOUBHEAD_KW) > occurence) { - const ecl_kw_type * doubhead_kw = ecl_file_iget_named_kw( rst_file , DOUBHEAD_KW , occurence); - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); - } - + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (ecl_file_get_num_named_kw(rst_file, LOGIHEAD_KW) > occurence) { const ecl_kw_type * logihead_kw = ecl_file_iget_named_kw( rst_file , LOGIHEAD_KW , occurence); rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); diff --git a/ThirdParty/Ert/devel/libecl/src/ecl_sum_tstep.c b/ThirdParty/Ert/devel/libecl/src/ecl_sum_tstep.c index 11efcc4fca..898b04c8f1 100644 --- a/ThirdParty/Ert/devel/libecl/src/ecl_sum_tstep.c +++ b/ThirdParty/Ert/devel/libecl/src/ecl_sum_tstep.c @@ -294,6 +294,16 @@ void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_k ecl_sum_tstep_set_from_node( tstep , smspec_node , value); } +double ecl_sum_tstep_get_from_key(const ecl_sum_tstep_type * tstep , const char * gen_key) { + const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key ); + int data_index = smspec_node_get_params_index( smspec_node ); + return ecl_sum_tstep_iget( tstep , data_index); +} + +bool ecl_sum_tstep_has_key(const ecl_sum_tstep_type * tstep , const char * gen_key) { + return ecl_smspec_has_general_var(tstep->smspec, gen_key); +} + bool ecl_sum_tstep_sim_time_equal( const ecl_sum_tstep_type * tstep1 , const ecl_sum_tstep_type * tstep2 ) { if (tstep1->sim_time == tstep2->sim_time) diff --git a/ThirdParty/Ert/devel/libecl/src/ecl_util.c b/ThirdParty/Ert/devel/libecl/src/ecl_util.c index ad32fe86aa..0c55d1cf74 100644 --- a/ThirdParty/Ert/devel/libecl/src/ecl_util.c +++ b/ThirdParty/Ert/devel/libecl/src/ecl_util.c @@ -1522,9 +1522,6 @@ time_t ecl_util_make_date(int mday , int month , int year) { /* Small functions to support enum introspection. */ #ifdef HAVE_FORK -const char * ecl_util_file_enum_iget( int index, int * value) { - return util_enum_iget( index , ECL_FILE_ENUM_SIZE , (const util_enum_element_type []) { ECL_FILE_ENUM_DEFS }, value); -} const char * ecl_util_phase_enum_iget( int index, int * value) { return util_enum_iget( index , ECL_PHASE_ENUM_SIZE , (const util_enum_element_type []) { ECL_PHASE_ENUM_DEFS }, value); diff --git a/ThirdParty/Ert/devel/libecl/src/layer.c b/ThirdParty/Ert/devel/libecl/src/layer.c index 45dd8db976..ecd0972aa1 100644 --- a/ThirdParty/Ert/devel/libecl/src/layer.c +++ b/ThirdParty/Ert/devel/libecl/src/layer.c @@ -772,6 +772,21 @@ void layer_cells_equal( const layer_type * layer , int value , int_vector_type * } +int layer_count_equal( const layer_type * layer , int value ) { + int num_equal = 0; + int i,j; + for (j=0; j < layer->ny; j++) { + for (i=0; i < layer->nx; i++) { + cell_type * cell = layer_iget_cell( layer , i , j ); + if (cell->cell_value == value) + num_equal++; + } + } + return num_equal; +} + + + void layer_update_active( layer_type * layer , const ecl_grid_type * grid , int k) { diff --git a/ThirdParty/Ert/devel/libecl/tests/tests.cmake b/ThirdParty/Ert/devel/libecl/tests/tests.cmake index d540312d5b..a819f6fd12 100644 --- a/ThirdParty/Ert/devel/libecl/tests/tests.cmake +++ b/ThirdParty/Ert/devel/libecl/tests/tests.cmake @@ -114,6 +114,9 @@ add_executable( ecl_grid_simple ecl_grid_simple.c ) target_link_libraries( ecl_grid_simple ecl test_util ) add_test( ecl_grid_simple ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) +add_test( ecl_grid_ecl2015_1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_NOSIM_GRID.EGRID ) +add_test( ecl_grid_ecl2015_2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_20142.EGRID ) + add_executable( ecl_grid_DEPTHZ ecl_grid_DEPTHZ.c ) target_link_libraries( ecl_grid_DEPTHZ ecl test_util ) @@ -370,4 +373,6 @@ set_property( TEST ecl_grid_copy_statoil3 PROPERTY LABELS StatoilData ) set_property( TEST ecl_grid_copy_statoil4 PROPERTY LABELS StatoilData ) set_property( TEST ecl_layer_statoil PROPERTY LABELS StatoilData ) set_property( TEST ecl_grid_layer_contains1 PROPERTY LABELS StatoilData ) -set_property( TEST ecl_grid_layer_contains2 PROPERTY LABELS StatoilData ) \ No newline at end of file +set_property( TEST ecl_grid_layer_contains2 PROPERTY LABELS StatoilData ) +set_property( TEST ecl_grid_ecl2015_1 PROPERTY LABELS StatoilData ) +set_property( TEST ecl_grid_ecl2015_2 PROPERTY LABELS StatoilData ) diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/active_list.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/active_list.h index 9e1e90c68b..613796c374 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/active_list.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/active_list.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'active_list.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __ACTIVE_LIST_H__ @@ -29,7 +29,7 @@ extern "C" { typedef struct active_list_struct active_list_type; - active_list_type * active_list_alloc( ); + active_list_type * active_list_alloc( ); void active_list_reset(active_list_type * ); void active_list_add_index(active_list_type * , int); void active_list_free( active_list_type *); @@ -41,10 +41,11 @@ typedef struct active_list_struct active_list_type; active_mode_type active_list_get_mode(const active_list_type * ); void active_list_free__( void * arg ); active_list_type * active_list_alloc_copy( const active_list_type * src); - void active_list_fprintf( const active_list_type * active_list , bool obs , const char * key , FILE * stream ); + void active_list_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream ); + void active_list_summary_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream); bool active_list_iget( const active_list_type * active_list , int index ); bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2); - void active_list_copy( active_list_type * target , const active_list_type * src); + void active_list_copy( active_list_type * target , const active_list_type * src); UTIL_IS_INSTANCE_HEADER( active_list ); diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/custom_kw_config.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/custom_kw_config.h index 48d1387d9f..2328964ee7 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/custom_kw_config.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/custom_kw_config.h @@ -21,7 +21,7 @@ extern "C" { char * custom_kw_config_get_result_file(const custom_kw_config_type * config); char * custom_kw_config_get_output_file(const custom_kw_config_type * config); bool custom_kw_config_parse_result_file(custom_kw_config_type * config, const char * result_file, stringlist_type * result); - void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type * config_set); + void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set); void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set); bool custom_kw_config_has_key(const custom_kw_config_type * config, const char * key); bool custom_kw_config_key_is_double(const custom_kw_config_type * config, const char * key); diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_analysis.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_analysis.h index d6a8877db3..1cc7033130 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_analysis.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_analysis.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_analysis.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'enkf_analysis.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ @@ -33,19 +33,21 @@ extern "C" { -void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , - const meas_data_type * meas_data , - const int_vector_type * step_list , +void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , + const meas_data_type * meas_data , + const int_vector_type * step_list , const char * ministep_name , FILE * stream ); - -void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , - meas_data_type * meas_data , - double std_cutoff , - double alpha); + +void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , + meas_data_type * meas_data , + double std_cutoff , + double alpha, + bool verbose); void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , - meas_data_type * meas_data); + meas_data_type * meas_data, + bool verbose); #ifdef __cplusplus diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_defaults.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_defaults.h index 8b51a6d9e3..de0d7bd335 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_defaults.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_defaults.h @@ -254,7 +254,7 @@ #define DEFAULT_START_TAG "<" #define DEFAULT_END_TAG ">" -#define DEFAULT_MANUAL_URL "http://ert.nr.no/wiki/index.php/User_Manual" +#define DEFAULT_MANUAL_URL "http://ert.nr.no/ert/index.php/User_Manual" #define DEFAULT_BROWSER "firefox" /*****************************************************************/ diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_obs.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_obs.h index 10a349b4bd..f045ba16b9 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_obs.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_obs.h @@ -26,6 +26,7 @@ extern "C" { #include #include #include +#include #include @@ -96,6 +97,8 @@ extern "C" { double enkf_obs_scale_correlated_std(const enkf_obs_type * enkf_obs , enkf_fs_type * fs , const int_vector_type * ens_active_list , const local_obsdata_type * local_obsdata); local_obsdata_type * enkf_obs_alloc_all_active_local_obs( const enkf_obs_type * enkf_obs , const char * key); + UTIL_IS_INSTANCE_HEADER( enkf_obs ); + #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_state.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_state.h index 8b4c3e8eed..2d2bf321e8 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_state.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/enkf_state.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_state.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'enkf_state.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __ENKF_STATE_H__ @@ -32,7 +32,7 @@ extern "C" { #include - + #include #include @@ -57,7 +57,7 @@ typedef struct enkf_state_struct enkf_state_type; bool enkf_state_get_pre_clear_runpath( const enkf_state_type * enkf_state ); void enkf_state_set_pre_clear_runpath( enkf_state_type * enkf_state , bool pre_clear_runpath ); - + keep_runpath_type enkf_state_get_keep_runpath( const enkf_state_type * enkf_state ); void enkf_state_set_keep_runpath( enkf_state_type * enkf_state , keep_runpath_type keep_runpath); keep_runpath_type member_config_get_keep_runpath(const member_config_type * member_config); @@ -77,24 +77,24 @@ typedef struct enkf_state_struct enkf_state_type; void * enkf_state_run_eclipse__(void * ); void * enkf_state_start_forward_model__(void * ); - void enkf_state_load_from_forward_model(enkf_state_type * enkf_state , - run_arg_type * run_arg , - int * result , - bool interactive , + void enkf_state_load_from_forward_model(enkf_state_type * enkf_state , + run_arg_type * run_arg , + int * result , + bool interactive , stringlist_type * msg_list); - void enkf_state_forward_init(enkf_state_type * enkf_state , - run_arg_type * run_arg , + void enkf_state_forward_init(enkf_state_type * enkf_state , + run_arg_type * run_arg , int * result ); void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * run_arg ); - + enkf_state_type * enkf_state_alloc(int , - rng_type * main_rng , - enkf_fs_type * fs, - const char * casename , - bool pre_clear_runpath, - keep_runpath_type , + rng_type * main_rng , + enkf_fs_type * fs, + const char * casename , + bool pre_clear_runpath, + keep_runpath_type , model_config_type * , ensemble_config_type * , const site_config_type * , diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_config.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_config.h index 76cbb69fb0..e7324df691 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_config.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_config.h @@ -39,7 +39,7 @@ typedef enum { CREATE_MINISTEP = 2, /* MINISTEP_NAME OBSSET_NAME -> local_config_alloc_ministep(); */ ATTACH_MINISTEP = 3, /* UPDATESTEP_NAME , MINISTEP_NAME -> local_updatestep_add_ministep(); */ CREATE_DATASET = 4, /* NAME */ - ATTACH_DATASET = 5, /* DATASET_NAME MINISETP_NAME */ + ATTACH_DATASET = 5, /* DATASET_NAME MINISTEP_NAME */ CREATE_OBSSET = 6, /* NAME */ ADD_DATA = 7, /* DATA_KEY -> local_ministep_add_node(); */ ADD_OBS = 8, /* OBS_KEY -> local_ministep_add_obs(); */ @@ -47,8 +47,6 @@ typedef enum { ACTIVE_LIST_ADD_DATA_INDEX = 10, /* DATA_KEY , ACTIVE_INDEX */ ACTIVE_LIST_ADD_MANY_OBS_INDEX = 11, /* OBS_KEY , NUM_INDEX , INDEX1, INDEX2, INDEX3,... */ ACTIVE_LIST_ADD_MANY_DATA_INDEX = 12, /* DATA_KEY , NUM_INDEX , INDEX1 , INDEX2 , INDEX3 ,... */ - INSTALL_UPDATESTEP = 13, /* UPDATESTEP_NAME , STEP1 , STEP2 local_config_set_updatestep() */ - INSTALL_DEFAULT_UPDATESTEP = 14, /* UPDATETSTEP_NAME local_config_set_default_updatestep() */ DEL_DATA = 16, /* DATASET KEY*/ DEL_OBS = 17, /* MINISTEP OBS_KEY */ DATASET_DEL_ALL_DATA = 18, /* DATASET */ @@ -56,6 +54,7 @@ typedef enum { ADD_FIELD = 20, /* MINISTEP FIELD_NAME REGION_NAME */ COPY_DATASET = 21, /* SRC_NAME TARGET_NAME */ COPY_OBSSET = 22, /* SRC_NAME TARGET_NAME */ + ATTACH_OBSSET = 23, /* OBSSET_NAME MINISTEP_NAME */ /*****************************************************************/ CREATE_ECLREGION = 100, /* Name of region TRUE|FALSE*/ LOAD_FILE = 101, /* Key, filename */ @@ -87,14 +86,13 @@ typedef enum { #define CREATE_DATASET_STRING "CREATE_DATASET" #define ATTACH_DATASET_STRING "ATTACH_DATASET" #define CREATE_OBSSET_STRING "CREATE_OBSSET" +#define ATTACH_OBSSET_STRING "ATTACH_OBSSET" #define ADD_DATA_STRING "ADD_DATA" #define ADD_OBS_STRING "ADD_OBS" #define ACTIVE_LIST_ADD_OBS_INDEX_STRING "ACTIVE_LIST_ADD_OBS_INDEX" #define ACTIVE_LIST_ADD_DATA_INDEX_STRING "ACTIVE_LIST_ADD_DATA_INDEX" #define ACTIVE_LIST_ADD_MANY_OBS_INDEX_STRING "ACTIVE_LIST_ADD_MANY_OBS_INDEX" #define ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING "ACTIVE_LIST_ADD_MANY_DATA_INDEX" -#define INSTALL_UPDATESTEP_STRING "INSTALL_UPDATESTEP" -#define INSTALL_DEFAULT_UPDATESTEP_STRING "INSTALL_DEFAULT_UPDATESTEP" #define DEL_DATA_STRING "DEL_DATA" #define DEL_OBS_STRING "DEL_OBS" #define ADD_FIELD_STRING "ADD_FIELD" @@ -124,13 +122,12 @@ typedef enum { typedef struct local_config_struct local_config_type; local_config_type * local_config_alloc( ); +void local_config_clear( local_config_type * local_config ); void local_config_free( local_config_type * local_config ); -local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ); -local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key , const char * obsset_name); +local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key ); local_ministep_type * local_config_alloc_ministep_copy( local_config_type * local_config , const char * src_key , const char * new_key); -void local_config_set_default_updatestep( local_config_type * local_config , const char * default_key); -const local_updatestep_type * local_config_iget_updatestep( const local_config_type * local_config , int index); -local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config , const char * key); +void local_config_set_default_updatestep( local_config_type * local_config , local_updatestep_type * update_step ); +local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config ); local_ministep_type * local_config_get_ministep( const local_config_type * local_config , const char * key); void local_config_set_updatestep(local_config_type * local_config, int step1 , int step2 , const char * key); void local_config_reload( local_config_type * local_config , const ecl_grid_type * ecl_grid , const ensemble_config_type * ensemble_config , const enkf_obs_type * enkf_obs , @@ -140,9 +137,12 @@ const char * local_config_get_cmd_string( local_config_instruct stringlist_type * local_config_get_config_files( const local_config_type * local_config ); void local_config_clear_config_files( local_config_type * local_config ); void local_config_add_config_file( local_config_type * local_config , const char * config_file ); -void local_config_fprintf( const local_config_type * local_config , const char * config_file); -void local_config_fprintf_config( const local_config_type * local_config , FILE * stream); +void local_config_fprintf( const local_config_type * local_config , const char * config_file); +void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file); +void local_config_fprintf_config( const local_config_type * local_config , FILE * stream); +local_obsdata_type * local_config_alloc_obsset( local_config_type * local_config , const char * obsset_name ); +local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key ); #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_dataset.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_dataset.h index 2a8d2d59fa..0a4e107c2f 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_dataset.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_dataset.h @@ -1,20 +1,20 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - + Copyright (C) 2011 Statoil ASA, Norway. + The file 'local_dataset.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __LOCAL_DATASET_H__ @@ -35,15 +35,16 @@ void local_dataset_del_node( local_dataset_type * dataset , cons void local_dataset_clear( local_dataset_type * dataset); const char * local_dataset_get_name( const local_dataset_type * dataset); void local_dataset_fprintf( const local_dataset_type * dataset , FILE * stream); +void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream); active_list_type * local_dataset_get_node_active_list(const local_dataset_type * dataset , const char * node_key ); stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset ); int local_dataset_get_size( const local_dataset_type * dataset ); void local_dataset_del_node( local_dataset_type * dataset , const char * node_key); void local_dataset_clear( local_dataset_type * dataset); +bool local_dataset_has_key(const local_dataset_type * dataset, const char * key); - #ifdef __cplusplus } #endif -#endif +#endif diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_ministep.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_ministep.h index d09177fc17..0a71053a77 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_ministep.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_ministep.h @@ -29,15 +29,18 @@ extern "C" { #include #include #include +#include typedef struct local_ministep_struct local_ministep_type; -local_ministep_type * local_ministep_alloc(const char * name , local_obsdata_type * observations); +local_ministep_type * local_ministep_alloc(const char * name); void local_ministep_free(local_ministep_type * ministep); void local_ministep_free__(void * arg); void local_ministep_add_obs(local_ministep_type * ministep, const char * obs_key); active_list_type * local_ministep_get_node_active_list(const local_ministep_type * ministep , const char * node_key ); hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep ); +stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep ); +bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key); local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src , const char * name); void local_ministep_del_obs( local_ministep_type * ministep , const char * obs_key); void local_ministep_del_node( local_ministep_type * ministep , const char * node_key); @@ -45,9 +48,14 @@ const char * local_ministep_get_name( const local_ministep_type * minis void local_ministep_clear_nodes( local_ministep_type * ministep); void local_ministep_clear_observations( local_ministep_type * ministep); void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ); +void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream); void local_ministep_add_dataset( local_ministep_type * ministep , const local_dataset_type * dataset); +void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata); +void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode); local_obsdata_type * local_ministep_get_obsdata(const local_ministep_type * ministep); local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name); +bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name); +int local_ministep_get_num_dataset( const local_ministep_type * ministep ); UTIL_SAFE_CAST_HEADER(local_ministep); UTIL_IS_INSTANCE_HEADER(local_ministep); diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_obsdata.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_obsdata.h index dcb2ae5d14..7b0fb5c878 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_obsdata.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_obsdata.h @@ -42,7 +42,9 @@ typedef struct local_obsdata_struct local_obsdata_type; local_obsdata_node_type * local_obsdata_get( const local_obsdata_type * data , const char * key); void local_obsdata_clear( local_obsdata_type * data ); void local_obsdata_del_node( local_obsdata_type * data , const char * key); - void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list); + void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list); + void local_obsdata_fprintf( const local_obsdata_type * obsdata , FILE * stream ); + void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream); UTIL_IS_INSTANCE_HEADER( local_obsdata ); diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_updatestep.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_updatestep.h index 324a69f5c3..043f0c5f57 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_updatestep.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/local_updatestep.h @@ -37,6 +37,7 @@ int local_updatestep_get_num_ministep( const local_updateste local_updatestep_type * local_updatestep_alloc_copy( const local_updatestep_type * src , const char * name ); void local_updatestep_fprintf( const local_updatestep_type * updatestep , FILE * stream); const char * local_updatestep_get_name( const local_updatestep_type * updatestep ); +bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key); #ifdef __cplusplus } diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/obs_data.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/obs_data.h index db56079675..d6c9cf2d0b 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/obs_data.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/obs_data.h @@ -39,7 +39,7 @@ const char * obs_data_iget_keyword( const obs_data_type * obs_data , int index ) double obs_data_iget_value( const obs_data_type * obs_data , int index ); double obs_data_iget_std( const obs_data_type * obs_data , int index ); active_type obs_data_iget_active_mode( const obs_data_type * obs_data , int index ); -void obs_block_deactivate( obs_block_type * obs_block , int iobs , const char * msg); +void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg); int obs_block_get_size( const obs_block_type * obs_block ); void obs_block_iset( obs_block_type * obs_block , int iobs , double value , double std); void obs_block_iset_missing( obs_block_type * obs_block , int iobs ); @@ -68,8 +68,12 @@ void obs_data_scale_kernel(const obs_data_type * obs_data , matr void obs_data_fprintf(const obs_data_type * , const meas_data_type * meas_data , FILE *); void obs_data_iget_value_std(const obs_data_type * obs_data , int index , double * value , double * std); int obs_data_get_active_size(const obs_data_type * obs_data ); +int obs_data_get_total_size( const obs_data_type * obs_data ); int obs_data_get_num_blocks( const obs_data_type * obs_data ); const char * obs_block_get_key( const obs_block_type * obs_block) ; +double obs_data_iget_value( const obs_data_type * obs_data , int total_index ); +double obs_data_iget_std( const obs_data_type * obs_data , int total_index ); + #ifdef __cplusplus } diff --git a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/run_arg.h b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/run_arg.h index 6eb5a8f88a..2c154ac00b 100644 --- a/ThirdParty/Ert/devel/libenkf/include/ert/enkf/run_arg.h +++ b/ThirdParty/Ert/devel/libenkf/include/ert/enkf/run_arg.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2014 Statoil ASA, Norway. + + The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __RUN_ARG_H__ @@ -29,22 +29,22 @@ extern "C" { #include #include - + typedef struct run_arg_struct run_arg_type; UTIL_SAFE_CAST_HEADER( run_arg ); -UTIL_IS_INSTANCE_HEADER( run_arg ); +UTIL_IS_INSTANCE_HEADER( run_arg ); run_arg_type * run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , int iens , int iter , const char * runpath); run_arg_type * run_arg_alloc_INIT_ONLY(enkf_fs_type * init_fs , int iens , int iter , const char * runpath); run_arg_type * run_arg_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * update_target_fs , int iens , int iter , const char * runpath); - run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs , - int iens , + run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs , + int iens , state_enum init_state_parameter , state_enum init_state_dynamic , - int step1 , + int step1 , int step2 , const char * runpath); @@ -67,9 +67,9 @@ UTIL_IS_INSTANCE_HEADER( run_arg ); const char * run_arg_get_runpath( const run_arg_type * run_arg); void run_arg_complete_run(run_arg_type * run_arg); run_status_type run_arg_get_run_status( const run_arg_type * run_arg ); - - void run_arg_set_inactive( run_arg_type * run_arg ); + int run_arg_get_queue_index( const run_arg_type * run_arg ); + bool run_arg_is_submitted( const run_arg_type * run_arg ); bool run_arg_can_retry( const run_arg_type * run_arg ); diff --git a/ThirdParty/Ert/devel/libenkf/src/CMakeLists.txt b/ThirdParty/Ert/devel/libenkf/src/CMakeLists.txt index f261889a39..546433b426 100644 --- a/ThirdParty/Ert/devel/libenkf/src/CMakeLists.txt +++ b/ThirdParty/Ert/devel/libenkf/src/CMakeLists.txt @@ -209,6 +209,11 @@ if (USE_RUNPATH) add_runpath( enkf ) endif() +add_custom_target(ert_share_symlinking ALL + COMMENT "Symlinking to the development share directory." + COMMAND ln -sf -t ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/share +) + #----------------------------------------------------------------- if (INSTALL_ERT) install(TARGETS enkf DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/ThirdParty/Ert/devel/libenkf/src/active_list.c b/ThirdParty/Ert/devel/libenkf/src/active_list.c index 77e20efda9..6768cf9f3f 100644 --- a/ThirdParty/Ert/devel/libenkf/src/active_list.c +++ b/ThirdParty/Ert/devel/libenkf/src/active_list.c @@ -207,22 +207,32 @@ bool active_list_iget( const active_list_type * active_list , int index ) { /*****************************************************************/ -void active_list_fprintf( const active_list_type * active_list , bool obs , const char *key , FILE * stream ) { +void active_list_fprintf( const active_list_type * active_list , const char *dataset_key, const char *key , FILE * stream ) { if (active_list->mode == PARTLY_ACTIVE) { int i; - if (obs) - fprintf(stream , "%s %s %d\n" , local_config_get_cmd_string( ACTIVE_LIST_ADD_MANY_OBS_INDEX ) , key , int_vector_size( active_list->index_list )); - else - fprintf(stream , "%s %s %d\n" , local_config_get_cmd_string( ACTIVE_LIST_ADD_MANY_OBS_INDEX ) , key , int_vector_size( active_list->index_list )); + fprintf(stream , "%s %s %s " , local_config_get_cmd_string( ACTIVE_LIST_ADD_DATA_INDEX ) , dataset_key, key); for (i = 0; i < int_vector_size( active_list->index_list ); i++) { - fprintf(stream , "%6d " , int_vector_iget( active_list->index_list , i)); + fprintf(stream , " %6d " , int_vector_iget( active_list->index_list , i)); if ((i % 10) == 9) fprintf(stream , "\n"); } + fprintf(stream , "\n"); } /* else: if mode == ALL_ACTIVE nothing is written */ } +void active_list_summary_fprintf( const active_list_type * active_list , const char *dataset_key, const char *key , FILE * stream) { + int number_of_active = int_vector_size( active_list->index_list ); + if (active_list->mode == ALL_ACTIVE){ + fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "ALL_ACTIVE"); + } + else if (active_list->mode == PARTLY_ACTIVE){ + fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "PARTLY_ACTIVE"); + } + else + fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "INACTIVE"); +} + bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2) { diff --git a/ThirdParty/Ert/devel/libenkf/src/custom_kw_config.c b/ThirdParty/Ert/devel/libenkf/src/custom_kw_config.c index 847d497c65..c0187de12a 100644 --- a/ThirdParty/Ert/devel/libenkf/src/custom_kw_config.c +++ b/ThirdParty/Ert/devel/libenkf/src/custom_kw_config.c @@ -80,8 +80,9 @@ static void custom_kw_config_reset__(custom_kw_config_type * config) { config->key_definition_file = NULL; } -void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type * config_set) { - pthread_rwlock_rdlock(& config->rw_lock); +void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set) { + pthread_rwlock_t * rw_lock = (pthread_rwlock_t *)& config->rw_lock; + pthread_rwlock_rdlock(rw_lock); { stringlist_clear(config_set); @@ -100,7 +101,7 @@ void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type stringlist_free(configured_keys); } - pthread_rwlock_unlock(& config->rw_lock); + pthread_rwlock_unlock(rw_lock); } void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set) { diff --git a/ThirdParty/Ert/devel/libenkf/src/enkf_analysis.c b/ThirdParty/Ert/devel/libenkf/src/enkf_analysis.c index fcb7d3a5c3..901e029a30 100644 --- a/ThirdParty/Ert/devel/libenkf/src/enkf_analysis.c +++ b/ThirdParty/Ert/devel/libenkf/src/enkf_analysis.c @@ -106,7 +106,7 @@ void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , const me -void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type * meas_data , double std_cutoff , double alpha) { +void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type * meas_data , double std_cutoff , double alpha, bool verbose) { for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) { obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr); meas_block_type * meas_block = meas_data_iget_block( meas_data , block_nr ); @@ -121,7 +121,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type De activated because the ensemble has to small variation for this particular measurement. */ - obs_block_deactivate( obs_block , iobs , "No ensemble variation"); + obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation"); meas_block_deactivate( meas_block , iobs ); } else { double ens_mean = meas_block_iget_ens_mean( meas_block , iobs ); @@ -136,7 +136,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type */ if (fabs( innov ) > alpha * (ens_std + obs_std)) { - obs_block_deactivate(obs_block , iobs , "No overlap"); + obs_block_deactivate(obs_block , iobs , verbose , "No overlap"); meas_block_deactivate(meas_block , iobs); } } @@ -146,7 +146,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type } } -void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type * meas_data) { +void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type * meas_data , bool verbose) { for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) { obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr); @@ -162,7 +162,7 @@ void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type De activated because the ensemble has to small variation for this particular measurement. */ - obs_block_deactivate( obs_block , iobs , "No ensemble variation"); + obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation"); meas_block_deactivate( meas_block , iobs ); } } diff --git a/ThirdParty/Ert/devel/libenkf/src/enkf_main.c b/ThirdParty/Ert/devel/libenkf/src/enkf_main.c index e870978d9b..b04229162b 100644 --- a/ThirdParty/Ert/devel/libenkf/src/enkf_main.c +++ b/ThirdParty/Ert/devel/libenkf/src/enkf_main.c @@ -330,30 +330,6 @@ qc_module_type * enkf_main_get_qc_module( const enkf_main_type * enkf_main ) { } -/* - Adding inverse observation keys to the enkf_nodes; can be called - several times. -*/ - - -void enkf_main_update_obs_keys( enkf_main_type * enkf_main ) { - /* First clear all existing observation keys. */ - ensemble_config_clear_obs_keys( enkf_main->ensemble_config ); - - /* Add new observation keys. */ - { - hash_type * map = enkf_obs_alloc_data_map(enkf_main->obs); - hash_iter_type * iter = hash_iter_alloc(map); - const char * obs_key = hash_iter_get_next_key(iter); - while (obs_key != NULL) { - const char * state_kw = hash_get(map , obs_key); - ensemble_config_add_obs_key(enkf_main->ensemble_config , state_kw , obs_key); - obs_key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - hash_free(map); - } -} void enkf_main_alloc_obs( enkf_main_type * enkf_main ) { enkf_main->obs = enkf_obs_alloc( model_config_get_history(enkf_main->model_config), @@ -370,8 +346,7 @@ void enkf_main_load_obs( enkf_main_type * enkf_main , const char * obs_config_fi if (enkf_obs_load(enkf_main->obs , obs_config_file , analysis_config_get_std_cutoff(enkf_main->analysis_config))) { - enkf_main_update_obs_keys(enkf_main); - enkf_main_update_local_updates(enkf_main ); + enkf_main_update_local_updates( enkf_main ); } else fprintf(stderr,"** Warning: failed to load observation data from: %s \n",obs_config_file); } @@ -1067,7 +1042,7 @@ void enkf_main_init_PC( const enkf_main_type * enkf_main , double std_cutoff = analysis_config_get_std_cutoff( analysis_config ); double alpha = analysis_config_get_alpha( analysis_config ); - enkf_analysis_deactivate_outliers( obs_data , meas_data , std_cutoff , alpha); + enkf_analysis_deactivate_outliers( obs_data , meas_data , std_cutoff , alpha, enkf_main->verbose); } { @@ -1181,8 +1156,7 @@ static void enkf_main_analysis_update( enkf_main_type * enkf_main , analysis_module_init_update( module , ens_mask , S , R , dObs , E , D ); { hash_iter_type * dataset_iter = local_ministep_alloc_dataset_iter( ministep ); - enkf_fs_type * src_fs = enkf_main_get_fs( enkf_main ); - serialize_info_type * serialize_info = serialize_info_alloc( src_fs , + serialize_info_type * serialize_info = serialize_info_alloc( target_fs, //src_fs - we have already copied the parameters from the src_fs to the target_fs target_fs , iens_active_index, target_step , @@ -1268,6 +1242,7 @@ static void enkf_main_analysis_update( enkf_main_type * enkf_main , matrix_free( R ); matrix_free( dObs ); matrix_free( X ); + matrix_free( A ); } @@ -1316,12 +1291,35 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_ meas_data_type * meas_forecast = meas_data_alloc( ens_mask ); meas_data_type * meas_analyzed = meas_data_alloc( ens_mask ); local_config_type * local_config = enkf_main->local_config; - const local_updatestep_type * updatestep = local_config_iget_updatestep( local_config , current_step ); /* Only last step considered when forming local update */ + const local_updatestep_type * updatestep = local_config_get_updatestep( local_config ); hash_type * use_count = hash_alloc(); const char * log_path = analysis_config_get_log_path( enkf_main->analysis_config ); FILE * log_stream; + + /* Copy all the parameter nodes. */ + if (target_fs != source_fs) { + stringlist_type * param_keys = ensemble_config_alloc_keylist_from_var_type(enkf_main->ensemble_config, PARAMETER ); + for (int i=0; i < stringlist_get_size( param_keys ); i++) { + const char * key = stringlist_iget( param_keys , i ); + if (local_updatestep_has_data_key(updatestep, key)) { + enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key ); + enkf_node_type * data_node = enkf_node_alloc( config_node ); + for (int j=0; j < int_vector_size( ens_active_list ); j++) { + node_id_type node_id = {.iens = int_vector_iget( ens_active_list , j ), + .state = FORECAST , + .report_step = 0 }; + enkf_node_load( data_node , source_fs , node_id ); + enkf_node_store( data_node , target_fs , false , node_id ); + } + enkf_node_free( data_node ); + } + } + stringlist_free( param_keys ); + } + + if ((local_updatestep_get_num_ministep( updatestep ) > 1) && (analysis_config_get_module_option( analysis_config , ANALYSIS_ITERABLE))) { util_exit("** ERROR: Can not combine iterable modules with multi step updates - sorry\n"); @@ -1368,7 +1366,7 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_ - enkf_analysis_deactivate_outliers( obs_data , meas_forecast , std_cutoff , alpha); + enkf_analysis_deactivate_outliers( obs_data , meas_forecast , std_cutoff , alpha , enkf_main->verbose); if (enkf_main->verbose) enkf_analysis_fprintf_obs_summary( obs_data , meas_forecast , step_list , local_ministep_get_name( ministep ) , stdout ); @@ -1407,8 +1405,30 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_ if (target_state_map != source_state_map) { state_map_set_from_inverted_mask( target_state_map , ens_mask , STATE_PARENT_FAILURE); state_map_set_from_mask( target_state_map , ens_mask , STATE_INITIALIZED ); - enkf_fs_fsync( target_fs ); - } + enkf_fs_fsync( target_fs ); + } + + /* Copy all the nodes which have been updates */ + if (target_fs != source_fs) { + stringlist_type * param_keys = ensemble_config_alloc_keylist_from_var_type(enkf_main->ensemble_config, PARAMETER ); + for (int i=0; i < stringlist_get_size( param_keys ); i++) { + const char * key = stringlist_iget( param_keys , i ); + if (!local_updatestep_has_data_key(updatestep, key)) { + enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key ); + enkf_node_type * data_node = enkf_node_alloc( config_node ); + for (int j=0; j < int_vector_size( ens_active_list ); j++) { + node_id_type node_id = {.iens = int_vector_iget( ens_active_list , j ), + .state = FORECAST , + .report_step = 0 }; + enkf_node_load( data_node , source_fs , node_id ); + enkf_node_store( data_node , target_fs , false , node_id ); + } + enkf_node_free( data_node ); + } + } + stringlist_free( param_keys ); + } + } bool_vector_free( ens_mask ); int_vector_free( ens_active_list ); @@ -1545,26 +1565,26 @@ void enkf_main_isubmit_job( enkf_main_type * enkf_main , run_arg_type * run_arg if (run_arg_get_run_mode(run_arg) != INIT_ONLY) { // The job_queue_node will take ownership of this arg_pack; and destroy it when // the job_queue_node is discarded. - arg_pack_type * load_arg = arg_pack_alloc(); + arg_pack_type * callback_arg = arg_pack_alloc(); /* Prepare the job and submit it to the queue */ - arg_pack_append_ptr( load_arg , enkf_state ); - arg_pack_append_ptr( load_arg , run_arg ); + arg_pack_append_ptr( callback_arg , enkf_state ); + arg_pack_append_ptr( callback_arg , run_arg ); { - int queue_index = job_queue_add_job_mt( job_queue , - job_script , - enkf_state_complete_forward_modelOK__ , - enkf_state_complete_forward_modelRETRY__ , - enkf_state_complete_forward_modelEXIT__, - load_arg , - ecl_config_get_num_cpu( ecl_config ), - run_path , - member_config_get_jobname( member_config ) , - 1, - (const char *[1]) { run_path } ); + int queue_index = job_queue_add_job( job_queue , + job_script , + enkf_state_complete_forward_modelOK__ , + enkf_state_complete_forward_modelRETRY__ , + enkf_state_complete_forward_modelEXIT__, + callback_arg , + ecl_config_get_num_cpu( ecl_config ), + run_path , + member_config_get_jobname( member_config ) , + 1, + (const char *[1]) { run_path } ); run_arg_set_queue_index( run_arg , queue_index ); run_arg_increase_submit_count( run_arg ); @@ -1574,13 +1594,12 @@ void enkf_main_isubmit_job( enkf_main_type * enkf_main , run_arg_type * run_arg -static void * enkf_main_isubmit_job__( void * arg ) { +void * enkf_main_isubmit_job__( void * arg ) { arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); enkf_main_type * enkf_main = enkf_main_safe_cast( arg_pack_iget_ptr( arg_pack , 0 )); run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1)); enkf_main_isubmit_job( enkf_main , run_arg ); - arg_pack_free( arg_pack ); return NULL; } @@ -1588,21 +1607,21 @@ static void * enkf_main_isubmit_job__( void * arg ) { -void enkf_main_submit_jobs( enkf_main_type * enkf_main , - const ert_run_context_type * run_context ) { +void enkf_main_submit_jobs__( enkf_main_type * enkf_main , + const ert_run_context_type * run_context , + thread_pool_type * submit_threads, + arg_pack_type ** arg_pack_list) { runpath_list_type * runpath_list = qc_module_get_runpath_list( enkf_main->qc_module ); - runpath_list_clear( runpath_list ); { int iens; const bool_vector_type * iactive = ert_run_context_get_iactive( run_context ); const int active_ens_size = util_int_min( bool_vector_size( iactive ) , enkf_main_get_ensemble_size( enkf_main )); - thread_pool_type * submit_threads = thread_pool_alloc( 4 , true ); for (iens = 0; iens < active_ens_size; iens++) { if (bool_vector_iget(iactive , iens)) { run_arg_type * run_arg = ert_run_context_iens_get_arg( run_context , iens); - arg_pack_type * arg_pack = arg_pack_alloc( ); // This is discarded by the enkf_main_isubmit_job__() + arg_pack_type * arg_pack = arg_pack_list[iens]; arg_pack_append_ptr( arg_pack , enkf_main ); arg_pack_append_ptr( arg_pack , run_arg); @@ -1610,20 +1629,38 @@ void enkf_main_submit_jobs( enkf_main_type * enkf_main , thread_pool_add_job(submit_threads , enkf_main_isubmit_job__ , arg_pack); } } - - /* - After this join all directories/files for the simulations - have been set up correctly, and all the jobs have been added - to the job_queue manager. - */ - - thread_pool_join(submit_threads); - thread_pool_free(submit_threads); } runpath_list_fprintf( runpath_list ); } +void enkf_main_submit_jobs( enkf_main_type * enkf_main , + const ert_run_context_type * run_context) { + + int ens_size = enkf_main_get_ensemble_size( enkf_main ); + arg_pack_type ** arg_pack_list = util_malloc( ens_size * sizeof * arg_pack_list ); + thread_pool_type * submit_threads = thread_pool_alloc( 4 , true ); + int iens; + for (iens = 0; iens < ens_size; iens++) + arg_pack_list[iens] = arg_pack_alloc( ); + + enkf_main_submit_jobs__(enkf_main , run_context , submit_threads , arg_pack_list); + + /* + After this join all directories/files for the simulations + have been set up correctly, and all the jobs have been added + to the job_queue manager. + */ + + thread_pool_join(submit_threads); + thread_pool_free(submit_threads); + + for (iens = 0; iens < ens_size; iens++) + arg_pack_free( arg_pack_list[iens] ); + free( arg_pack_list ); +} + + /** If all simulations have completed successfully the function will @@ -1693,11 +1730,12 @@ static bool enkf_main_run_step(enkf_main_type * enkf_main , { job_queue_type * job_queue = site_config_get_job_queue(enkf_main->site_config); job_queue_manager_type * queue_manager = job_queue_manager_alloc( job_queue ); + bool restart_queue = true; /* Start the queue */ if (ert_run_context_get_mode( run_context ) != INIT_ONLY) { if (site_config_has_job_script( enkf_main->site_config )) - job_queue_manager_start_queue( queue_manager , job_size , verbose_queue ); + job_queue_manager_start_queue( queue_manager , job_size , verbose_queue , restart_queue); else util_exit("No job script specified, can not start any jobs. Use the key JOB_SCRIPT in the config file\n"); } @@ -2165,76 +2203,69 @@ ert_run_context_type * enkf_main_alloc_ert_run_context_ENKF_ASSIMILATION( const here... */ -void enkf_main_create_all_active_config( const enkf_main_type * enkf_main , - const char * local_config_file ) { +void enkf_main_create_all_active_config( const enkf_main_type * enkf_main) { bool single_node_update = analysis_config_get_single_node_update( enkf_main->analysis_config ); bool update_results = analysis_config_get_update_results( enkf_main->analysis_config ); - - const char * update_step_name = "ALL_ACTIVE"; - const char * ministep_name = "ALL_ACTIVE"; - const char * obsset_name = "ALL_OBS"; - const char * dataset_name = "ALL_DATA"; // <- This is is created for possible further use, even if - // single_node_update is true. - - FILE * stream = util_fopen( local_config_file , "w"); - - fprintf(stream , "%-32s %s\n", local_config_get_cmd_string( CREATE_UPDATESTEP ) , update_step_name); - fprintf(stream , "%-32s %s \n", local_config_get_cmd_string( CREATE_OBSSET ) , obsset_name); - fprintf(stream , "%-32s %s %s \n", local_config_get_cmd_string( CREATE_MINISTEP ) , ministep_name , obsset_name); - fprintf(stream , "%-32s %s %s \n" , local_config_get_cmd_string( ATTACH_MINISTEP ), update_step_name , ministep_name); - - fprintf(stream , "%-32s %s \n", local_config_get_cmd_string( CREATE_DATASET ) , dataset_name); - if (!single_node_update) - fprintf(stream , "%-32s %s %s \n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep_name , dataset_name); - - /* Adding all observation keys */ + local_config_type * local_config = enkf_main->local_config; + local_config_clear( local_config ); { - hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_main->obs ); - while ( !hash_iter_is_complete(obs_iter) ) { - const char * obs_key = hash_iter_get_next_key( obs_iter ); - fprintf(stream , "%-32s %s %s\n",local_config_get_cmd_string( ADD_OBS ) , obsset_name , obs_key); - } - hash_iter_free( obs_iter ); - } + local_updatestep_type * default_step = local_config_get_updatestep(local_config); + local_ministep_type * ministep = local_config_alloc_ministep( local_config , "ALL_ACTIVE"); + local_obsdata_type * obsdata = local_config_alloc_obsset(local_config, "ALL_OBS"); + local_dataset_type * all_active_dataset = local_config_alloc_dataset(local_config, "ALL_DATA"); - /* Adding all node which can be updated. */ - { - stringlist_type * keylist = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER + DYNAMIC_STATE + DYNAMIC_RESULT); - int i; - for (i = 0; i < stringlist_get_size( keylist ); i++) { - const char * key = stringlist_iget( keylist , i); - const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key ); - enkf_var_type var_type = enkf_config_node_get_var_type( config_node ); - bool add_node = true; + local_updatestep_add_ministep( default_step , ministep ); - if ((var_type == DYNAMIC_RESULT) && (!update_results)) - add_node = false; - - /* - Make sure the funny GEN_KW instance masquerading as - SCHEDULE_PREDICTION_FILE is not added to the soup. - */ - if (util_string_equal(key , "PRED")) - add_node = false; - - - if (add_node) { - if (single_node_update) { - fprintf(stream , "%-32s %s \n" , local_config_get_cmd_string( CREATE_DATASET ) , key); - fprintf(stream , "%-32s %s %s \n" , local_config_get_cmd_string( ATTACH_DATASET ) , ministep_name , key); - fprintf(stream , "%-32s %s %s\n" , local_config_get_cmd_string( ADD_DATA ) , key , key); - } - fprintf(stream , "%-32s %s %s\n",local_config_get_cmd_string( ADD_DATA ) , dataset_name , key); + /* Adding all observation keys */ + { + hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_main->obs ); + while ( !hash_iter_is_complete(obs_iter) ) { + const char * obs_key = hash_iter_get_next_key( obs_iter ); + local_obsdata_node_type * obsdata_node = local_obsdata_node_alloc( obs_key ); + local_obsdata_add_node(obsdata, obsdata_node ); } + local_ministep_add_obsdata(ministep, obsdata); + hash_iter_free( obs_iter ); } - stringlist_free( keylist); - } - /* Install the ALL_ACTIVE step as the default. */ - fprintf(stream , "%-32s ALL_ACTIVE" , local_config_get_cmd_string( INSTALL_DEFAULT_UPDATESTEP )); - fclose( stream ); + /* Adding all node which can be updated. */ + { + stringlist_type * keylist = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER + DYNAMIC_STATE + DYNAMIC_RESULT); + int i; + for (i = 0; i < stringlist_get_size( keylist ); i++) { + const char * key = stringlist_iget( keylist , i); + const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key ); + enkf_var_type var_type = enkf_config_node_get_var_type( config_node ); + bool add_node = true; + + if ((var_type == DYNAMIC_RESULT) && (!update_results)) + add_node = false; + + /* + Make sure the funny GEN_KW instance masquerading as + SCHEDULE_PREDICTION_FILE is not added to the soup. + */ + if (util_string_equal(key , "PRED")) + add_node = false; + + + if (add_node) { + if (single_node_update) { + local_dataset_type * this_dataset = local_config_alloc_dataset(local_config, key); + local_dataset_add_node(this_dataset, key); + local_ministep_add_dataset(ministep, this_dataset); + } + local_dataset_add_node(all_active_dataset, key); + } + } + stringlist_free( keylist); + } + if (!single_node_update) + local_ministep_add_dataset(ministep, all_active_dataset); + + } } @@ -2777,23 +2808,7 @@ void enkf_main_update_local_updates( enkf_main_type * enkf_main) { const enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); if (enkf_obs_have_obs( enkf_obs )) { /* First create the default ALL_ACTIVE configuration. */ - { - char * all_active_config_file = util_alloc_tmp_file("/tmp" , "enkf_local_config" , true); - enkf_main_create_all_active_config( enkf_main , - all_active_config_file ); - - /** - This is where the local configuration files are actually parsed. - */ - local_config_reload( enkf_main->local_config , - ecl_config_get_grid( enkf_main->ecl_config ), - enkf_main->ensemble_config , - enkf_main->obs , - all_active_config_file ); - - unlink( all_active_config_file ); - free(all_active_config_file); - } + enkf_main_create_all_active_config( enkf_main ); } } diff --git a/ThirdParty/Ert/devel/libenkf/src/enkf_main_jobs.c b/ThirdParty/Ert/devel/libenkf/src/enkf_main_jobs.c index ffe2471244..7a9cf14497 100644 --- a/ThirdParty/Ert/devel/libenkf/src/enkf_main_jobs.c +++ b/ThirdParty/Ert/devel/libenkf/src/enkf_main_jobs.c @@ -256,11 +256,9 @@ void * enkf_main_scale_obs_std_JOB(void * self, const stringlist_type * args ) { enkf_main_type * enkf_main = enkf_main_safe_cast( self ); double scale_factor; - util_sscanf_double(stringlist_iget(args, 0), &scale_factor); - - if (enkf_main_have_obs(enkf_main)) { - enkf_obs_type * observations = enkf_main_get_obs(enkf_main); - enkf_obs_scale_std(observations, scale_factor); + if (util_sscanf_double(stringlist_iget(args, 0), &scale_factor)) { + analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); + analysis_config_set_global_std_scaling( analysis_config , scale_factor ); } return NULL; } diff --git a/ThirdParty/Ert/devel/libenkf/src/enkf_obs.c b/ThirdParty/Ert/devel/libenkf/src/enkf_obs.c index 81418a1d7b..8270d31371 100644 --- a/ThirdParty/Ert/devel/libenkf/src/enkf_obs.c +++ b/ThirdParty/Ert/devel/libenkf/src/enkf_obs.c @@ -186,8 +186,9 @@ static conf_class_type * enkf_obs_get_obs_conf_class(); ////////////////////////////////////////////////////////////////////////////////////// - +#define ENKF_OBS_TYPE_ID 637297 struct enkf_obs_struct { + UTIL_TYPE_ID_DECLARATION; /** A hash of obs_vector_types indexed by user provided keys. */ vector_type * obs_vector; hash_type * obs_hash; @@ -218,7 +219,7 @@ static int enkf_obs_get_last_restart( const enkf_obs_type * enkf_obs ) { return time_map_get_size( enkf_obs->obs_time ) - 1; } - +UTIL_IS_INSTANCE_FUNCTION( enkf_obs , ENKF_OBS_TYPE_ID ) enkf_obs_type * enkf_obs_alloc( const history_type * history , time_map_type * external_time_map , @@ -227,6 +228,7 @@ enkf_obs_type * enkf_obs_alloc( const history_type * history , ensemble_config_type * ensemble_config ) { enkf_obs_type * enkf_obs = util_malloc(sizeof * enkf_obs); + UTIL_TYPE_ID_INIT( enkf_obs , ENKF_OBS_TYPE_ID ); enkf_obs->obs_hash = hash_alloc(); enkf_obs->obs_vector = vector_alloc_new(); enkf_obs->obs_time = time_map_alloc(); @@ -356,7 +358,7 @@ static void enkf_obs_get_obs_and_measure_summary(const enkf_obs_type * enkf if (obs_vector_iget_active( obs_vector , step ) && active_list_iget( active_list , 0 /* Index into the scalar summary observation */)) { { const summary_obs_type * summary_obs = obs_vector_iget_node( obs_vector , step ); - double_vector_iset( obs_std , active_count , summary_obs_get_std( summary_obs )); + double_vector_iset( obs_std , active_count , summary_obs_get_std( summary_obs ) * summary_obs_get_std_scaling( summary_obs )); double_vector_iset( obs_value , active_count , summary_obs_get_value( summary_obs )); last_step = step; } @@ -518,6 +520,34 @@ void enkf_obs_clear( enkf_obs_type * enkf_obs ) { + +/* + Adding inverse observation keys to the enkf_nodes; can be called + several times. +*/ + + +static void enkf_obs_update_keys( enkf_obs_type * enkf_obs ) { + /* First clear all existing observation keys. */ + ensemble_config_clear_obs_keys( enkf_obs->ensemble_config ); + + /* Add new observation keys. */ + { + hash_type * map = enkf_obs_alloc_data_map(enkf_obs); + hash_iter_type * iter = hash_iter_alloc(map); + const char * obs_key = hash_iter_get_next_key(iter); + while (obs_key != NULL) { + const char * state_kw = hash_get(map , obs_key); + ensemble_config_add_obs_key(enkf_obs->ensemble_config , state_kw , obs_key); + obs_key = hash_iter_get_next_key(iter); + } + hash_iter_free(iter); + hash_free(map); + } +} + + + /** This function will load an observation configuration from the observation file @config_file. @@ -531,7 +561,7 @@ void enkf_obs_clear( enkf_obs_type * enkf_obs ) { bool enkf_obs_load(enkf_obs_type * enkf_obs , const char * config_file, double std_cutoff) { - + if (enkf_obs->valid) { int last_report = enkf_obs_get_last_restart( enkf_obs ); conf_class_type * enkf_conf_class = enkf_obs_get_obs_conf_class(); @@ -643,6 +673,7 @@ bool enkf_obs_load(enkf_obs_type * enkf_obs , conf_instance_free(enkf_conf ); conf_class_free( enkf_conf_class); + enkf_obs_update_keys( enkf_obs ); return true; } else return false; diff --git a/ThirdParty/Ert/devel/libenkf/src/enkf_state.c b/ThirdParty/Ert/devel/libenkf/src/enkf_state.c index 40195cb5e3..168ed7cfef 100644 --- a/ThirdParty/Ert/devel/libenkf/src/enkf_state.c +++ b/ThirdParty/Ert/devel/libenkf/src/enkf_state.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_state.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'enkf_state.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -85,21 +85,21 @@ This struct contains various objects which the enkf_state needs during operation, which the enkf_state_object *DOES NOT* own. The struct only contains pointers to objects owned by (typically) the - enkf_main object. + enkf_main object. If the enkf_state object writes to any of the objects in this struct that can be considered a serious *BUG*. The elements in this struct should not change during the - application lifetime? + application lifetime? */ typedef struct shared_info_struct { model_config_type * model_config; /* .... */ ext_joblist_type * joblist; /* The list of external jobs which are installed - and *how* they should be run (with Python code) */ - job_queue_type * job_queue; /* The queue handling external jobs. (i.e. LSF / TORQUE / rsh / local / ... )*/ + job_queue_type * job_queue; /* The queue handling external jobs. (i.e. LSF / TORQUE / rsh / local / ... )*/ const site_config_type * site_config; - ert_templates_type * templates; + ert_templates_type * templates; const ecl_config_type * ecl_config; } shared_info_type; @@ -118,7 +118,7 @@ struct enkf_state_struct { operation on the ECLIPSE data file. Will at least contain the key INIT" - which will describe initialization of ECLIPSE (EQUIL or RESTART).*/ ensemble_config_type * ensemble_config; /* The config nodes for the enkf_node objects contained in node_hash. */ - + shared_info_type * shared_info; /* Pointers to shared objects which is needed by the enkf_state object (read only). */ member_config_type * my_config; /* Private config information for this member; not updated during a simulation. */ rng_type * rng; @@ -144,14 +144,14 @@ static shared_info_type * shared_info_alloc(const site_config_type * site_config static void shared_info_free(shared_info_type * shared_info) { - /** - Adding something here is a BUG - this object does + /** + Adding something here is a BUG - this object does not own anything. */ free( shared_info ); } - + @@ -173,9 +173,9 @@ void enkf_state_initialize(enkf_state_type * enkf_state , enkf_fs_type * fs , co enkf_node_type * param_node = enkf_state_get_node(enkf_state, stringlist_iget(param_list, ip)); node_id_type node_id = { .report_step = 0, .iens = iens, .state = init_state }; bool has_data = enkf_node_has_data(param_node, fs, node_id); - + if ((init_mode == INIT_FORCE) || (has_data == false) || (current_state == STATE_LOAD_FAILURE)) { - if (enkf_node_initialize(param_node, iens, enkf_state->rng)) + if (enkf_node_initialize(param_node, iens, enkf_state->rng)) enkf_node_store(param_node, fs, true, node_id); } } @@ -227,9 +227,9 @@ void enkf_state_update_eclbase( enkf_state_type * enkf_state ) { const char * eclbase = member_config_update_eclbase( enkf_state->my_config , enkf_state->shared_info->ecl_config , enkf_state->subst_list); const char * casename = member_config_get_casename( enkf_state->my_config ); /* Mostly NULL */ { - enkf_state_add_subst_kw(enkf_state , "ECL_BASE" , eclbase , NULL); - enkf_state_add_subst_kw(enkf_state , "ECLBASE" , eclbase , NULL); - + enkf_state_add_subst_kw(enkf_state , "ECL_BASE" , eclbase , NULL); + enkf_state_add_subst_kw(enkf_state , "ECLBASE" , eclbase , NULL); + if (casename == NULL) enkf_state_add_subst_kw( enkf_state , "CASE" , eclbase , NULL); /* No CASE_TABLE loaded - using the eclbase as default. */ else @@ -239,8 +239,8 @@ void enkf_state_update_eclbase( enkf_state_type * enkf_state ) { void enkf_state_update_jobname( enkf_state_type * enkf_state ) { - member_config_update_jobname( enkf_state->my_config , - model_config_get_jobname_fmt( enkf_state->shared_info->model_config ) , + member_config_update_jobname( enkf_state->my_config , + model_config_get_jobname_fmt( enkf_state->shared_info->model_config ) , enkf_state->subst_list); } @@ -259,7 +259,7 @@ static void enkf_state_set_static_subst_kw(enkf_state_type * enkf_state) { enkf_state_add_subst_kw(enkf_state , "IENS" , iens_s , NULL); enkf_state_add_subst_kw(enkf_state , "IENSP1" , iensp1_s , NULL); enkf_state_add_subst_kw(enkf_state , "IENS4" , iens4_s , NULL); - + free(iensp1_s); free(iens_s); free(iens4_s); @@ -282,7 +282,7 @@ static void enkf_state_add_nodes( enkf_state_type * enkf_state, const ensemble_c } else enkf_state_add_node(enkf_state , key , config_node); } - + // 2: Add container nodes - must ensure that all other nodes have // been added already (this implies that containers of containers // will be victim of hash retrieval order problems .... @@ -292,7 +292,7 @@ static void enkf_state_add_nodes( enkf_state_type * enkf_state, const ensemble_c const enkf_config_node_type * config_node = ensemble_config_get_node(ensemble_config , key); enkf_state_add_node( enkf_state , key , config_node ); } - + stringlist_free(keylist); stringlist_free( container_keys ); } @@ -315,33 +315,33 @@ void enkf_state_set_pre_clear_runpath( enkf_state_type * enkf_state , bool pre_c enkf_state_type * enkf_state_alloc(int iens, - rng_type * main_rng , - enkf_fs_type * fs, - const char * casename , - bool pre_clear_runpath , - keep_runpath_type keep_runpath , + rng_type * main_rng , + enkf_fs_type * fs, + const char * casename , + bool pre_clear_runpath , + keep_runpath_type keep_runpath , model_config_type * model_config, ensemble_config_type * ensemble_config, const site_config_type * site_config, const ecl_config_type * ecl_config, ert_templates_type * templates, - subst_list_type * subst_parent) { - + subst_list_type * subst_parent) { + enkf_state_type * enkf_state = util_malloc(sizeof *enkf_state ); UTIL_TYPE_ID_INIT( enkf_state , ENKF_STATE_TYPE_ID ); enkf_state->ensemble_config = ensemble_config; enkf_state->shared_info = shared_info_alloc(site_config , model_config , ecl_config , templates); - + enkf_state->node_hash = hash_alloc(); enkf_state->restart_kw_list = stringlist_alloc_new(); enkf_state->subst_list = subst_list_alloc( subst_parent ); - enkf_state->rng = rng_alloc( rng_get_type( main_rng ) , INIT_DEFAULT ); + enkf_state->rng = rng_alloc( rng_get_type( main_rng ) , INIT_DEFAULT ); rng_rng_init( enkf_state->rng , main_rng ); /* <- Not thread safe */ /* The user MUST specify an INIT_FILE, and for the first timestep the - tag in the data file will be replaced by an + tag in the data file will be replaced by an INCLDUE EQUIL_INIT_FILE @@ -386,8 +386,8 @@ enkf_state_type * enkf_state_alloc(int iens, enkf_state_add_subst_kw(enkf_state , "RESTART_FILE2" , "---" , "The ECLIPSE restart file this simulation should end with."); enkf_state_add_subst_kw(enkf_state , "RANDINT" , "---" , "Random integer value (depreceated: use __RANDINT__() instead)."); enkf_state_add_subst_kw(enkf_state , "RANDFLOAT" , "---" , "Random float value (depreceated: use __RANDFLOAT__() instead)."); - enkf_state_add_subst_kw(enkf_state , "INIT" , "---" , "The code which will be inserted at the tag"); - if (casename != NULL) + enkf_state_add_subst_kw(enkf_state , "INIT" , "---" , "The code which will be inserted at the tag"); + if (casename != NULL) enkf_state_add_subst_kw(enkf_state , "CASE" , casename , "The casename for this realization - as loaded from the CASE_TABLE file."); else enkf_state_add_subst_kw(enkf_state , "CASE" , "---" , "The casename for this realization - similar to ECLBASE."); @@ -395,7 +395,7 @@ enkf_state_type * enkf_state_alloc(int iens, enkf_state->my_config = member_config_alloc( iens , casename , pre_clear_runpath , keep_runpath , ecl_config , ensemble_config , fs); enkf_state_set_static_subst_kw( enkf_state ); enkf_state_add_nodes( enkf_state , ensemble_config ); - + return enkf_state; } @@ -421,7 +421,7 @@ bool enkf_state_has_node(const enkf_state_type * enkf_state , const char * node_ void enkf_state_add_node(enkf_state_type * enkf_state , const char * node_key , const enkf_config_node_type * config) { - if (enkf_state_has_node(enkf_state , node_key)) + if (enkf_state_has_node(enkf_state , node_key)) enkf_state_del_node( enkf_state , node_key ); /* Deleting the old instance (if we had one). */ { enkf_node_type *enkf_node; @@ -429,9 +429,9 @@ void enkf_state_add_node(enkf_state_type * enkf_state , const char * node_key , enkf_node = enkf_node_alloc_shared_container( config , enkf_state->node_hash ); else enkf_node = enkf_node_alloc( config ); - + hash_insert_hash_owned_ref(enkf_state->node_hash , node_key , enkf_node, enkf_node_free__); - + /* Setting the global subst list so that the GEN_KW templates can contain e.g. and . */ if (enkf_node_get_impl_type( enkf_node ) == GEN_KW) gen_kw_set_subst_parent( enkf_node_value_ptr( enkf_node ) , enkf_state->subst_list ); @@ -457,7 +457,7 @@ void enkf_state_update_node( enkf_state_type * enkf_state , const char * node_ke bool modified = true; /* ehhhh? */ if (modified) - enkf_state_add_node( enkf_state , node_key , config_node ); + enkf_state_add_node( enkf_state , node_key , config_node ); } } @@ -472,42 +472,42 @@ static ecl_sum_type * enkf_state_load_ecl_sum(const enkf_state_type * enkf_state if (ecl_config_active( ecl_config )) { const bool fmt_file = ecl_config_get_formatted(ecl_config); const char * eclbase = enkf_state_get_eclbase( enkf_state ); - + stringlist_type * data_files = stringlist_alloc_new(); char * header_file = ecl_util_alloc_exfilename(run_arg_get_runpath(run_arg) , eclbase , ECL_SUMMARY_HEADER_FILE , fmt_file , -1); char * unified_file = ecl_util_alloc_exfilename(run_arg_get_runpath(run_arg) , eclbase , ECL_UNIFIED_SUMMARY_FILE , fmt_file , -1); - ecl_sum_type * summary = NULL; - + ecl_sum_type * summary = NULL; + /* Should we load from a unified summary file, or from several non-unified files? */ - if (unified_file != NULL) + if (unified_file != NULL) /* Use unified file: */ stringlist_append_ref( data_files , unified_file); else { - /* Use several non unified files. */ + /* Use several non unified files. */ /* Bypassing the query to model_config_load_results() */ int report_step = run_arg_get_load_start( run_arg ); if (report_step == 0) report_step++; // Ignore looking for the .S0000 summary file (it does not exist). while (true) { char * summary_file = ecl_util_alloc_exfilename(run_arg_get_runpath( run_arg ) , eclbase , ECL_SUMMARY_FILE , fmt_file , report_step); - + if (summary_file != NULL) stringlist_append_owned_ref( data_files , summary_file); else - /* + /* We stop the loading at first 'hole' in the series of summary files; the internalize layer must report failure if we are missing data. */ break; - + if ((run_arg_get_run_mode( run_arg ) == ENKF_ASSIMILATION) && (run_arg_get_step2( run_arg ) == report_step)) break; report_step++; } - } - + } + if ((header_file != NULL) && (stringlist_get_size(data_files) > 0)) { summary = ecl_sum_fread_alloc(header_file , data_files , SUMMARY_KEY_JOIN_STRING ); { @@ -519,17 +519,17 @@ static ecl_sum_type * enkf_state_load_ecl_sum(const enkf_state_type * enkf_state { int end_day,end_month,end_year; int sum_day,sum_month,sum_year; - + util_set_date_values( end_time , &end_day , &end_month , &end_year ); util_set_date_values( ecl_sum_get_end_time( summary ) , &sum_day , &sum_month , &sum_year ); - stringlist_append_owned_ref( messages , - util_alloc_sprintf("Summary ended at %02d/%02d/%4d - expected at least END_DATE: %02d/%02d/%4d" , - sum_day , sum_month , sum_year , + stringlist_append_owned_ref( messages , + util_alloc_sprintf("Summary ended at %02d/%02d/%4d - expected at least END_DATE: %02d/%02d/%4d" , + sum_day , sum_month , sum_year , end_day , end_month , end_year )); } ecl_sum_free( summary ); summary = NULL; - *result |= LOAD_FAILURE; + *result |= LOAD_FAILURE; } } } @@ -543,14 +543,14 @@ static ecl_sum_type * enkf_state_load_ecl_sum(const enkf_state_type * enkf_state } -static void enkf_state_log_GEN_DATA_load( const enkf_node_type * enkf_node , int report_step , stringlist_type * msg_list) { +static void enkf_state_log_GEN_DATA_load( const enkf_node_type * enkf_node , int report_step , stringlist_type * msg_list) { /* In interactive mode we explicitly report the loads of GEN_DATA instances. */ char * load_file = enkf_config_node_alloc_infile(enkf_node_get_config( enkf_node ) , report_step); int data_size = gen_data_get_size( enkf_node_value_ptr( enkf_node )); - stringlist_append_owned_ref( msg_list , - util_alloc_sprintf("Loaded GEN_DATA:%s instance for step:%d from file:%s size:%d" , - enkf_node_get_key( enkf_node ) , - report_step , + stringlist_append_owned_ref( msg_list , + util_alloc_sprintf("Loaded GEN_DATA:%s instance for step:%d from file:%s size:%d" , + enkf_node_get_key( enkf_node ) , + report_step , load_file , data_size)); free( load_file ); @@ -568,15 +568,15 @@ static void enkf_state_log_custom_kw_load(const enkf_node_type * enkf_node, int } static bool enkf_state_report_step_compatible(const enkf_state_type * enkf_state, const ecl_sum_type * ecl_sum_simulated) { - bool ret = true; + bool ret = true; const model_config_type * model_config = enkf_state->shared_info->model_config; - const ecl_sum_type * ecl_sum_reference = model_config_get_refcase(model_config); + const ecl_sum_type * ecl_sum_reference = model_config_get_refcase(model_config); if (ecl_sum_reference) //Can be NULL - ret = ecl_sum_report_step_compatible(ecl_sum_reference, ecl_sum_simulated); - - return ret; + ret = ecl_sum_report_step_compatible(ecl_sum_reference, ecl_sum_simulated); + + return ret; } @@ -591,11 +591,11 @@ static bool enkf_state_internalize_dynamic_eclipse_results(enkf_state_type * enk bool load_summary = ensemble_config_has_impl_type(enkf_state->ensemble_config, SUMMARY); if (load_summary) { int load_start = run_arg_get_load_start( run_arg ); - + if (load_start == 0) { /* Do not attempt to load the "S0000" summary results. */ load_start++; } - + { /* Looking for summary files on disk, and loading them. */ ecl_sum_type * summary = enkf_state_load_ecl_sum( enkf_state , run_arg , msg_list , result ); @@ -604,23 +604,23 @@ static bool enkf_state_internalize_dynamic_eclipse_results(enkf_state_type * enk if (summary != NULL) { int_vector_type * time_index = __enkf_state_get_time_index(result_fs, summary); - /* + /* Now there are two related / conflicting(?) systems for checking summary time consistency, both internally in the time_map and also through the enkf_state_report_step_compatible() function. */ - + /*Check the loaded summary against the reference ecl_sum_type */ if (!enkf_state_report_step_compatible(enkf_state, summary)) { *result |= REPORT_STEP_INCOMPATIBLE; } - + /* The actual loading internalizing - from ecl_sum -> enkf_node. */ const int iens = member_config_get_iens( enkf_state->my_config ); const int step2 = ecl_sum_get_last_report_step( summary ); /* Step2 is just taken from the number of steps found in the summary file. */ - + int_vector_iset_block( time_index , 0 , load_start , -1 ); int_vector_resize( time_index , step2 + 1); @@ -661,7 +661,7 @@ static bool enkf_state_internalize_dynamic_eclipse_results(enkf_state_type * enk } stringlist_free(keys); - ecl_sum_free( summary ); + ecl_sum_free( summary ); int_vector_free( time_index ); return true; } else { @@ -690,14 +690,14 @@ static bool enkf_state_internalize_dynamic_eclipse_results(enkf_state_type * enk __realloc_static_kw("INTEHEAD" , 0) ==> "INTEHEAD_0" - In the enkf layer the key used will then be INTEHEAD_0. + In the enkf layer the key used will then be INTEHEAD_0. */ static char * __realloc_static_kw(char * kw , int occurence) { char * new_kw = util_alloc_sprintf("%s_%d" , kw , occurence); free(kw); - ecl_util_escape_kw(new_kw); + ecl_util_escape_kw(new_kw); return new_kw; } @@ -758,22 +758,22 @@ static void enkf_state_internalize_custom_kw(enkf_state_type * enkf_state, -static void enkf_state_internalize_GEN_DATA(enkf_state_type * enkf_state , - run_arg_type * run_arg , - const model_config_type * model_config , - int last_report , - int * result, - bool interactive , +static void enkf_state_internalize_GEN_DATA(enkf_state_type * enkf_state , + run_arg_type * run_arg , + const model_config_type * model_config , + int last_report , + int * result, + bool interactive , stringlist_type * msg_list) { { member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); + const int iens = member_config_get_iens( my_config ); stringlist_type * keylist_GEN_DATA = ensemble_config_alloc_keylist_from_impl_type(enkf_state->ensemble_config , GEN_DATA ); enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - + for (int ikey=0; ikey < stringlist_get_size( keylist_GEN_DATA ); ikey++) { enkf_node_type * node = enkf_state_get_node( enkf_state , stringlist_iget( keylist_GEN_DATA , ikey)); - + if (enkf_node_vector_storage(node)) { util_abort("%s: holy shit - vector storage not correctly implemented for GEN_DATA\n",__func__); @@ -783,39 +783,39 @@ static void enkf_state_internalize_GEN_DATA(enkf_state_type * enkf_state , if (interactive) enkf_state_log_GEN_DATA_load( node , 0 , msg_list ); } else { - *result |= LOAD_FAILURE; + *result |= LOAD_FAILURE; ert_log_add_fmt_message(3 , NULL , "[%03d:----] Failed to load data for vector node:%s.",iens , enkf_node_get_key( node )); - if (interactive) + if (interactive) stringlist_append_owned_ref( msg_list , util_alloc_sprintf("Failed to load vector:%s" , enkf_node_get_key( node ))); } - + } else { - + for (int report_step = run_arg_get_load_start( run_arg ); report_step <= last_report; report_step++) { if (enkf_node_internalize(node , report_step)) { - + if (enkf_node_has_func(node , forward_load_func)) { if (enkf_node_forward_load(node , run_arg_get_runpath( run_arg ) , NULL , NULL , report_step , iens )) { - node_id_type node_id = {.report_step = report_step , - .iens = iens , + node_id_type node_id = {.report_step = report_step , + .iens = iens , .state = FORECAST }; enkf_node_store( node , result_fs, false , node_id ); - - if (interactive) + + if (interactive) enkf_state_log_GEN_DATA_load( node , report_step , msg_list ); - + } else { - *result |= LOAD_FAILURE; + *result |= LOAD_FAILURE; ert_log_add_fmt_message(1 , stderr , "[%03d:%04d] Failed load data for node:%s.",iens , report_step , enkf_node_get_key( node )); - - if (interactive) - stringlist_append_owned_ref(msg_list , + + if (interactive) + stringlist_append_owned_ref(msg_list , util_alloc_sprintf("Failed to load: %s at step:%d" , enkf_node_get_key( node ) , report_step)); } } - } - } + } + } } } } @@ -826,66 +826,66 @@ static void enkf_state_internalize_GEN_DATA(enkf_state_type * enkf_state , This function loads the STATE from a forward simulation. In ECLIPSE speak that means to load the solution vectors (PRESSURE/SWAT/..) and the necessary static keywords. - + When the state has been loaded it goes straight to disk. */ -static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , - run_arg_type * run_arg , - const model_config_type * model_config , - int report_step , - bool store_vectors , - int * result, - bool interactive , +static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , + run_arg_type * run_arg , + const model_config_type * model_config , + int report_step , + bool store_vectors , + int * result, + bool interactive , stringlist_type * msg_list) { shared_info_type * shared_info = enkf_state->shared_info; const ecl_config_type * ecl_config = shared_info->ecl_config; enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); if (ecl_config_active( ecl_config )) { member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); + const int iens = member_config_get_iens( my_config ); const bool fmt_file = ecl_config_get_formatted( ecl_config ); const bool unified = ecl_config_get_unified_restart( ecl_config ); const bool internalize_state = model_config_internalize_state( model_config , report_step ); ecl_file_type * restart_file; - - + + /** Loading the restart block. */ - - if (unified) + + if (unified) util_abort("%s: sorry - unified restart files are not supported \n",__func__); { char * filename = ecl_util_alloc_exfilename(run_arg_get_runpath(run_arg) , member_config_get_eclbase(enkf_state->my_config) , ECL_RESTART_FILE , fmt_file , report_step); if (filename) { restart_file = ecl_file_open( filename , 0 ); free(filename); - } else + } else restart_file = NULL; /* No restart information was found; if that is expected the program will fail hard in the enkf_node_forward_load() functions. */ } - + /*****************************************************************/ - - + + /** Iterating through the restart file: - + 1. Build up enkf_state->restart_kw_list. 2. Send static keywords straight out. */ - + if (restart_file) { stringlist_clear( enkf_state->restart_kw_list ); { - int ikw; + int ikw; for (ikw =0; ikw < ecl_file_get_size( restart_file ); ikw++) { ert_impl_type impl_type; const ecl_kw_type * ecl_kw = ecl_file_iget_kw( restart_file , ikw); int occurence = ecl_file_iget_occurence( restart_file , ikw ); /* This is essentially the static counter value. */ char * kw = util_alloc_string_copy( ecl_kw_get_header( ecl_kw ) ); - /** + /** Observe that this test will never succeed for static keywords, because the internalized key has appended a _. */ @@ -896,71 +896,71 @@ static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , PRESSURE. The first occurence of PRESSURE will be for the ordinary grid, and then there will be subsequent PRESSURE sections for each LGR section. The way this is implemented here is as follows: - + 1. The first occurence of pressure is internalized as the enkf_node pressure (if we indeed have a pressure node). - + 2. The consecutive pressure nodes are internalized as static parameters. - + The variable 'occurence' is the key here. */ - + if (occurence == 0) { const enkf_config_node_type * config_node = ensemble_config_get_node(enkf_state->ensemble_config , kw); impl_type = enkf_config_node_get_impl_type(config_node); - } else + } else impl_type = STATIC; } else impl_type = STATIC; - - - if (impl_type == FIELD) + + + if (impl_type == FIELD) stringlist_append_copy(enkf_state->restart_kw_list , kw); else if (impl_type == STATIC) { if (ecl_config_include_static_kw(ecl_config , kw)) { /* It is a static kw like INTEHEAD or SCON */ - /* + /* Observe that for static keywords we do NOT ask the node 'privately' if internalize_state is false: It is impossible to single out static keywords for internalization. */ - + /* Now we mangle the static keyword .... */ kw = __realloc_static_kw(kw , occurence); - - if (internalize_state) { + + if (internalize_state) { stringlist_append_copy( enkf_state->restart_kw_list , kw); - + ensemble_config_ensure_static_key(enkf_state->ensemble_config , kw ); - + if (!enkf_state_has_node(enkf_state , kw)) { const enkf_config_node_type * config_node = ensemble_config_get_node(enkf_state->ensemble_config , kw); - enkf_state_add_node(enkf_state , kw , config_node); + enkf_state_add_node(enkf_state , kw , config_node); } - - /* + + /* The following thing can happen: - + 1. A static keyword appears at report step n, and is added to the enkf_state object. - + 2. At report step n+k that static keyword is no longer active, and it is consequently no longer part of restart_kw_list(). - + 3. However it is still part of the enkf_state. Not loaded here, and subsequently purged from enkf_main. - + One keyword where this occurs is FIPOIL, which at least might appear only in the first restart file. Unused static keywords of this type are purged from the enkf_main object by a call to enkf_main_del_unused_static(). The purge is based on looking at the internal __report_step state of the static kw. */ - + { enkf_node_type * enkf_node = enkf_state_get_node(enkf_state , kw); node_id_type node_id = {.report_step = report_step , .iens = iens , .state = FORECAST }; - + enkf_node_ecl_load_static(enkf_node , ecl_kw , report_step , iens); /* Static kewyords go straight out .... @@ -969,7 +969,7 @@ static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , enkf_node_free_data(enkf_node); } } - } + } } else util_abort("%s: hm - something wrong - can (currently) only load FIELD/STATIC implementations from restart files - aborting \n",__func__); free(kw); @@ -977,49 +977,49 @@ static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , enkf_fs_fwrite_restart_kw_list( result_fs , report_step , iens , enkf_state->restart_kw_list ); } } - + /******************************************************************/ - /** + /** Starting on the enkf_node_forward_load() function calls. This is where the actual loading (apart from static keywords) is done. Observe that this loading might involve other load functions than the ones used for loading PRESSURE++ from ECLIPSE restart files (e.g. for loading seismic results..) */ - + { hash_iter_type * iter = hash_iter_alloc(enkf_state->node_hash); while ( !hash_iter_is_complete(iter) ) { enkf_node_type * enkf_node = hash_iter_get_next_value(iter); - if (enkf_node_get_var_type(enkf_node) == DYNAMIC_STATE && + if (enkf_node_get_var_type(enkf_node) == DYNAMIC_STATE && enkf_node_get_impl_type(enkf_node) == FIELD) { bool internalize_kw = internalize_state; if (!internalize_kw) internalize_kw = enkf_node_internalize(enkf_node , report_step); - + if (internalize_kw) { if (enkf_node_has_func(enkf_node , forward_load_func)) { if (enkf_node_forward_load(enkf_node , run_arg_get_runpath( run_arg ) , NULL , restart_file , report_step , iens )) { - node_id_type node_id = {.report_step = report_step , - .iens = iens , + node_id_type node_id = {.report_step = report_step , + .iens = iens , .state = FORECAST }; enkf_node_store( enkf_node , result_fs, store_vectors , node_id ); } else { - *result |= LOAD_FAILURE; + *result |= LOAD_FAILURE; ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d] Failed load data for node:%s.",iens , report_step , enkf_node_get_key( enkf_node )); - - if (interactive) + + if (interactive) stringlist_append_owned_ref(msg_list , util_alloc_sprintf("Failed to load: %s at step:%d" , enkf_node_get_key( enkf_node ) , report_step)); } } - } - } - } + } + } + } hash_iter_free(iter); } - + /*****************************************************************/ /* Cleaning up */ if (restart_file != NULL) ecl_file_close( restart_file ); @@ -1037,7 +1037,7 @@ static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , Will mainly be called at the end of the forward model, but can also be called manually from external scope. */ - + static void enkf_state_internalize_results(enkf_state_type * enkf_state , run_arg_type * run_arg , int * result , bool interactive , stringlist_type * msg_list) { model_config_type * model_config = enkf_state->shared_info->model_config; @@ -1048,7 +1048,7 @@ static void enkf_state_internalize_results(enkf_state_type * enkf_state , run_ar in these results are inferred from the loading of summary results, hence we must load the summary results first. */ - + enkf_state_internalize_dynamic_eclipse_results(enkf_state , run_arg , model_config , result, interactive , msg_list); { enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); @@ -1058,28 +1058,28 @@ static void enkf_state_internalize_results(enkf_state_type * enkf_state , run_ar /* If we are in true assimilation mode we use the step2 setting, otherwise we are - just in plain gready-load-mode. + just in plain gready-load-mode. */ if (run_arg_get_run_mode(run_arg) == ENKF_ASSIMILATION) last_report = run_arg_get_step2( run_arg ); /* Ensure that the last step is internalized? */ model_config_set_internalize_state( model_config , last_report); - + for (report_step = run_arg_get_load_start( run_arg ); report_step <= last_report; report_step++) { bool store_vectors = (report_step == last_report) ? true : false; - if (model_config_load_state( model_config , report_step)) + if (model_config_load_state( model_config , report_step)) enkf_state_internalize_eclipse_state(enkf_state , run_arg , model_config , report_step , store_vectors , result , interactive , msg_list); } - + enkf_state_internalize_GEN_DATA(enkf_state , run_arg , model_config , last_report , result , interactive , msg_list); enkf_state_internalize_custom_kw(enkf_state, run_arg, model_config, result, interactive, msg_list); } } -void enkf_state_forward_init(enkf_state_type * enkf_state , - run_arg_type * run_arg , +void enkf_state_forward_init(enkf_state_type * enkf_state , + run_arg_type * run_arg , int * result ) { if (run_arg_get_step1(run_arg) == 0) { @@ -1089,28 +1089,28 @@ void enkf_state_forward_init(enkf_state_type * enkf_state , enkf_node_type * node = hash_iter_get_next_value(iter); if (enkf_node_use_forward_init(node)) { enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - node_id_type node_id = {.report_step = 0 , - .iens = iens , + node_id_type node_id = {.report_step = 0 , + .iens = iens , .state = ANALYZED }; - /* + /* Will not reinitialize; i.e. it is essential that the forward model uses the state given from the stored - instance, and not from the current run of e.g. RMS. + instance, and not from the current run of e.g. RMS. */ - if (!enkf_node_has_data( node , result_fs , node_id)) { + if (!enkf_node_has_data( node , result_fs , node_id)) { if (enkf_node_forward_init(node , run_arg_get_runpath( run_arg ) , iens )) enkf_node_store( node , result_fs , false , node_id ); else { char * init_file = enkf_config_node_alloc_initfile( enkf_node_get_config( node ) , run_arg_get_runpath(run_arg) , iens ); - if (init_file && !util_file_exists( init_file )) + if (init_file && !util_file_exists( init_file )) fprintf(stderr,"File not found: %s - failed to initialize node: %s\n", init_file , enkf_node_get_key( node )); else fprintf(stderr,"Failed to initialize node: %s\n", enkf_node_get_key( node )); - + util_safe_free( init_file ); *result |= LOAD_FAILURE; } @@ -1125,21 +1125,21 @@ void enkf_state_forward_init(enkf_state_type * enkf_state , -void enkf_state_load_from_forward_model(enkf_state_type * enkf_state , - run_arg_type * run_arg , - int * result, - bool interactive , +void enkf_state_load_from_forward_model(enkf_state_type * enkf_state , + run_arg_type * run_arg , + int * result, + bool interactive , stringlist_type * msg_list) { - - + + if (ensemble_config_have_forward_init( enkf_state->ensemble_config )) enkf_state_forward_init( enkf_state , run_arg , result ); - + enkf_state_internalize_results( enkf_state , run_arg , result , interactive , msg_list ); { state_map_type * state_map = enkf_fs_get_state_map( run_arg_get_result_fs( run_arg ) ); int iens = member_config_get_iens( enkf_state->my_config ); - if (*result & LOAD_FAILURE) + if (*result & LOAD_FAILURE) state_map_iset( state_map , iens , STATE_LOAD_FAILURE); else state_map_iset( state_map , iens , STATE_HAS_DATA); @@ -1149,36 +1149,36 @@ void enkf_state_load_from_forward_model(enkf_state_type * enkf_state , /** Observe that this does not return the loadOK flag; it will load as - good as it can all the data it should, and be done with it. + good as it can all the data it should, and be done with it. */ void * enkf_state_load_from_forward_model_mt( void * arg ) { arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); enkf_state_type * enkf_state = enkf_state_safe_cast(arg_pack_iget_ptr( arg_pack , 0 )); run_arg_type * run_arg = arg_pack_iget_ptr( arg_pack , 1 ); - bool interactive = arg_pack_iget_bool( arg_pack , 2 ); + bool interactive = arg_pack_iget_bool( arg_pack , 2 ); stringlist_type * msg_list = arg_pack_iget_ptr( arg_pack , 3 ); bool manual_load = arg_pack_iget_bool( arg_pack , 4 ); int * result = arg_pack_iget_ptr( arg_pack , 5 ); - - int iens = run_arg_get_iens( run_arg ); - - if (manual_load) + + int iens = run_arg_get_iens( run_arg ); + + if (manual_load) state_map_update_undefined(enkf_fs_get_state_map( run_arg_get_result_fs(run_arg) ) , iens , STATE_INITIALIZED); - + enkf_state_load_from_forward_model( enkf_state , run_arg , result , interactive , msg_list ); if (*result & REPORT_STEP_INCOMPATIBLE) { // If refcase has been used for observations: crash and burn. fprintf(stderr,"** Warning the timesteps in refcase and current simulation are not in accordance - something wrong with schedule file?\n"); *result -= REPORT_STEP_INCOMPATIBLE; } - + if (interactive) { printf("."); fflush(stdout); - } + } return NULL; -} +} @@ -1204,7 +1204,7 @@ static void enkf_state_write_restart_file(enkf_state_type * enkf_state , const r for (ikw = 0; ikw < stringlist_get_size(enkf_state->restart_kw_list); ikw++) { kw = stringlist_iget( enkf_state->restart_kw_list , ikw); - /* + /* Observe that here we are *ONLY* iterating over the restart_kw_list instance, and *NOT* the enkf_state instance. I.e. arbitrary dynamic keys, and no-longer-active @@ -1212,26 +1212,26 @@ static void enkf_state_write_restart_file(enkf_state_type * enkf_state , const r If the restart kw_list asks for a keyword which we do not have, we assume it is a static keyword and add it it to the - enkf_state instance. - + enkf_state instance. + This is a bit unfortunate, because a bug/problem of some sort, might be masked (seemingly solved) by adding a static keyword, before things blow up completely at a later instant. - */ - if (!ensemble_config_has_key(enkf_state->ensemble_config , kw)) + */ + if (!ensemble_config_has_key(enkf_state->ensemble_config , kw)) ensemble_config_ensure_static_key(enkf_state->ensemble_config , kw ); - + if (!enkf_state_has_node(enkf_state , kw)) { const enkf_config_node_type * config_node = ensemble_config_get_node(enkf_state->ensemble_config , kw); - enkf_state_add_node(enkf_state , kw , config_node); + enkf_state_add_node(enkf_state , kw , config_node); } - + { - enkf_node_type * enkf_node = enkf_state_get_node(enkf_state , kw); - enkf_var_type var_type = enkf_node_get_var_type(enkf_node); + enkf_node_type * enkf_node = enkf_state_get_node(enkf_state , kw); + enkf_var_type var_type = enkf_node_get_var_type(enkf_node); if (var_type == STATIC_STATE) { - node_id_type node_id = {.report_step = run_arg_get_step1(run_arg) , - .iens = iens , + node_id_type node_id = {.report_step = run_arg_get_step1(run_arg) , + .iens = iens , .state = run_arg_get_dynamic_init_state(run_arg) }; enkf_node_load( enkf_node , fs , node_id); } @@ -1239,7 +1239,7 @@ static void enkf_state_write_restart_file(enkf_state_type * enkf_state , const r /* Pressure and saturations */ if (enkf_node_get_impl_type(enkf_node) == FIELD) enkf_node_ecl_write(enkf_node , NULL , fortio , run_arg_get_step1(run_arg)); - else + else util_abort("%s: internal error wrong implementetion type:%d - node:%s aborting \n",__func__ , enkf_node_get_impl_type(enkf_node) , enkf_node_get_key(enkf_node)); } else if (var_type == STATIC_STATE) { enkf_node_ecl_write(enkf_node , NULL , fortio , run_arg_get_step1(run_arg)); @@ -1249,7 +1249,7 @@ static void enkf_state_write_restart_file(enkf_state_type * enkf_state , const r fprintf(stderr,"node : %s \n",enkf_node_get_key(enkf_node)); util_abort("%s: internal error - should not be here ... \n",__func__); } - + } } fortio_fclose(fortio); @@ -1281,16 +1281,16 @@ void enkf_state_ecl_write(enkf_state_type * enkf_state, const run_arg_type * run stringlist_append_copy(enkf_state->restart_kw_list , "RV"); stringlist_append_copy(enkf_state->restart_kw_list , "RS"); } - + { - /** - This iteration manipulates the hash (thorugh the enkf_state_del_node() call) - + /** + This iteration manipulates the hash (thorugh the enkf_state_del_node() call) + ----------------------------------------------------------------------------------------- T H I S W I L L D E A D L O C K I F T H E H A S H _ I T E R A P I I S U S E D. ----------------------------------------------------------------------------------------- */ - + const shared_info_type * shared_info = enkf_state->shared_info; const model_config_type * model_config = shared_info->model_config; const char * base_name = model_config_get_gen_kw_export_file(model_config); @@ -1310,8 +1310,8 @@ void enkf_state_ecl_write(enkf_state_type * enkf_state, const run_arg_type * run bool forward_init = enkf_node_use_forward_init( enkf_node ); if ((run_arg_get_step1(run_arg) == 0) && (forward_init)) { - node_id_type node_id = {.report_step = 0, - .iens = iens , + node_id_type node_id = {.report_step = 0, + .iens = iens , .state = ANALYZED }; if (enkf_node_has_data( enkf_node , fs , node_id)) @@ -1333,7 +1333,7 @@ void enkf_state_ecl_write(enkf_state_type * enkf_state, const run_arg_type * run /** This function takes a report_step and a analyzed|forecast state as input; the enkf_state instance is set accordingly and written to - disk. + disk. */ @@ -1342,14 +1342,14 @@ void enkf_state_fwrite(const enkf_state_type * enkf_state , enkf_fs_type * fs , const int num_keys = hash_get_size(enkf_state->node_hash); char ** key_list = hash_alloc_keylist(enkf_state->node_hash); int ikey; - + for (ikey = 0; ikey < num_keys; ikey++) { enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_include_type(enkf_node , mask)) { + if (enkf_node_include_type(enkf_node , mask)) { node_id_type node_id = {.report_step = report_step , .iens = member_config_get_iens( my_config ) , .state = state }; enkf_node_store( enkf_node, fs , true , node_id ); } - } + } util_free_stringlist(key_list , num_keys); } @@ -1363,8 +1363,8 @@ void enkf_state_fread(enkf_state_type * enkf_state , enkf_fs_type * fs , int mas for (ikey = 0; ikey < num_keys; ikey++) { enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); if (enkf_node_include_type(enkf_node , mask)) { - node_id_type node_id = {.report_step = report_step , - .iens = member_config_get_iens( my_config ) , + node_id_type node_id = {.report_step = report_step , + .iens = member_config_get_iens( my_config ) , .state = state }; bool forward_init = enkf_node_use_forward_init( enkf_node ); if (forward_init) @@ -1391,7 +1391,7 @@ static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_ int ikey; - /* + /* First pass - load all the STATIC nodes. It is essential to use the restart_kw_list when loading static nodes, otherwise static nodes which were only present at e.g. step == 0 will create @@ -1410,7 +1410,7 @@ static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_ The restart_kw_list mentions a keyword which is (not yet) part of the enkf_state object. This is assumed to be a static keyword and added as such. - + This will break hard for the following situation: 1. Someone has simulated with a dynamic keyword (i.e. field @@ -1425,7 +1425,7 @@ static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_ (or node not found); hopefully this scenario is not very probable. */ - + /* add the config node. */ if (!ensemble_config_has_key( enkf_state->ensemble_config , key)) ensemble_config_ensure_static_key( enkf_state->ensemble_config , key); @@ -1433,15 +1433,15 @@ static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_ /* Add the state node */ if (!enkf_state_has_node( enkf_state , key )) { const enkf_config_node_type * config_node = ensemble_config_get_node(enkf_state->ensemble_config , key); - enkf_state_add_node(enkf_state , key , config_node); + enkf_state_add_node(enkf_state , key , config_node); } - + enkf_node = hash_get(enkf_state->node_hash , key); var_type = enkf_node_get_var_type( enkf_node ); - + if (var_type == STATIC_STATE) { - node_id_type node_id = { .report_step = report_step , - .iens = iens , + node_id_type node_id = { .report_step = report_step , + .iens = iens , .state = load_state }; enkf_node_load( enkf_node , fs , node_id); } @@ -1453,25 +1453,25 @@ static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_ const int num_keys = hash_get_size(enkf_state->node_hash); char ** key_list = hash_alloc_keylist(enkf_state->node_hash); int ikey; - + for (ikey = 0; ikey < num_keys; ikey++) { enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); enkf_var_type var_type = enkf_node_get_var_type( enkf_node ); - node_id_type node_id = {.report_step = report_step , - .iens = iens , + node_id_type node_id = {.report_step = report_step , + .iens = iens , .state = BOTH }; - + if (var_type == DYNAMIC_STATE) { - /* + /* Here the enkf_node_try_load() function is used NOT because we accept that the node is not present, but because the try_fread() function accepts the BOTH state type. */ - if (!enkf_node_try_load(enkf_node , fs , node_id)) + if (!enkf_node_try_load(enkf_node , fs , node_id)) util_abort("%s: failed to load node:%s report_step:%d iens:%d \n",__func__ , key_list[ikey] , report_step , iens ); } } - util_free_stringlist(key_list , num_keys); + util_free_stringlist(key_list , num_keys); } } @@ -1490,7 +1490,7 @@ static void enkf_state_fread_initial_state(enkf_state_type * enkf_state , enkf_f const int num_keys = hash_get_size(enkf_state->node_hash); char ** key_list = hash_alloc_keylist(enkf_state->node_hash); int ikey; - + for (ikey = 0; ikey < num_keys; ikey++) { enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); if (enkf_node_get_var_type(enkf_node) == DYNAMIC_STATE) { @@ -1499,15 +1499,15 @@ static void enkf_state_fread_initial_state(enkf_state_type * enkf_state , enkf_f /* Just checked for != NULL */ char * load_file = enkf_config_node_alloc_infile( config_node , 0); if (load_file != NULL) { - node_id_type node_id = {.report_step = 0 , - .iens = member_config_get_iens( my_config ) , + node_id_type node_id = {.report_step = 0 , + .iens = member_config_get_iens( my_config ) , .state = ANALYZED }; enkf_node_load(enkf_node , fs , node_id); } - + util_safe_free( load_file ); } - } + } util_free_stringlist(key_list , num_keys); } @@ -1516,16 +1516,16 @@ void enkf_state_free_nodes(enkf_state_type * enkf_state, int mask) { const int num_keys = hash_get_size(enkf_state->node_hash); char ** key_list = hash_alloc_keylist(enkf_state->node_hash); int ikey; - + for (ikey = 0; ikey < num_keys; ikey++) { enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_include_type(enkf_node , mask)) + if (enkf_node_include_type(enkf_node , mask)) enkf_state_del_node(enkf_state , enkf_node_get_key(enkf_node)); - } + } util_free_stringlist(key_list , num_keys); } - + @@ -1555,9 +1555,9 @@ enkf_node_type * enkf_state_get_node(const enkf_state_type * enkf_state , const void enkf_state_del_node(enkf_state_type * enkf_state , const char * node_key) { - if (hash_has_key(enkf_state->node_hash , node_key)) + if (hash_has_key(enkf_state->node_hash , node_key)) hash_del(enkf_state->node_hash , node_key); - else + else fprintf(stderr,"%s: tried to remove node:%s which is not in state - internal error?? \n",__func__ , node_key); } @@ -1591,14 +1591,14 @@ static void enkf_state_set_dynamic_subst_kw__(enkf_state_type * enkf_state , con enkf_state_add_subst_kw(enkf_state , "TSTEP2" , step2_s , NULL); enkf_state_add_subst_kw(enkf_state , "TSTEP1_04" , step1_s04 , NULL); enkf_state_add_subst_kw(enkf_state , "TSTEP2_04" , step2_s04 , NULL); - + free(step1_s); free(step2_s); free(step1_s04); free(step2_s04); } - + /* Restart file names and RESTART keyword in datafile. */ { const char * eclbase = member_config_get_eclbase( enkf_state->my_config ); @@ -1606,10 +1606,10 @@ static void enkf_state_set_dynamic_subst_kw__(enkf_state_type * enkf_state , con { char * restart_file1 = ecl_util_alloc_filename(NULL , eclbase , ECL_RESTART_FILE , fmt_file , step1); char * restart_file2 = ecl_util_alloc_filename(NULL , eclbase , ECL_RESTART_FILE , fmt_file , step2); - + enkf_state_add_subst_kw(enkf_state , "RESTART_FILE1" , restart_file1 , NULL); enkf_state_add_subst_kw(enkf_state , "RESTART_FILE2" , restart_file2 , NULL); - + free(restart_file1); free(restart_file2); } @@ -1631,25 +1631,25 @@ static void enkf_state_set_dynamic_subst_kw__(enkf_state_type * enkf_state , con char * tmp_include = util_alloc_sprintf("INCLUDE\n \'%s\' /\n",init_file); enkf_state_add_subst_kw(enkf_state , "INIT" , tmp_include , NULL); free(tmp_include); - } /* - if init_file == NULL that means the user has not supplied the INIT_SECTION keyword, + } /* + if init_file == NULL that means the user has not supplied the INIT_SECTION keyword, and the EQUIL (or whatever) info to initialize the model is inlined in the datafile. */ - } - - + } + + { - /** + /** Adding keys for and - these are only added for backwards compatibility, should be replaced with prober function callbacks. */ char * randint_value = util_alloc_sprintf( "%u" , rng_forward( enkf_state->rng )); char * randfloat_value = util_alloc_sprintf( "%12.10f" , rng_get_double( enkf_state->rng )); - + enkf_state_add_subst_kw( enkf_state , "RANDINT" , randint_value , NULL); enkf_state_add_subst_kw( enkf_state , "RANDFLOAT" , randfloat_value , NULL); - + free( randint_value ); free( randfloat_value ); } @@ -1674,14 +1674,14 @@ void enkf_state_printf_subst_list(enkf_state_type * enkf_state , int step1 , int const char * key = subst_list_iget_key( enkf_state->subst_list , ikw); const char * value = subst_list_iget_value( enkf_state->subst_list , ikw); const char * desc = subst_list_iget_doc_string( enkf_state->subst_list , ikw ); - + if (value != NULL) printf(fmt_string , key , value , desc); else printf(fmt_string , key , "[Not set]" , desc); } printf("------------------------------------------------------------------------------------------------------------------------\n"); - + } @@ -1689,7 +1689,7 @@ void enkf_state_printf_subst_list(enkf_state_type * enkf_state , int step1 , int /** init_step : The parameters are loaded from this EnKF/report step. - report_step1 : The simulation should start from this report step; + report_step1 : The simulation should start from this report step; dynamic data are loaded from this step. report_step2 : The simulation should stop at this report step. (unless run_mode == ENSEMBLE_PREDICTION - where it just runs til end.) @@ -1702,10 +1702,10 @@ void enkf_state_printf_subst_list(enkf_state_type * enkf_state , int step1 , int void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * run_arg ) { - const member_config_type * my_config = enkf_state->my_config; + const member_config_type * my_config = enkf_state->my_config; const ecl_config_type * ecl_config = enkf_state->shared_info->ecl_config; { - if (member_config_pre_clear_runpath( my_config )) + if (member_config_pre_clear_runpath( my_config )) util_clear_directory( run_arg_get_runpath( run_arg ) , true , false ); util_make_path(run_arg_get_runpath( run_arg )); @@ -1721,7 +1721,7 @@ void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * r sched_file_fprintf_i( ecl_config_get_sched_file( ecl_config ) , run_arg_get_step2(run_arg) , schedule_file_target); else sched_file_fprintf( ecl_config_get_sched_file( ecl_config ) , schedule_file_target); - + free(schedule_file_target); } } @@ -1735,20 +1735,20 @@ void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * r enkf_fs_type * init_fs = run_arg_get_init_fs( run_arg ); /* Loading parameter information: loaded from timestep: run_arg->init_step_parameters. */ enkf_state_fread(enkf_state , init_fs , PARAMETER , run_arg_get_parameter_init_step(run_arg) , run_arg_get_parameter_init_state(run_arg)); - - + + /* Loading state information: loaded from timestep: run_arg->step1 */ if (run_arg_get_step1(run_arg) == 0) - enkf_state_fread_initial_state(enkf_state , init_fs); + enkf_state_fread_initial_state(enkf_state , init_fs); else enkf_state_fread_state_nodes( enkf_state , init_fs , run_arg_get_step1(run_arg) , run_arg_get_dynamic_init_state(run_arg)); enkf_state_set_dynamic_subst_kw( enkf_state , run_arg ); ert_templates_instansiate( enkf_state->shared_info->templates , run_arg_get_runpath( run_arg ) , enkf_state->subst_list ); enkf_state_ecl_write( enkf_state , run_arg , init_fs); - + if (member_config_get_eclbase( my_config ) != NULL) { - + /* Writing the ECLIPSE data file. */ if (ecl_config_get_data_file( ecl_config ) != NULL) { char * data_file = ecl_util_alloc_filename(run_arg_get_runpath( run_arg ) , member_config_get_eclbase( my_config ) , ECL_DATA_FILE , true , -1); @@ -1774,14 +1774,14 @@ bool enkf_state_complete_forward_modelEXIT__(void * arg ); bool enkf_state_complete_forward_modelRETRY__(void * arg ); -/** +/** This function is called when: 1. The external queue system has said that everything is OK; BUT the ert layer failed to load all the data. - + 2. The external queue system has seen the job fail. - + The parameter and state variables will be resampled before retrying. And all random elements in templates+++ will be resampled. @@ -1798,7 +1798,7 @@ static void enkf_state_internal_retry(enkf_state_type * enkf_state , run_arg_typ ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d - %04d] Failed to load all data.",iens , run_arg_get_step1(run_arg) , run_arg_get_step2(run_arg)); else ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d - %04d] Forward model failed.",iens, run_arg_get_step1(run_arg) , run_arg_get_step2(run_arg)); - + if (run_arg_can_retry( run_arg ) ) { ert_log_add_fmt_message( 1 , NULL , "[%03d] Resampling and resubmitting realization." ,iens); { @@ -1810,11 +1810,11 @@ static void enkf_state_internal_retry(enkf_state_type * enkf_state , run_arg_typ } stringlist_free( init_keys ); } - + enkf_state_init_eclipse( enkf_state , run_arg ); /* Possibly clear the directory and do a FULL rewrite of ALL the necessary files. */ job_queue_iset_external_restart( shared_info->job_queue , run_arg_get_queue_index(run_arg) ); /* Here we inform the queue system that it should pick up this job and try again. */ run_arg_increase_submit_count( run_arg ); - } + } } @@ -1848,16 +1848,16 @@ static void enkf_state_clear_runpath( const enkf_state_type * enkf_state , run_a unlink_runpath = false; /* Compiler .. */ } } - + if (unlink_runpath) util_clear_directory(run_arg_get_runpath( run_arg ) , true , true); } -/** +/** Observe that if run_arg == false, this routine will return with job_completeOK == true, that might be a bit misleading. - + Observe that if an internal retry is performed, this function will be called several times - MUST BE REENTRANT. */ @@ -1865,9 +1865,9 @@ static void enkf_state_clear_runpath( const enkf_state_type * enkf_state , run_a static bool enkf_state_complete_forward_modelOK(enkf_state_type * enkf_state , run_arg_type * run_arg) { const member_config_type * my_config = enkf_state->my_config; const int iens = member_config_get_iens( my_config ); - int result = 0; + int result = 0; + - /** The queue system has reported that the run is OK, i.e. it has completed and produced the targetfile it should. We then check @@ -1875,15 +1875,15 @@ static bool enkf_state_complete_forward_modelOK(enkf_state_type * enkf_state , r is OK the final status is updated, otherwise: restart. */ ert_log_add_fmt_message( 2 , NULL , "[%03d:%04d-%04d] Forward model complete - starting to load results." , iens , run_arg_get_step1(run_arg), run_arg_get_step2(run_arg)); - enkf_state_load_from_forward_model(enkf_state , run_arg , &result , false , NULL); - + enkf_state_load_from_forward_model(enkf_state , run_arg , &result , false , NULL); + if (result & REPORT_STEP_INCOMPATIBLE) { // If refcase has been used for observations: crash and burn. fprintf(stderr,"** Warning the timesteps in refcase and current simulation are not in accordance - something wrong with schedule file?\n"); result -= REPORT_STEP_INCOMPATIBLE; } - - + + if (0 == result) { /* The loading succeded - so this is a howling success! We set @@ -1893,11 +1893,11 @@ static bool enkf_state_complete_forward_modelOK(enkf_state_type * enkf_state , r */ run_arg_set_run_status( run_arg , JOB_RUN_OK); ert_log_add_fmt_message( 2 , NULL , "[%03d:%04d-%04d] Results loaded successfully." , iens , run_arg_get_step1(run_arg), run_arg_get_step2(run_arg)); - + enkf_state_clear_runpath( enkf_state , run_arg ); run_arg_complete_run(run_arg); /* free() on runpath */ - } - return (0 == result) ? true : false; + } + return (0 == result) ? true : false; } @@ -1905,7 +1905,7 @@ bool enkf_state_complete_forward_modelOK__(void * arg ) { arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); enkf_state_type * enkf_state = enkf_state_safe_cast( arg_pack_iget_ptr( arg_pack , 0 )); run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1 )); - + return enkf_state_complete_forward_modelOK( enkf_state , run_arg); } @@ -1914,12 +1914,12 @@ bool enkf_state_complete_forward_modelOK__(void * arg ) { static bool enkf_state_complete_forward_model_EXIT_handler__(enkf_state_type * enkf_state , run_arg_type * run_arg , bool is_retry) { const member_config_type * my_config = enkf_state->my_config; const int iens = member_config_get_iens( my_config ); - /* + /* The external queue system has said that the job failed - we might give it another try from this scope, possibly involving a resampling. */ - + if (is_retry) { if (run_arg_can_retry(run_arg)) { enkf_state_internal_retry(enkf_state, run_arg , false); @@ -1942,10 +1942,10 @@ static bool enkf_state_complete_forward_model_EXIT_handler__(enkf_state_type * e static bool enkf_state_complete_forward_model_EXIT_handler(void * arg, bool allow_retry ) { arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - + enkf_state_type * enkf_state = arg_pack_iget_ptr( arg_pack , 0 ); run_arg_type * run_arg = arg_pack_iget_ptr( arg_pack , 1 ); - + return enkf_state_complete_forward_model_EXIT_handler__( enkf_state , run_arg , allow_retry ); } diff --git a/ThirdParty/Ert/devel/libenkf/src/local_config.c b/ThirdParty/Ert/devel/libenkf/src/local_config.c index b885f1ba39..2930e0ee94 100644 --- a/ThirdParty/Ert/devel/libenkf/src/local_config.c +++ b/ThirdParty/Ert/devel/libenkf/src/local_config.c @@ -60,11 +60,10 @@ ministep to the updatestep, otherwise it will not be able to do anything. -CREATE_MINISTEP [NAME_OF_MINISTEP OBSSET_NAME] +CREATE_MINISTEP [NAME_OF_MINISTEP] ----------------------------------------------- This function will create a new ministep with the name -'NAME_OF_MINISTEP'. The ministep will be based on the observation -set given by OBSSET_NAME (which must be created first).The ministep +'NAME_OF_MINISTEP'. A given OBSSET can be attached to a given ministep.The ministep is then ready for adding data. Before the ministep can be used you must attach it to an updatestep with the ATTACH_MINISTEP command @@ -147,7 +146,7 @@ This function will delete the obs 'OBS_KEY' from the obsset DATASET_DEL_ALL_DATA [NAME_OF_DATASET] -------------------------------------- This function will delete all the data keys from the dataset -'NAME_OF_MINISTEP'. +'NAME_OF_DATASET'. OBSSET_DEL_ALL_OBS [NAME_OF_OBSSET] @@ -171,26 +170,13 @@ with name 'DATASTEP_NAME' should have the index 'INDEX' active. ACTIVE_LIST_ADD_MANY_OBS_INDEX[OBSSET_NAME OBS_KEY N INDEX1 INDEX2 INDEX3 .. INDEXN] ---------------------------------------------------------------------------------------- -This function is simular to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices. +This function is similar to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices. ACTIVE_LIST_ADD_MANY_DATA_INDEX[DATA_NAME DATA_KEY N INDEX1 INDEX2 INDEX3 .. INDEXN] ------------------------------------------------------------------------------------------ -This function is simular to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices. - - -INSTALL_UPDATESTEP [NAME_OF_UPDATESTEP STEP1 STEP2] ----------------------------------------------------- -This function will install the updatestep 'NAME_OF_UPDATESTEP' for the -report steps [STEP1,..,STEP2]. - - -INSTALL_DEFAULT_UPDATESTEP [NAME_OF_UPDATESTEP] ------------------------------------------------ -This function will install 'NAME_OF_UPDATESTEP' as the default -updatestep which applies to all report streps where you have not -explicitly set another updatestep with the INSTALL_UPDATESTEP function. +This function is similar to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices. @@ -522,7 +508,6 @@ core EnKF updating: struct local_config_struct { - vector_type * updatestep; /* This is an indexed vector with (pointers to) local_reportsstep instances. */ local_updatestep_type * default_updatestep; /* A default report step returned if no particular report step has been installed for this time index. */ hash_type * updatestep_storage; /* These three hash tables are the 'holding area' for the local_updatestep, */ hash_type * ministep_storage; /* local_ministep instances. */ @@ -532,13 +517,26 @@ struct local_config_struct { }; -static void local_config_clear( local_config_type * local_config ) { +/** + Instances of local_updatestep and local_ministep are allocated from + the local_config object, and then subsequently manipulated from the calling scope. +*/ + +static local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ) { + local_updatestep_type * updatestep = local_updatestep_alloc( key ); + hash_insert_hash_owned_ref( local_config->updatestep_storage , key , updatestep , local_updatestep_free__); + return updatestep; +} + + + +void local_config_clear( local_config_type * local_config ) { local_config->default_updatestep = NULL; hash_clear( local_config->updatestep_storage ); hash_clear( local_config->ministep_storage ); hash_clear( local_config->dataset_storage ); hash_clear( local_config->obsdata_storage ); - vector_clear( local_config->updatestep ); + local_config->default_updatestep = local_config_alloc_updatestep(local_config, "DEFAULT"); } @@ -552,7 +550,6 @@ local_config_type * local_config_alloc( ) { local_config->ministep_storage = hash_alloc(); local_config->dataset_storage = hash_alloc(); local_config->obsdata_storage = hash_alloc(); - local_config->updatestep = vector_alloc_new(); local_config->config_files = stringlist_alloc_new(); local_config_clear( local_config ); @@ -561,7 +558,6 @@ local_config_type * local_config_alloc( ) { void local_config_free(local_config_type * local_config) { - vector_free( local_config->updatestep ); hash_free( local_config->updatestep_storage ); hash_free( local_config->ministep_storage); hash_free( local_config->dataset_storage); @@ -571,32 +567,12 @@ void local_config_free(local_config_type * local_config) { -/** - Actual report step must have been installed in the - updatestep_storage with local_config_alloc_updatestep() first. -*/ - -void local_config_set_default_updatestep( local_config_type * local_config , const char * default_key) { - local_updatestep_type * default_updatestep = local_config_get_updatestep( local_config , default_key ); - local_config->default_updatestep = default_updatestep; -} -/** - Instances of local_updatestep and local_ministep are allocated from - the local_config object, and then subsequently manipulated from the calling scope. -*/ - -local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ) { - local_updatestep_type * updatestep = local_updatestep_alloc( key ); - hash_insert_hash_owned_ref( local_config->updatestep_storage , key , updatestep , local_updatestep_free__); - return updatestep; -} -local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key , const char * obsset_name) { - local_obsdata_type * obsdata = hash_get( local_config->obsdata_storage , obsset_name ); - local_ministep_type * ministep = local_ministep_alloc( key , obsdata ); +local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key) { + local_ministep_type * ministep = local_ministep_alloc( key ); hash_insert_hash_owned_ref( local_config->ministep_storage , key , ministep , local_ministep_free__); return ministep; } @@ -608,7 +584,6 @@ local_obsdata_type * local_config_alloc_obsset( local_config_type * local_config } - local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key ) { local_dataset_type * dataset = local_dataset_alloc( key ); hash_insert_hash_owned_ref( local_config->dataset_storage , key , dataset , local_dataset_free__); @@ -664,14 +639,8 @@ local_ministep_type * local_config_alloc_ministep_copy( local_config_type * loca -const local_updatestep_type * local_config_iget_updatestep( const local_config_type * local_config , int index) { - const local_updatestep_type * updatestep = vector_safe_iget_const( local_config->updatestep , index ); - if (updatestep == NULL) - /* - No particular report step has been installed for this - time-index, revert to the default. - */ - updatestep = local_config->default_updatestep; +local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config) { + local_updatestep_type * updatestep = local_config->default_updatestep; if (updatestep == NULL) util_exit("%s: fatal error. No report step information for step:%d - and no default \n",__func__ , index); @@ -680,27 +649,6 @@ const local_updatestep_type * local_config_iget_updatestep( const local_config_t } -local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config , const char * key) { - return hash_get( local_config->updatestep_storage , key ); -} - - -/** - This will 'install' the updatestep instance identified with 'key' - for report steps [step1,step2]. Observe that the report step must - have been allocated with 'local_config_alloc_updatestep()' first. -*/ - - -void local_config_set_updatestep(local_config_type * local_config, int step1 , int step2 , const char * key) { - local_updatestep_type * updatestep = hash_get( local_config->updatestep_storage , key ); - int step; - - for ( step = step1; step < step2 + 1; step++) - vector_safe_iset_ref(local_config->updatestep , step , updatestep ); - -} - /*******************************************************************/ /* Functions related to loading a local config instance from disk. */ @@ -739,6 +687,9 @@ const char * local_config_get_cmd_string( local_config_instruction_type cmd ) { case(CREATE_OBSSET): return CREATE_OBSSET_STRING; break; + case(ATTACH_OBSSET): + return ATTACH_OBSSET_STRING; + break; case(ADD_DATA): return ADD_DATA_STRING; break; @@ -757,12 +708,6 @@ const char * local_config_get_cmd_string( local_config_instruction_type cmd ) { case(ACTIVE_LIST_ADD_MANY_DATA_INDEX): return ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING; break; - case(INSTALL_UPDATESTEP): - return INSTALL_UPDATESTEP_STRING; - break; - case(INSTALL_DEFAULT_UPDATESTEP): - return INSTALL_DEFAULT_UPDATESTEP_STRING; - break; case(DEL_DATA): return DEL_DATA_STRING; break; @@ -947,12 +892,11 @@ static void local_config_init_cmd_table( hash_type * cmd_table ) { hash_insert_int(cmd_table , CREATE_OBSSET_STRING , CREATE_OBSSET); hash_insert_int(cmd_table , ADD_DATA_STRING , ADD_DATA); hash_insert_int(cmd_table , ADD_OBS_STRING , ADD_OBS ); + hash_insert_int(cmd_table , ATTACH_OBSSET_STRING , ATTACH_OBSSET); hash_insert_int(cmd_table , ACTIVE_LIST_ADD_OBS_INDEX_STRING , ACTIVE_LIST_ADD_OBS_INDEX); hash_insert_int(cmd_table , ACTIVE_LIST_ADD_DATA_INDEX_STRING , ACTIVE_LIST_ADD_DATA_INDEX); hash_insert_int(cmd_table , ACTIVE_LIST_ADD_MANY_OBS_INDEX_STRING , ACTIVE_LIST_ADD_MANY_OBS_INDEX); hash_insert_int(cmd_table , ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING , ACTIVE_LIST_ADD_MANY_DATA_INDEX); - hash_insert_int(cmd_table , INSTALL_UPDATESTEP_STRING , INSTALL_UPDATESTEP); - hash_insert_int(cmd_table , INSTALL_DEFAULT_UPDATESTEP_STRING , INSTALL_DEFAULT_UPDATESTEP); hash_insert_int(cmd_table , DEL_DATA_STRING , DEL_DATA); hash_insert_int(cmd_table , DEL_OBS_STRING , DEL_OBS); hash_insert_int(cmd_table , COPY_DATASET_STRING , COPY_DATASET); @@ -990,10 +934,8 @@ static void local_config_CREATE_UPDATESTEP( local_config_type * config , local_c static void local_config_CREATE_MINISTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { char * mini_name = read_alloc_string( stream , binary ); - char * obs_name = read_alloc_string( stream , binary ); - local_config_alloc_ministep( config , mini_name , obs_name ); + local_config_alloc_ministep( config , mini_name ); free( mini_name ); - free( obs_name ); } @@ -1009,7 +951,7 @@ static void local_config_ATTACH_MINISTEP( local_config_type * config , local_con char * update_name = read_alloc_string( stream , binary ); char * mini_name = read_alloc_string( stream , binary ); { - local_updatestep_type * update = local_config_get_updatestep( config , update_name ); + local_updatestep_type * update = local_config_get_updatestep( config ); local_ministep_type * ministep = local_config_get_ministep( config , mini_name ); local_updatestep_add_ministep( update , ministep ); } @@ -1054,6 +996,18 @@ static void local_config_ATTACH_DATASET( local_config_type * config , local_cont free( dataset_name ); } +static void local_config_ATTACH_OBSSET( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { + char * mini_name = read_alloc_string( stream , binary ); + char * obsset_name = read_alloc_string( stream , binary ); + { + local_ministep_type * ministep = local_config_get_ministep( config , mini_name ); + local_obsdata_type * obsdata = hash_get( config->obsdata_storage , obsset_name ); + local_ministep_add_obsdata(ministep, obsdata); + } + free( mini_name ); + free( obsset_name ); +} + static void local_config_ADD_DATA( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { char * dataset_name = read_alloc_string( stream , binary ); char * data_key = read_alloc_string( stream , binary ); @@ -1158,23 +1112,7 @@ static void local_config_ACTIVE_LIST_ADD_MANY_DATA_INDEX( local_config_type * co int_vector_free( int_vector ); } -static void local_config_INSTALL_UPDATESTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { - char * update_name = read_alloc_string( stream , binary ); - { - int step1,step2; - step1 = read_int( stream , binary ); - step2 = read_int( stream , binary ); - local_config_set_updatestep( config , step1 , step2 , update_name ); - } - free( update_name ); -} - -static void local_config_INSTALL_DEFAULT_UPDATESTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { - char * update_name = read_alloc_string( stream , binary ); - local_config_set_default_updatestep( config , update_name ); - free( update_name ); -} static void local_config_DEL_DATA( local_config_type * config , local_context_type * context , FILE * stream , bool binary) { char * dataset_name = read_alloc_string( stream , binary ); @@ -1606,6 +1544,9 @@ static void local_config_load_file( local_config_type * local_config , case(ATTACH_DATASET): local_config_ATTACH_DATASET( local_config , context , stream , binary ); break; + case(ATTACH_OBSSET): + local_config_ATTACH_OBSSET( local_config , context , stream , binary ); + break; case(ADD_DATA): local_config_ADD_DATA( local_config , context , stream , binary ); break; @@ -1624,12 +1565,6 @@ static void local_config_load_file( local_config_type * local_config , case(ACTIVE_LIST_ADD_MANY_DATA_INDEX): local_config_ACTIVE_LIST_ADD_MANY_DATA_INDEX( local_config , context , stream , binary ); break; - case(INSTALL_UPDATESTEP): - local_config_INSTALL_UPDATESTEP( local_config , context , stream , binary ); - break; - case(INSTALL_DEFAULT_UPDATESTEP): - local_config_INSTALL_DEFAULT_UPDATESTEP( local_config , context , stream , binary ); - break; case(DEL_DATA): local_config_DEL_DATA( local_config , context , stream , binary ); break; @@ -1729,7 +1664,33 @@ void local_config_reload( local_config_type * local_config , void local_config_fprintf( const local_config_type * local_config , const char * config_file) { FILE * stream = util_mkdir_fopen( config_file , "w"); - /* Start with dumping all the ministep instances. */ + + /* Write DATASET. */ + { + hash_iter_type * hash_iter = hash_iter_alloc( local_config->dataset_storage ); + + while (!hash_iter_is_complete( hash_iter )) { + const local_dataset_type * dataset = hash_iter_get_next_value( hash_iter ); + local_dataset_fprintf( dataset , stream ); + } + + hash_iter_free( hash_iter ); + } + + /* Write OBSDATA. */ + { + hash_iter_type * hash_iter = hash_iter_alloc( local_config->obsdata_storage ); + + while (!hash_iter_is_complete( hash_iter )) { + const local_obsdata_type * obsdata = hash_iter_get_next_value( hash_iter ); + local_obsdata_fprintf( obsdata , stream ); + } + + hash_iter_free( hash_iter ); + } + + + /* Write MINISTEP. */ { hash_iter_type * hash_iter = hash_iter_alloc( local_config->ministep_storage ); @@ -1742,37 +1703,36 @@ void local_config_fprintf( const local_config_type * local_config , const char * } - /* Dumping all the reportstep instances as ATTACH_MINISTEP commands. */ + /* Write UPDATESTEP */ + if (local_config->default_updatestep) + local_updatestep_fprintf( local_config->default_updatestep , stream ); + + fclose( stream ); +} + +void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file) { + + FILE * stream = util_mkdir_fopen( config_file , "w"); + + const local_updatestep_type * updatestep = local_config_get_updatestep( local_config ); // There is only one update step, the default { - hash_iter_type * hash_iter = hash_iter_alloc( local_config->updatestep_storage ); + hash_iter_type * hash_iter = hash_iter_alloc( local_config->ministep_storage ); while (!hash_iter_is_complete( hash_iter )) { - const local_updatestep_type * updatestep = hash_iter_get_next_value( hash_iter ); - local_updatestep_fprintf( updatestep , stream ); + const local_ministep_type * ministep = hash_iter_get_next_value( hash_iter ); + + fprintf(stream , "UPDATE_STEP:%s,", local_updatestep_get_name(updatestep)); + + local_ministep_summary_fprintf( ministep , stream); + } hash_iter_free( hash_iter ); } - /* Writing out the updatestep / time */ - { - int i; - for (i=0; i < vector_get_size( local_config->updatestep ); i++) { - const local_updatestep_type * updatestep = vector_iget_const( local_config->updatestep , i ); - if (updatestep != NULL) - fprintf(stream , "%s %s %d %d \n", local_config_get_cmd_string( INSTALL_UPDATESTEP ) , local_updatestep_get_name( updatestep ) , i , i ); - } - } - - /* Installing the default updatestep */ - if (local_config->default_updatestep != NULL) - fprintf(stream , "%s %s\n", local_config_get_cmd_string( INSTALL_DEFAULT_UPDATESTEP ) , local_updatestep_get_name( local_config->default_updatestep )); - fclose( stream ); } - - void local_config_fprintf_config( const local_config_type * local_config , FILE * stream) { fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes the config files used for setting up local analysis."); diff --git a/ThirdParty/Ert/devel/libenkf/src/local_dataset.c b/ThirdParty/Ert/devel/libenkf/src/local_dataset.c index aa29cf4040..e1351242e9 100644 --- a/ThirdParty/Ert/devel/libenkf/src/local_dataset.c +++ b/ThirdParty/Ert/devel/libenkf/src/local_dataset.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_nodeset.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'local_dataset.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -93,6 +93,10 @@ void local_dataset_add_node(local_dataset_type * dataset, const char *node_key) hash_insert_hash_owned_ref( dataset->nodes , node_key , active_list_alloc( ALL_ACTIVE ) , active_list_free__); } +bool local_dataset_has_key(const local_dataset_type * dataset, const char * key) { + return hash_has_key( dataset->nodes , key ); +} + void local_dataset_del_node( local_dataset_type * dataset , const char * node_key) { hash_del( dataset->nodes , node_key ); @@ -114,17 +118,33 @@ stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset ) void local_dataset_fprintf( const local_dataset_type * dataset , FILE * stream) { + fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_DATASET ), local_dataset_get_name(dataset)); + { hash_iter_type * data_iter = hash_iter_alloc( dataset->nodes ); while (!hash_iter_is_complete( data_iter )) { const char * data_key = hash_iter_get_next_key( data_iter ); active_list_type * active_list = hash_get( dataset->nodes , data_key ); - + fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ADD_DATA ) , dataset->name , data_key ); - active_list_fprintf( active_list , false , data_key , stream ); + active_list_fprintf( active_list , local_dataset_get_name(dataset) , data_key , stream ); } hash_iter_free( data_iter ); + } } +void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream) { +{ + hash_iter_type * data_iter = hash_iter_alloc( dataset->nodes ); + while (!hash_iter_is_complete( data_iter )) { + const char * data_key = hash_iter_get_next_key( data_iter ); + fprintf(stream , "NAME OF DATA:%s,", data_key ); + + active_list_type * active_list = hash_get( dataset->nodes , data_key ); + active_list_summary_fprintf( active_list , local_dataset_get_name(dataset) , data_key , stream); + } + hash_iter_free( data_iter ); + } +} int local_dataset_get_size( const local_dataset_type * dataset ) { diff --git a/ThirdParty/Ert/devel/libenkf/src/local_ministep.c b/ThirdParty/Ert/devel/libenkf/src/local_ministep.c index e96d226ca2..345d67eb78 100644 --- a/ThirdParty/Ert/devel/libenkf/src/local_ministep.c +++ b/ThirdParty/Ert/devel/libenkf/src/local_ministep.c @@ -28,6 +28,7 @@ #include #include #include +#include /** This file implements a 'ministep' configuration for active / @@ -65,11 +66,18 @@ struct local_ministep_struct { UTIL_SAFE_CAST_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID) UTIL_IS_INSTANCE_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID) -local_ministep_type * local_ministep_alloc(const char * name , local_obsdata_type * observations) { +local_ministep_type * local_ministep_alloc(const char * name) { local_ministep_type * ministep = util_malloc( sizeof * ministep ); ministep->name = util_alloc_string_copy( name ); - ministep->observations = observations; + + char* obsdata_name = "OBSDATA_"; + char* result = malloc(strlen(obsdata_name)+strlen(name)+1); + strcpy(result, obsdata_name); + strcat(result, name); + ministep->observations = local_obsdata_alloc(result); + + ministep->datasets = hash_alloc(); UTIL_TYPE_ID_INIT( ministep , LOCAL_MINISTEP_TYPE_ID); @@ -106,6 +114,7 @@ local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src void local_ministep_free(local_ministep_type * ministep) { free(ministep->name); hash_free( ministep->datasets ); + local_obsdata_free(ministep->observations); free( ministep ); } @@ -135,7 +144,31 @@ void local_ministep_add_dataset( local_ministep_type * ministep , const local_da hash_insert_ref( ministep->datasets , local_dataset_get_name( dataset ) , dataset ); } +void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata) { + if (ministep->observations == NULL) + ministep->observations = obsdata; + else { // Add nodes from input observations to existing observations + int iobs; + for (iobs = 0; iobs < local_obsdata_get_size( obsdata ); iobs++) { + local_obsdata_node_type * obs_node = local_obsdata_iget( obsdata , iobs ); + local_obsdata_node_type * new_node = local_obsdata_node_alloc_copy(obs_node); + local_ministep_add_obsdata_node(ministep, new_node); + } + } +} +void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode) { + local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); + local_obsdata_add_node(obsdata, obsdatanode); +} + +bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name) { + return hash_has_key( ministep->datasets, dataset_name ); +} + +int local_ministep_get_num_dataset( const local_ministep_type * ministep ) { + return hash_get_size( ministep->datasets ); +} local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name) { return hash_get( ministep->datasets, dataset_name ); @@ -145,29 +178,108 @@ local_obsdata_type * local_ministep_get_obsdata( const local_ministep_type * min return ministep->observations; } - - const char * local_ministep_get_name( const local_ministep_type * ministep ) { return ministep->name; } - /*****************************************************************/ hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep ) { return hash_iter_alloc( ministep->datasets ); } +/*****************************************************************/ -void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ) { - fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( CREATE_MINISTEP ), ministep->name , local_obsdata_get_name( ministep->observations) ); +/* + The keys referenced in the local_ministep_alloc_data_keys() and + local_ministep_has_data_key() are the underlying *enkf_node* keys - + not the keys used to index the local_datasets managed by this + local_ministep. +*/ + +stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep ) { + stringlist_type * keys = stringlist_alloc_new(); { hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); while (!hash_iter_is_complete( dataset_iter )) { - const char * dataset_key = hash_iter_get_next_key( dataset_iter ); - - fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep->name , dataset_key ); + const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); + stringlist_type * node_keys = local_dataset_alloc_keys( dataset ); + for (int i=0; i < stringlist_get_size( node_keys ); i++) { + const char * data_key = stringlist_iget( node_keys , i ); + if (!stringlist_contains(keys , data_key )) + stringlist_append_copy( keys , data_key ); + } + stringlist_free( node_keys ); } hash_iter_free( dataset_iter ); } + return keys; } + + +bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key) { + bool has_key = false; + { + hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); + + while (true) { + const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); + if (dataset) { + if (local_dataset_has_key( dataset , key)) { + has_key = true; + break; + } + } else + break; + } + + hash_iter_free( dataset_iter ); + } + return has_key; +} + +/*****************************************************************/ + +void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ) { + fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_MINISTEP ), ministep->name); + { + /* Dumping all the DATASET instances. */ + { + hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); + while (!hash_iter_is_complete( dataset_iter )) { + const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); + fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep->name , local_dataset_get_name( dataset ) ); + } + hash_iter_free( dataset_iter ); + } + + /* Only one OBSDATA */ + local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); + local_obsdata_fprintf( obsdata , stream ); + fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_OBSSET ) , ministep->name, local_obsdata_get_name(obsdata)); + } +} + +void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream) { + + fprintf(stream , "MINISTEP:%s,", ministep->name); + + { + /* Dumping all the DATASET instances. */ + { + hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); + while (!hash_iter_is_complete( dataset_iter )) { + const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); + local_dataset_summary_fprintf(dataset, stream); + } + hash_iter_free( dataset_iter ); + } + + /* Only one OBSDATA */ + local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); + local_obsdata_summary_fprintf( obsdata , stream); + fprintf(stream, "\n"); + } +} + + diff --git a/ThirdParty/Ert/devel/libenkf/src/local_obsdata.c b/ThirdParty/Ert/devel/libenkf/src/local_obsdata.c index e4f4f40672..fa33e8d14e 100644 --- a/ThirdParty/Ert/devel/libenkf/src/local_obsdata.c +++ b/ThirdParty/Ert/devel/libenkf/src/local_obsdata.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -145,3 +146,29 @@ void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vecto local_obsdata_node_reset_tstep_list(node, step_list); } } + + +void local_obsdata_fprintf( const local_obsdata_type * obsdata , FILE * stream ) { +fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_OBSSET ) , local_obsdata_get_name(obsdata)); + { + int i; + for (i=0; i < local_obsdata_get_size( obsdata ); i++ ) { + local_obsdata_node_type * node = local_obsdata_iget( obsdata , i ); + const char * obs_key = local_obsdata_node_get_key(node); + + fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ADD_OBS ) , local_obsdata_get_name(obsdata) , obs_key ); + } + } +} + +void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream) { + + fprintf(stream , "LOCAL OBSDATA NAME:%s,LOCAL OBSDATA SIZE:%d,", local_obsdata_get_name(obsdata), local_obsdata_get_size(obsdata) ); + + int i; + for (i = 0; i < local_obsdata_get_size( obsdata ); i++ ) { + local_obsdata_node_type * node = local_obsdata_iget( obsdata , i ); + const char * obs_key = local_obsdata_node_get_key(node); + fprintf(stream , "OBSERVATION:%s,", obs_key ); + } +} diff --git a/ThirdParty/Ert/devel/libenkf/src/local_updatestep.c b/ThirdParty/Ert/devel/libenkf/src/local_updatestep.c index 0ebeff175c..6d4ea53260 100644 --- a/ThirdParty/Ert/devel/libenkf/src/local_updatestep.c +++ b/ThirdParty/Ert/devel/libenkf/src/local_updatestep.c @@ -57,6 +57,16 @@ local_updatestep_type * local_updatestep_alloc( const char * name ) { } +bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key) { + bool has_key = false; + for (int i = 0; i < vector_get_size( update_step->ministep ); i++) { + const local_ministep_type * ministep = vector_iget_const( update_step->ministep , i ); + if (local_ministep_has_data_key(ministep, key)) + has_key = true; + } + return has_key; +} + /** Observe that use_count values are not copied. */ @@ -110,7 +120,7 @@ const char * local_updatestep_get_name( const local_updatestep_type * updatestep void local_updatestep_fprintf( const local_updatestep_type * updatestep , FILE * stream) { - fprintf(stream , "%s %s\n" , local_config_get_cmd_string( CREATE_UPDATESTEP ) , updatestep->name ); + fprintf(stream , "\n%s %s\n" , local_config_get_cmd_string( CREATE_UPDATESTEP ) , updatestep->name ); { int i; for (i=0; i < vector_get_size( updatestep->ministep ); i++) { diff --git a/ThirdParty/Ert/devel/libenkf/src/obs_data.c b/ThirdParty/Ert/devel/libenkf/src/obs_data.c index 1d1390838b..90868c5413 100644 --- a/ThirdParty/Ert/devel/libenkf/src/obs_data.c +++ b/ThirdParty/Ert/devel/libenkf/src/obs_data.c @@ -139,12 +139,12 @@ static void obs_block_free__( void * arg ) { } -void obs_block_deactivate( obs_block_type * obs_block , int iobs , const char * msg) { +void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg) { if (obs_block->active_mode[ iobs ] == ACTIVE) { - printf("Deactivating: %s(%d) : %s \n",obs_block->obs_key , iobs , msg); + if (verbose) + printf("Deactivating: %s(%d) : %s \n",obs_block->obs_key , iobs , msg); obs_block->active_mode[ iobs ] = DEACTIVATED; obs_block->active_size--; - } } @@ -692,3 +692,54 @@ int obs_data_get_active_size( const obs_data_type * obs_data ) { int obs_data_get_num_blocks( const obs_data_type * obs_data ) { return vector_get_size( obs_data->data ); } + + + +int obs_data_get_total_size( const obs_data_type * obs_data ) { + int total_size = 0; + for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { + const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); + total_size += obs_block->size; + } + return total_size; +} + + +static const obs_block_type * obs_data_lookup_block( const obs_data_type * obs_data, int total_index , int * block_offset) { + if (total_index < obs_data_get_total_size( obs_data )) { + const obs_block_type * obs_block; + int total_offset = 0; + int block_index = 0; + int block_size; + + + while (true) { + obs_block = vector_iget_const( obs_data->data , block_index ); + block_size = obs_block->size; + if ((block_size + total_offset) > total_index) + break; + + total_offset += block_size; + block_index++; + } + *block_offset = total_offset; + return obs_block; + } else { + util_abort("%s: could not lookup obs-block \n",__func__); + return NULL; + } +} + + +double obs_data_iget_value( const obs_data_type * obs_data , int total_index ) { + int total_offset; + const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset ); + return obs_block_iget_value( obs_block , total_index - total_offset ); +} + + +double obs_data_iget_std( const obs_data_type * obs_data , int total_index ) { + int total_offset; + const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset ); + return obs_block_iget_std( obs_block , total_index - total_offset ); +} diff --git a/ThirdParty/Ert/devel/libenkf/src/run_arg.c b/ThirdParty/Ert/devel/libenkf/src/run_arg.c index ad09ae797d..96e343c3b1 100644 --- a/ThirdParty/Ert/devel/libenkf/src/run_arg.c +++ b/ThirdParty/Ert/devel/libenkf/src/run_arg.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2014 Statoil ASA, Norway. + + The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ @@ -27,18 +27,17 @@ #define RUN_ARG_TYPE_ID 66143287 - +#define INVALID_QUEUE_INDEX -99 struct run_arg_struct { UTIL_TYPE_ID_DECLARATION; int iens; - bool active; /* Is this state object active at all - used for instance in ensemble experiments where only some of the members are integrated. */ int init_step_parameters; /* The report step we initialize parameters from - will often be equal to step1, but can be different. */ state_enum init_state_parameter; /* Whether we should init from a forecast or an analyzed state - parameters. */ state_enum init_state_dynamic; /* Whether we should init from a forecast or an analyzed state - dynamic state variables. */ - int max_internal_submit; /* How many times the enkf_state object should try to resubmit when the queueu has said everything is OK - but the load fails. */ - int num_internal_submit; + int max_internal_submit; /* How many times the enkf_state object should try to resubmit when the queueu has said everything is OK - but the load fails. */ + int num_internal_submit; int load_start; /* When loading back results - start at this step. */ int step1; /* The forward model is integrated: step1 -> step2 */ int step2; @@ -46,7 +45,7 @@ struct run_arg_struct { char * run_path; /* The currently used runpath - is realloced / freed for every step. */ run_mode_type run_mode; /* What type of run this is */ int queue_index; /* The job will in general have a different index in the queue than the iens number. */ - + enkf_fs_type * init_fs; enkf_fs_type * result_fs; enkf_fs_type * update_target_fs; @@ -55,28 +54,28 @@ struct run_arg_struct { /* Return value - set by the called routine!! */ run_status_type run_status; }; - + UTIL_SAFE_CAST_FUNCTION( run_arg , RUN_ARG_TYPE_ID ) UTIL_IS_INSTANCE_FUNCTION( run_arg , RUN_ARG_TYPE_ID ) -static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs , - enkf_fs_type * result_fs , - enkf_fs_type * update_target_fs , - int iens , - run_mode_type run_mode , - int init_step_parameters , +static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs , + enkf_fs_type * result_fs , + enkf_fs_type * update_target_fs , + int iens , + run_mode_type run_mode , + int init_step_parameters , state_enum init_state_parameter , state_enum init_state_dynamic , - int step1 , + int step1 , int step2 , int iter , const char * runpath) { - + run_arg_type * run_arg = util_malloc(sizeof * run_arg ); UTIL_TYPE_ID_INIT(run_arg , RUN_ARG_TYPE_ID); - + run_arg->init_fs = init_fs; run_arg->result_fs = result_fs; run_arg->update_target_fs = update_target_fs; @@ -91,24 +90,25 @@ static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs , run_arg->iter = iter; run_arg->run_path = util_alloc_abs_path( runpath ); run_arg->num_internal_submit = 0; + run_arg->queue_index = INVALID_QUEUE_INDEX; if (step1 == 0) run_arg->load_start = 1; else run_arg->load_start = step1; - + return run_arg; } -run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs , - int iens , +run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs , + int iens , state_enum init_state_parameter , state_enum init_state_dynamic , - int step1 , + int step1 , int step2 , const char * runpath) { - + return run_arg_alloc(fs,fs,fs,iens,ENKF_ASSIMILATION,step1 , init_state_parameter, init_state_dynamic , step1 , step2 , 0 , runpath); } @@ -157,7 +157,10 @@ void run_arg_increase_submit_count( run_arg_type * run_arg ) { void run_arg_set_queue_index( run_arg_type * run_arg , int queue_index) { - run_arg->queue_index = queue_index; + if (run_arg->queue_index == INVALID_QUEUE_INDEX) + run_arg->queue_index = queue_index; + else + util_abort("%s: attempt to reset run_arg->queue_index. These objects should not be recycled\n",__func__); } @@ -222,13 +225,18 @@ int run_arg_get_parameter_init_step( const run_arg_type * run_arg ) { -void run_arg_set_inactive( run_arg_type * run_arg ) { - run_arg->active = false; +int run_arg_get_queue_index( const run_arg_type * run_arg ) { + if (run_arg->queue_index == INVALID_QUEUE_INDEX) + util_abort("%s: sorry internal error - asking for the queue_index in a not-initialized run_arg object.\n" , __func__); + + return run_arg->queue_index; } - -int run_arg_get_queue_index( const run_arg_type * run_arg ) { - return run_arg->queue_index; +bool run_arg_is_submitted( const run_arg_type * run_arg ) { + if (run_arg->queue_index == INVALID_QUEUE_INDEX) + return false; + else + return true; } diff --git a/ThirdParty/Ert/devel/libenkf/src/site_config.c b/ThirdParty/Ert/devel/libenkf/src/site_config.c index 3bcd51e615..5a2fb10941 100644 --- a/ThirdParty/Ert/devel/libenkf/src/site_config.c +++ b/ThirdParty/Ert/devel/libenkf/src/site_config.c @@ -581,11 +581,6 @@ static void site_config_set_job_queue__(site_config_type * site_config, job_driv site_config->driver_type_site = driver_type; } -void site_config_set_job_queue(site_config_type * site_config, const char * queue_name) { - job_driver_type driver_type = job_queue_lookup_driver_name(queue_name); - site_config_set_job_queue__(site_config, driver_type); -} - bool site_config_queue_is_running(const site_config_type * site_config) { return job_queue_is_running(site_config->job_queue); } diff --git a/ThirdParty/Ert/devel/libenkf/tests/enkf_obs_fs.c b/ThirdParty/Ert/devel/libenkf/tests/enkf_obs_fs.c index f3c86c2401..bc56830f09 100644 --- a/ThirdParty/Ert/devel/libenkf/tests/enkf_obs_fs.c +++ b/ThirdParty/Ert/devel/libenkf/tests/enkf_obs_fs.c @@ -75,7 +75,7 @@ void test_iget(ert_test_context_type * test_context) { enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - test_assert_int_equal( 31 , enkf_obs_get_size( enkf_obs ) ); + test_assert_int_equal( 32 , enkf_obs_get_size( enkf_obs ) ); for (int iobs = 0; iobs < enkf_obs_get_size( enkf_obs ); iobs++) { obs_vector_type * vec1 = enkf_obs_iget_vector( enkf_obs , iobs ); obs_vector_type * vec2 = enkf_obs_get_vector( enkf_obs , obs_vector_get_key( vec1 )); diff --git a/ThirdParty/Ert/devel/libenkf/tests/enkf_run_arg.c b/ThirdParty/Ert/devel/libenkf/tests/enkf_run_arg.c index df1401a04d..5c472a529d 100644 --- a/ThirdParty/Ert/devel/libenkf/tests/enkf_run_arg.c +++ b/ThirdParty/Ert/devel/libenkf/tests/enkf_run_arg.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_run_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2014 Statoil ASA, Norway. + + The file 'ert_run_context.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -26,6 +26,38 @@ #include #include + +void call_get_queue_index( void * arg ) { + run_arg_type * run_arg = run_arg_safe_cast( arg ); + run_arg_get_queue_index( run_arg ); +} + +void call_set_queue_index( void * arg ) { + run_arg_type * run_arg = run_arg_safe_cast( arg ); + run_arg_set_queue_index( run_arg , 88 ); +} + + +void test_queue_index() { + test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS"); + { + enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); + run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path"); + + test_assert_false( run_arg_is_submitted( run_arg ) ); + test_assert_util_abort("run_arg_get_queue_index" , call_get_queue_index , run_arg ); + + run_arg_set_queue_index(run_arg, 78); + test_assert_true( run_arg_is_submitted( run_arg ) ); + test_assert_int_equal( 78 , run_arg_get_queue_index( run_arg )); + + test_assert_util_abort("run_arg_set_queue_index" , call_set_queue_index , run_arg ); + run_arg_free( run_arg ); + enkf_fs_decref( fs ); + } + test_work_area_free( test_area ); +} + void call_get_result_fs( void * arg ) { run_arg_type * run_arg = run_arg_safe_cast( arg ); run_arg_get_result_fs( run_arg ); @@ -51,7 +83,7 @@ void test_SMOOTHER_RUN( ) { test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , sim_fs ); test_assert_ptr_equal( run_arg_get_update_target_fs( run_arg ) , target_fs ); run_arg_free( run_arg ); - + enkf_fs_decref( sim_fs ); enkf_fs_decref( target_fs ); } @@ -71,7 +103,7 @@ void test_INIT_ONLY( ) { test_assert_util_abort( "run_arg_get_result_fs" , call_get_result_fs , run_arg ); test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg ); run_arg_free( run_arg ); - + enkf_fs_decref( init_fs ); } test_work_area_free( test_area ); @@ -82,10 +114,10 @@ void test_ENSEMBLE_EXPERIMENT( ) { test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS"); { enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); - + run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path"); test_assert_true( run_arg_is_instance( run_arg )); - + test_assert_ptr_equal( run_arg_get_init_fs( run_arg ) , fs ); test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , fs ); test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg ); @@ -102,6 +134,7 @@ void test_ENKF_ASSIMILATION( ) { } int main(int argc , char ** argv) { + test_queue_index(); test_SMOOTHER_RUN(); test_INIT_ONLY(); test_ENSEMBLE_EXPERIMENT(); diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/arg_pack.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/arg_pack.h index 9c95f8cb48..a05c56db84 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/arg_pack.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/arg_pack.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'arg_pack.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'arg_pack.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __ARG_PACK_H__ @@ -42,12 +42,12 @@ typedef void * (arg_node_copyc_ftype) (const void *); void arg_pack_lock(arg_pack_type *); void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename); void arg_pack_fprintf(const arg_pack_type * , FILE * ); - + void arg_pack_append_ptr(arg_pack_type * , void *); void arg_pack_append_const_ptr(arg_pack_type * , const void *); void arg_pack_append_owned_ptr(arg_pack_type * , void * , arg_node_free_ftype *); void arg_pack_append_copy(arg_pack_type * , void * , arg_node_copyc_ftype * , arg_node_free_ftype *); - + /* void arg_pack_iset_copy(arg_pack_type * arg_pack , int index , void * ptr, arg_node_copyc_ftype * copyc , arg_node_free_ftype * freef); void arg_pack_iset_ptr(arg_pack_type * arg_pack, int index , void * ptr); @@ -59,9 +59,9 @@ typedef void * (arg_node_copyc_ftype) (const void *); node_ctype arg_pack_iget_ctype(const arg_pack_type * arg_pack ,int index); int arg_pack_size( const arg_pack_type * arg_pack ); - + /*****************************************************************/ - + #define APPEND_TYPED_HEADER(type) void arg_pack_append_ ## type (arg_pack_type * , type); #define IGET_TYPED_HEADER(type) type arg_pack_iget_ ## type( const arg_pack_type * , int ); #define ISET_TYPED_HEADER(type) void arg_pack_iset_ ## type( arg_pack_type * , int , type value); @@ -95,4 +95,4 @@ ISET_TYPED_HEADER(size_t) } #endif #endif - + diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer.h index b5201d4c73..1c7de976d1 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'buffer.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'buffer.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __BUFFER_H__ @@ -28,6 +28,7 @@ extern "C" { #include #include +#include #include @@ -49,13 +50,10 @@ extern "C" { size_t buffer_fread(buffer_type * buffer , void * target_ptr , size_t item_size , size_t items); size_t buffer_safe_fwrite(buffer_type * buffer , const void * src_ptr , size_t item_size , size_t items); size_t buffer_fwrite(buffer_type * buffer , const void * src_ptr , size_t item_size , size_t items); - const char * buffer_fread_string(buffer_type * buffer); - char * buffer_fread_alloc_string(buffer_type * buffer); - void buffer_fwrite_string(buffer_type * buffer , const char * string); void buffer_summarize(const buffer_type * buffer , const char *); - + void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr ); - void buffer_terminate_char_ptr( buffer_type * buffer ); + void buffer_strcat(buffer_type * buffer , const char * string); void buffer_fwrite_char(buffer_type * buffer , char value); void buffer_fwrite_int(buffer_type * buffer , int value); void buffer_fskip_bool(buffer_type * buffer); @@ -72,21 +70,22 @@ extern "C" { size_t buffer_get_remaining_size(const buffer_type * buffer); void * buffer_get_data(const buffer_type * buffer); void * buffer_alloc_data_copy(const buffer_type * buffer); + void * buffer_iget_data(const buffer_type * buffer, size_t offset); void buffer_stream_fwrite( const buffer_type * buffer , FILE * stream ); int buffer_fgetc( buffer_type * buffer ); void buffer_fseek(buffer_type * buffer , ssize_t offset , int whence); void buffer_fskip(buffer_type * buffer, ssize_t offset); void buffer_clear( buffer_type * buffer ); - + void buffer_fskip_int(buffer_type * buffer); void buffer_fskip_time_t(buffer_type * buffer); time_t buffer_fread_time_t(buffer_type * buffer); void buffer_fwrite_time_t(buffer_type * buffer , time_t value); void buffer_rewind(buffer_type * buffer ); - + double buffer_fread_double(buffer_type * buffer); void buffer_fwrite_double(buffer_type * buffer , double value); - + size_t buffer_stream_fwrite_n( const buffer_type * buffer , size_t offset , ssize_t write_size , FILE * stream ); void buffer_stream_fprintf( const buffer_type * buffer , FILE * stream ); void buffer_stream_fread( buffer_type * buffer , size_t byte_size , FILE * stream); @@ -97,6 +96,13 @@ extern "C" { size_t buffer_fwrite_compressed(buffer_type * buffer, const void * ptr , size_t byte_size); size_t buffer_fread_compressed(buffer_type * buffer , size_t compressed_size , void * target_ptr , size_t target_size); #endif + + +#include "buffer_string.h" + + UTIL_IS_INSTANCE_HEADER( buffer ); + UTIL_SAFE_CAST_HEADER( buffer ); + #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer_string.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer_string.h new file mode 100644 index 0000000000..c516bbd028 --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/buffer_string.h @@ -0,0 +1,7 @@ +/* + These functions are very deprecated and should not be used further. +*/ + +const char * buffer_fread_string(buffer_type * buffer); +char * buffer_fread_alloc_string(buffer_type * buffer); +void buffer_fwrite_string(buffer_type * buffer , const char * string); diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/hash.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/hash.h index 8c3428e792..478c8e366a 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/hash.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/hash.h @@ -49,7 +49,7 @@ bool hash_has_key(const hash_type *, const char *); void * hash_pop( hash_type * hash , const char * key); void * hash_safe_get( const hash_type * hash , const char * key ); void * hash_get(const hash_type *, const char *); -char * hash_get_string(hash_type * , const char *); +char * hash_get_string(const hash_type * , const char *); void hash_del(hash_type *, const char *); void hash_safe_del(hash_type * , const char * ); void hash_clear(hash_type *); @@ -75,11 +75,11 @@ hash_type * hash_alloc_from_options(const stringlist_type *); bool hash_add_option( hash_type * hash, const char * key_value); int hash_inc_counter(hash_type * hash , const char * counter_key); -int hash_get_counter(hash_type * hash , const char * key); +int hash_get_counter(const hash_type * hash , const char * key); void hash_insert_int(hash_type * , const char * , int); -int hash_get_int(hash_type * , const char *); +int hash_get_int(const hash_type * , const char *); void hash_insert_double(hash_type * , const char * , double); -double hash_get_double(hash_type * , const char *); +double hash_get_double(const hash_type * , const char *); void hash_apply( hash_type * hash , hash_apply_ftype * func); UTIL_IS_INSTANCE_HEADER(hash); diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/rng.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/rng.h index 73ea7e6259..4e3385bc25 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/rng.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/rng.h @@ -68,6 +68,7 @@ typedef enum { unsigned int rng_forward( rng_type * rng ); double rng_get_double( rng_type * rng ); int rng_get_int( rng_type * rng , int max_value ); + unsigned int rng_get_max_int(const rng_type * rng); double rng_std_normal( rng_type * rng ); void rng_shuffle_int( rng_type * rng , int * data , size_t num_elements); diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/subst_list.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/subst_list.h index 1db5f55078..8f08133250 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/subst_list.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/subst_list.h @@ -1,30 +1,31 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'subst_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'subst_list.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __SUBST_H__ #define __SUBST_H__ -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif #include #include +#include #include typedef struct subst_list_struct subst_list_type; @@ -43,7 +44,7 @@ extern "C" { void subst_list_prepend_copy(subst_list_type * , const char * , const char * , const char * doc_string); void subst_list_prepend_ref(subst_list_type * , const char * , const char * , const char * doc_string); void subst_list_prepend_owned_ref(subst_list_type * , const char * , const char * , const char * doc_string); - + bool subst_list_filter_file(const subst_list_type * , const char * , const char * ); bool subst_list_update_file(const subst_list_type * , const char * ); bool subst_list_update_string(const subst_list_type * , char ** ); @@ -57,8 +58,9 @@ extern "C" { bool subst_list_has_key( const subst_list_type * subst_list , const char * key); char * subst_list_alloc_string_representation( const subst_list_type * subst_list ); int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_string, bool append); - -#ifdef __cplusplus + + UTIL_IS_INSTANCE_HEADER( subst_list ); +#ifdef __cplusplus } #endif #endif diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/thread_pool_posix.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/thread_pool_posix.h index 3f456c39e9..a749ed2c35 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/thread_pool_posix.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/thread_pool_posix.h @@ -29,7 +29,7 @@ extern "C" { void thread_pool_restart( thread_pool_type * tp ); void * thread_pool_iget_return_value( const thread_pool_type * pool , int queue_index ); int thread_pool_get_max_running( const thread_pool_type * pool ); - + bool thread_pool_try_join(thread_pool_type * pool, int timeout_seconds); #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/devel/libert_util/include/ert/util/util.h b/ThirdParty/Ert/devel/libert_util/include/ert/util/util.h index 9097d87a03..c91fc6ba52 100644 --- a/ThirdParty/Ert/devel/libert_util/include/ert/util/util.h +++ b/ThirdParty/Ert/devel/libert_util/include/ert/util/util.h @@ -104,6 +104,7 @@ typedef enum {left_pad = 0, //#define UTIL_CXX_MALLOC(var , num_elm) (typeof (var)) util_malloc( (num_elm) * sizeof var) void util_bitmask_on(int * , int ); + char * util_get_timezone(); time_t util_make_datetime(int , int , int , int , int , int ); void util_fprintf_datetime(time_t , FILE * ); void util_fprintf_date(time_t , FILE * ); diff --git a/ThirdParty/Ert/devel/libert_util/src/CMakeLists.txt b/ThirdParty/Ert/devel/libert_util/src/CMakeLists.txt index a72e315e87..42d20cc758 100644 --- a/ThirdParty/Ert/devel/libert_util/src/CMakeLists.txt +++ b/ThirdParty/Ert/devel/libert_util/src/CMakeLists.txt @@ -67,6 +67,7 @@ set(header_files type_vector_functions.h ui_return.h struct_vector.h + buffer_string.h ) set( test_source test_util.c ) diff --git a/ThirdParty/Ert/devel/libert_util/src/arg_pack.c b/ThirdParty/Ert/devel/libert_util/src/arg_pack.c index 32789760e2..b1b3bcc207 100644 --- a/ThirdParty/Ert/devel/libert_util/src/arg_pack.c +++ b/ThirdParty/Ert/devel/libert_util/src/arg_pack.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'arg_pack.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'arg_pack.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -61,14 +61,14 @@ void some_function(const char * arg1 , int arg2 , double arg3) { ..... - } + } + - void some_function__(void * __arg_pack) { arg_pack_type * arg_pack = arg_pack_safe_cast( __arg_pack ); const char * arg1 = arg_pack_iget_ptr( arg_pack , 0); int arg2 = arg_pack_iget_int( arg_pack , 1); - double arg3 = arg_pack_iget_double(arg_pack , 2); + double arg3 = arg_pack_iget_double(arg_pack , 2); some_function( arg1 , arg2 , arg3 ); } @@ -76,7 +76,7 @@ ..... arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack , "ARG1"); + arg_pack_append_ptr(arg_pack , "ARG1"); arg_pack_append_int(arg_pack , 1); arg_pack_append_double(arg_pack , 3.14159265); @@ -84,7 +84,7 @@ */ - + #define ARG_PACK_TYPE_ID 668268 @@ -101,10 +101,10 @@ typedef struct { struct arg_pack_struct { UTIL_TYPE_ID_DECLARATION; - int size; /* The number of arguments appended to this arg_pack instance. */ + int size; /* The number of arguments appended to this arg_pack instance. */ int alloc_size; /* The number of nodes allocated to this arg_pack - will in general be greater than size. */ - bool locked; /* To insure against unwaranted modifictaions - you can explicitly lock the arg_pack instance. This only */ - arg_node_type **nodes; /* Vector of nodes */ + bool locked; /* To insure against unwaranted modifictaions - you can explicitly lock the arg_pack instance. This only */ + arg_node_type **nodes; /* Vector of nodes */ }; @@ -126,7 +126,7 @@ static void arg_node_realloc_buffer(arg_node_type * node , int new_size) { static void __arg_node_assert_type(const arg_node_type * node , node_ctype arg_type) { - if (arg_type != node->ctype) + if (arg_type != node->ctype) util_abort("%s: asked for type:\'%s\' inserted as:\'%s\' - aborting \n" , __func__ , node_ctype_name(arg_type) , node_ctype_name(node->ctype)); } @@ -182,7 +182,7 @@ static size_t arg_node_get_size_t( const arg_node_type * node) { arg_pack, as that will delete the pointer you are using as well. */ - + static void * arg_node_get_ptr(const arg_node_type * node , bool get_ptr) { if (get_ptr) { if (node->ctype != CTYPE_VOID_POINTER) @@ -250,7 +250,7 @@ static void arg_node_set_size_t( arg_node_type * node , size_t value) { static void arg_node_set_ptr(arg_node_type * node , const void * ptr , arg_node_copyc_ftype * copyc , arg_node_free_ftype * destructor) { node->ctype = CTYPE_VOID_POINTER; node->destructor = destructor; - node->copyc = copyc; + node->copyc = copyc; if (copyc != NULL) node->buffer = copyc( ptr ); else @@ -264,7 +264,7 @@ static void arg_node_set_ptr(arg_node_type * node , const void * ptr , arg_node_ static void arg_node_clear(arg_node_type * node) { if (node->ctype == CTYPE_VOID_POINTER) { - if (node->destructor != NULL) + if (node->destructor != NULL) node->destructor( node->buffer ); /* When you have cleared - must not reuse the thing. */ node->destructor = NULL; @@ -338,7 +338,7 @@ UTIL_SAFE_CAST_FUNCTION_CONST( arg_pack , ARG_PACK_TYPE_ID) UTIL_IS_INSTANCE_FUNCTION(arg_pack , ARG_PACK_TYPE_ID) static void __arg_pack_assert_index(const arg_pack_type * arg , int iarg) { - if (iarg < 0 || iarg >= arg->size) + if (iarg < 0 || iarg >= arg->size) util_abort("%s: arg_pack() object filled with %d arguments - %d invalid argument number - aborting \n",__func__ , arg->size , iarg); } @@ -369,11 +369,11 @@ static arg_node_type * arg_pack_iget_new_node( arg_pack_type * arg_pack , int in arg_node_free( arg_pack->nodes[index] ); /* Free the existing current node. */ arg_pack->nodes[index] = arg_node_alloc_empty( ); /* Allocate a new fresh instance. */ } - + if (arg_pack->size == arg_pack->alloc_size) arg_pack_realloc_nodes(arg_pack , 1 + arg_pack->alloc_size * 2); /* We have to grow the vector of nodes. */ - if (index == arg_pack->size) + if (index == arg_pack->size) arg_pack->size++; /* We are asking for the first element beyond the current length of the vector, i.e. append. */ return arg_pack->nodes[index]; } @@ -414,7 +414,7 @@ arg_pack_type * arg_pack_alloc() { void arg_pack_free(arg_pack_type * arg_pack) { int i; - for (i=0; i < arg_pack->alloc_size; i++) + for (i=0; i < arg_pack->alloc_size; i++) arg_node_free( arg_pack->nodes[i] ); free(arg_pack->nodes); @@ -430,7 +430,7 @@ void arg_pack_free__(void * __arg_pack) { void arg_pack_clear(arg_pack_type * arg_pack) { - if (arg_pack->locked) + if (arg_pack->locked) util_abort("%s: arg_pack has been locked - abortng \n",__func__); { int i; @@ -445,7 +445,7 @@ void arg_pack_clear(arg_pack_type * arg_pack) { /* Access functions: 1. Append - 2. iget + 2. iget 3. iset (can NOT create holes in the vector) ******************************************************************/ @@ -527,7 +527,7 @@ node_ctype arg_pack_iget_ctype(const arg_pack_type * arg_pack ,int index) { void arg_pack_iset_copy(arg_pack_type * arg_pack , int index , const void * ptr, arg_node_copyc_ftype * copyc , arg_node_free_ftype * freef) { - arg_node_type * node = arg_pack_iget_new_node( arg_pack , index ); + arg_node_type * node = arg_pack_iget_new_node( arg_pack , index ); arg_node_set_ptr(node , ptr , copyc , freef); } @@ -577,7 +577,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename) arg_node_type * node = arg->nodes[iarg]; fmt = util_strcat_realloc(fmt , arg_node_fmt(node)); } - + switch(arg->size) { case(0): break; @@ -603,7 +603,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename) arg0 = arg_pack_iget_adress(arg , 0); arg1 = arg_pack_iget_adress(arg , 1); arg2 = arg_pack_iget_adress(arg , 2); - + scan_count = fscanf(stream , fmt , arg0 , arg1 , arg2); break; } @@ -614,7 +614,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename) arg1 = arg_pack_iget_adress(arg , 1); arg2 = arg_pack_iget_adress(arg , 2); arg3 = arg_pack_iget_adress(arg , 3); - + scan_count = fscanf(stream , fmt , arg0 , arg1 , arg2 , arg3); break; } @@ -635,11 +635,11 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename) util_abort("%s: sorry %s not allocated for %d arguments from file %s\n",__func__ , __func__ , arg->size, filename); } - + if (scan_count != arg->size) { util_abort("%s: wanted %d arguments - only found: %d in file %s \n", __func__ , arg->size , scan_count, filename); } - + free(fmt); } diff --git a/ThirdParty/Ert/devel/libert_util/src/buffer.c b/ThirdParty/Ert/devel/libert_util/src/buffer.c index 7a2491d9ba..46b56f6ab3 100644 --- a/ThirdParty/Ert/devel/libert_util/src/buffer.c +++ b/ThirdParty/Ert/devel/libert_util/src/buffer.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'buffer.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'buffer.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ @@ -25,6 +25,7 @@ #include #include +#include #include @@ -53,7 +54,7 @@ struct buffer_struct { - size_t __id; + UTIL_TYPE_ID_DECLARATION; char * data; /* The actual storage. */ size_t alloc_size; /* The total byte size of the buffer. */ size_t content_size; /* The extent of initialized data in the buffer - i.e. the meaningful content in the buffer. */ @@ -64,8 +65,8 @@ struct buffer_struct { /*****************************************************************/ - - +UTIL_IS_INSTANCE_FUNCTION( buffer , BUFFER_TYPE_ID ) +UTIL_SAFE_CAST_FUNCTION( buffer , BUFFER_TYPE_ID ) /** @@ -99,7 +100,7 @@ static void buffer_resize__(buffer_type * buffer , size_t new_size, bool abort_o static buffer_type * buffer_alloc_empty( ) { buffer_type * buffer = util_malloc( sizeof * buffer ); - buffer->__id = BUFFER_TYPE_ID; + UTIL_TYPE_ID_INIT( buffer , BUFFER_TYPE_ID ); buffer->data = NULL; buffer->alloc_size = 0; @@ -128,11 +129,11 @@ void buffer_shrink_to_fit( buffer_type * buffer ) { data. Observe that the buffer will 'steal' the input data pointer, in the process the data pointer might very well be realloced() leaving the original pointer invalid. - + All the content of the input data pointer will be assumed to be valid, i.e. the fields content_size and pos will be set to the value @buffer_size. - + When calling buffer_free() at a later stage the hijacked data will also be freed. */ @@ -144,7 +145,7 @@ buffer_type * buffer_alloc_private_wrapper(void * data , size_t buffer_size ) { buffer->content_size = buffer_size; buffer->pos = buffer_size; buffer->alloc_size = buffer_size; - + return buffer; } @@ -193,7 +194,7 @@ void buffer_clear( buffer_type * buffer ) { /*****************************************************************/ -/** +/** Observe that it is the functions with _safe_ in the name which most closely mimicks the behaviour of fread(), and fwrite() - these functions will *NOT* abort if the buffer is to small, @@ -212,19 +213,19 @@ static size_t buffer_fread__(buffer_type * buffer , void * target_ptr , size_t i size_t remaining_items = remaining_size / item_size; size_t read_items = util_size_t_min( items , remaining_items ); size_t read_bytes = read_items * item_size; - + memcpy( target_ptr , &buffer->data[buffer->pos] , read_bytes ); buffer->pos += read_bytes; - + if (read_items < items) { /* The buffer was not large enough - what to do now???? */ - if (abort_on_error) + if (abort_on_error) util_abort("%s: tried to read beyond the length of the buffer: Wanted:%ld Size:%ld \n",__func__ , items , read_items); - else + else /* OK we emulate fread() behaviour - setting errno to EOVERFLOW*/ errno = ENOMEM;//EOVERFLOW; } - + return read_items; } @@ -253,7 +254,7 @@ static size_t buffer_fwrite__(buffer_type * buffer , const void * src_ptr , size */ remaining_size = buffer->alloc_size - buffer->pos; } - + { size_t remaining_items = remaining_size / item_size; @@ -262,12 +263,12 @@ static size_t buffer_fwrite__(buffer_type * buffer , const void * src_ptr , size memcpy( &buffer->data[buffer->pos] , src_ptr , write_bytes ); buffer->pos += write_bytes; - + if (write_items < items) { /* The buffer was not large enough - what to do now???? */ if (abort_on_error) util_abort("%s: failed to write %d elements to the buffer \n",__func__ , items); /* This code is never executed - abort is in resize__(); */ - else + else /* OK we emulate fwrite() behaviour - setting errno to ENOMEM */ errno = ENOMEM; } @@ -308,10 +309,10 @@ void buffer_fseek(buffer_type * buffer , ssize_t offset , int whence) { new_pos = buffer->pos + offset; else if (whence == SEEK_END) new_pos = buffer->content_size + offset; - else + else util_abort("%s: unrecognized whence indicator - aborting \n",__func__); - - /** + + /** Observe that we can seek to the very end of the buffer. I.e. for a buffer with content_size == 20 we can seek to position 20. */ @@ -360,15 +361,26 @@ int buffer_fgetc( buffer_type * buffer ) { } /** - This function writes all the elements in the string __NOT__ - including the terminating \0 character into the buffer. This should - not be confused with buffer_fwrite_string() function which both - prepends the string with an integer length specifier and also - includes the terminating \0. + This function writes all the elements in the string including the + terminating \0 character into the buffer. This should not be + confused with buffer_fwrite_string() function which in addition + prepends the string with an integer length. */ void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr ) { - buffer_fwrite(buffer , string_ptr , sizeof * string_ptr , strlen( string_ptr )); + buffer_fwrite(buffer , string_ptr , sizeof * string_ptr , strlen( string_ptr ) + 1); +} + + +void buffer_strcat(buffer_type * buffer , const char * string) { + if (buffer->content_size == 0) + buffer_fwrite_char_ptr( buffer , string ); + else { + if (buffer->data[ buffer->content_size - 1] == '\0') { + buffer_fseek( buffer , -1 , SEEK_END); + buffer_fwrite_char_ptr( buffer , string ); + } + } } @@ -377,7 +389,7 @@ void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr ) { of the buffer will be checked, and no new \0 will be added if the buffer is already \0 terminated. */ -void buffer_terminate_char_ptr( buffer_type * buffer ) { +static void buffer_terminate_char_ptr( buffer_type * buffer ) { if (buffer->data[ buffer->content_size - 1] != '\0') buffer_fwrite_char( buffer , '\0'); } @@ -448,57 +460,6 @@ void buffer_fwrite_double(buffer_type * buffer , double value) { -/** - Storing strings: - ---------------- - - When storing a string (\0 terminated char pointer) what is actually - written to the buffer is - - 1. The length of the string - as returned from strlen(). - 2. The string content INCLUDING the terminating \0. - - -*/ - - -/** - This function will return a pointer to the current position in the - buffer, and advance the buffer position forward until a \0 - terminater is found. If \0 is not found the thing will abort(). - - Observe that the return value will point straight into the buffer, - this is highly volatile memory, and in general it will be safer to - use buffer_fread_alloc_string() to get a copy of the string. -*/ - -const char * buffer_fread_string(buffer_type * buffer) { - int string_length = buffer_fread_int( buffer ); - char * string_ptr = &buffer->data[buffer->pos]; - char c; - buffer_fskip( buffer , string_length ); - c = buffer_fread_char( buffer ); - if (c != '\0') - util_abort("%s: internal error - malformed string representation in buffer \n",__func__); - return string_ptr; -} - - - -char * buffer_fread_alloc_string(buffer_type * buffer) { - return util_alloc_string_copy( buffer_fread_string( buffer )); -} - - - -/** - Observe that this function writes a leading integer string length. -*/ -void buffer_fwrite_string(buffer_type * buffer , const char * string) { - buffer_fwrite_int( buffer , strlen( string )); /* Writing the length of the string */ - buffer_fwrite(buffer , string , 1 , strlen( string ) + 1); /* Writing the string content ** WITH ** the terminating \0 */ -} - @@ -528,22 +489,27 @@ size_t buffer_get_remaining_size(const buffer_type * buffer) { return buffer->content_size - buffer->pos; } -/** +/** Returns a pointer to the internal storage of the buffer. Observe that this storage is volatile, and the return value from this function should not be kept around; alternatively you can use buffer_alloc_data_copy(). */ -void * buffer_get_data(const buffer_type * buffer) { +void * buffer_get_data(const buffer_type * buffer) { return buffer->data; } +void * buffer_iget_data(const buffer_type * buffer, size_t offset) { + return &buffer->data[offset]; +} + + /** Returns a copy of the initialized (i.e. buffer->content_size) buffer content. */ -void * buffer_alloc_data_copy(const buffer_type * buffer) { +void * buffer_alloc_data_copy(const buffer_type * buffer) { return util_alloc_copy(buffer->data , buffer->content_size ); } @@ -571,11 +537,11 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) { ------------------------------------------------- | 0 | 1 | 2 | 3 | x | x | x | 4 | 5 | 6 | 7 | x | ------------------------------------------------- - + If you are shifting beyound the end of the buffer, it will be automatically resized. - + buffer_memshift(buffer , 2 , -4) -------------------------------- @@ -583,7 +549,7 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) { | 4 | 5 | 6 | 7 | 8 | x | x | x | x | x | x | x | ------------------------------------------------- - + When shifting to the left, content is lost (without warning/error) when it is shifted beyond the start of the buffer. @@ -593,7 +559,7 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) { case it is set to the new end of the buffer. */ -void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) { +void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) { /* Do we need to grow the buffer? */ if (shift > 0) { if (buffer->alloc_size <= (buffer->content_size + shift)) { @@ -601,7 +567,7 @@ void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) { buffer_resize__(buffer , new_size , true ); } } - + { size_t move_size; if (shift < 0) @@ -611,7 +577,7 @@ void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) { move_size = buffer->content_size - offset; memmove( &buffer->data[offset + shift] , &buffer->data[offset] , move_size ); buffer->content_size += shift; - buffer->pos = util_size_t_min( buffer->pos , buffer->content_size); + buffer->pos = util_size_t_min( buffer->pos , buffer->content_size); } } @@ -625,7 +591,6 @@ void buffer_replace_data(buffer_type * buffer , size_t offset , size_t old_size void buffer_replace_string( buffer_type * buffer , size_t offset , size_t old_size , const char * new_string) { - buffer_replace_data( buffer , offset , old_size , new_string , strlen(new_string)); } @@ -635,34 +600,28 @@ void buffer_replace_string( buffer_type * buffer , size_t offset , size_t old_si the string @expr in @buffer. The search will start at the current position in the buffer, if the string is found true is returned AND the internal pos is updated to point at the match. - + If the string is NOT found the function will return false, without touching internal state. */ bool buffer_strstr( buffer_type * buffer , const char * expr ) { - /** - If this condition is satisfied the assumption that buffer->data - is a \0 terminated string certainly breaks down. - */ - if ((buffer->content_size == 0) || (buffer->pos == buffer->content_size)) - return false; + bool match = false; - { - char * match = NULL; - - match = strstr( &buffer->data[buffer->pos] , expr); - if (match != NULL) - buffer->pos = match - buffer->data; - - return (match != NULL); + if (strlen(expr) > 0) { + char * match_ptr = strstr( &buffer->data[buffer->pos] , expr ); + if (match_ptr) { + buffer->pos += match_ptr - &buffer->data[buffer->pos]; + match = true; + } } + return match; } bool buffer_strchr( buffer_type * buffer , int c) { - /** + /** If this condition is satisfied the assumption that buffer->data is a \0 terminated string certainly breaks down. */ @@ -670,30 +629,37 @@ bool buffer_strchr( buffer_type * buffer , int c) { return false; { - char * match = NULL; - - match = strchr( &buffer->data[buffer->pos] , c); - if (match != NULL) - buffer->pos = match - buffer->data; - - return (match != NULL); + bool match = false; + size_t pos = buffer->pos; + + while (true) { + if (buffer->data[pos] == c) { + match = true; + buffer->pos = pos; + break; + } + pos++; + if (pos == buffer->content_size) + break; + } + + return match; } } - bool buffer_search_replace( buffer_type * buffer , const char * old_string , const char * new_string) { - const int shift = strlen( new_string ) - strlen( old_string ); - bool match = buffer_strstr( buffer , old_string ); + bool match = buffer_strstr( buffer , old_string ); if (match) { size_t offset = buffer_get_offset( buffer ) + strlen( old_string ); + const int shift = strlen( new_string ) - strlen( old_string ); if (shift != 0) buffer_memshift( buffer , offset , shift ); - - /** Search continues at the end of the newly inserted string - i.e. no room for recursions. */ - buffer_fwrite( buffer , new_string , strlen( new_string ) , sizeof * new_string ); + + buffer_fwrite( buffer , new_string , 1 , strlen(new_string)); + buffer_terminate_char_ptr( buffer ); } return match; } @@ -723,14 +689,14 @@ void buffer_summarize(const buffer_type * buffer , const char * header) { /** This is the lowest level: 'read buffer content from file' function. It will read 'byte_size' bytes from stream and fill the - buffer with the data. - + buffer with the data. + When the function completes the buffer position is at the end of the buffer, i.e. it is ready for more calls to buffer_stream_fread; this is in contrast to the higher level functions buffer_fread_alloc() / buffer_fread_realloc() which reposition the buffer position to the beginning of the buffer. - + Before reading from the buffer with e.g. buffer_fread_int() the buffer must be repositioned with buffer_rewind(). */ @@ -758,8 +724,8 @@ void buffer_stream_fread( buffer_type * buffer , size_t byte_size , FILE * strea void buffer_fread_realloc(buffer_type * buffer , const char * filename) { size_t file_size = util_file_size( filename ); - FILE * stream = util_fopen( filename , "r"); - + FILE * stream = util_fopen( filename , "r"); + buffer_clear( buffer ); /* Setting: content_size = 0; pos = 0; */ buffer_stream_fread( buffer , file_size , stream ); buffer_rewind( buffer ); /* Setting: pos = 0; */ @@ -779,7 +745,7 @@ buffer_type * buffer_fread_alloc(const char * filename) { /** Will write parts of the buffer to the stream. Will start at buffer position @offset and write @write_size bytes. - + o If @offset is invalid, i.e. less than zero or greater than buffer->content_size the function will fail hard. @@ -787,7 +753,7 @@ buffer_type * buffer_fread_alloc(const char * filename) { function will just write all the available data, but not complain any more. - o @write_size == 0 that is interpreted as "write everything from offset". + o @write_size == 0 that is interpreted as "write everything from offset". o @write_size < 0 is interpreted as : "Write everything except the abs(@write_size) last bytes. @@ -802,15 +768,15 @@ size_t buffer_stream_fwrite_n( const buffer_type * buffer , size_t offset , ssiz ssize_t len; if (write_size > 0) /* Normal - write @write_size bytes from offset */ - len = write_size; - else if (write_size == 0) /* Write everything from the offset */ + len = write_size; + else if (write_size == 0) /* Write everything from the offset */ len = buffer->content_size - offset; else /* @write_size < 0 - write everything excluding the last abs(write_size) bytes. */ len = buffer->content_size - offset - abs( write_size ); if (len < 0) util_abort("%s: invalid length spesifier - tried to write %ld bytes \n",__func__ , len); - + util_fwrite( &buffer->data[offset] , 1 , len , stream , __func__); return len; } @@ -829,7 +795,7 @@ void buffer_stream_fprintf( const buffer_type * buffer , FILE * stream ) { /** - Dumps buffer content to a stream - without any metadata. + Dumps buffer content to a stream - without any metadata. */ void buffer_store(const buffer_type * buffer , const char * filename) { FILE * stream = util_fopen(filename , "w"); @@ -838,6 +804,8 @@ void buffer_store(const buffer_type * buffer , const char * filename) { } +#include "buffer_string.c" + #ifdef WITH_ZLIB #include "buffer_zlib.c" #endif diff --git a/ThirdParty/Ert/devel/libert_util/src/buffer_string.c b/ThirdParty/Ert/devel/libert_util/src/buffer_string.c new file mode 100644 index 0000000000..ab8ed74dc1 --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/src/buffer_string.c @@ -0,0 +1,57 @@ +/* + The functions buffer_fread_string() and buffer_fwrite_string() + should not be used; the embedded integer just creates chaos and + should the sole responsability of the calling scope. +*/ + +/** + Storing strings: + ---------------- + + When storing a string (\0 terminated char pointer) what is actually + written to the buffer is + + 1. The length of the string - as returned from strlen(). + 2. The string content INCLUDING the terminating \0. + + +*/ + + +/** + This function will return a pointer to the current position in the + buffer, and advance the buffer position forward until a \0 + terminater is found. If \0 is not found the thing will abort(). + + Observe that the return value will point straight into the buffer, + this is highly volatile memory, and in general it will be safer to + use buffer_fread_alloc_string() to get a copy of the string. +*/ + +const char * buffer_fread_string(buffer_type * buffer) { + int string_length = buffer_fread_int( buffer ); + char * string_ptr = &buffer->data[buffer->pos]; + char c; + buffer_fskip( buffer , string_length ); + c = buffer_fread_char( buffer ); + if (c != '\0') + util_abort("%s: internal error - malformed string representation in buffer \n",__func__); + return string_ptr; +} + + + +char * buffer_fread_alloc_string(buffer_type * buffer) { + return util_alloc_string_copy( buffer_fread_string( buffer )); +} + + + +/** + Observe that this function writes a leading integer string length. +*/ +void buffer_fwrite_string(buffer_type * buffer , const char * string) { + buffer_fwrite_int( buffer , strlen( string )); /* Writing the length of the string */ + buffer_fwrite(buffer , string , 1 , strlen( string ) + 1); /* Writing the string content ** WITH ** the terminating \0 */ +} + diff --git a/ThirdParty/Ert/devel/libert_util/src/hash.c b/ThirdParty/Ert/devel/libert_util/src/hash.c index 1007e3d982..0237da18f1 100644 --- a/ThirdParty/Ert/devel/libert_util/src/hash.c +++ b/ThirdParty/Ert/devel/libert_util/src/hash.c @@ -159,8 +159,9 @@ static void * __hash_get_node_unlocked(const hash_type *__hash , const char *key difficult due to locking requirements. */ -static void * __hash_get_node(hash_type *hash , const char *key, bool abort_on_error) { +static void * __hash_get_node(const hash_type *hash_in , const char *key, bool abort_on_error) { hash_node_type * node; + hash_type * hash = (hash_type *)hash_in; __hash_rdlock( hash ); node = __hash_get_node_unlocked(hash , key , abort_on_error); __hash_unlock( hash ); @@ -168,7 +169,7 @@ static void * __hash_get_node(hash_type *hash , const char *key, bool abort_on_e } -static node_data_type * hash_get_node_data(hash_type *hash , const char *key) { +static node_data_type * hash_get_node_data(const hash_type *hash , const char *key) { hash_node_type * node = __hash_get_node(hash , key , true); return hash_node_get_data(node); } @@ -356,7 +357,7 @@ void hash_insert_string(hash_type * hash , const char * key , const char * value } -char * hash_get_string(hash_type * hash , const char * key) { +char * hash_get_string(const hash_type * hash , const char * key) { node_data_type * node_data = hash_get_node_data(hash , key); return node_data_get_string( node_data ); } @@ -369,7 +370,7 @@ void hash_insert_int(hash_type * hash , const char * key , int value) { } -int hash_get_int(hash_type * hash , const char * key) { +int hash_get_int(const hash_type * hash , const char * key) { node_data_type * node_data = hash_get_node_data(hash , key); return node_data_get_int( node_data ); } @@ -400,7 +401,7 @@ int hash_inc_counter(hash_type * hash , const char * counter_key) { Will return 0 if the key is not in the hash. */ -int hash_get_counter(hash_type * hash , const char * key) { +int hash_get_counter(const hash_type * hash , const char * key) { if (hash_has_key( hash , key )) return hash_get_int( hash , key ); else @@ -414,7 +415,7 @@ void hash_insert_double(hash_type * hash , const char * key , double value) { __hash_insert_node(hash , hash_node); } -double hash_get_double(hash_type * hash , const char * key) { +double hash_get_double(const hash_type * hash , const char * key) { node_data_type * node_data = hash_get_node_data(hash , key); return node_data_get_double( node_data ); } diff --git a/ThirdParty/Ert/devel/libert_util/src/rng.c b/ThirdParty/Ert/devel/libert_util/src/rng.c index 037c7ab50f..90851e423a 100644 --- a/ThirdParty/Ert/devel/libert_util/src/rng.c +++ b/ThirdParty/Ert/devel/libert_util/src/rng.c @@ -230,6 +230,15 @@ rng_alg_type rng_get_type( const rng_type * rng ) { return rng->type; } +unsigned int rng_get_max_int(const rng_type * rng) { + unsigned int MAX = -1; + if(rng->max_value < MAX) { + return rng->max_value; + } else { + return MAX; + } +} + /*****************************************************************/ void rng_shuffle( rng_type * rng , char * data , size_t element_size , size_t num_elements) { diff --git a/ThirdParty/Ert/devel/libert_util/src/string_util.c b/ThirdParty/Ert/devel/libert_util/src/string_util.c index 53a788564b..ec7c85b654 100644 --- a/ThirdParty/Ert/devel/libert_util/src/string_util.c +++ b/ThirdParty/Ert/devel/libert_util/src/string_util.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'string_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2013 Statoil ASA, Norway. + + The file 'string_util.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -27,13 +27,13 @@ /*****************************************************************/ -/* +/* This functions parses an input string 'range_string' of the type: "0,1,8, 10 - 20 , 15,17-21" - + I.e. integers separated by "," and "-". The integer values are - parsed out. + parsed out. */ //#include @@ -47,11 +47,11 @@ // NULL ); // stringlist_type * tokens; // tokens = tokenize_buffer( tokenizer , range_string , true); -// +// // stringlist_free( tokens ); // tokenizer_free( tokenizer ); -//} - +//} + static bool valid_characters( const char * range_string ) { @@ -63,7 +63,7 @@ static bool valid_characters( const char * range_string ) { char c = range_string[offset]; if (isspace(c) || isdigit(c) || c == ',' || c == '-') offset++; - else + else valid = false; if (offset == strlen( range_string ) || !valid) break; @@ -90,14 +90,14 @@ static int_vector_type * string_util_sscanf_alloc_active_list(const char * range int item; active_list = int_vector_alloc(0,0); tokens = basic_parser_tokenize_buffer( parser , range_string , true); - + for (item = 0; item < stringlist_get_size( tokens ); item++) { const char * string_item = stringlist_iget( tokens , item ); char * pos_ptr = (char *) string_item; int value1 , value2; - + value1 = strtol( string_item , &pos_ptr , 10); - if (*pos_ptr == '\0') + if (*pos_ptr == '\0') // The pos_ptr points to the end of the string, i.e. this was a single digit. value2 = value1; else { @@ -105,20 +105,20 @@ static int_vector_type * string_util_sscanf_alloc_active_list(const char * range while (isspace(*pos_ptr) || *pos_ptr == '-') pos_ptr++; util_sscanf_int( pos_ptr , &value2); - } - + } + { int value; - for (value = value1; value <= value2; value++) + for (value = value1; value <= value2; value++) int_vector_append( active_list , value ); } } - - + + stringlist_free( tokens ); basic_parser_free( parser ); } - + return active_list; } @@ -170,7 +170,7 @@ int_vector_type * string_util_alloc_active_list( const char * range_string ) { /* This is the only function which actually invokes the low level - string parsing in util_sscanf_alloc_active_list(). + string parsing in util_sscanf_alloc_active_list(). */ bool string_util_update_active_mask( const char * range_string , bool_vector_type * active_mask) { @@ -179,7 +179,7 @@ bool string_util_update_active_mask( const char * range_string , bool_vector_typ if (sscanf_active) { for (i=0; i < int_vector_size( sscanf_active ); i++) bool_vector_iset( active_mask , int_vector_iget(sscanf_active , i) , true ); - + int_vector_free( sscanf_active ); return true; } else @@ -223,6 +223,6 @@ bool string_util_init_value_list( const char * range_string , int_vector_type * int_vector_type * string_util_alloc_value_list(const char * range_string) { int_vector_type * value_list = int_vector_alloc(0,0); - string_util_init_value_list( range_string , value_list); + string_util_init_value_list( range_string , value_list); return value_list; } diff --git a/ThirdParty/Ert/devel/libert_util/src/stringlist.c b/ThirdParty/Ert/devel/libert_util/src/stringlist.c index 5e9cab85e4..ff8ea03bf5 100644 --- a/ThirdParty/Ert/devel/libert_util/src/stringlist.c +++ b/ThirdParty/Ert/devel/libert_util/src/stringlist.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'stringlist.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'stringlist.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -38,7 +38,7 @@ This file implements a very thin wrapper around a list (vector) of strings, and the total number of strings. It is mostly to avoid sending both argc and argv. - + Most of the functionality is implemented through vector.c and stateless functions in util.c */ @@ -63,7 +63,7 @@ static void stringlist_fprintf__(const stringlist_type * stringlist, const char const char * s = stringlist_iget(stringlist , i); fprintf(stream , "%s%s", s , sep); } - + fprintf(stream , "%s", stringlist_iget( stringlist , length - 1 )); } } @@ -140,7 +140,7 @@ static stringlist_type * stringlist_alloc_empty( bool alloc_vector ) { stringlist->strings = vector_alloc_new(); else stringlist->strings = NULL; - + return stringlist; } @@ -156,9 +156,9 @@ stringlist_type * stringlist_alloc_new() { stringlist_type * stringlist_alloc_argv_copy(const char ** argv , int argc) { int iarg; stringlist_type * stringlist = stringlist_alloc_empty( true); - for (iarg = 0; iarg < argc; iarg++) + for (iarg = 0; iarg < argc; iarg++) stringlist_append_copy( stringlist , argv[iarg]); - + return stringlist; } @@ -166,7 +166,7 @@ stringlist_type * stringlist_alloc_argv_copy(const char ** argv , int argc) { stringlist_type * stringlist_alloc_argv_ref(const char ** argv , int argc) { int iarg; stringlist_type * stringlist = stringlist_alloc_empty( true ); - for (iarg = 0; iarg < argc; iarg++) + for (iarg = 0; iarg < argc; iarg++) stringlist_append_ref( stringlist , argv[iarg]); return stringlist; @@ -176,19 +176,19 @@ stringlist_type * stringlist_alloc_argv_ref(const char ** argv , int argc) { stringlist_type * stringlist_alloc_argv_owned_ref(const char ** argv , int argc) { int iarg; stringlist_type * stringlist = stringlist_alloc_empty( true ); - for (iarg = 0; iarg < argc; iarg++) + for (iarg = 0; iarg < argc; iarg++) stringlist_append_owned_ref( stringlist , argv[iarg]); - + return stringlist; } -/** +/** Allocates a new stringlist instance where all the new string are references to the string found in the existing stringlist - instance. -*/ + instance. +*/ stringlist_type * stringlist_alloc_shallow_copy(const stringlist_type * src) { stringlist_type * copy = stringlist_alloc_empty( false ); copy->strings = vector_alloc_copy( src->strings , false); @@ -223,7 +223,7 @@ stringlist_type * stringlist_alloc_shallow_copy_with_limits(const stringlist_typ stringlist_type * stringlist_alloc_deep_copy_with_limits(const stringlist_type * src, int offset , int num_strings) { stringlist_type * copy = stringlist_alloc_empty( true ); int i; - for (i = 0; i < num_strings; i++) + for (i = 0; i < num_strings; i++) stringlist_append_copy( copy , stringlist_iget( src , i + offset)); return copy; } @@ -256,7 +256,7 @@ void stringlist_append_stringlist_ref(stringlist_type * stringlist , const strin /** Insert a copy of a stringlist in some position. - + Can probably be made more efficient. */ @@ -302,7 +302,7 @@ void stringlist_deep_copy( stringlist_type * target , const stringlist_type * sr -/** +/** Frees all the memory contained by the stringlist. */ void stringlist_clear(stringlist_type * stringlist) { @@ -352,11 +352,11 @@ const char * stringlist_back(const stringlist_type * stringlist) { int stringlist_iget_as_int( const stringlist_type * stringlist , int index , bool * valid) { const char * string_value = stringlist_iget( stringlist , index ); int value = -1; - + if (valid != NULL) *valid = false; - if (util_sscanf_int(string_value , &value)) + if (util_sscanf_int(string_value , &value)) if (valid != NULL) *valid = true; @@ -430,7 +430,7 @@ int stringlist_get_size(const stringlist_type * stringlist) { /* - Return NULL if the list has zero entries. + Return NULL if the list has zero entries. */ static char ** stringlist_alloc_char__(const stringlist_type * stringlist, bool deep_copy) { char ** strings = NULL; @@ -460,7 +460,7 @@ char ** stringlist_alloc_char_ref(const stringlist_type * stringlist) { -/** +/** Scans the stringlist (linear scan) to see if it contains (at least) one occurence of 's'. Will never return true if the input string @s equals NULL, altough the stringlist itself can contain @@ -471,7 +471,7 @@ bool stringlist_contains(const stringlist_type * stringlist , const char * s) { int size = stringlist_get_size( stringlist ); int index = 0; bool contains = false; - + while ((index < size) && (!contains)) { const char * istring = stringlist_iget(stringlist , index); if (istring != NULL) @@ -491,7 +491,7 @@ int_vector_type * stringlist_find(const stringlist_type * stringlist, const char int_vector_type * indicies = int_vector_alloc(0, -1); int size = stringlist_get_size( stringlist ); int index = 0; - + while (index < size ) { const char * istring = stringlist_iget(stringlist , index); if (istring != NULL) @@ -562,25 +562,25 @@ char * stringlist_alloc_joined_substring( const stringlist_type * s , int start_ { char * string = NULL; int i; - + /* Start with allocating a string long enough to hold all the substrings. */ { int sep_length = strlen( sep ); int total_length = 0; for (i=start_index; i < end_index; i++) total_length += (strlen(stringlist_iget( s , i)) + sep_length); - + total_length += (1 - sep_length); string = util_malloc( total_length * sizeof * string ); string[0] = '\0'; } - + for (i = start_index; i < end_index; i ++) { strcat( string , stringlist_iget( s , i)); if (i < (end_index - 1)) strcat( string , sep ); } - + return string; } } @@ -602,7 +602,7 @@ char * stringlist_alloc_joined_string(const stringlist_type * s , const char * s in the list. The actual functionality is in the util_split_string() function. */ - + stringlist_type * stringlist_alloc_from_split( const char * input_string , const char * sep ) { @@ -624,7 +624,7 @@ void stringlist_buffer_fwrite( const stringlist_type * s , buffer_type * buffer int i; int size = stringlist_get_size( s ); buffer_fwrite_int( buffer , size ); - for (i=0; i < size; i++) + for (i=0; i < size; i++) buffer_fwrite_string(buffer , stringlist_iget(s , i) ); } @@ -633,11 +633,11 @@ void stringlist_fwrite(const stringlist_type * s, FILE * stream) { int i; int size = stringlist_get_size( s ); util_fwrite_int( size , stream); - for (i=0; i < size; i++) + for (i=0; i < size; i++) util_fwrite_string(stringlist_iget(s , i) , stream); } -/* +/* When a stringlist is loaded from file the current content of the stringlist is discarded; and the stringlist becomes the owner of all the data read in. @@ -754,7 +754,7 @@ int stringlist_select_matching_files(stringlist_type * names , const char * path WIN32_FIND_DATA file_data; HANDLE file_handle; char * pattern = util_alloc_filename( path , file_pattern , NULL ); - + stringlist_clear( names ); file_handle = FindFirstFile( pattern , &file_data ); if (file_handle != INVALID_HANDLE_VALUE) { @@ -765,7 +765,7 @@ int stringlist_select_matching_files(stringlist_type * names , const char * path } FindClose( file_handle ); free( pattern ); - + return stringlist_get_size( names ); } #endif @@ -783,7 +783,7 @@ int stringlist_append_matching_elements(stringlist_type * target , const stringl } return match_count; } - + int stringlist_select_matching_elements(stringlist_type * target , const stringlist_type * src , const char * pattern) { stringlist_clear( target ); return stringlist_append_matching_elements( target , src , pattern ); diff --git a/ThirdParty/Ert/devel/libert_util/src/subst_list.c b/ThirdParty/Ert/devel/libert_util/src/subst_list.c index ec51b8fb76..b9bb515114 100644 --- a/ThirdParty/Ert/devel/libert_util/src/subst_list.c +++ b/ThirdParty/Ert/devel/libert_util/src/subst_list.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'subst_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'subst_list.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include @@ -32,7 +32,7 @@ /** This file implements a small support struct for search-replace operations, along with wrapped calls to util_string_replace_inplace(). - + Substitutions can be carried out on files and string in memory (char * with \0 termination); and the operations can be carried out inplace, or in a filtering mode where a new file/string is created. @@ -46,16 +46,16 @@ * subst_list_insert_ref(subst_list , key , value); * subst_list_insert_owned_ref(subst_list , key , value); - * subst_list_insert_copy(subst_list , key , value ); - + * subst_list_insert_copy(subst_list , key , value ); + The difference between these functions is who is owning the memory pointed to by the value pointer. 3. Do the actual search-replace operation on a file or memory buffer: - + * subst_list_filter_file() : Does search-replace on a file. * subst_list_update_string() : Does search-replace on a buffer. - + 4. Free the subst_list and go home. Internally the (key,value) pairs used for substitutions are stored in a @@ -71,10 +71,10 @@ */ -typedef enum { SUBST_DEEP_COPY = 1, +typedef enum { SUBST_DEEP_COPY = 1, SUBST_MANAGED_REF = 2, SUBST_SHARED_REF = 3} subst_insert_type; /* Mode used in the subst_list_insert__() function */ - + #define SUBST_LIST_TYPE_ID 6614320 struct subst_list_struct { @@ -83,7 +83,7 @@ struct subst_list_struct { vector_type * string_data; /* The string substitutions we should do. */ vector_type * func_data; /* The functions we support. */ const subst_func_pool_type * func_pool; /* NOT owned by the subst_list instance - can be NULL */ - hash_type * map; + hash_type * map; }; @@ -96,16 +96,16 @@ typedef struct { -/* +/* The subst_list type is implemented as a hash of subst_list_node instances. This node type is not exported out of this file scope at all. */ -typedef struct { +typedef struct { bool value_owner; /* Wether the memory pointed to by value should bee freed.*/ char * value; - char * key; + char * key; char * doc_string; /* A doc_string of this substitution - only for documentation - can be NULL. */ } subst_list_string_type; @@ -120,7 +120,7 @@ static subst_list_string_type * subst_list_string_alloc(const char * key) { subst_list_string_type * node = util_malloc(sizeof * node ); node->value_owner = false; node->value = NULL; - node->doc_string = NULL; + node->doc_string = NULL; node->key = util_alloc_string_copy( key ); return node; } @@ -148,7 +148,7 @@ static void subst_list_string_free__(void * node) { /** - input_value can be NULL. + input_value can be NULL. */ static void subst_list_string_set_value(subst_list_string_type * node, const char * input_value , const char * doc_string , subst_insert_type insert_mode) { subst_list_string_free_content( node ); @@ -158,15 +158,15 @@ static void subst_list_string_set_value(subst_list_string_type * node, const cha value = util_alloc_string_copy(input_value); else value = (char *) input_value; - + if (insert_mode == SUBST_SHARED_REF) node->value_owner = false; else node->value_owner = true; - + node->value = value; } - + if (doc_string != NULL) node->doc_string = util_realloc_string_copy( node->doc_string , doc_string ); } @@ -176,7 +176,7 @@ static void subst_list_string_set_value(subst_list_string_type * node, const cha When arriving at this function the main subst scope should already have verified that the requested function is available in the function pool. */ - + static subst_list_func_type * subst_list_func_alloc( const char * func_name, subst_func_type * func) { subst_list_func_type * subst_func = util_malloc( sizeof * subst_func ); subst_func->name = util_alloc_string_copy( func_name ); @@ -231,14 +231,14 @@ static subst_list_string_type * subst_list_insert_new_node(subst_list_type * sub vector_append_owned_ref( subst_list->string_data , new_node , subst_list_string_free__ ); else vector_insert_owned_ref( subst_list->string_data , 0 , new_node , subst_list_string_free__ ); - + hash_insert_ref( subst_list->map , key , new_node ); return new_node; } /*****************************************************************/ -static UTIL_IS_INSTANCE_FUNCTION( subst_list , SUBST_LIST_TYPE_ID ) +UTIL_IS_INSTANCE_FUNCTION( subst_list , SUBST_LIST_TYPE_ID ) /** @@ -266,13 +266,13 @@ bool subst_list_has_key( const subst_list_type * subst_list , const char * key) } -/* +/* The input argument is currently only (void *), runtime it will be checked whether it is of type subst_list_type, in which case it is interpreted as a parent instance, if it is of type subst_func_pool_type it is interpreted as a func_pool instance, otherwise the function will fail hard. - + If the the input argument is a subst_list parent, the func_pool of the parent is used also for the newly allocated subst_list instance. @@ -289,14 +289,14 @@ subst_list_type * subst_list_alloc(const void * input_arg) { subst_list->func_data = vector_alloc_new(); if (input_arg != NULL) { - if (subst_list_is_instance( input_arg )) + if (subst_list_is_instance( input_arg )) subst_list_set_parent( subst_list , input_arg ); else if (subst_func_pool_is_instance( input_arg )) subst_list->func_pool = input_arg; else util_abort("%s: run_time cast failed - invalid type on input argument.\n",__func__); } - + return subst_list; } @@ -315,10 +315,10 @@ subst_list_type * subst_list_alloc(const void * input_arg) { */ -static void subst_list_insert__(subst_list_type * subst_list , const char * key , const char * value , const char * doc_string, bool append , +static void subst_list_insert__(subst_list_type * subst_list , const char * key , const char * value , const char * doc_string, bool append , subst_insert_type insert_mode) { subst_list_string_type * node = subst_list_get_string_node(subst_list , key); - + if (node == NULL) /* Did not have the node. */ node = subst_list_insert_new_node(subst_list , key ,append); subst_list_string_set_value(node , value , doc_string , insert_mode); @@ -346,7 +346,7 @@ static void subst_list_insert__(subst_list_type * subst_list , const char * key to do whatever it wants with the value pointer. */ - + void subst_list_append_ref(subst_list_type * subst_list , const char * key , const char * value, const char * doc_string) { subst_list_insert__(subst_list , key , value , doc_string , true , SUBST_SHARED_REF); } @@ -381,7 +381,7 @@ void subst_list_prepend_copy(subst_list_type * subst_list , const char * key , c */ void subst_list_insert_func(subst_list_type * subst_list , const char * func_name , const char * local_func_name) { - + if (subst_list->func_pool != NULL && subst_func_pool_has_func( subst_list->func_pool , func_name )) { subst_list_func_type * subst_func = subst_list_func_alloc( local_func_name , subst_func_pool_get_func( subst_list->func_pool , func_name )); vector_append_owned_ref( subst_list->func_data , subst_func , subst_list_func_free__ ); @@ -407,10 +407,10 @@ void subst_list_free(subst_list_type * subst_list) { /* Below comes many different functions for doing the actual updating the functions differ in the form of the input and output. At the - lowest level, is the function - + lowest level, is the function + subst_list_uppdate_buffer() - + which will update a buffer instance. This function again will call two separate functions for pure string substitutions and for function evaluation. @@ -486,19 +486,19 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const for (index = 0; index < vector_get_size( subst_list->func_data); index++) { const subst_list_func_type * subst_func = vector_iget_const( subst_list->func_data , index ); const char * func_name = subst_func->name; - + bool match; buffer_rewind( buffer ); do { size_t match_pos; match = buffer_strstr( buffer , func_name ); match_pos = buffer_get_offset( buffer ); - + if (match) { bool update = false; char * arg_start = buffer_get_data( buffer ); arg_start += buffer_get_offset( buffer ) + strlen( func_name ); - + if (arg_start[0] == '(') { /* We require that an opening paren follows immediately behind the function name. */ char * arg_end = strchr( arg_start , ')'); if (arg_end != NULL) { @@ -506,8 +506,8 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const char * arg_content = util_alloc_substring_copy( arg_start, 1 , arg_end - arg_start - 1); stringlist_type * arg_list = basic_parser_tokenize_buffer( parser , arg_content , true); char * func_eval = subst_list_func_eval( subst_func , arg_list ); - int old_len = strlen(func_name) + strlen( arg_content) + 2; - + int old_len = strlen(func_name) + strlen( arg_content) + 2; + if (func_eval != NULL) { buffer_memshift( buffer , match_pos + old_len , strlen( func_eval ) - old_len); buffer_fwrite( buffer , func_eval , strlen( func_eval ) , sizeof * func_eval ); @@ -515,17 +515,17 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const update = true; global_match = true; } - + free( arg_content ); stringlist_free( arg_list ); - } - } - if (!update) + } + } + if (!update) buffer_fseek( buffer , match_pos + strlen( func_name ) , SEEK_SET); } } while (match); } - if (subst_list->parent != NULL) + if (subst_list->parent != NULL) global_match = (subst_list_eval_funcs____( subst_list->parent , parser , buffer ) || global_match); return global_match; } @@ -548,7 +548,7 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_ Inherited defintions -------------------- - + In this situation we have defined a (key,value) substitution, where the value depends on a value following afterwards: @@ -559,7 +559,7 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_ subsequently "" is replaced with "Test4". A typical use case here is that the common definition of "" is in the parent, and consequently parent should run first (i.e. top - down). + down). However, in other cases the order of defintion might very well be opposite, i.e. with "" first and then things will blow up: @@ -569,8 +569,8 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_ and, the final will not be resolved. I.e. there is no obvious 'right' way to do it. - - + + Overriding defaults ------------------- @@ -598,7 +598,7 @@ static bool subst_list_replace_strings( const subst_list_type * subst_list , buf bool match = false; if (subst_list->parent != NULL) match = subst_list_replace_strings( subst_list->parent , buffer ); - + /* The actual string replace */ match = (subst_list_replace_strings__( subst_list , buffer ) || match); return match; @@ -641,7 +641,7 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr buffer_type * buffer = buffer_fread_alloc( src_file ); buffer_fseek( buffer , 0 , SEEK_END ); /* Ensure that the buffer is a \0 terminated string. */ buffer_fwrite_char( buffer , '\0'); - + /*****************************************************************/ /* Backup file ?? */ if (util_same_file(src_file , target_file)) { @@ -649,19 +649,19 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr backup_file = util_alloc_tmp_file("/tmp" , backup_prefix , false); free(backup_prefix); } - - + + /* Writing backup file */ if (backup_file != NULL) { FILE * stream = util_fopen(backup_file , "w"); buffer_stream_fwrite_n( buffer , 0 , -1 , stream ); /* -1: Do not write the trailing \0. */ fclose(stream); } - - + + /* Doing the actual update */ match = subst_list_update_buffer(subst_list , buffer); - + /* Writing updated file */ { @@ -669,7 +669,7 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr buffer_stream_fwrite_n( buffer , 0 , -1 , stream ); /* -1: Do not write the trailing \0. */ fclose(stream); } - + /* OK - all went hunka dory - unlink the backup file and leave the building. */ if (backup_file != NULL) { remove( backup_file ); @@ -697,7 +697,7 @@ bool subst_list_update_string(const subst_list_type * subst_list , char ** strin bool match = subst_list_update_buffer(subst_list , buffer); *string = buffer_get_data( buffer ); buffer_free_container( buffer ); - + return match; } @@ -774,7 +774,7 @@ subst_list_type * subst_list_alloc_deep_copy(const subst_list_type * src) { copy = subst_list_alloc( src->parent ); else copy = subst_list_alloc( src->func_pool); - + { int index; for (index = 0; index < vector_get_size( src->string_data ); index++) { @@ -787,7 +787,7 @@ subst_list_type * subst_list_alloc_deep_copy(const subst_list_type * src) { subst_list_func_type * copy_node = subst_list_func_alloc( src_node->name , src_node->func ); vector_append_owned_ref( copy->func_data , copy_node , subst_list_func_free__ ); } - + } return copy; } @@ -856,29 +856,28 @@ void subst_list_fprintf(const subst_list_type * subst_list , FILE * stream) { KEY1=Value1, Key2=Value2, Key3=Value3. Will return NULL is there are no elements in the subst_list. */ - + char * subst_list_alloc_string_representation( const subst_list_type * subst_list ) { int size = subst_list_get_size( subst_list ); char * return_string = NULL; if (size > 0) { buffer_type * buffer = buffer_alloc( 512 ); int i; - + for (i=0; i < size; i++) { buffer_fwrite_char_ptr( buffer , subst_list_iget_key( subst_list , i)); - buffer_fwrite_char(buffer , '='); - buffer_fwrite_char_ptr( buffer , subst_list_iget_value( subst_list , i)); - if (i < (size - 1)) - buffer_fwrite_char_ptr( buffer , ", "); + buffer_strcat(buffer , "="); + buffer_strcat( buffer , subst_list_iget_value( subst_list , i)); + if (i < (size - 1)) + buffer_strcat( buffer , ", "); } - buffer_fwrite_char( buffer , '\0'); buffer_shrink_to_fit( buffer ); return_string = buffer_get_data( buffer ); buffer_free_container( buffer ); } return return_string; } - + /** Will loose tagging .... */ int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_string, bool append) { @@ -886,7 +885,7 @@ int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_ if (arg_string != NULL) { char ** key_value_list; int num_arg, iarg; - + util_split_string(arg_string , "," , &num_arg , &key_value_list); for (iarg = 0; iarg < num_arg; iarg++) { if (strchr(key_value_list[iarg] , '=') == NULL) @@ -902,27 +901,27 @@ int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_ int arg_length , value_length; while (isspace(*tmp)) /* Skipping initial space */ tmp++; - + arg_length = strcspn(tmp , " ="); key = util_alloc_substring_copy(tmp , 0 , arg_length); tmp += arg_length; while ((*tmp == ' ') || (*tmp == '=')) tmp++; - + value_length = strcspn(tmp , " "); value = util_alloc_substring_copy( tmp , 0 , value_length); - + /* Setting the argument */ if (append) subst_list_append_copy( subst_list , key , value , NULL); else subst_list_prepend_copy( subst_list , key , value , NULL); - + free(key); free(value); tmp += value_length; - - + + /* Accept only trailing space - any other character indicates a failed parsing. */ while (*tmp != '\0') { if (!isspace(*tmp)) diff --git a/ThirdParty/Ert/devel/libert_util/src/template_loop.c b/ThirdParty/Ert/devel/libert_util/src/template_loop.c index 9bd37d2ed8..a56be8149d 100644 --- a/ThirdParty/Ert/devel/libert_util/src/template_loop.c +++ b/ThirdParty/Ert/devel/libert_util/src/template_loop.c @@ -119,15 +119,13 @@ static void loop_free( loop_type * loop ) { static void replace_1var( buffer_type * var_expansion , int shift , int write_offset , int shift_offset , const char * value) { buffer_memshift( var_expansion , shift_offset , shift ); buffer_fseek( var_expansion , write_offset , SEEK_SET ); - buffer_fwrite_char_ptr( var_expansion , value ); + buffer_fwrite( var_expansion , value , strlen(value) , 1); } static void loop_eval( const loop_type * loop , const char * body , buffer_type * var_expansion , int ivar) { buffer_clear( var_expansion ); buffer_fwrite_char_ptr( var_expansion , body ); - buffer_terminate_char_ptr( var_expansion ); - { const char * value = stringlist_iget( loop->items , ivar ); int value_length = strlen( value ); @@ -235,13 +233,12 @@ static int template_eval_loop( const template_type * template , buffer_type * bu for (ivar =0; ivar < stringlist_get_size( loop->items ); ivar++) { loop_eval(loop , body , var_expansion , ivar ); - buffer_fwrite_char_ptr( loop_expansion , buffer_get_data( var_expansion )); + buffer_strcat( loop_expansion , buffer_get_data( var_expansion )); } buffer_free( var_expansion ); util_safe_free( body ); } - buffer_terminate_char_ptr( loop_expansion ); { int tag_length = loop->endtag_offset + loop->endtag_length - loop->opentag_offset; int offset = loop->endtag_offset + loop->endtag_length; @@ -249,7 +246,7 @@ static int template_eval_loop( const template_type * template , buffer_type * bu buffer_memshift( buffer , offset , shift ); buffer_fseek( buffer , loop->opentag_offset , SEEK_SET ); - buffer_fwrite_char_ptr( buffer , buffer_get_data( loop_expansion )); + buffer_fwrite( buffer , buffer_get_data( loop_expansion ) , 1 , buffer_get_string_size( loop_expansion )); global_offset = loop->opentag_offset + buffer_get_string_size( loop_expansion ); } diff --git a/ThirdParty/Ert/devel/libert_util/src/test_util.c b/ThirdParty/Ert/devel/libert_util/src/test_util.c index b7569c57a2..c92189d41e 100644 --- a/ThirdParty/Ert/devel/libert_util/src/test_util.c +++ b/ThirdParty/Ert/devel/libert_util/src/test_util.c @@ -25,7 +25,9 @@ #include #include +#include #include +#include void test_error_exit( const char * fmt , ...) { @@ -317,3 +319,28 @@ void test_assert_util_abort(const char * function_name , void call_func (void *) #endif + + +/*****************************************************************/ + +#ifdef WITH_PTHREAD +#include + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +void * thread_pool_test_func1( void * arg ) { + int * value = (int *) arg; + pthread_mutex_lock( &mutex ); + value[0]++; + pthread_mutex_unlock( &mutex ); + return NULL; +} +#endif + + +void * test_argpack_is_stringlist( void * arg ) { + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + void * arg0 = arg_pack_iget_ptr( arg_pack , 0 ); + test_assert_true( stringlist_is_instance( arg0 ) ); + return NULL; +} diff --git a/ThirdParty/Ert/devel/libert_util/src/thread_pool.c b/ThirdParty/Ert/devel/libert_util/src/thread_pool.c index 9673623814..a55864d560 100644 --- a/ThirdParty/Ert/devel/libert_util/src/thread_pool.c +++ b/ThirdParty/Ert/devel/libert_util/src/thread_pool.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'thread_pool.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'thread_pool.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include diff --git a/ThirdParty/Ert/devel/libert_util/src/thread_pool_posix.c b/ThirdParty/Ert/devel/libert_util/src/thread_pool_posix.c index 1439d9ac08..e890c70364 100644 --- a/ThirdParty/Ert/devel/libert_util/src/thread_pool_posix.c +++ b/ThirdParty/Ert/devel/libert_util/src/thread_pool_posix.c @@ -20,11 +20,13 @@ #include #include #include +#include #include #include #include #include +#include /** This file implements a small thread_pool object based on @@ -117,8 +119,9 @@ typedef struct { - +#define THREAD_POOL_TYPE_ID 71443207 struct thread_pool_struct { + UTIL_TYPE_ID_DECLARATION; thread_pool_arg_type * queue; /* The jobs to be executed are appended in this vector. */ int queue_index; /* The index of the next job to run. */ int queue_size; /* The number of jobs in the queue - including those which are complete. [Should be protected / atomic / ... ] */ @@ -134,7 +137,7 @@ struct thread_pool_struct { }; - +static UTIL_SAFE_CAST_FUNCTION( thread_pool , THREAD_POOL_TYPE_ID ) /** @@ -212,7 +215,7 @@ static void * thread_pool_start_job( void * arg ) { */ static void * thread_pool_main_loop( void * arg ) { - thread_pool_type * tp = (thread_pool_type *) arg; + thread_pool_type * tp = thread_pool_safe_cast( arg ); { const int usleep_init = 1000; /* The sleep time when there are free slots available - but no jobs wanting to run. */ int internal_offset = 0; /* Keep track of the (index of) the last job slot fired off - minor time saving. */ @@ -262,9 +265,8 @@ static void * thread_pool_main_loop( void * arg ) { if (!slot_found) { util_yield(); } - } else { - util_usleep(usleep_init); /* There are no jobs wanting to run. */ - } + } else + util_usleep(usleep_init); /* There are no jobs wanting to run. */ /*****************************************************************/ /* @@ -349,6 +351,65 @@ void thread_pool_join(thread_pool_type * pool) { } } +/* + This will try to join the thread; if the manager thread has not + completed within @timeout_seconds the function will return false. If + the join fails the queue will be reset in a non-joining state and it + will be open for more jobs. Probably not in a 100% sane state. +*/ + +bool thread_pool_try_join(thread_pool_type * pool, int timeout_seconds) { + bool join_ok = true; + + pool->join = true; /* Signals to the main thread that joining can start. */ + if (pool->max_running > 0) { + struct timespec ts; + time_t timeout_time = time( NULL ); + + util_inplace_forward_seconds(&timeout_time , timeout_seconds ); + ts.tv_sec = timeout_time; + ts.tv_nsec = 0; + +#ifdef HAVE_TIMEDJOIN + + { + int join_return = pthread_timedjoin_np( pool->dispatch_thread , NULL , &ts); /* Wait for the main thread to complete. */ + if (join_return == 0) + pool->accepting_jobs = false; + else { + pool->join = false; + join_ok = false; + } + } + +#else + + while(true) { + if (pthread_kill(pool->dispatch_thread, 0) == 0){ + util_yield(); + } else { + pthread_join(pool->dispatch_thread, NULL); + pool->accepting_jobs = false; + break; + } + + time_t now = time(NULL); + + if(util_difftime_seconds(now, timeout_time) <= 0) { + join_ok = false; + break; + } + } + +#endif + + + + } + return join_ok; +} + + /** @@ -360,6 +421,7 @@ void thread_pool_join(thread_pool_type * pool) { thread_pool_type * thread_pool_alloc(int max_running , bool start_queue) { thread_pool_type * pool = util_malloc( sizeof *pool ); + UTIL_TYPE_ID_INIT( pool , THREAD_POOL_TYPE_ID ); pool->job_slots = util_calloc( max_running , sizeof * pool->job_slots ); pool->max_running = max_running; pool->queue = NULL; diff --git a/ThirdParty/Ert/devel/libert_util/src/util.c b/ThirdParty/Ert/devel/libert_util/src/util.c index 3d071d4da8..7943741047 100644 --- a/ThirdParty/Ert/devel/libert_util/src/util.c +++ b/ThirdParty/Ert/devel/libert_util/src/util.c @@ -2637,6 +2637,7 @@ static int util_get_base_length(const char * file) { int path_length = util_get_path_length(file); const char * base_start; const char * last_point; + long character_index; if (path_length == strlen(file)) return 0; @@ -2646,7 +2647,9 @@ static int util_get_base_length(const char * file) { base_start = &file[path_length + 1]; last_point = strrchr(base_start , '.'); - if (last_point == NULL) + character_index = last_point - base_start; + + if (last_point == NULL || character_index == 0) return strlen(base_start); else return last_point - base_start; @@ -3243,6 +3246,15 @@ double util_difftime_seconds( time_t start_time , time_t end_time) { */ +char * util_get_timezone() { +#if defined(HAVE_TZNAME) + return tzname[0]; +#elif defined(HAVE_WINDOWS_TZNAME) + return _tzname[0]; +#endif +} + + time_t util_make_datetime(int sec, int min, int hour , int mday , int month , int year) { struct tm ts; ts.tm_sec = sec; @@ -3250,7 +3262,7 @@ time_t util_make_datetime(int sec, int min, int hour , int mday , int month , in ts.tm_hour = hour; ts.tm_mday = mday; ts.tm_mon = month - 1; - ts.tm_year = year - 1900; + ts.tm_year = year - 1900; ts.tm_isdst = -1; /* Negative value means mktime tries to determine automagically whether Daylight Saving Time is in effect. */ { time_t t = mktime( &ts ); @@ -4849,6 +4861,7 @@ void util_install_signals(void) { Killing with SIGKILL (-9) will not give a backtrace.*/ signal(SIGABRT , util_abort_signal); /* Signal abort. */ signal(SIGILL , util_abort_signal); /* Signal illegal instruction. */ + signal(SIGFPE , util_abort_signal); /* Floating point exception */ } diff --git a/ThirdParty/Ert/devel/libert_util/src/util_env.c b/ThirdParty/Ert/devel/libert_util/src/util_env.c index 934e3e75ae..c52a473931 100644 --- a/ThirdParty/Ert/devel/libert_util/src/util_env.c +++ b/ThirdParty/Ert/devel/libert_util/src/util_env.c @@ -228,7 +228,6 @@ char * util_alloc_envvar( const char * value ) { buffer_type * buffer = buffer_alloc( 1024 ); /* Start by filling up a buffer instance with the current content of @value. */ buffer_fwrite_char_ptr( buffer , value ); - buffer_fwrite_char( buffer , '\0' ); buffer_rewind( buffer ); diff --git a/ThirdParty/Ert/devel/libert_util/tests/CMakeLists.txt b/ThirdParty/Ert/devel/libert_util/tests/CMakeLists.txt index 996618d796..2b5c522c49 100644 --- a/ThirdParty/Ert/devel/libert_util/tests/CMakeLists.txt +++ b/ThirdParty/Ert/devel/libert_util/tests/CMakeLists.txt @@ -10,6 +10,11 @@ set(PING_SERVERS "" CACHE STRING "List of servers for testing ping") link_directories( ${ERT_BINARY_DIR}/libert_util/src ) +add_executable( test_thread_pool test_thread_pool.c ) +target_link_libraries( test_thread_pool ert_util test_util ) +add_test( test_thread_pool valgrind --error-exitcode=1 --tool=memcheck ${EXECUTABLE_OUTPUT_PATH}/test_thread_pool ) + + add_executable( ert_util_type_vector_test ert_util_type_vector_test.c ) target_link_libraries( ert_util_type_vector_test ert_util test_util ) add_test( ert_util_type_vector_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_type_vector_test ) @@ -18,10 +23,19 @@ add_executable( ert_util_matrix ert_util_matrix.c ) target_link_libraries( ert_util_matrix ert_util test_util ) add_test( ert_util_matrix ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix ) +add_executable( ert_util_subst_list ert_util_subst_list.c ) +target_link_libraries( ert_util_subst_list ert_util test_util ) +add_test( ert_util_subst_list ${EXECUTABLE_OUTPUT_PATH}/ert_util_subst_list ) + + add_executable( ert_util_matrix_stat ert_util_matrix_stat.c ) target_link_libraries( ert_util_matrix_stat ert_util test_util ) add_test( ert_util_matrix_stat ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix_stat ) +add_executable( ert_util_buffer ert_util_buffer.c ) +target_link_libraries( ert_util_buffer ert_util test_util ) +add_test( ert_util_buffer ${EXECUTABLE_OUTPUT_PATH}/ert_util_buffer ) + add_executable( ert_util_statistics ert_util_statistics.c ) target_link_libraries( ert_util_statistics ert_util test_util ) add_test( ert_util_statistics ${EXECUTABLE_OUTPUT_PATH}/ert_util_statistics ) @@ -146,6 +160,10 @@ add_executable( ert_util_parent_path ert_util_parent_path.c ) target_link_libraries( ert_util_parent_path ert_util test_util ) add_test( ert_util_parent_path ${EXECUTABLE_OUTPUT_PATH}/ert_util_parent_path) +add_executable( ert_util_alloc_file_components ert_util_alloc_file_components.c ) +target_link_libraries( ert_util_alloc_file_components ert_util test_util ) +add_test( ert_util_alloc_file_components ${EXECUTABLE_OUTPUT_PATH}/ert_util_alloc_file_components) + add_executable( ert_util_work_area ert_util_work_area.c ) target_link_libraries( ert_util_work_area ert_util test_util ) add_test( NAME ert_util_work_area diff --git a/ThirdParty/Ert/devel/libert_util/tests/ert_util_alloc_file_components.c b/ThirdParty/Ert/devel/libert_util/tests/ert_util_alloc_file_components.c new file mode 100644 index 0000000000..bb9e6d57a9 --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/tests/ert_util_alloc_file_components.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +#include +#include + + +bool checkPath(const char * path, const char * directory, const char * base_name, const char * extension) { + char * dir; + char * base; + char * ext; + + util_alloc_file_components(path, &dir, &base, &ext); + + bool success = true; + + success = success && (util_string_equal(dir, directory) || dir == directory); + success = success && (util_string_equal(base, base_name) || base == base_name); + success = success && (util_string_equal(ext, extension) || ext == extension); + + free(dir); + free(base); + free(ext); + + return success; +} + +int main(int argc , char ** argv) { + + test_assert_true(checkPath("/dir/filename.ext", "/dir", "filename", "ext")); + test_assert_true(checkPath("/dir/subdir/filename.ext", "/dir/subdir", "filename", "ext")); + test_assert_true(checkPath("/dir/subdir/filename.name.ext", "/dir/subdir", "filename.name", "ext")); + test_assert_true(checkPath("/dir/subdir/filename", "/dir/subdir", "filename", NULL)); + test_assert_true(checkPath("filename.ext", NULL, "filename", "ext")); + test_assert_true(checkPath("filename", NULL, "filename", NULL)); + test_assert_true(checkPath(".filename", NULL, ".filename", NULL)); + test_assert_true(checkPath(".filename.ext", NULL, ".filename", "ext")); + + exit(0); +} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/libert_util/tests/ert_util_buffer.c b/ThirdParty/Ert/devel/libert_util/tests/ert_util_buffer.c new file mode 100644 index 0000000000..8c032474ce --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/tests/ert_util_buffer.c @@ -0,0 +1,144 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'ert_util_buffer.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include +#include + +#include +#include + + + +void test_create() { + buffer_type * buffer = buffer_alloc( 1024 ); + test_assert_true( buffer_is_instance( buffer )); + buffer_free( buffer ); +} + + +void test_buffer_strchr() { + buffer_type * buffer = buffer_alloc( 1024 ); + test_assert_false( buffer_strchr( buffer , 'A')); + buffer_fwrite_char_ptr(buffer , "XX AB AB AB"); + test_assert_false( buffer_strchr( buffer , 'A')); + + buffer_rewind( buffer ); + test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1); + test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1); + test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1); + test_assert_false( buffer_strchr( buffer , 'A')); + buffer_free( buffer ); +} + +void test_buffer_strstr() { + buffer_type * buffer = buffer_alloc( 1024 ); + test_assert_false( buffer_strstr( buffer , "Hello World" )); + test_assert_false( buffer_strstr( buffer , "" )); + + buffer_fwrite_char_ptr( buffer , "ABC"); + test_assert_int_equal( buffer_get_size( buffer ), 4 ); + test_assert_false( buffer_strstr( buffer , "ABC")); + + buffer_rewind( buffer ); + test_assert_true( buffer_strstr( buffer , "ABC")); + test_assert_int_equal( buffer_get_offset(buffer) , 0); + test_assert_string_equal( "ABC" , buffer_get_data(buffer)); + + { + size_t pos = buffer_get_offset( buffer ); + test_assert_false( buffer_strstr( buffer , "ABCD" )); + test_assert_size_t_equal( pos , buffer_get_offset( buffer )); + } + buffer_rewind( buffer ); + test_assert_true( buffer_strstr( buffer , "AB" )); + test_assert_true( buffer_strstr( buffer , "ABC" )); + test_assert_true( buffer_strstr( buffer , "BC" )); + test_assert_false( buffer_strstr( buffer , "ABC" )); +} + + + + +void test_buffer_search_replace1() { + buffer_type * buffer = buffer_alloc( 1024 ); + test_assert_false( buffer_search_replace( buffer , "" , "XYZ")); + test_assert_false( buffer_search_replace( buffer , "XYZ" , "ABC")); + test_assert_false( buffer_search_replace( buffer , "XYZ" , "")); + + buffer_fwrite_char_ptr(buffer , "ABC 123"); + buffer_rewind(buffer); + test_assert_true( buffer_search_replace( buffer, "ABC" , "XYZ" )); + buffer_rewind( buffer ); + test_assert_string_equal( "XYZ 123" , buffer_get_data( buffer )); + + buffer_rewind( buffer ); + test_assert_true( buffer_search_replace( buffer, "XYZ" , "A")); + buffer_rewind( buffer ); + test_assert_string_equal( "A 123" , buffer_get_data( buffer )); + + buffer_rewind( buffer ); + test_assert_true( buffer_search_replace( buffer, "A", "XYZ")); + buffer_rewind( buffer ); + test_assert_string_equal( "XYZ 123" , buffer_get_data( buffer )); + + buffer_free( buffer ); +} + + +void test_buffer_search_replace2() { + buffer_type * buffer = buffer_alloc( 1024 ); + buffer_fwrite_char_ptr(buffer , "MAGIC_PRINT magic-list.txt __MAGIC__"); + + buffer_rewind( buffer ); + test_assert_false( buffer_search_replace( buffer , "" , "SUPERCase")); + test_assert_string_equal( "MAGIC_PRINT magic-list.txt __MAGIC__" , buffer_get_data( buffer)); + + buffer_rewind( buffer ); + test_assert_true( buffer_search_replace( buffer , "" , "default")); + test_assert_string_equal( "MAGIC_PRINT magic-list.txt default __MAGIC__" , buffer_get_data( buffer)); + + + buffer_free( buffer ); +} + + +void test_char_ptr( ) { + buffer_type * buffer = buffer_alloc(1024); + buffer_fwrite_char_ptr( buffer , "Hello World"); + test_assert_size_t_equal( buffer_get_size( buffer ) , 12 ); + test_assert_int_equal( strlen( buffer_get_data( buffer )) , 11); + + buffer_clear( buffer ); + buffer_fwrite_char_ptr(buffer , "Hello" ); + buffer_strcat( buffer , " " ); + buffer_strcat( buffer , "World" ); + test_assert_size_t_equal( buffer_get_size( buffer ) , 12 ); + test_assert_int_equal( strlen( buffer_get_data( buffer )) , 11); + + buffer_free( buffer ); +} + + +int main( int argc , char ** argv) { + test_create(); + test_char_ptr(); + test_buffer_strchr(); + test_buffer_strstr(); + test_buffer_search_replace1(); + test_buffer_search_replace2(); + exit(0); +} diff --git a/ThirdParty/Ert/devel/libert_util/tests/ert_util_subst_list.c b/ThirdParty/Ert/devel/libert_util/tests/ert_util_subst_list.c new file mode 100644 index 0000000000..e5d5c1a526 --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/tests/ert_util_subst_list.c @@ -0,0 +1,97 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'ert_util_subst_list.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include +#include +#include + +#include +#include +#include + + +void test_create() { + subst_list_type * subst_list = subst_list_alloc( NULL ); + test_assert_true( subst_list_is_instance( subst_list ) ); + subst_list_free( subst_list ); +} + + +void test_filter_file1() { + subst_list_type * subst_list = subst_list_alloc( NULL ); + test_work_area_type * work_area = test_work_area_alloc("subst_list/filter1"); + { + FILE * stream = util_fopen("template" , "w"); + fprintf(stream , "\n\n\n\n"); + fclose(stream); + } + subst_list_append_copy( subst_list , "" , "Value1" , NULL); + subst_list_append_copy( subst_list , "" , "Value2" , NULL); + subst_list_append_copy( subst_list , "" , "Value3" , NULL); + subst_list_append_copy( subst_list , "" , "Value4" , NULL); + + subst_list_filter_file( subst_list , "template" , "target"); + + { + FILE * stream = util_fopen("target" , "r"); + char s1[128],s2[128],s3[128],s4[128]; + + test_assert_int_equal( 4 , fscanf( stream , "%s %s %s %s" , s1,s2,s3,s4)); + fclose(stream); + + test_assert_string_equal( s1 , "Value1"); + test_assert_string_equal( s2 , "Value2"); + test_assert_string_equal( s3 , "Value3"); + test_assert_string_equal( s4 , "Value4"); + } + test_work_area_free( work_area ); + subst_list_free( subst_list ); +} + + +void test_filter_file2() { + subst_list_type * subst_list = subst_list_alloc( NULL ); + test_work_area_type * work_area = test_work_area_alloc("subst_list/filter2"); + { + FILE * stream = util_fopen("template" , "w"); + fprintf(stream , "MAGIC_PRINT magic-list.txt __MAGIC__"); + fclose(stream); + } + + subst_list_append_copy( subst_list , "" , "QC" , NULL); + subst_list_append_copy( subst_list , "__MAGIC__" , "MagicAllTheWayToWorkFlow" , NULL); + subst_list_append_copy( subst_list , "" , "SUPERcase" , NULL); + subst_list_append_copy( subst_list , "" , "default" , NULL); + subst_list_filter_file( subst_list , "template" , "target"); + + { + char * target_string = util_fread_alloc_file_content( "target" , NULL ); + test_assert_string_equal( target_string , "MAGIC_PRINT magic-list.txt default MagicAllTheWayToWorkFlow"); + free( target_string ); + } + test_work_area_free( work_area ); + subst_list_free( subst_list ); +} + + + + +int main(int argc , char ** argv) { + test_create(); + test_filter_file1(); + test_filter_file2(); +} diff --git a/ThirdParty/Ert/devel/libert_util/tests/test_thread_pool.c b/ThirdParty/Ert/devel/libert_util/tests/test_thread_pool.c new file mode 100644 index 0000000000..d7338a9522 --- /dev/null +++ b/ThirdParty/Ert/devel/libert_util/tests/test_thread_pool.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'test_thread_pool.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include +#include + +#include +#include + + +pthread_mutex_t lock; + + +void create_and_destroy() { + int run_size = 10; + thread_pool_type * tp = thread_pool_alloc( run_size , true ); + + thread_pool_join( tp ); + thread_pool_free( tp ); +} + + +void * inc(void * arg) { + int * int_arg = (int *) arg; + pthread_mutex_lock( &lock ); + int_arg[0]++; + pthread_mutex_unlock( &lock ); + return NULL; +} + + +void run() { + int run_size = 10; + int job_size = 1000; + int value = 0; + thread_pool_type * tp = thread_pool_alloc( run_size , true ); + + pthread_mutex_init(&lock , NULL); + for (int i=0; i < job_size; i++) + thread_pool_add_job( tp , inc , &value ); + + thread_pool_join( tp ); + thread_pool_free( tp ); + test_assert_int_equal( job_size , value ); + pthread_mutex_destroy( &lock ); +} + + + + + + +int main( int argc , char ** argv) { + create_and_destroy(); + run(); +} diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_list.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_list.h new file mode 100644 index 0000000000..9ab6070065 --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_list.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_node.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#ifndef __JOB_LIST_H__ +#define __JOB_LIST_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include + + +typedef struct job_list_struct job_list_type; + + job_list_type * job_list_alloc(); + void job_list_free( job_list_type * job_list ); + int job_list_get_size( const job_list_type * job_list ); + void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node ); + job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index); + void job_list_reset( job_list_type * job_list ); + void job_list_get_wrlock( job_list_type * list); + void job_list_get_rdlock( job_list_type * list); + void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2); + void job_list_unlock( job_list_type * list); + + UTIL_SAFE_CAST_HEADER( job_list ); + UTIL_IS_INSTANCE_HEADER( job_list ); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_node.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_node.h new file mode 100644 index 0000000000..e41196651c --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_node.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_node.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#ifndef __JOB_NODE_H__ +#define __JOB_NODE_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + This struct holds the job_queue information about one job. Observe + the following: + + 1. This struct is purely static - i.e. it is invisible outside of + this file-scope. + + 2. Typically the driver would like to store some additional + information, i.e. the PID of the running process for the local + driver; that is stored in a (driver specific) struct under the + field job_data. + + 3. If the driver detects that a job has failed it leaves an EXIT + file, the exit status is (currently) not reliably transferred + back to to the job_queue layer. + +*/ + +typedef bool (job_callback_ftype) (void *); +typedef struct job_queue_node_struct job_queue_node_type; + + + bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status); + submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); + void job_queue_node_free_error_info( job_queue_node_type * node ); + void job_queue_node_fscanf_EXIT( job_queue_node_type * node ); + void job_queue_node_clear_error_info(job_queue_node_type * node); + void job_queue_node_clear(job_queue_node_type * node); + void job_queue_node_free_data(job_queue_node_type * node); + job_queue_node_type * job_queue_node_alloc( const char * job_name , + const char * run_path , + const char * run_cmd , + int argc , + const char ** argv , + int num_cpu , + const char * ok_file, + const char * exit_file, + job_callback_ftype * done_callback, + job_callback_ftype * retry_callback, + job_callback_ftype * exit_callback, + void * callback_arg); + + + job_queue_node_type * job_queue_node_alloc_simple( const char * job_name , + const char * run_path , + const char * run_cmd , + int argc , + const char ** argv ); + + bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); + void job_queue_node_free(job_queue_node_type * node); + job_status_type job_queue_node_get_status(const job_queue_node_type * node); + void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver); + void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status); + bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); + + const char * job_queue_node_get_run_path( const job_queue_node_type * node); + const char * job_queue_node_get_name( const job_queue_node_type * node); + int job_queue_node_get_submit_attempt( const job_queue_node_type * node); + void job_queue_node_reset_submit_attempt( job_queue_node_type * node); + const char * job_queue_node_get_failed_job( const job_queue_node_type * node); + const char * job_queue_node_get_error_reason( const job_queue_node_type * node); + const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node); + const char * job_queue_node_get_stderr_file( const job_queue_node_type * node); + + time_t job_queue_node_get_sim_start( const job_queue_node_type * node ); + time_t job_queue_node_get_sim_end( const job_queue_node_type * node ); + time_t job_queue_node_get_submit_time( const job_queue_node_type * node ); + + const char * job_queue_node_get_ok_file( const job_queue_node_type * node); + const char * job_queue_node_get_exit_file( const job_queue_node_type * node); + + bool job_queue_node_run_DONE_callback( job_queue_node_type * node ); + bool job_queue_node_run_RETRY_callback( job_queue_node_type * node ); + void job_queue_node_run_EXIT_callback( job_queue_node_type * node ); + int job_queue_node_get_queue_index( const job_queue_node_type * node ); + void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index); + + UTIL_IS_INSTANCE_HEADER( job_queue_node ); + UTIL_SAFE_CAST_HEADER( job_queue_node ); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue.h index e74eaa770b..94be97734c 100644 --- a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue.h +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue.h @@ -27,11 +27,11 @@ extern "C" { #include #include +#include - typedef bool (job_callback_ftype) (void *); typedef struct job_queue_struct job_queue_type; - typedef struct job_queue_node_struct job_queue_node_type; + void job_queue_submit_complete( job_queue_type * queue ); job_driver_type job_queue_get_driver_type( const job_queue_type * queue ); @@ -42,29 +42,17 @@ extern "C" { job_queue_type * job_queue_alloc( int , const char * ok_file , const char * exit_file); void job_queue_free(job_queue_type *); - int job_queue_add_job_mt(job_queue_type * , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * , - const char * , - int argc , - const char ** argv ); - - int job_queue_add_job_st(job_queue_type * , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * , - const char * , - int argc , - const char ** argv ); + int job_queue_add_job(job_queue_type * , + const char * run_cmd , + job_callback_ftype * done_callback, + job_callback_ftype * retry_callback, + job_callback_ftype * exit_callback, + void * callback_arg , + int num_cpu , + const char * , + const char * , + int argc , + const char ** argv ); void job_queue_reset(job_queue_type * queue); void job_queue_run_jobs(job_queue_type * queue, int num_total_run, bool verbose); @@ -72,14 +60,12 @@ extern "C" { void * job_queue_run_jobs__(void * ); void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * queue_thread , int job_size , bool verbose); - job_status_type job_queue_iget_job_status(const job_queue_type * , int ); - const char * job_queue_status_name( job_status_type status ); + job_status_type job_queue_iget_job_status(job_queue_type * , int ); int job_queue_iget_status_summary( const job_queue_type * queue , job_status_type status); time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index); time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index); time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index); - job_driver_type job_queue_lookup_driver_name( const char * driver_name ); void job_queue_set_max_job_duration(job_queue_type * queue, int max_duration_seconds); int job_queue_get_max_job_duration(const job_queue_type * queue); @@ -98,20 +84,25 @@ extern "C" { void * job_queue_iget_job_data( job_queue_type * job_queue , int job_nr ); int job_queue_get_active_size( const job_queue_type * queue ); + int job_queue_get_num_callback( const job_queue_type * queue); int job_queue_get_num_running( const job_queue_type * queue); int job_queue_get_num_pending( const job_queue_type * queue); int job_queue_get_num_waiting( const job_queue_type * queue); int job_queue_get_num_complete( const job_queue_type * queue); int job_queue_get_num_failed( const job_queue_type * queue); int job_queue_get_num_killed( const job_queue_type * queue); - const char * job_queue_iget_failed_job( const job_queue_type * queue , int job_index); - const char * job_queue_iget_error_reason( const job_queue_type * queue , int job_index); - const char * job_queue_iget_stderr_capture( const job_queue_type * queue , int job_index); - const char * job_queue_iget_stderr_file( const job_queue_type * queue , int job_index); - const char * job_queue_iget_run_path( const job_queue_type * queue , int job_index); + const char * job_queue_iget_failed_job( job_queue_type * queue , int job_index); + const char * job_queue_iget_error_reason( job_queue_type * queue , int job_index); + const char * job_queue_iget_stderr_capture( job_queue_type * queue , int job_index); + const char * job_queue_iget_stderr_file( job_queue_type * queue , int job_index); + const char * job_queue_iget_run_path( job_queue_type * queue , int job_index); void job_queue_iset_external_restart(job_queue_type * queue , int job_index); job_queue_node_type * job_queue_iget_job( job_queue_type * job_queue , int job_nr ); bool job_queue_has_driver(const job_queue_type * queue ); + job_queue_node_type * job_queue_iget_node(job_queue_type * queue , int job_index); + int job_queue_get_max_running( const job_queue_type * queue ); + + UTIL_SAFE_CAST_HEADER( job_queue ); #ifdef __cplusplus } diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_manager.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_manager.h index e4bbf8554d..72bd72e292 100644 --- a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_manager.h +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_manager.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'job_queue.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2011 Statoil ASA, Norway. + + The file 'job_queue.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #ifndef __JOB_QUEUE_MANAGER_H__ @@ -30,12 +30,19 @@ typedef struct job_queue_manager_struct job_queue_manager_type; job_queue_manager_type * job_queue_manager_alloc( job_queue_type * job_queue ); void job_queue_manager_free( job_queue_manager_type * manager ); - void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose); + void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue); + bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds); void job_queue_manager_wait( job_queue_manager_type * manager); int job_queue_manager_get_num_running( const job_queue_manager_type * manager); - int job_queue_manager_get_num_complete( const job_queue_manager_type * manager); + int job_queue_manager_get_num_success( const job_queue_manager_type * manager); + int job_queue_manager_get_num_failed( const job_queue_manager_type * manager); bool job_queue_manager_is_running( const job_queue_manager_type * manager); + + bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index); bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index); + bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index); + bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index); + bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index); UTIL_IS_INSTANCE_HEADER( job_queue_manager ); diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_status.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_status.h new file mode 100644 index 0000000000..78684b05cd --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/job_queue_status.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_status_test.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#ifndef __JOB_QUEUE_STATUS_H__ +#define __JOB_QUEUE_STATUS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + typedef struct job_queue_status_struct job_queue_status_type; + + job_queue_status_type * job_queue_status_alloc(); + void job_queue_status_free( job_queue_status_type * status ); + int job_queue_status_get_count( job_queue_status_type * status , job_status_type status_type); + void job_queue_status_clear( job_queue_status_type * status ); + void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type); + bool job_queue_status_transition( job_queue_status_type * status_count , job_status_type src_status , job_status_type target_status); + int job_queue_status_get_total_count( const job_queue_status_type * status ); + const char * job_queue_status_name( job_status_type status ); + + UTIL_IS_INSTANCE_HEADER( job_queue_status ); + UTIL_SAFE_CAST_HEADER( job_queue_status ); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/queue_driver.h b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/queue_driver.h index d30a917122..c24e130d36 100644 --- a/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/queue_driver.h +++ b/ThirdParty/Ert/devel/libjob_queue/include/ert/job_queue/queue_driver.h @@ -103,12 +103,10 @@ extern "C" { */ #define JOB_QUEUE_CAN_KILL (JOB_QUEUE_WAITING + JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED + JOB_QUEUE_USER_EXIT) - - +#define JOB_QUEUE_WAITING_STATUS (JOB_QUEUE_WAITING + JOB_QUEUE_PENDING) #define JOB_QUEUE_CAN_UPDATE_STATUS (JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED) - #define JOB_QUEUE_COMPLETE_STATUS (JOB_QUEUE_USER_EXIT + JOB_QUEUE_SUCCESS + JOB_QUEUE_FAILED) @@ -147,6 +145,13 @@ extern "C" { const char * queue_driver_type_enum_iget(int index, int * value); const char * queue_driver_status_enum_iget(int index, int * value); + typedef enum {SUBMIT_OK = 0 , + SUBMIT_JOB_FAIL = 1 , /* Typically no more attempts. */ + SUBMIT_DRIVER_FAIL = 2 , /* The driver would not take the job - for whatever reason?? */ + SUBMIT_QUEUE_CLOSED = 3 } /* The queue is currently not accepting more jobs - either (temporarilty) + because of pause or it is going down. */ submit_status_type; + + #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/devel/libjob_queue/src/CMakeLists.txt b/ThirdParty/Ert/devel/libjob_queue/src/CMakeLists.txt index 6db8d00d34..04b71eef7d 100644 --- a/ThirdParty/Ert/devel/libjob_queue/src/CMakeLists.txt +++ b/ThirdParty/Ert/devel/libjob_queue/src/CMakeLists.txt @@ -1,7 +1,8 @@ #configure_file (${CMAKE_CURRENT_SOURCE_DIR}/CMake/include/libjob_queue_build_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libjob_queue_build_config.h) -set(source_files forward_model.c queue_driver.c job_queue.c local_driver.c rsh_driver.c torque_driver.c ext_job.c ext_joblist.c workflow_job.c workflow.c workflow_joblist.c job_queue_manager.c) -set(header_files job_queue.h queue_driver.h local_driver.h rsh_driver.h torque_driver.h ext_job.h ext_joblist.h forward_model.h workflow_job.h workflow.h workflow_joblist.h job_queue_manager.h) + +set(source_files job_queue_status.c forward_model.c queue_driver.c job_queue.c job_node.c job_list.c local_driver.c rsh_driver.c torque_driver.c ext_job.c ext_joblist.c workflow_job.c workflow.c workflow_joblist.c job_queue_manager.c) +set(header_files job_queue.h queue_driver.h local_driver.h job_node.h job_list.h rsh_driver.h torque_driver.h ext_job.h ext_joblist.h forward_model.h workflow_job.h workflow.h workflow_joblist.h job_queue_manager.h) set_property(SOURCE rsh_driver.c PROPERTY COMPILE_FLAGS "-Wno-error") list( APPEND source_files lsf_driver.c) diff --git a/ThirdParty/Ert/devel/libjob_queue/src/job_list.c b/ThirdParty/Ert/devel/libjob_queue/src/job_list.c new file mode 100644 index 0000000000..99805cb13d --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/src/job_list.c @@ -0,0 +1,151 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_list.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +#define JOB_LIST_TYPE_ID 8154222 + +struct job_list_struct { + UTIL_TYPE_ID_DECLARATION; + int active_size; + int alloc_size; + job_queue_node_type ** jobs; + pthread_rwlock_t lock; +}; + + +UTIL_IS_INSTANCE_FUNCTION( job_list , JOB_LIST_TYPE_ID ) +UTIL_SAFE_CAST_FUNCTION( job_list , JOB_LIST_TYPE_ID ) + +job_list_type * job_list_alloc() { + job_list_type * job_list = util_malloc( sizeof * job_list ); + UTIL_TYPE_ID_INIT( job_list , JOB_LIST_TYPE_ID ); + job_list->active_size = 0; + job_list->alloc_size = 0; + job_list->jobs = NULL; + pthread_rwlock_init( &job_list->lock , NULL); + return job_list; +} + + +void job_list_reset( job_list_type * job_list ) { + int queue_index; + for (queue_index = 0; queue_index < job_list->active_size; queue_index++) { + job_queue_node_type * node = job_list_iget_job( job_list , queue_index ); + job_queue_node_free( node ); + job_list->jobs[queue_index] = NULL; + } + job_list->active_size = 0; +} + + +int job_list_get_size( const job_list_type * job_list ) { + return job_list->active_size; +} + + +/* + This takes ownership to the job node instance. +*/ +#define QUEUE_DEBUG 1 +void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node ) { + if (job_list->alloc_size == job_list->active_size) { + +#ifdef QUEUE_DEBUG + int new_alloc_size = job_list->alloc_size + 1; + job_queue_node_type ** new_jobs = util_malloc( sizeof * new_jobs * new_alloc_size ); + memcpy( new_jobs , job_list->jobs , sizeof * new_jobs * job_list->active_size ); + free( job_list->jobs ); + job_list->jobs = new_jobs; +#else + int new_alloc_size = util_int_max( 16 , job_list->alloc_size * 2); + job_list->jobs = util_realloc( job_list->jobs , sizeof * job_list->jobs * new_alloc_size ); +#endif + + job_list->alloc_size = new_alloc_size; + } + + { + int queue_index = job_list_get_size( job_list ); + job_queue_node_set_queue_index(job_node, queue_index ); + job_list->jobs[queue_index] = job_node; + } + job_list->active_size++; + +} + + +job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index) { + if (queue_index >= 0 && queue_index < job_list->active_size) + return job_list->jobs[queue_index]; + else { + util_abort("%s: invalid queue_index:%d Valid range: [0,%d) \n",__func__ , queue_index , queue_index); + return NULL; + } +} + + +void job_list_free( job_list_type * job_list ) { + if (job_list->alloc_size > 0) { + job_list_reset( job_list ); + free( job_list->jobs ); + } + free( job_list ); +} + + + +void job_list_get_wrlock( job_list_type * list) { + pthread_rwlock_wrlock( &list->lock ); +} + +void job_list_get_rdlock( job_list_type * list) { + pthread_rwlock_rdlock( &list->lock ); +} + + +void job_list_unlock( job_list_type * list) { + pthread_rwlock_unlock( &list->lock ); +} + + +void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2) { + if (pthread_rwlock_tryrdlock( &list->lock ) == 0) { + // Seems to be no writers waiting - take a short sleep and return. + pthread_rwlock_unlock( &list->lock ); + usleep( usleep_time1 ); + } else + // A writer already has the lock - let more writers get access; sleep longer. + usleep( usleep_time2 ); + +} diff --git a/ThirdParty/Ert/devel/libjob_queue/src/job_node.c b/ThirdParty/Ert/devel/libjob_queue/src/job_node.c new file mode 100644 index 0000000000..94c8f5077a --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/src/job_node.c @@ -0,0 +1,558 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_node.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define JOB_QUEUE_NODE_TYPE_ID 3315299 +#define INVALID_QUEUE_INDEX -999 + +struct job_queue_node_struct { + UTIL_TYPE_ID_DECLARATION; + int num_cpu; /* How many cpu's will this job need - the driver is free to ignore if not relevant. */ + char *run_cmd; /* The path to the actual executable. */ + char *exit_file; /* The queue will look for the occurence of this file to detect a failure. */ + char *ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */ + char *job_name; /* The name of the job. */ + char *run_path; /* Where the job is run - absolute path. */ + job_callback_ftype *done_callback; + job_callback_ftype *retry_callback; /* To determine if job can be retried */ + job_callback_ftype *exit_callback; /* Callback to perform any cleanup */ + void *callback_arg; + int argc; /* The number of commandline arguments to pass when starting the job. */ + char **argv; /* The commandline arguments. */ + int queue_index; + + /*-----------------------------------------------------------------*/ + char *failed_job; /* Name of the job (in the chain) which has failed. */ + char *error_reason; /* The error message from the failed job. */ + char *stderr_capture; + char *stderr_file; /* Name of the file containing stderr information. */ + /*-----------------------------------------------------------------*/ + + int submit_attempt; /* Which attempt is this ... */ + job_status_type job_status; /* The current status of the job. */ + pthread_mutex_t data_mutex; /* Protecting the access to the job_data pointer. */ + void *job_data; /* Driver specific data about this job - fully handled by the driver. */ + time_t submit_time; /* When was the job added to job_queue - the FIRST TIME. */ + time_t sim_start; /* When did the job change status -> RUNNING - the LAST TIME. */ + time_t sim_end ; /* When did the job finish successfully */ +}; + + + +void job_queue_node_free_error_info( job_queue_node_type * node ) { + util_safe_free(node->error_reason); + util_safe_free(node->stderr_capture); + util_safe_free(node->stderr_file); + util_safe_free(node->failed_job); +} + + + +/* + When the job script has detected failure it will create a "EXIT" + file in the runpath directory; this function will inspect the EXIT + file and determine which job has failed, the reason the job script + has given to fail the job (typically missing TARGET_FILE) and + capture the stderr from the job. + + The file is XML formatted: + + ------------------------------------------------ + + + Name of job + Reason why the job failed + + Capture of stderr from the job, can typically be + a multiline string. + + + ------------------------------------------------ + + This format is written by the dump_EXIT_file() function in the + job_dispatch.py script. +*/ + +/* + This extremely half-assed XML "parsing" should of course be kept a + secret... +*/ + +static char * __alloc_tag_content( const char * xml_buffer , const char * tag) { + char * open_tag = util_alloc_sprintf("<%s>" , tag); + char * close_tag = util_alloc_sprintf("" , tag); + + char * start_ptr = strstr( xml_buffer , open_tag ); + char * end_ptr = strstr( xml_buffer , close_tag ); + char * tag_content = NULL; + + if ((start_ptr != NULL) && (end_ptr != NULL)) { + int length; + start_ptr += strlen(open_tag); + + length = end_ptr - start_ptr; + tag_content = util_alloc_substring_copy( start_ptr , 0 , length ); + } + + free( open_tag ); + free( close_tag ); + return tag_content; +} + + + + +/** + This code is meant to capture which of the jobs has failed; why it + has failed and the stderr stream of the failing job. Depending on + the failure circumstances the EXIT file might not be around. +*/ + +void job_queue_node_fscanf_EXIT( job_queue_node_type * node ) { + job_queue_node_free_error_info( node ); + if (node->exit_file) { + if (util_file_exists( node->exit_file )) { + char * xml_buffer = util_fread_alloc_file_content( node->exit_file, NULL); + + node->failed_job = __alloc_tag_content( xml_buffer , "job" ); + node->error_reason = __alloc_tag_content( xml_buffer , "reason" ); + node->stderr_capture = __alloc_tag_content( xml_buffer , "stderr"); + node->stderr_file = __alloc_tag_content( xml_buffer , "stderr_file"); + + free( xml_buffer ); + } else + node->failed_job = util_alloc_sprintf("EXIT file:%s not found - load failure?" , node->exit_file); + } +} + + + + + + +UTIL_IS_INSTANCE_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID ) +UTIL_SAFE_CAST_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID ) + + + +int job_queue_node_get_queue_index( const job_queue_node_type * node ) { + if (node->queue_index == INVALID_QUEUE_INDEX) + util_abort("%s: internal error: asked for not-yet-initialized node->queue_index\n",__func__); + return node->queue_index; +} + +void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index) { + if (node->queue_index == INVALID_QUEUE_INDEX) + node->queue_index = queue_index; + else + util_abort("%s: internal error: atteeempt to reset queue_index \n",__func__); +} + + +/* + The error information is retained even after the job has completed + completely, so that calling scope can ask for it - that is the + reason there are separate free() and clear functions for the error related fields. +*/ + +void job_queue_node_free_data(job_queue_node_type * node) { + util_safe_free( node->job_name ); + util_safe_free( node->exit_file ); + util_safe_free( node->ok_file ); + util_safe_free( node->run_cmd ); + util_free_stringlist( node->argv , node->argc ); + + if (node->job_data != NULL) + util_abort("%s: internal error - driver spesific job data has not been freed - will leak.\n",__func__); +} + + +void job_queue_node_free(job_queue_node_type * node) { + job_queue_node_free_data(node); + job_queue_node_free_error_info(node); + util_safe_free(node->run_path); + free(node); +} + + +job_status_type job_queue_node_get_status(const job_queue_node_type * node) { + return node->job_status; +} + + + + + + +/******************************************************************/ +/* + These four functions all require that the caller has aquired the + data lock before entering. +*/ + + + + + +void job_queue_node_reset_submit_attempt( job_queue_node_type * node) { + node->submit_attempt = 0; +} + +int job_queue_node_get_submit_attempt( const job_queue_node_type * node) { + return node->submit_attempt; +} + + + + + + + + + +job_queue_node_type * job_queue_node_alloc_simple( const char * job_name , + const char * run_path , + const char * run_cmd , + int argc , + const char ** argv) { + return job_queue_node_alloc( job_name , run_path , run_cmd , argc , argv , 1, NULL , NULL, NULL, NULL, NULL, NULL); +} + + +job_queue_node_type * job_queue_node_alloc( const char * job_name , + const char * run_path , + const char * run_cmd , + int argc , + const char ** argv, + int num_cpu, + const char * ok_file, + const char * exit_file, + job_callback_ftype * done_callback, + job_callback_ftype * retry_callback, + job_callback_ftype * exit_callback, + void * callback_arg) { + + if (util_is_directory( run_path )) { + job_queue_node_type * node = util_malloc(sizeof * node ); + + UTIL_TYPE_ID_INIT( node , JOB_QUEUE_NODE_TYPE_ID ); + { + /* The data initialized in this block should *NEVER* change. */ + node->job_name = util_alloc_string_copy( job_name ); + + if (util_is_abs_path(run_path)) + node->run_path = util_alloc_string_copy( run_path ); + else + node->run_path = util_alloc_realpath( run_path ); + + node->run_cmd = util_alloc_string_copy( run_cmd ); + node->argc = argc; + node->argv = util_alloc_stringlist_copy( argv , argc ); + node->num_cpu = num_cpu; + + if (ok_file) + node->ok_file = util_alloc_filename(node->run_path , ok_file , NULL); + else + node->ok_file = NULL; + + if (exit_file) + node->exit_file = util_alloc_filename(node->run_path , exit_file , NULL); + else + node->exit_file = NULL; + + node->exit_callback = exit_callback; + node->retry_callback = retry_callback; + node->done_callback = done_callback; + node->callback_arg = callback_arg; + } + { + node->error_reason = NULL; + node->stderr_capture = NULL; + node->stderr_file = NULL; + node->failed_job = NULL; + } + { + node->job_status = JOB_QUEUE_NOT_ACTIVE; + node->queue_index = INVALID_QUEUE_INDEX; + node->submit_attempt = 0; + node->job_data = NULL; /* The allocation is run in single thread mode - we assume. */ + node->sim_start = 0; + node->sim_end = 0; + node->submit_time = time( NULL ); + } + + pthread_mutex_init( &node->data_mutex , NULL ); + return node; + } else + return NULL; +} + + +const char * job_queue_node_get_error_reason( const job_queue_node_type * node) { + return node->error_reason; +} + +const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node) { + return node->stderr_capture; +} + + +const char * job_queue_node_get_stderr_file( const job_queue_node_type * node) { + return node->stderr_file; +} + + +const char * job_queue_node_get_exit_file( const job_queue_node_type * node) { + return node->exit_file; +} + + +const char * job_queue_node_get_ok_file( const job_queue_node_type * node) { + return node->ok_file; +} + + + +const char * job_queue_node_get_run_path( const job_queue_node_type * node) { + return node->run_path; +} + +const char * job_queue_node_get_name( const job_queue_node_type * node) { + return node->job_name; +} + +const char * job_queue_node_get_failed_job( const job_queue_node_type * node) { + return node->failed_job; +} + + +time_t job_queue_node_get_sim_start( const job_queue_node_type * node ) { + return node->sim_start; +} + + +time_t job_queue_node_get_sim_end( const job_queue_node_type * node ) { + return node->sim_end; +} + +time_t job_queue_node_get_submit_time( const job_queue_node_type * node ) { + return node->submit_time; +} + + + +bool job_queue_node_run_DONE_callback( job_queue_node_type * node ) { + bool OK = true; + if (node->done_callback) + OK = node->done_callback( node->callback_arg ); + + return OK; +} + + +bool job_queue_node_run_RETRY_callback( job_queue_node_type * node ) { + bool retry = false; + if (node->retry_callback) + retry = node->retry_callback( node->callback_arg ); + + return retry; +} + + +void job_queue_node_run_EXIT_callback( job_queue_node_type * node ) { + if (node->exit_callback) + node->exit_callback( node->callback_arg ); +} + +static void job_queue_node_set_status(job_queue_node_type * node , job_status_type new_status) { + if (new_status != node->job_status) { + node->job_status = new_status; + + /* + We record sim start when the node is in state JOB_QUEUE_WAITING + to be sure that we do not miss the start time completely for + very fast jobs which are registered in the state + JOB_QUEUE_RUNNING. + */ + if (new_status == JOB_QUEUE_WAITING) + node->sim_start = time( NULL ); + + if (new_status == JOB_QUEUE_RUNNING) + node->sim_start = time( NULL ); + + if (new_status == JOB_QUEUE_SUCCESS) + node->sim_end = time( NULL ); + + if (new_status == JOB_QUEUE_FAILED) + job_queue_node_fscanf_EXIT( node ); + + } +} + + +submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) { + submit_status_type submit_status; + void * job_data = queue_driver_submit_job( driver, + node->run_cmd, + node->num_cpu, + node->run_path, + node->job_name, + node->argc, + (const char **) node->argv); + pthread_mutex_lock( &node->data_mutex ); + { + if (job_data != NULL) { + job_status_type old_status = node->job_status; + job_status_type new_status = JOB_QUEUE_SUBMITTED; + + node->job_data = job_data; + node->submit_attempt++; + /* + The status JOB_QUEUE_SUBMITTED is internal, and not + exported anywhere. The job_queue_update_status() will + update this to PENDING or RUNNING at the next call. The + important difference between SUBMITTED and WAITING is + that SUBMITTED have job_data != NULL and the + job_queue_node free function must be called on it. + */ + submit_status = SUBMIT_OK; + job_queue_node_set_status( node , new_status); + job_queue_status_transition(status, old_status, new_status); + } else + /* + In this case the status of the job itself will be + unmodified; i.e. it will still be WAITING, and a new attempt + to submit it will be performed in the next round. + */ + submit_status = SUBMIT_DRIVER_FAIL; + } + pthread_mutex_unlock( &node->data_mutex ); + return submit_status; +} + + +bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) { + bool status_change = false; + pthread_mutex_lock( &node->data_mutex ); + { + if (node->job_data) { + job_status_type current_status = job_queue_node_get_status(node); + if (current_status & JOB_QUEUE_CAN_UPDATE_STATUS) { + job_status_type new_status = queue_driver_get_status( driver , node->job_data); + status_change = job_queue_status_transition(status , current_status , new_status); + job_queue_node_set_status(node,new_status); + } + } + } + pthread_mutex_unlock( &node->data_mutex ); + return status_change; +} + + +bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status) { + bool status_change; + pthread_mutex_lock( &node->data_mutex ); + { + job_status_type old_status = job_queue_node_get_status( node ); + status_change = job_queue_status_transition(status , old_status, new_status); + + if (status_change) + job_queue_node_set_status( node , new_status ); + } + pthread_mutex_unlock( &node->data_mutex ); + return status_change; +} + + + +bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) { + bool result = false; + pthread_mutex_lock( &node->data_mutex ); + { + job_status_type current_status = job_queue_node_get_status( node ); + if (current_status & JOB_QUEUE_CAN_KILL) { + /* + Jobs with status JOB_QUEUE_WAITING are killable - in the + sense that status should be set to JOB_QUEUE_USER_KILLED; but + they do not have any driver specific job_data, and the + driver->kill_job() function can NOT be called. + */ + if (current_status != JOB_QUEUE_WAITING) { + queue_driver_kill_job( driver , node->job_data ); + if (node->job_data) { + queue_driver_free_job( driver , node->job_data ); + node->job_data = NULL; + } + } + job_queue_status_transition(status, current_status, JOB_QUEUE_USER_KILLED); + job_queue_node_set_status( node , JOB_QUEUE_USER_KILLED); + result = true; + } + } + pthread_mutex_unlock( &node->data_mutex ); + return result; +} + + +/* + This frees the storage allocated by the driver - the storage + allocated by the queue layer is retained. + + In the case of jobs which are first marked as successfull by the + queue layer, and then subsequently set to status EXIT by the + DONE_callback this function will be called twice; i.e. we must + protect against a double free. +*/ + +void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver) { + pthread_mutex_lock( &node->data_mutex ); + { + if (node->job_data != NULL) + queue_driver_free_job( driver , node->job_data ); + node->job_data = NULL; + } + pthread_mutex_unlock( &node->data_mutex ); +} + + + +void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status) { + pthread_mutex_lock( &node->data_mutex ); + { + job_status_type current_status = job_queue_node_get_status( node ); + job_queue_status_transition(status, current_status, JOB_QUEUE_WAITING); + job_queue_node_set_status( node , JOB_QUEUE_WAITING); + job_queue_node_reset_submit_attempt(node); + } + pthread_mutex_unlock( &node->data_mutex ); +} diff --git a/ThirdParty/Ert/devel/libjob_queue/src/job_queue.c b/ThirdParty/Ert/devel/libjob_queue/src/job_queue.c index 78cbce65ff..0ad7df26f6 100644 --- a/ThirdParty/Ert/devel/libjob_queue/src/job_queue.c +++ b/ThirdParty/Ert/devel/libjob_queue/src/job_queue.c @@ -30,13 +30,14 @@ #include #include +#include +#include +#include #include - -#define JOB_QUEUE_START_SIZE 16 - /** + The running of external jobs is handled thruogh an abstract job_queue implemented in this file; the job_queue then contains a 'driver' which actually runs the job. All drivers must support the @@ -88,46 +89,6 @@ */ -/* - Threads and such. - ================= - - The job_queue is executed with mulitple threads, and the potential for - thread-related fuckups is immense. There are essentially two different scopes - which acces the internal state of the queue concurrently: - - 1. The function job_queue_run_jobs() is the main function administrating the - queue, this includes starting and stopping jobs, and collecting the - status of the various jobs. The thread running this function is the - default 'owner' of the information in the job_queue instance. - - 2. External scope can: - - o Query the status of the queue / individual jobs. [Read access] - - o Issue commands to make the queue resubmit/kill/wait/... [Write access] - - Observe that there can be maaany concurrent invokations of the second - type. Data structures which can change must obviously be protected with - read/write locking, however scalars are NOT protected, i.e the two code blocks: - - - ... - state = new_value; - ... - - and - - ... - return state; - - can run concurrently. In principle we might risk that the return value from - "return state;" is inconsistent, i.e. different from both new_value and the - value state had prior to the statement "state = new_value;" - however all - tests should be explicit so that such an inconsistency is actually OK. - -*/ - /* Some words about status @@ -224,12 +185,6 @@ -typedef enum {SUBMIT_OK = 0 , - SUBMIT_JOB_FAIL = 1 , /* Typically no more attempts. */ - SUBMIT_DRIVER_FAIL = 2 , /* The driver would not take the job - for whatever reason?? */ - SUBMIT_QUEUE_CLOSED = 3 } /* The queue is currently not accepting more jobs - either (temporarilty) - because of pause or it is going down. */ submit_status_type; - /** @@ -250,436 +205,57 @@ typedef enum {SUBMIT_OK = 0 , */ -struct job_queue_node_struct { - job_status_type job_status; /* The current status of the job. */ - int submit_attempt; /* Which attempt is this ... */ - int num_cpu; /* How many cpu's will this job need - the driver is free to ignore if not relevant. */ - char *run_cmd; /* The path to the actual executable. */ - char *exit_file; /* The queue will look for the occurence of this file to detect a failure. */ - char *ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */ - char *job_name; /* The name of the job. */ - char *run_path; /* Where the job is run - absolute path. */ - /*-----------------------------------------------------------------*/ - char *failed_job; /* Name of the job (in the chain) which has failed. */ - char *error_reason; /* The error message from the failed job. */ - char *stderr_capture; - char *stderr_file; /* Name of the file containing stderr information. */ - /*-----------------------------------------------------------------*/ - void *job_data; /* Driver specific data about this job - fully handled by the driver. */ - int argc; /* The number of commandline arguments to pass when starting the job. */ - char **argv; /* The commandline arguments. */ - time_t submit_time; /* When was the job added to job_queue - the FIRST TIME. */ - time_t sim_start; /* When did the job change status -> RUNNING - the LAST TIME. */ - time_t sim_end ; /* When did the job finish successfully */ - pthread_rwlock_t job_lock; /* This lock provides read/write locking of the job_data field. */ - job_callback_ftype *done_callback; - job_callback_ftype *retry_callback; /* To determine if job can be retried */ - job_callback_ftype *exit_callback; /* Callback to perform any cleanup */ - void *callback_arg; -}; - -static const int status_index[] = { JOB_QUEUE_NOT_ACTIVE , // Initial, allocated job state, job not added - controlled by job_queue - JOB_QUEUE_WAITING , // The job is ready to be started - controlled by job_queue - JOB_QUEUE_SUBMITTED , // Job is submitted to driver - temporary state - controlled by job_queue - JOB_QUEUE_PENDING , // Job is pending, before actual execution - controlled by queue_driver - JOB_QUEUE_RUNNING , // Job is executing - controlled by queue_driver - JOB_QUEUE_DONE , // Job is done (sucessful or not), temporary state - controlled/returned by by queue_driver - JOB_QUEUE_EXIT , // Job is done, with exit status != 0, temporary state - controlled/returned by by queue_driver - JOB_QUEUE_USER_EXIT , // User / queue system has requested killing of job - controlled by job_queue / external scope - JOB_QUEUE_USER_KILLED, // Job has been killed, due to JOB_QUEUE_USER_EXIT, FINAL STATE - controlled by job_queue - JOB_QUEUE_SUCCESS , // All good, comes after JOB_QUEUE_DONE, with additional checks, FINAL STATE - controlled by job_queue - JOB_QUEUE_RUNNING_CALLBACK, // Temporary state, while running requested callbacks after an ended job - controlled by job_queue - JOB_QUEUE_FAILED }; // Job has failed, no more retries, FINAL STATE - -static const char* status_name[] = { "JOB_QUEUE_NOT_ACTIVE" , - "JOB_QUEUE_WAITING" , - "JOB_QUEUE_SUBMITTED" , - "JOB_QUEUE_PENDING" , - "JOB_QUEUE_RUNNING" , - "JOB_QUEUE_DONE" , - "JOB_QUEUE_EXIT" , - "JOB_QUEUE_USER_KILLED" , - "JOB_QUEUE_USER_EXIT" , - "JOB_QUEUE_SUCCESS" , - "JOB_QUEUE_RUNNING_CALLBACK", - "JOB_QUEUE_FAILED" }; - - - /*****************************************************************/ - -/** - - This is the struct for a whole queue. Observe the following: - - 1. The number of elements is specified at the allocation time, and - all nodes are allocated then; i.e. when xx_insert_job() is called - from external scope a new node is not actaully created - internally, it is just an existing node which is initialized. - - 2. The queue can start running before all jobs are added. - -*/ +#define JOB_QUEUE_TYPE_ID 665210 struct job_queue_struct { - int active_size; /* The current number of job slots in the queue. */ - int alloc_size; /* The current allocated size of jobs array. */ - int max_submit; /* The maximum number of submit attempts for one job. */ + UTIL_TYPE_ID_DECLARATION; + job_list_type * job_list; + job_queue_status_type * status; char * exit_file; /* The queue will look for the occurence of this file to detect a failure. */ char * ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */ - job_queue_node_type ** jobs; /* A vector of job nodes .*/ - queue_driver_type * driver; /* A pointer to a driver instance (LSF|LOCAL|RSH) which actually 'does it'. */ - int status_list[JOB_QUEUE_MAX_STATE]; /* The number of jobs in the different states. */ - int old_status_list[JOB_QUEUE_MAX_STATE]; /* Should the display be updated ?? */ + queue_driver_type * driver; /* A pointer to a driver instance (LSF|LOCAL|RSH) which actually 'does it'. */ + bool open; /* True if the queue has been reset and is ready for use, false if the queue has been used and not reset */ bool user_exit; /* If there comes an external signal to abondond the whole thing user_exit will be set to true, and things start to dwindle down. */ bool running; bool pause_on; bool submit_complete; - bool grow; /* The function adding new jobs is requesting the job_queue function to grow the jobs array. */ + + int max_submit; /* The maximum number of submit attempts for one job. */ int max_ok_wait_time; /* Seconds to wait for an OK file - when the job itself has said all OK. */ int max_duration; /* Maximum allowed time for a job to run, 0 = unlimited */ time_t stop_time; /* A job is only allowed to run until this time. 0 = no time set, ignore stop_time */ unsigned long usleep_time; /* The sleep time before checking for updates. */ - pthread_mutex_t status_mutex; /* This mutex ensure that the status-change code is only run by one thread. */ pthread_mutex_t run_mutex; /* This mutex is used to ensure that ONLY one thread is executing the job_queue_run_jobs(). */ - pthread_mutex_t queue_mutex; thread_pool_type * work_pool; }; -/*****************************************************************/ - -static void job_queue_grow( job_queue_type * queue ); -static int STATUS_INDEX( job_status_type status ) { - int index = 0; - - while (true) { - if (status_index[index] == status) - return index; - - index++; - if (index == JOB_QUEUE_MAX_STATE) - util_abort("%s: failed to get index from status:%d \n",__func__ , status); - } -} - -/* - int status_index = 0; - int status = input_status; - while ( (status != 1) && (status_index < JOB_QUEUE_MAX_STATE)) { - status >>= 1; - status_index++; - } - if (status != 1) - util_abort("%s: failed to get index from status:%d \n",__func__ , status); - return status_index; -} -*/ - - - -/*****************************************************************/ - -/* - When the job script has detected failure it will create a "EXIT" - file in the runpath directory; this function will inspect the EXIT - file and determine which job has failed, the reason the job script - has given to fail the job (typically missing TARGET_FILE) and - capture the stderr from the job. - - The file is XML formatted: - - ------------------------------------------------ - - - Name of job - Reason why the job failed - - Capture of stderr from the job, can typically be - a multiline string. - - - ------------------------------------------------ - - This format is written by the dump_EXIT_file() function in the - job_dispatch.py script. -*/ - -/* - This extremely half-assed XML "parsing" should of course be kept a - secret... -*/ - -static char * __alloc_tag_content( const char * xml_buffer , const char * tag) { - char * open_tag = util_alloc_sprintf("<%s>" , tag); - char * close_tag = util_alloc_sprintf("" , tag); - - char * start_ptr = strstr( xml_buffer , open_tag ); - char * end_ptr = strstr( xml_buffer , close_tag ); - char * tag_content = NULL; - - if ((start_ptr != NULL) && (end_ptr != NULL)) { - int length; - start_ptr += strlen(open_tag); - - length = end_ptr - start_ptr; - tag_content = util_alloc_substring_copy( start_ptr , 0 , length ); - } - - free( open_tag ); - free( close_tag ); - return tag_content; -} - - -static void job_queue_node_free_error_info( job_queue_node_type * node ) { - util_safe_free(node->error_reason); - util_safe_free(node->stderr_capture); - util_safe_free(node->stderr_file); - util_safe_free(node->failed_job); -} - - - -/** - This code is meant to capture which of the jobs has failed; why it - has failed and the stderr stream of the failing job. Depending on - the failure circumstances the EXIT file might not be around. -*/ - -static void job_queue_node_fscanf_EXIT( job_queue_node_type * node ) { - job_queue_node_free_error_info( node ); - if (node->exit_file) { - if (util_file_exists( node->exit_file )) { - char * xml_buffer = util_fread_alloc_file_content( node->exit_file, NULL); - - node->failed_job = __alloc_tag_content( xml_buffer , "job" ); - node->error_reason = __alloc_tag_content( xml_buffer , "reason" ); - node->stderr_capture = __alloc_tag_content( xml_buffer , "stderr"); - node->stderr_file = __alloc_tag_content( xml_buffer , "stderr_file"); - - free( xml_buffer ); - } else - node->failed_job = util_alloc_sprintf("EXIT file:%s not found - load failure?" , node->exit_file); - } -} - - - -static void job_queue_node_clear_error_info(job_queue_node_type * node) { - node->failed_job = NULL; - node->error_reason = NULL; - node->stderr_capture = NULL; - node->stderr_file = NULL; - node->run_path = NULL; -} - - - -static void job_queue_node_clear(job_queue_node_type * node) { - node->job_status = JOB_QUEUE_NOT_ACTIVE; - node->submit_attempt = 0; - node->job_name = NULL; - node->job_data = NULL; - node->exit_file = NULL; - node->ok_file = NULL; - node->run_cmd = NULL; - node->argc = 0; - node->argv = NULL; - node->exit_callback = NULL; - node->retry_callback = NULL; - node->done_callback = NULL; - node->callback_arg = NULL; - node->sim_start = 0; - node->sim_end = 0; -} - - -static job_queue_node_type * job_queue_node_alloc( ) { - job_queue_node_type * node = util_malloc(sizeof * node ); - - job_queue_node_clear(node); - job_queue_node_clear_error_info(node); - pthread_rwlock_init( &node->job_lock , NULL); - - return node; -} - - /* - The error information is retained even after the job has completed - completely, so that calling scope can ask for it - that is the - reason there are separate free() and clear functions for the error related fields. + Must hold on to: + + 1. A write lock for the job node. + 3. A read lock for the job_list + */ - -static void job_queue_node_free_data(job_queue_node_type * node) { - util_safe_free( node->job_name ); - util_safe_free( node->exit_file ); - util_safe_free( node->ok_file ); - util_safe_free( node->run_cmd ); - util_free_stringlist( node->argv , node->argc ); - if (node->callback_arg) { - arg_pack_free( node->callback_arg ); - node->callback_arg = NULL; - } - - if (node->job_data != NULL) - util_abort("%s: internal error - driver spesific job data has not been freed - will leak.\n",__func__); -} - - -static void job_queue_node_free(job_queue_node_type * node) { - job_queue_node_free_data(node); - job_queue_node_free_error_info(node); - util_safe_free(node->run_path); - free(node); -} - - -static job_status_type job_queue_node_get_status(const job_queue_node_type * node) { - return node->job_status; -} - - - - -static void job_queue_node_finalize(job_queue_node_type * node) { - job_queue_node_free_data(node); - job_queue_node_clear(node); -} - - - -/*****************************************************************/ - -static bool job_queue_change_node_status(job_queue_type * , job_queue_node_type * , job_status_type ); - - -static void job_queue_initialize_node(job_queue_type * queue , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * run_path , - const char * job_name , - int job_index , - int argc , - const char ** argv) { - - job_queue_node_type * node = queue->jobs[job_index]; - node->submit_attempt = 0; - node->num_cpu = num_cpu; - node->job_name = util_alloc_string_copy( job_name ); - node->job_data = NULL; /* The allocation is run in single thread mode - we assume. */ - node->argc = argc; - node->argv = util_alloc_stringlist_copy( argv , argc ); - - util_safe_free(node->run_path); // Might have a value from previous run. - if (util_is_abs_path(run_path)) - node->run_path = util_alloc_string_copy( run_path ); - else - node->run_path = util_alloc_realpath( run_path ); - - if ( !util_is_directory(node->run_path) ) - util_abort("%s: the run_path: %s does not exist - aborting \n",__func__ , node->run_path); - - if (queue->exit_file != NULL) - node->exit_file = util_alloc_filename(node->run_path , queue->exit_file , NULL); - if (queue->ok_file != NULL) - node->ok_file = util_alloc_filename(node->run_path , queue->ok_file , NULL); - node->run_cmd = util_alloc_string_copy( run_cmd ); - - node->exit_callback = exit_callback; - node->retry_callback = retry_callback; - node->done_callback = done_callback; - node->callback_arg = callback_arg; - node->sim_start = 0; - node->sim_end = 0; - node->submit_time = time( NULL ); - - /* Now the job is ready to be picked by the queue manager. */ - job_queue_change_node_status(queue , node , JOB_QUEUE_WAITING); -} - - - - -static void job_queue_assert_queue_index(const job_queue_type * queue , int queue_index) { - if (queue_index < 0 || queue_index >= queue->active_size) - util_abort("%s: invalid queue_index - internal error - aborting \n",__func__); -} - - - -/** - This function WILL be called by several threads concurrently; both - directly from the thread running the job_queue_run_jobs() function, - and indirectly thorugh exported functions like: - - job_queue_set_external_restart(); - job_queue_set_external_fail(); - ... - - It is therefor essential that only one thread is running this code - at time. -*/ - static bool job_queue_change_node_status(job_queue_type * queue , job_queue_node_type * node , job_status_type new_status) { - bool status_change = false; - pthread_mutex_lock( &queue->status_mutex ); - { - job_status_type old_status = job_queue_node_get_status( node ); - - if (new_status != old_status) { - node->job_status = new_status; - queue->status_list[ STATUS_INDEX(old_status) ]--; - queue->status_list[ STATUS_INDEX(new_status) ]++; - - if (new_status == JOB_QUEUE_RUNNING) - node->sim_start = time( NULL ); - - if (new_status == JOB_QUEUE_SUCCESS) - node->sim_end = time( NULL ); - - status_change = true; - - if (new_status == JOB_QUEUE_FAILED) - job_queue_node_fscanf_EXIT( node ); - } - } - pthread_mutex_unlock( &queue->status_mutex ); - return status_change; + return job_queue_node_status_transition( node , queue->status , new_status ); } -/* - This frees the storage allocated by the driver - the storage - allocated by the queue layer is retained. - In the case of jobs which are first marked as successfull by the - queue layer, and then subsequently set to status EXIT by the - DONE_callback this function will be called twice; i.e. we must - protect against a double free. -*/ +/*****************************************************************/ + + + -static void job_queue_free_job_driver_data(job_queue_type * queue , job_queue_node_type * node) { - pthread_rwlock_wrlock( &node->job_lock ); - { - if (node->job_data != NULL) - queue_driver_free_job( queue->driver , node->job_data ); - node->job_data = NULL; - } - pthread_rwlock_unlock( &node->job_lock ); -} @@ -694,82 +270,35 @@ static void job_queue_free_job_driver_data(job_queue_type * queue , job_queue_no */ /* - Will return true if the status has changed since the last time. + Will return true if there is any status change. Must already hold + on to joblist readlock */ static bool job_queue_update_status(job_queue_type * queue ) { bool update = false; - queue_driver_type *driver = queue->driver; int ijob; - - for (ijob = 0; ijob < queue->active_size; ijob++) { - job_queue_node_type * node = queue->jobs[ijob]; - - pthread_rwlock_rdlock( &node->job_lock ); - { - if (node->job_data != NULL) { - job_status_type current_status = job_queue_node_get_status(node); - if (current_status & JOB_QUEUE_CAN_UPDATE_STATUS) { - job_status_type new_status = queue_driver_get_status( driver , node->job_data); - job_queue_change_node_status(queue , node , new_status); - } - } - } - pthread_rwlock_unlock( &node->job_lock ); - } - - /* Has the net status changed? */ - { - int istat; - for (istat = 0; istat < JOB_QUEUE_MAX_STATE; istat++) { - if (queue->old_status_list[istat] != queue->status_list[istat]) - update = true; - queue->old_status_list[istat] = queue->status_list[istat]; - } + for (ijob = 0; ijob < job_list_get_size( queue->job_list ); ijob++) { + job_queue_node_type * node = job_list_iget_job( queue->job_list , ijob ); + bool node_update = job_queue_node_update_status( node , queue->status , queue->driver ); + if (node_update) + update = true; } return update; } - +/* + Must hold on to joblist readlock +*/ static submit_status_type job_queue_submit_job(job_queue_type * queue , int queue_index) { submit_status_type submit_status; if (queue->user_exit || queue->pause_on) submit_status = SUBMIT_QUEUE_CLOSED; /* The queue is currently not accepting more jobs. */ else { - job_queue_assert_queue_index(queue , queue_index); { - job_queue_node_type * node = queue->jobs[queue_index]; - void * job_data = queue_driver_submit_job( queue->driver , - node->run_cmd , - node->num_cpu , - node->run_path , - node->job_name , - node->argc , - (const char **) node->argv ); - - if (job_data != NULL) { - pthread_rwlock_wrlock( &node->job_lock ); - { - node->job_data = job_data; - node->submit_attempt++; - job_queue_change_node_status(queue , node , JOB_QUEUE_SUBMITTED ); - submit_status = SUBMIT_OK; - /* - The status JOB_QUEUE_SUBMITTED is internal, and not exported anywhere. The job_queue_update_status() will - update this to PENDING or RUNNING at the next call. The important difference between SUBMITTED and WAITING - is that SUBMITTED have job_data != NULL and the job_queue_node free function must be called on it. - */ - } - pthread_rwlock_unlock( &node->job_lock ); - } else - /* - In this case the status of the job itself will be - unmodified; i.e. it will still be WAITING, and a new attempt - to submit it will be performed in the next round. - */ - submit_status = SUBMIT_DRIVER_FAIL; + job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); + submit_status = job_queue_node_submit( node , queue->status , queue->driver ); } } return submit_status; @@ -780,42 +309,6 @@ static submit_status_type job_queue_submit_job(job_queue_type * queue , int queu -const char * job_queue_iget_run_path( const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->run_path; -} - - -const char * job_queue_iget_failed_job( const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->failed_job; -} - - -const char * job_queue_iget_error_reason( const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->error_reason; -} - - -const char * job_queue_iget_stderr_capture( const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->stderr_capture; -} - - -const char * job_queue_iget_stderr_file( const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->stderr_file; -} - - - - -job_status_type job_queue_iget_job_status(const job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->job_status; -} @@ -836,9 +329,12 @@ job_status_type job_queue_iget_job_status(const job_queue_type * queue , int job */ int job_queue_iget_status_summary( const job_queue_type * queue , job_status_type status) { - return queue->status_list[ STATUS_INDEX( status ) ]; + return job_queue_status_get_count(queue->status, status); } +int job_queue_get_num_callback( const job_queue_type * queue) { + return job_queue_iget_status_summary( queue , JOB_QUEUE_RUNNING_CALLBACK ); +} int job_queue_get_num_running( const job_queue_type * queue) { return job_queue_iget_status_summary( queue , JOB_QUEUE_RUNNING ); @@ -865,7 +361,7 @@ int job_queue_get_num_killed( const job_queue_type * queue) { } int job_queue_get_active_size( const job_queue_type * queue ) { - return queue->active_size; + return job_list_get_size( queue->job_list ); } void job_queue_set_max_job_duration(job_queue_type * queue, int max_duration_seconds) { @@ -887,10 +383,11 @@ time_t job_queue_get_job_stop_time(const job_queue_type * queue) { void job_queue_set_auto_job_stop_time(job_queue_type * queue) { time_t sum_run_time_succeded_jobs = 0; int num_succeded_jobs = 0; - for (int i = 0; i < queue->active_size; ++i) { - if (JOB_QUEUE_SUCCESS == job_queue_iget_job_status(queue,i)) { + + for (int i = 0; i < job_list_get_size( queue->job_list ); i++) { + if (job_queue_iget_job_status(queue,i) == JOB_QUEUE_SUCCESS) { sum_run_time_succeded_jobs += difftime(job_queue_iget_sim_end(queue, i), job_queue_iget_sim_start(queue, i)); - ++num_succeded_jobs; + num_succeded_jobs++; } } @@ -918,38 +415,100 @@ void job_queue_set_auto_job_stop_time(job_queue_type * queue) { meaningfully killed; that is because these jobs have not yet been submitted to the queue system, and there is not yet established a mapping between external id and queue_index. -*/ -bool job_queue_kill_job_node( job_queue_type * queue , job_queue_node_type * node) { - bool result = false; - pthread_rwlock_wrlock( &node->job_lock ); - { - if (node->job_status & JOB_QUEUE_CAN_KILL) { - queue_driver_type * driver = queue->driver; - /* - Jobs with status JOB_QUEUE_WAITING are killable - in the sense that status should be set to - JOB_QUEUE_USER_KILLED; but they do not have any driver specific job_data, and the driver->kill_job() function - can NOT be called. - */ - if (node->job_status != JOB_QUEUE_WAITING) { - queue_driver_kill_job( driver , node->job_data ); - queue_driver_free_job( driver , node->job_data ); - node->job_data = NULL; - } - job_queue_change_node_status( queue , node , JOB_QUEUE_USER_KILLED ); - result = true; - } - } - pthread_rwlock_unlock( &node->job_lock ); + Must hold on to joblist:read lock. +*/ + +static bool job_queue_kill_job_node( job_queue_type * queue , job_queue_node_type * node) { + bool result = job_queue_node_kill( node , queue->status , queue->driver ); return result; } +#define ASSIGN_LOCKED_ATTRIBUTE( var , func , ...) \ +job_list_get_rdlock( queue->job_list ); \ +{ \ + job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); \ + var = func(__VA_ARGS__); \ +} \ +job_list_unlock( queue->job_list ); + + + bool job_queue_kill_job( job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return job_queue_kill_job_node(queue, node); + bool result; + ASSIGN_LOCKED_ATTRIBUTE( result , job_queue_kill_job_node , queue , node); + return result; } +time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index) { + time_t sim_start; + ASSIGN_LOCKED_ATTRIBUTE( sim_start , job_queue_node_get_sim_start , node ); + return sim_start; +} + + +time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index) { + time_t sim_end; + ASSIGN_LOCKED_ATTRIBUTE( sim_end , job_queue_node_get_sim_end , node ); + return sim_end; +} + + +time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index) { + time_t submit_time; + ASSIGN_LOCKED_ATTRIBUTE( submit_time , job_queue_node_get_submit_time , node ); + return submit_time; +} + +const char * job_queue_iget_run_path( job_queue_type * queue , int job_index) { + const char * run_path; + ASSIGN_LOCKED_ATTRIBUTE(run_path, job_queue_node_get_run_path, node ); + return run_path; +} + + +const char * job_queue_iget_failed_job( job_queue_type * queue , int job_index) { + const char * failed_job; + ASSIGN_LOCKED_ATTRIBUTE(failed_job, job_queue_node_get_failed_job, node ); + return failed_job; +} + + +const char * job_queue_iget_error_reason( job_queue_type * queue , int job_index) { + const char * error_reason; + ASSIGN_LOCKED_ATTRIBUTE(error_reason, job_queue_node_get_error_reason, node ); + return error_reason; +} + + +const char * job_queue_iget_stderr_capture( job_queue_type * queue , int job_index) { + const char * stderr_capture; + ASSIGN_LOCKED_ATTRIBUTE(stderr_capture, job_queue_node_get_stderr_capture, node ); + return stderr_capture; +} + + +const char * job_queue_iget_stderr_file( job_queue_type * queue , int job_index) { + const char * stderr_file; + ASSIGN_LOCKED_ATTRIBUTE(stderr_file, job_queue_node_get_stderr_file, node ); + return stderr_file; +} + + + +job_status_type job_queue_iget_job_status( job_queue_type * queue , int job_index) { + job_status_type job_status; + ASSIGN_LOCKED_ATTRIBUTE(job_status, job_queue_node_get_status , node ); + return job_status; +} + + + + + + + /** The external scope asks the queue to restart the the job; we reset the submit counter to zero. This function should typically be used @@ -958,9 +517,12 @@ bool job_queue_kill_job( job_queue_type * queue , int job_index) { */ void job_queue_iset_external_restart(job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - node->submit_attempt = 0; - job_queue_change_node_status( queue , node , JOB_QUEUE_WAITING ); + job_list_get_rdlock( queue->job_list ); + { + job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); + job_queue_node_restart(node,queue->status); + } + job_list_unlock( queue->job_list ); } @@ -980,26 +542,16 @@ void job_queue_iset_external_restart(job_queue_type * queue , int job_index) { */ void job_queue_iset_external_fail(job_queue_type * queue , int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - job_queue_change_node_status( queue , node , JOB_QUEUE_EXIT); + job_list_get_rdlock( queue->job_list ); + { + job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); + job_queue_node_status_transition(node,queue->status,JOB_QUEUE_EXIT); + } + job_list_unlock( queue->job_list ); } -time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->sim_start; -} - -time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->sim_end; -} - -time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index) { - job_queue_node_type * node = queue->jobs[job_index]; - return node->submit_time; -} @@ -1013,25 +565,28 @@ static void job_queue_update_spinner( int * phase ) { } -static void job_queue_print_summary(const job_queue_type *queue, bool status_change ) { +static void job_queue_print_summary(job_queue_type *queue, bool status_change ) { const char * status_fmt = "Waiting: %3d Pending: %3d Running: %3d Checking/Loading: %3d Failed: %3d Complete: %3d [ ]\b\b"; int string_length = 105; if (status_change) { for (int i=0; i < string_length; i++) printf("\b"); + { - int waiting = queue->status_list[ STATUS_INDEX(JOB_QUEUE_WAITING) ]; - int pending = queue->status_list[ STATUS_INDEX(JOB_QUEUE_PENDING) ]; + int waiting = job_queue_status_get_count( queue->status , JOB_QUEUE_WAITING ); + int pending = job_queue_status_get_count( queue->status , JOB_QUEUE_PENDING ); /* EXIT and DONE are included in "xxx_running", because the target file has not yet been checked. */ - int running = queue->status_list[ STATUS_INDEX(JOB_QUEUE_RUNNING) ] + queue->status_list[ STATUS_INDEX(JOB_QUEUE_DONE) ] + queue->status_list[ STATUS_INDEX(JOB_QUEUE_EXIT) ]; - int complete = queue->status_list[ STATUS_INDEX(JOB_QUEUE_SUCCESS) ]; - int failed = queue->status_list[ STATUS_INDEX(JOB_QUEUE_FAILED) ]; - int loading = queue->status_list[ STATUS_INDEX(JOB_QUEUE_RUNNING_CALLBACK) ]; + int running = job_queue_status_get_count( queue->status , JOB_QUEUE_RUNNING ) + + job_queue_status_get_count( queue->status , JOB_QUEUE_DONE ) + + job_queue_status_get_count( queue->status , JOB_QUEUE_EXIT ); + int complete = job_queue_status_get_count( queue->status , JOB_QUEUE_SUCCESS ); + int failed = job_queue_status_get_count( queue->status , JOB_QUEUE_FAILED ); + int loading = job_queue_status_get_count( queue->status , JOB_QUEUE_RUNNING_CALLBACK ); printf(status_fmt , waiting , pending , running , loading , failed , complete); } @@ -1042,39 +597,26 @@ static void job_queue_print_summary(const job_queue_type *queue, bool status_cha - -static void job_queue_clear_status( job_queue_type * queue ) { - for (int i=0; i < JOB_QUEUE_MAX_STATE; i++) { - queue->status_list[i] = 0; - queue->old_status_list[i] = 0; - } -} - - /** This function goes through all the nodes and call finalize on - them. hat about jobs which were NOT in a CAN_KILL state when the + them. What about jobs which were NOT in a CAN_KILL state when the killing was done, i.e. jobs which are in one of the intermediate load like states?? They */ void job_queue_reset(job_queue_type * queue) { - int i; - - for (i=0; i < queue->active_size; i++) - job_queue_node_finalize(queue->jobs[i]); - - job_queue_clear_status( queue ); + job_list_get_wrlock( queue->job_list ); + job_list_reset( queue->job_list ); + job_list_unlock( queue->job_list ); + job_queue_status_clear(queue->status); /* Be ready for the next run */ - queue->grow = false; queue->submit_complete = false; queue->pause_on = false; queue->user_exit = false; queue->open = true; - queue->active_size = 0; queue->stop_time = 0; } @@ -1086,24 +628,27 @@ bool job_queue_is_running( const job_queue_type * queue ) { static void job_queue_user_exit__( job_queue_type * queue ) { int queue_index; - for (queue_index = 0; queue_index < queue->active_size; queue_index++) { - job_queue_change_node_status( queue , queue->jobs[queue_index] , JOB_QUEUE_USER_EXIT); + for (queue_index = 0; queue_index < job_list_get_size( queue->job_list ); queue_index++) { + job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); + job_queue_node_status_transition(node,queue->status,JOB_QUEUE_USER_EXIT); } } static bool job_queue_check_node_status_files( const job_queue_type * job_queue , job_queue_node_type * node) { - if ((node->exit_file != NULL) && util_file_exists(node->exit_file)) + const char * exit_file = job_queue_node_get_exit_file( node ); + if ((exit_file != NULL) && util_file_exists(exit_file)) return false; /* It has failed. */ else { - if (node->ok_file == NULL) + const char * ok_file = job_queue_node_get_ok_file( node ); + if (ok_file == NULL) return true; /* If the ok-file has not been set we just return true immediately. */ else { int ok_sleep_time = 1; /* Time to wait between checks for OK|EXIT file. */ int total_wait_time = 0; while (true) { - if (util_file_exists( node->ok_file )) { + if (util_file_exists( ok_file )) { return true; break; } else { @@ -1123,27 +668,26 @@ static bool job_queue_check_node_status_files( const job_queue_type * job_queue static void * job_queue_run_DONE_callback( void * arg ) { - job_queue_type * job_queue; - job_queue_node_type * node; - { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - node = arg_pack_iget_ptr( arg_pack , 1 ); - arg_pack_free( arg_pack ); - } - job_queue_free_job_driver_data( job_queue , node ); + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); + int queue_index = arg_pack_iget_int( arg_pack , 1 ); + job_list_get_rdlock( job_queue->job_list ); { + job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); bool OK = job_queue_check_node_status_files( job_queue , node ); if (OK) - if (node->done_callback != NULL) - OK = node->done_callback( node->callback_arg ); + OK = job_queue_node_run_DONE_callback( node ); if (OK) job_queue_change_node_status( job_queue , node , JOB_QUEUE_SUCCESS ); else job_queue_change_node_status( job_queue , node , JOB_QUEUE_EXIT ); + + job_queue_node_free_driver_data( node , job_queue->driver ); } + job_list_unlock(job_queue->job_list ); + arg_pack_free( arg_pack ); return NULL; } @@ -1153,75 +697,76 @@ static void job_queue_handle_DONE( job_queue_type * queue , job_queue_node_type { arg_pack_type * arg_pack = arg_pack_alloc(); arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_ptr( arg_pack , node ); + arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); thread_pool_add_job( queue->work_pool , job_queue_run_DONE_callback , arg_pack ); } } static void * job_queue_run_EXIT_callback( void * arg ) { - job_queue_type * job_queue; - job_queue_node_type * node; + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); + int queue_index = arg_pack_iget_int( arg_pack , 1 ); + + job_list_get_rdlock( job_queue->job_list ); { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - node = arg_pack_iget_ptr( arg_pack , 1 ); - arg_pack_free( arg_pack ); - } - job_queue_free_job_driver_data( job_queue , node ); + job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); - if (node->submit_attempt < job_queue->max_submit) - job_queue_change_node_status( job_queue , node , JOB_QUEUE_WAITING ); /* The job will be picked up for antother go. */ - else { - bool retry = false; + if (job_queue_node_get_submit_attempt( node ) < job_queue->max_submit) + job_queue_change_node_status( job_queue , node , JOB_QUEUE_WAITING ); /* The job will be picked up for antother go. */ + else { + bool retry = job_queue_node_run_RETRY_callback( node ); - if (node->retry_callback != NULL) - retry = node->retry_callback( node->callback_arg ); + if (retry) { + /* OK - we have invoked the retry_callback() - and that has returned true; + giving this job a brand new start. */ + job_queue_node_reset_submit_attempt( node ); + job_queue_change_node_status(job_queue , node , JOB_QUEUE_WAITING); + } else { + // It's time to call it a day - if (retry) { - /* OK - we have invoked the retry_callback() - and that has returned true; - giving this job a brand new start. */ - node->submit_attempt = 0; - job_queue_change_node_status(job_queue , node , JOB_QUEUE_WAITING); - } else { - // It's time to call it a day - - if (node->exit_callback != NULL) - node->exit_callback( node->callback_arg ); - job_queue_change_node_status(job_queue , node , JOB_QUEUE_FAILED); + job_queue_node_run_EXIT_callback( node ); + job_queue_change_node_status(job_queue , node , JOB_QUEUE_FAILED); + } } + job_queue_node_free_driver_data( node , job_queue->driver ); } + job_list_unlock(job_queue->job_list ); + arg_pack_free( arg_pack ); + return NULL; } static void * job_queue_run_USER_EXIT_callback( void * arg ) { - job_queue_type * job_queue; - job_queue_node_type * node; + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); + int queue_index = arg_pack_iget_int( arg_pack , 1 ); + + job_list_get_rdlock( job_queue->job_list ); { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - node = arg_pack_iget_ptr( arg_pack , 1 ); - arg_pack_free( arg_pack ); + job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); + job_queue_node_free_driver_data( node , job_queue->driver ); + + // It's time to call it a day + job_queue_node_run_EXIT_callback( node ); + job_queue_change_node_status(job_queue, node, JOB_QUEUE_USER_KILLED); } - job_queue_free_job_driver_data( job_queue , node ); - - // It's time to call it a day - if (node->exit_callback != NULL) - node->exit_callback( node->callback_arg ); - - job_queue_change_node_status(job_queue, node, JOB_QUEUE_USER_KILLED); + job_list_unlock(job_queue->job_list ); + arg_pack_free( arg_pack ); return NULL; } + + + static void job_queue_handle_USER_EXIT( job_queue_type * queue , job_queue_node_type * node) { - // TODO: Right place for this? job_queue_kill_job_node(queue, node); job_queue_change_node_status(queue , node , JOB_QUEUE_RUNNING_CALLBACK ); { arg_pack_type * arg_pack = arg_pack_alloc(); arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_ptr( arg_pack , node ); + arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); thread_pool_add_job( queue->work_pool , job_queue_run_USER_EXIT_callback , arg_pack ); } } @@ -1231,57 +776,12 @@ static void job_queue_handle_EXIT( job_queue_type * queue , job_queue_node_type { arg_pack_type * arg_pack = arg_pack_alloc(); arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_ptr( arg_pack , node ); + arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); thread_pool_add_job( queue->work_pool , job_queue_run_EXIT_callback , arg_pack ); } } -/*****************************************************************/ - -int job_queue_get_max_running_option(queue_driver_type * driver) { - char * max_running_string = (char*)queue_driver_get_option(driver, MAX_RUNNING); - int max_running; - if (!util_sscanf_int(max_running_string, &max_running)) { - fprintf(stderr, "%s: Unable to parse option MAX_RUNNING with value %s to an int", __func__, max_running_string); - } - return max_running; -} - -void job_queue_set_max_running_option(queue_driver_type * driver, int max_running) { - char * max_running_string = util_alloc_sprintf("%d", max_running); - queue_driver_set_option(driver, MAX_RUNNING, max_running_string); - free(max_running_string); -} - - -/** - Observe that if the max number of running jobs is decreased, - nothing will be done to reduce the number of jobs currently - running; but no more jobs will be submitted until the number of - running has fallen below the new limit. - - The updated value will also be pushed down to the current driver. - - NOTE: These next three *max_running functions should not be used, rather - use the set_option feature, with MAX_RUNNING. They are (maybe) used by python - therefore not removed. -*/ -int job_queue_get_max_running( const job_queue_type * queue ) { - return job_queue_get_max_running_option(queue->driver); -} - -void job_queue_set_max_running( job_queue_type * queue , int max_running ) { - job_queue_set_max_running_option(queue->driver, max_running); -} - -/* - The return value is the new value for max_running. -*/ -int job_queue_inc_max_runnning( job_queue_type * queue, int delta ) { - job_queue_set_max_running( queue , job_queue_get_max_running( queue ) + delta ); - return job_queue_get_max_running( queue ); -} /*****************************************************************/ @@ -1289,21 +789,19 @@ static void job_queue_check_expired(job_queue_type * queue) { if ((job_queue_get_max_job_duration(queue) <= 0) && (job_queue_get_job_stop_time(queue) <= 0)) return; - for (int i = 0; i < queue->active_size; i++) { - job_queue_node_type * node = queue->jobs[i]; + for (int i = 0; i < job_list_get_size( queue->job_list ); i++) { + job_queue_node_type * node = job_list_iget_job( queue->job_list , i ); if (job_queue_node_get_status(node) == JOB_QUEUE_RUNNING) { time_t now = time(NULL); if ( job_queue_get_max_job_duration(queue) > 0) { - double elapsed = difftime(now, node->sim_start); - if (elapsed > job_queue_get_max_job_duration(queue)) { + double elapsed = difftime(now, job_queue_node_get_sim_start( node )); + if (elapsed > job_queue_get_max_job_duration(queue)) job_queue_change_node_status(queue, node, JOB_QUEUE_USER_EXIT); - } } if (job_queue_get_job_stop_time(queue) > 0) { - if (now >= job_queue_get_job_stop_time(queue)) { + if (now >= job_queue_get_job_stop_time(queue)) job_queue_change_node_status(queue, node, JOB_QUEUE_USER_EXIT); - } } } } @@ -1322,6 +820,18 @@ void job_queue_check_open(job_queue_type* queue) { If the total number of jobs is not known in advance the job_queue_run_jobs function can be called with @num_total_run == 0. In that case it is paramount to call the function job_queue_submit_complete() whan all jobs have been submitted. + + Observe that this function is assumed to have ~exclusive access to + the jobs array; meaning that: + + 1. The jobs array is read without taking a reader lock. + + 2. Other functions accessing the jobs array concurrently must + take a read lock. + + 3. This function should be the *only* function modifying + the jobs array, and that is done *with* the write lock. + */ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose) { @@ -1344,6 +854,7 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose do { bool local_user_exit = false; + job_list_get_rdlock( queue->job_list ); /*****************************************************************/ if (queue->user_exit) {/* An external thread has called the job_queue_user_exit() function, and we should kill all jobs, do some clearing up and go home. Observe that we will go through the @@ -1365,9 +876,9 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose { - int num_complete = queue->status_list[ STATUS_INDEX(JOB_QUEUE_SUCCESS) ] + - queue->status_list[ STATUS_INDEX(JOB_QUEUE_FAILED) ] + - queue->status_list[ STATUS_INDEX(JOB_QUEUE_USER_KILLED) ]; + int num_complete = job_queue_status_get_count(queue->status, JOB_QUEUE_SUCCESS) + + job_queue_status_get_count(queue->status, JOB_QUEUE_FAILED) + + job_queue_status_get_count(queue->status, JOB_QUEUE_USER_KILLED); if ((num_total_run > 0) && (num_total_run == num_complete)) /* The number of jobs completed is equal to the number @@ -1386,7 +897,7 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose 2. The user has used job_queue_complete_submit() to signal that no more jobs will be forthcoming. */ - if ((num_complete == queue->active_size) && queue->submit_complete) + if ((num_complete == job_list_get_size( queue->job_list )) && queue->submit_complete) cont = false; } } @@ -1396,7 +907,7 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose /* Submitting new jobs */ int max_submit = 5; /* This is the maximum number of jobs submitted in one while() { ... } below. Only to ensure that the waiting time before a status update is not too long. */ - int total_active = queue->status_list[ STATUS_INDEX(JOB_QUEUE_PENDING) ] + queue->status_list[ STATUS_INDEX(JOB_QUEUE_RUNNING) ]; + int total_active = job_queue_status_get_count(queue->status, JOB_QUEUE_PENDING) + job_queue_status_get_count(queue->status, JOB_QUEUE_RUNNING); int num_submit_new; { @@ -1408,20 +919,20 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose If max_running == 0 that should be interpreted as no limit; i.e. the queue layer will attempt to send an unlimited number of jobs to the driver - the driver can reject the jobs. */ - num_submit_new = util_int_min( max_submit , queue->status_list[ STATUS_INDEX( JOB_QUEUE_WAITING )]); + num_submit_new = util_int_min( max_submit , job_queue_status_get_count(queue->status, JOB_QUEUE_WAITING)); } new_jobs = false; - if (queue->status_list[ STATUS_INDEX(JOB_QUEUE_WAITING) ] > 0) /* We have waiting jobs at all */ - if (num_submit_new > 0) /* The queue can allow more running jobs */ + if (job_queue_status_get_count(queue->status, JOB_QUEUE_WAITING) > 0) /* We have waiting jobs at all */ + if (num_submit_new > 0) /* The queue can allow more running jobs */ new_jobs = true; if (new_jobs) { int submit_count = 0; int queue_index = 0; - while ((queue_index < queue->active_size) && (num_submit_new > 0)) { - job_queue_node_type * node = queue->jobs[queue_index]; + while ((queue_index < job_list_get_size( queue->job_list )) && (num_submit_new > 0)) { + job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); if (job_queue_node_get_status(node) == JOB_QUEUE_WAITING) { { submit_status_type submit_status = job_queue_submit_job(queue , queue_index); @@ -1443,8 +954,8 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose Checking for complete / exited / overtime jobs */ int queue_index; - for (queue_index = 0; queue_index < queue->active_size; queue_index++) { - job_queue_node_type * node = queue->jobs[queue_index]; + for (queue_index = 0; queue_index < job_list_get_size( queue->job_list ); queue_index++) { + job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); switch (job_queue_node_get_status(node)) { case(JOB_QUEUE_DONE): @@ -1463,22 +974,18 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose } } - - if (local_user_exit) - cont = false; /* This is how we signal that we want to get out . */ - - if (queue->grow) - /* - The add_job function has signaled that it needs more - job slots. We must grow the jobs array. - */ - job_queue_grow( queue ); - else - if (!new_jobs && cont) - util_usleep(queue->usleep_time); - } + } else + /* print an updated status to stdout before exiting. */ + if (verbose) + job_queue_print_summary(queue , true); + } + job_list_unlock( queue->job_list ); + if (local_user_exit) + cont = false; /* This is how we signal that we want to get out . */ + else { + util_yield(); + job_list_reader_wait( queue->job_list , queue->usleep_time , 8 * queue->usleep_time); } - } while ( cont ); queue->running = false; } @@ -1489,29 +996,18 @@ void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose } /* - Set the queue's "open" flag to false to signal that the queue is not ready to be used in a - new job_queue_run_jobs or job_queue_add_job method call as it has not been reset yet. Not - resetting the queue here implies that the queue object is still available for queries after - this method has finished - */ - + Set the queue's "open" flag to false to signal that the queue is + not ready to be used in a new job_queue_run_jobs or + job_queue_add_job method call as it has not been reset yet. Not + resetting the queue here implies that the queue object is still + available for queries after this method has finished + */ queue->open = false; - - pthread_mutex_unlock( &queue->run_mutex ); } -/* - An external thread sets the user_exit flag to true, then subsequently the - thread managing the queue will see this, and close down the queue. -*/ - -void job_queue_user_exit( job_queue_type * queue) { - queue->user_exit = true; -} - void * job_queue_run_jobs__(void * __arg_pack) { @@ -1532,7 +1028,6 @@ void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * qu arg_pack_append_ptr(queue_args , job_queue); arg_pack_append_int(queue_args , job_size); arg_pack_append_bool(queue_args , verbose); - job_queue_reset(job_queue); /* The running status of the job is set to true here; this is to @@ -1550,7 +1045,7 @@ void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * qu The most flexible use scenario is as follows: 1. The job_queue_run_jobs() is run by one thread. - 2. Jobs are added asyncronously with job_queue_add_job_mt() from othread threads(s). + 2. Jobs are added asyncronously with job_queue_add_job() from othread threads(s). Unfortunately it does not work properly (i.e. Ctrl-C breaks) to use a Python @@ -1584,126 +1079,98 @@ void job_queue_run_jobs_threaded(job_queue_type * queue , int num_total_run, boo submitted proper to one of the drivers (when a slot is ready). When submitted the job will get (driver specific) job_data != NULL and status SUBMITTED. - - The internal data structure jobs will grow as needed when new jobs - are added. Exactly how this growth takes place is regulated by the - @mt parameter, and is very important to get right: - - mt == true: This means that we are running in multi threaded - mode, and in particular another thread is already running the - job_queue_run_jobs() function. In this case the - job_queue_add_job__() function will only signal that it needs - to grow the jobs array with the grow flag, and then block - until the job_queue_run_jobs() function actually expands the - array. - - mt == false: There is no other thread running the - job_queue_run_jobs() function and it is safe for the - job_queue_add_job__() function to manipulate the jobs array - itself. - - Other thread running job_queue_run_jobs() | mt == true | Result - --------------------------------------------------------------------------- - Yes | Yes | OK - Yes | No | Crash and burn - No | Yes | Deadlock - No | No | OK - --------------------------------------------------------------------------- */ -static int job_queue_add_job__(job_queue_type * queue , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * run_path , - const char * job_name , - int argc , - const char ** argv, - bool mt) { +int job_queue_add_job(job_queue_type * queue , + const char * run_cmd , + job_callback_ftype * done_callback, + job_callback_ftype * retry_callback, + job_callback_ftype * exit_callback, + void * callback_arg , + int num_cpu , + const char * run_path , + const char * job_name , + int argc , + const char ** argv) { //Fail hard if queue is not open job_queue_check_open(queue); - if (!queue->user_exit) {/* We do not accept new jobs if a user-shutdown has been iniated. */ - int job_index; // This should be better protected lockwise - - pthread_mutex_lock( &queue->queue_mutex ); - { - if (queue->active_size == queue->alloc_size) { - if (mt) { - queue->grow = true; /* Signal to the thread running the queue that we need more job slots. - Wait for the queue_size to increase; this will off course deadlock hard - unless another thread is ready to pick up the signal to grow. */ - while (queue->active_size == queue->alloc_size) { - sleep( 1 ); - } - } else - /* - The function is called in single threaded mode, and we - are certain that is safe for this thread to manipulate - the jobs array directly. - */ - job_queue_grow( queue ); + int queue_index; + job_queue_node_type * node = job_queue_node_alloc( job_name , + run_path , + run_cmd , + argc , + argv , + num_cpu , + queue->ok_file , + queue->exit_file, + done_callback , + retry_callback , + exit_callback , + callback_arg ); + if (node) { + job_list_get_wrlock( queue->job_list ); + { + job_list_add_job( queue->job_list , node ); + queue_index = job_queue_node_get_queue_index(node); + job_queue_change_node_status(queue , node , JOB_QUEUE_WAITING); } - - job_index = queue->active_size; - queue->active_size++; + job_list_unlock( queue->job_list ); + return queue_index; /* Handle used by the calling scope. */ + } else { + char * cwd = util_alloc_cwd(); + util_abort("%s: failed to create job %s in path: %s cwd:%s \n",__func__ , job_name , run_path , cwd); + return -1; } - pthread_mutex_unlock( &queue->queue_mutex ); - - job_queue_initialize_node(queue , run_cmd , done_callback , retry_callback , exit_callback, callback_arg , num_cpu , run_path , job_name , job_index , argc , argv); - return job_index; /* Handle used by the calling scope. */ } else return -1; } -/** - Adding a new job in multi-threaded mode, i.e. another thread is - running the job_queue_run_jobs() function. -*/ -int job_queue_add_job_mt(job_queue_type * queue , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * run_path , - const char * job_name , - int argc , - const char ** argv) { - return job_queue_add_job__(queue , run_cmd , done_callback, retry_callback, exit_callback , callback_arg , num_cpu , run_path , job_name , argc , argv , true); -} +UTIL_SAFE_CAST_FUNCTION( job_queue , JOB_QUEUE_TYPE_ID) /** - Adding a new job in single-threaded mode, i.e. no another thread is - accessing the queue. + Observe that the job_queue returned by this function is NOT ready + for use; a driver must be set explicitly with a call to + job_queue_set_driver() first. */ -int job_queue_add_job_st(job_queue_type * queue , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * run_path , - const char * job_name , - int argc , - const char ** argv) { - return job_queue_add_job__(queue , run_cmd , done_callback , retry_callback, exit_callback , callback_arg , num_cpu , run_path , job_name , argc , argv , false); -} +job_queue_type * job_queue_alloc(int max_submit , + const char * ok_file , + const char * exit_file ) { + job_queue_type * queue = util_malloc(sizeof * queue ); + UTIL_TYPE_ID_INIT( queue , JOB_QUEUE_TYPE_ID); + queue->usleep_time = 250000; /* 1000000 : 1 second */ + queue->max_ok_wait_time = 60; + queue->max_duration = 0; + queue->stop_time = 0; + queue->max_submit = max_submit; + queue->driver = NULL; + queue->ok_file = util_alloc_string_copy( ok_file ); + queue->exit_file = util_alloc_string_copy( exit_file ); + queue->open = true; + queue->user_exit = false; + queue->pause_on = false; + queue->running = false; + queue->submit_complete = false; + queue->work_pool = NULL; + queue->job_list = job_list_alloc( ); + queue->status = job_queue_status_alloc( ); + + pthread_mutex_init( &queue->run_mutex , NULL ); + + return queue; +} + + /** When the job_queue_run_jobs() has been called with @total_num_jobs == 0 that means that the total number of jobs to run is not known @@ -1738,23 +1205,6 @@ bool job_queue_has_driver(const job_queue_type * queue ) { } -job_driver_type job_queue_lookup_driver_name( const char * driver_name ) { - if (strcmp( driver_name , "LOCAL") == 0) - return LOCAL_DRIVER; - else if (strcmp( driver_name , "RSH") == 0) - return RSH_DRIVER; - else if (strcmp( driver_name , "LSF") == 0) - return LSF_DRIVER; - else { - util_abort("%s: driver:%s not recognized \n",__func__ , driver_name); - return NULL_DRIVER; - } -} - -/*****************************************************************/ - - - void job_queue_set_max_submit( job_queue_type * job_queue , int max_submit ) { job_queue->max_submit = max_submit; } @@ -1765,85 +1215,11 @@ int job_queue_get_max_submit(const job_queue_type * job_queue ) { } - -static void job_queue_grow( job_queue_type * queue ) { - int alloc_size = util_int_max( 2 * queue->alloc_size , JOB_QUEUE_START_SIZE ); - job_queue_node_type ** new_jobs = util_calloc(alloc_size , sizeof * queue->jobs ); - job_queue_node_type ** old_jobs = queue->jobs; - if (old_jobs != NULL) - memcpy( new_jobs , queue->jobs , queue->alloc_size * sizeof * queue->jobs ); - - - { - int i; - /* Creating the new nodes. */ - for (i = queue->alloc_size; i < alloc_size; i++) - new_jobs[i] = job_queue_node_alloc(); - - /* Assigning the job pointer to the new array. */ - queue->jobs = new_jobs; - - /* Free the old array - only the pointers, not the actual nodes! */ - util_safe_free( old_jobs ); - - /* Update the status with the new nodes. */ - for (i=queue->alloc_size; i < alloc_size; i++) - queue->status_list[ STATUS_INDEX(job_queue_node_get_status(queue->jobs[i])) ]++; - - queue->alloc_size = alloc_size; - } - queue->grow = false; -} - - -/** - Observe that the job_queue returned by this function is NOT ready - for use; a driver must be set explicitly with a call to - job_queue_set_driver() first. -*/ - -job_queue_type * job_queue_alloc(int max_submit , - const char * ok_file , - const char * exit_file ) { - - - - job_queue_type * queue = util_malloc(sizeof * queue ); - queue->jobs = NULL; - queue->usleep_time = 250000; /* 1000000 : 1 second */ - queue->max_ok_wait_time = 60; - queue->max_duration = 0; - queue->stop_time = 0; - queue->max_submit = max_submit; - queue->driver = NULL; - queue->ok_file = util_alloc_string_copy( ok_file ); - queue->exit_file = util_alloc_string_copy( exit_file ); - queue->open = true; - queue->user_exit = false; - queue->pause_on = false; - queue->running = false; - queue->grow = false; - queue->submit_complete = false; - queue->active_size = 0; - queue->alloc_size = 0; - queue->jobs = NULL; - queue->work_pool = NULL; - job_queue_grow( queue ); - - job_queue_clear_status( queue ); - pthread_mutex_init( &queue->status_mutex , NULL); - pthread_mutex_init( &queue->queue_mutex , NULL); - pthread_mutex_init( &queue->run_mutex , NULL ); - - return queue; -} - /** Returns true if the queue is currently paused, which means that no more jobs are submitted. */ - bool job_queue_get_pause( const job_queue_type * job_queue ) { return job_queue->pause_on; } @@ -1858,16 +1234,13 @@ void job_queue_set_pause_off( job_queue_type * job_queue) { job_queue->pause_on = false; } +/* + An external thread sets the user_exit flag to true, then subsequently the + thread managing the queue will see this, and close down the queue. +*/ -void * job_queue_iget_job_data( job_queue_type * job_queue , int job_nr ) { - job_queue_node_type * job = job_queue->jobs[ job_nr ]; - return job->job_data; -} - - -job_queue_node_type * job_queue_iget_job( job_queue_type * job_queue , int job_nr ) { - job_queue_node_type * job = job_queue->jobs[ job_nr ]; - return job; +void job_queue_user_exit( job_queue_type * queue) { + queue->user_exit = true; } @@ -1875,28 +1248,59 @@ job_queue_node_type * job_queue_iget_job( job_queue_type * job_queue , int job_n void job_queue_free(job_queue_type * queue) { util_safe_free( queue->ok_file ); util_safe_free( queue->exit_file ); - { - int i; - for (i=0; i < queue->alloc_size; i++) - job_queue_node_free(queue->jobs[i]); - - free(queue->jobs); - } + job_list_free( queue->job_list ); + job_queue_status_free( queue->status ); free(queue); - queue = NULL; } -/*****************************************************************/ -const char * job_queue_status_name( job_status_type status ) { - return status_name[ STATUS_INDEX(status) ]; + + + +int job_queue_get_max_running_option(queue_driver_type * driver) { + char * max_running_string = (char*)queue_driver_get_option(driver, MAX_RUNNING); + int max_running; + if (!util_sscanf_int(max_running_string, &max_running)) { + fprintf(stderr, "%s: Unable to parse option MAX_RUNNING with value %s to an int", __func__, max_running_string); + } + return max_running; } -/*****************************************************************/ - -job_status_type job_queue_get_status( queue_driver_type * driver , job_queue_node_type * job) { - return queue_driver_get_status( driver , job->job_data ); +void job_queue_set_max_running_option(queue_driver_type * driver, int max_running) { + char * max_running_string = util_alloc_sprintf("%d", max_running); + queue_driver_set_option(driver, MAX_RUNNING, max_running_string); + free(max_running_string); } + +/** + Observe that if the max number of running jobs is decreased, + nothing will be done to reduce the number of jobs currently + running; but no more jobs will be submitted until the number of + running has fallen below the new limit. + + The updated value will also be pushed down to the current driver. + + NOTE: These next three *max_running functions should not be used, rather + use the set_option feature, with MAX_RUNNING. They are (maybe) used by python + therefore not removed. +*/ +int job_queue_get_max_running( const job_queue_type * queue ) { + return job_queue_get_max_running_option(queue->driver); +} + +void job_queue_set_max_running( job_queue_type * queue , int max_running ) { + job_queue_set_max_running_option(queue->driver, max_running); +} + +/* + The return value is the new value for max_running. +*/ +int job_queue_inc_max_runnning( job_queue_type * queue, int delta ) { + job_queue_set_max_running( queue , job_queue_get_max_running( queue ) + delta ); + return job_queue_get_max_running( queue ); +} + + diff --git a/ThirdParty/Ert/devel/libjob_queue/src/job_queue_manager.c b/ThirdParty/Ert/devel/libjob_queue/src/job_queue_manager.c index c9140c2ed0..4890a21df6 100644 --- a/ThirdParty/Ert/devel/libjob_queue/src/job_queue_manager.c +++ b/ThirdParty/Ert/devel/libjob_queue/src/job_queue_manager.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'job_queue_manager.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2014 Statoil ASA, Norway. + + The file 'job_queue_manager.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -57,14 +58,52 @@ void job_queue_manager_free( job_queue_manager_type * manager) { } -void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose) { +void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue) { + if (reset_queue) + job_queue_reset( manager->job_queue ); + job_queue_start_manager_thread( manager->job_queue , &manager->queue_thread , num_total_run , verbose ); } void job_queue_manager_wait( job_queue_manager_type * manager) { - pthread_join( manager->queue_thread , NULL ); + pthread_join( manager->queue_thread , NULL ); +} + + +bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds) { + struct timespec ts; + time_t timeout_time = time( NULL ); + + util_inplace_forward_seconds(&timeout_time , timeout_seconds ); + ts.tv_sec = timeout_time; + ts.tv_nsec = 0; + +#ifdef HAVE_TIMEDJOIN + { + int join_return = pthread_timedjoin_np( manager->queue_thread , NULL , &ts); /* Wait for the main thread to complete. */ + if (join_return == 0) + return true; + else + return false; + } +#else + while(true) { + if (pthread_kill(manager->queue_thread, 0) == 0){ + util_yield(); + } else { + return true; + } + + time_t now = time(NULL); + + if(util_difftime_seconds(now, timeout_time) <= 0) { + return false; + } + } + +#endif } @@ -78,10 +117,15 @@ int job_queue_manager_get_num_running( const job_queue_manager_type * manager) { } -int job_queue_manager_get_num_complete( const job_queue_manager_type * manager) { +int job_queue_manager_get_num_success( const job_queue_manager_type * manager) { return job_queue_get_num_complete( manager->job_queue ); } +int job_queue_manager_get_num_failed( const job_queue_manager_type * manager) { + return job_queue_get_num_failed( manager->job_queue ); +} + + bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index) { job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); @@ -90,3 +134,38 @@ bool job_queue_manager_job_complete( const job_queue_manager_type * manager , in else return false; } + + +bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index) { + job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); + if (status & JOB_QUEUE_WAITING_STATUS) + return true; + else + return false; +} + +bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index) { + job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); + if (status == JOB_QUEUE_RUNNING) + return true; + else + return false; +} + + +bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index) { + job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); + if (status == JOB_QUEUE_FAILED) + return true; + else + return false; +} + + +bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index) { + job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); + if (status == JOB_QUEUE_SUCCESS) + return true; + else + return false; +} diff --git a/ThirdParty/Ert/devel/libjob_queue/src/job_queue_status.c b/ThirdParty/Ert/devel/libjob_queue/src/job_queue_status.c new file mode 100644 index 0000000000..7c54dab0ce --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/src/job_queue_status.c @@ -0,0 +1,161 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_status_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include + +#include +#include + +#include +#include + +#define JOB_QUEUE_STATUS_TYPE_ID 777620306 + +struct job_queue_status_struct { + UTIL_TYPE_ID_DECLARATION; + int status_list[JOB_QUEUE_MAX_STATE]; + pthread_mutex_t update_mutex; +}; + +static const int status_index[] = { JOB_QUEUE_NOT_ACTIVE , // Initial, allocated job state, job not added - controlled by job_queue + JOB_QUEUE_WAITING , // The job is ready to be started - controlled by job_queue + JOB_QUEUE_SUBMITTED , // Job is submitted to driver - temporary state - controlled by job_queue + JOB_QUEUE_PENDING , // Job is pending, before actual execution - controlled by queue_driver + JOB_QUEUE_RUNNING , // Job is executing - controlled by queue_driver + JOB_QUEUE_DONE , // Job is done (sucessful or not), temporary state - controlled/returned by by queue_driver + JOB_QUEUE_EXIT , // Job is done, with exit status != 0, temporary state - controlled/returned by by queue_driver + JOB_QUEUE_USER_EXIT , // User / queue system has requested killing of job - controlled by job_queue / external scope + JOB_QUEUE_USER_KILLED, // Job has been killed, due to JOB_QUEUE_USER_EXIT, FINAL STATE - controlled by job_queue + JOB_QUEUE_SUCCESS , // All good, comes after JOB_QUEUE_DONE, with additional checks, FINAL STATE - controlled by job_queue + JOB_QUEUE_RUNNING_CALLBACK, // Temporary state, while running requested callbacks after an ended job - controlled by job_queue + JOB_QUEUE_FAILED }; // Job has failed, no more retries, FINAL STATE + +static const char* status_name[] = { "JOB_QUEUE_NOT_ACTIVE" , + "JOB_QUEUE_WAITING" , + "JOB_QUEUE_SUBMITTED" , + "JOB_QUEUE_PENDING" , + "JOB_QUEUE_RUNNING" , + "JOB_QUEUE_DONE" , + "JOB_QUEUE_EXIT" , + "JOB_QUEUE_USER_KILLED" , + "JOB_QUEUE_USER_EXIT" , + "JOB_QUEUE_SUCCESS" , + "JOB_QUEUE_RUNNING_CALLBACK", + "JOB_QUEUE_FAILED" }; + +static int STATUS_INDEX( job_status_type status ) { + int index = 0; + + while (true) { + if (status_index[index] == status) + return index; + + index++; + if (index == JOB_QUEUE_MAX_STATE) + util_abort("%s: failed to get index from status:%d \n",__func__ , status); + } +} + + +UTIL_IS_INSTANCE_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID ) +UTIL_SAFE_CAST_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID ) + + +job_queue_status_type * job_queue_status_alloc() { + job_queue_status_type * status = util_malloc( sizeof * status ); + UTIL_TYPE_ID_INIT( status , JOB_QUEUE_STATUS_TYPE_ID ); + pthread_mutex_init( &status->update_mutex , NULL ); + job_queue_status_clear( status ); + return status; +} + + +void job_queue_status_free( job_queue_status_type * status ) { + free( status ); +} + + +void job_queue_status_clear( job_queue_status_type * status ) { + int index; + for (index = 0; index < JOB_QUEUE_MAX_STATE; index++) + status->status_list[ index ] = 0; +} + + +int job_queue_status_get_count( job_queue_status_type * status_count , job_status_type status_type) { + int index = STATUS_INDEX( status_type ); + int count; + + count = status_count->status_list[index]; + + return count; +} + + +void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type) { + int index = STATUS_INDEX( status_type ); + + pthread_mutex_lock( &status_count->update_mutex ); + { + int count = status_count->status_list[index]; + status_count->status_list[index] = count + 1; + } + pthread_mutex_unlock( &status_count->update_mutex ); +} + + +static void job_queue_status_dec( job_queue_status_type * status_count , job_status_type status_type) { + int index = STATUS_INDEX( status_type ); + + pthread_mutex_lock( &status_count->update_mutex ); + { + int count = status_count->status_list[index]; + status_count->status_list[index] = count - 1; + } + pthread_mutex_unlock( &status_count->update_mutex ); +} + + +/* + The important point is that each individual ++ and -- operation is + atomic, if the different status counts do not add upp perfectly at + all times that is ok. +*/ + + +bool job_queue_status_transition( job_queue_status_type * status_count , job_status_type src_status , job_status_type target_status) { + if (src_status != target_status) { + job_queue_status_dec( status_count , src_status ); + job_queue_status_inc( status_count , target_status ); + return true; + } else + return false; +} + + +int job_queue_status_get_total_count( const job_queue_status_type * status ) { + int total_count = 0; + for (int index = 0; index < JOB_QUEUE_MAX_STATE; index++) + total_count += status->status_list[ index ]; + return total_count; +} + + +const char * job_queue_status_name( job_status_type status ) { + int index = STATUS_INDEX( status ); + return status_name[index]; +} diff --git a/ThirdParty/Ert/devel/libjob_queue/src/lsf_driver.c b/ThirdParty/Ert/devel/libjob_queue/src/lsf_driver.c index 94813f684a..137e02a842 100644 --- a/ThirdParty/Ert/devel/libjob_queue/src/lsf_driver.c +++ b/ThirdParty/Ert/devel/libjob_queue/src/lsf_driver.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -348,12 +349,11 @@ static int lsf_driver_submit_internal_job( lsf_driver_type * driver , char * command; { buffer_type * command_buffer = buffer_alloc( 256 ); - buffer_fwrite_char_ptr( command_buffer , submit_cmd ); + buffer_strcat( command_buffer , submit_cmd ); for (int iarg = 0; iarg < argc; iarg++) { - buffer_fwrite_char( command_buffer , ' '); - buffer_fwrite_char_ptr( command_buffer , argv[ iarg ]); + buffer_strcat( command_buffer , " "); + buffer_strcat( command_buffer , argv[ iarg ]); } - buffer_terminate_char_ptr( command_buffer ); command = buffer_get_data( command_buffer ); buffer_free_container( command_buffer ); } diff --git a/ThirdParty/Ert/devel/libjob_queue/src/rsh_driver.c b/ThirdParty/Ert/devel/libjob_queue/src/rsh_driver.c index b1726f1ecf..38e0237320 100644 --- a/ThirdParty/Ert/devel/libjob_queue/src/rsh_driver.c +++ b/ThirdParty/Ert/devel/libjob_queue/src/rsh_driver.c @@ -341,7 +341,7 @@ void rsh_driver_free__(void * __driver) { } -void rsh_driver_set_host_list( rsh_driver_type * rsh_driver , hash_type * rsh_host_list) { +void rsh_driver_set_host_list( rsh_driver_type * rsh_driver , const hash_type * rsh_host_list) { rsh_driver_clear_host_list( rsh_driver ); if (rsh_host_list != NULL) { hash_iter_type * hash_iter = hash_iter_alloc( rsh_host_list ); @@ -429,7 +429,7 @@ bool rsh_driver_set_option( void * __driver , const char * option_key , const vo rsh_driver_add_host_from_string( driver , value ); else if (strcmp(RSH_HOSTLIST , option_key) == 0) { /* Set full host list - value should be hash of integers. */ if (value != NULL) { - hash_type * hash_value = hash_safe_cast( value ); + const hash_type * hash_value = hash_safe_cast_const( value ); rsh_driver_set_host_list( driver , hash_value ); } } else if (strcmp( RSH_CLEAR_HOSTLIST , option_key) == 0) diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/CMakeLists.txt b/ThirdParty/Ert/devel/libjob_queue/tests/CMakeLists.txt index c3d06dd340..e97c5a7a5c 100644 --- a/ThirdParty/Ert/devel/libjob_queue/tests/CMakeLists.txt +++ b/ThirdParty/Ert/devel/libjob_queue/tests/CMakeLists.txt @@ -1,17 +1,25 @@ +add_executable( job_status_test job_status_test.c ) add_executable( job_loadOK job_loadOK.c ) add_executable( job_loadFail job_loadFail.c ) +add_executable( job_node_test job_node_test.c ) +add_executable( job_list_test job_list_test.c ) add_executable( create_file create_file.c ) add_executable( job_workflow_test job_workflow_test.c ) add_executable( job_lsf_parse_bsub_stdout job_lsf_parse_bsub_stdout.c ) add_executable( ext_joblist_test ext_joblist_test.c ) + +target_link_libraries( job_status_test job_queue test_util ) target_link_libraries( job_workflow_test job_queue test_util ) target_link_libraries( create_file job_queue test_util ) target_link_libraries( job_loadOK job_queue test_util ) target_link_libraries( job_loadFail job_queue test_util ) target_link_libraries( ext_joblist_test job_queue test_util ) target_link_libraries( job_lsf_parse_bsub_stdout job_queue test_util) +target_link_libraries( job_node_test job_queue test_util) +target_link_libraries( job_list_test job_queue test_util) +add_test( job_status_test ${EXECUTABLE_OUTPUT_PATH}/job_status_test) add_test( job_lsf_parse_bsub_stdout ${EXECUTABLE_OUTPUT_PATH}/job_lsf_parse_bsub_stdout ) add_test( job_workflow_test ${EXECUTABLE_OUTPUT_PATH}/job_workflow_test ${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/data/internal_job) @@ -24,7 +32,8 @@ add_test( job_loadFail1 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_S add_test( job_loadFail2 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail) add_test( job_loadFail3 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/internalFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail) - +add_test( job_node_test ${EXECUTABLE_OUTPUT_PATH}/job_node_test) +add_test( job_list_test valgrind --leak-check=full --error-exitcode=1 ${EXECUTABLE_OUTPUT_PATH}/job_list_test) add_test( ext_joblist_test ${EXECUTABLE_OUTPUT_PATH}/ext_joblist_test ${CMAKE_CURRENT_SOURCE_DIR}/data/jobs/util ${CMAKE_CURRENT_SOURCE_DIR}) add_executable( job_program_output job_program_output.c ) @@ -34,6 +43,14 @@ add_executable( job_queue_test job_job_queue_test.c ) target_link_libraries( job_queue_test job_queue test_util ) add_test( job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_program_output ) +add_executable( job_queue_stress_task job_queue_stress_task.c ) +target_link_libraries( job_queue_stress_task ert_util ) + +add_executable( job_queue_stress_test job_queue_stress_test.c ) +target_link_libraries( job_queue_stress_test job_queue test_util ) +add_test( job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_task ) + + add_executable( job_queue_driver_test job_queue_driver_test.c ) target_link_libraries( job_queue_driver_test job_queue test_util ) add_test( job_queue_driver_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_driver_test ) diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_job_queue_test.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_job_queue_test.c index fb30d56e93..63baa2bdaa 100644 --- a/ThirdParty/Ert/devel/libjob_queue/tests/job_job_queue_test.c +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_job_queue_test.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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 3 of the License, or - (at your option) any later version. - - ERT 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 at - for more details. + Copyright (C) 2013 Statoil ASA, Norway. + + The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. */ #include #include @@ -27,8 +27,9 @@ #include #include +#include -void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_area, char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char* sleep_short, char* sleep_long, bool multithreaded) { +void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_area, char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char* sleep_short, char* sleep_long) { int submitted_slowjobs = 0; for (int i = 0; i < number_of_jobs; i++) { char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i); @@ -40,43 +41,29 @@ void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_are submitted_slowjobs++; } - if (multithreaded) { - - job_queue_add_job_mt(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) { - runpath, sleeptime - }); - } else { - - job_queue_add_job_st(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) { - runpath, sleeptime - }); - } + job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime}); free(runpath); } + test_assert_int_equal( number_of_jobs , job_queue_get_active_size(queue) ); } void monitor_job_queue(job_queue_type * queue, int max_job_duration, time_t stop_time, int min_realizations) { - bool cont = true; - - if (0 >= min_realizations) - cont = false; - - while (cont) { - //Check if minimum number of realizations have run, and if so, kill the rest after a certain time - if ((job_queue_get_num_complete(queue) >= min_realizations)) { - job_queue_set_max_job_duration(queue, max_job_duration); - - job_queue_set_job_stop_time(queue, stop_time); - - cont = false; - } - - if (cont) { + if (min_realizations > 0) { + while (true) { util_usleep(100); + + //Check if minimum number of realizations have run, and if so, kill the rest after a certain time + if ((job_queue_get_num_complete(queue) >= min_realizations)) { + job_queue_set_max_job_duration(queue, max_job_duration); + job_queue_set_job_stop_time(queue, stop_time); + break; + } } } } + + void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char * sleep_short, char * sleep_long, int max_sleep) { test_work_area_type * work_area = test_work_area_alloc("job_queue"); job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR"); @@ -85,9 +72,9 @@ void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs, job_queue_set_driver(queue, driver); job_queue_set_max_job_duration(queue, max_sleep); - submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, false); + submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); - job_queue_run_jobs(queue, number_of_jobs, true); + job_queue_run_jobs(queue, number_of_jobs, false); test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue)); test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue)); @@ -104,48 +91,46 @@ void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs, } -void run_and_monitor_jobs(char * executable_to_run, int max_job_duration, time_t stop_time, int min_realizations, int num_completed, int interval_between_jobs) { - int number_of_jobs = 10; +void run_and_monitor_jobs(char * executable_to_run, + int number_of_jobs , + int max_job_duration, + time_t stop_time, + int min_realizations, + int min_completed, + int max_completed , + int interval_between_jobs) { + test_work_area_type * work_area = test_work_area_alloc("job_queue"); job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR"); + job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); queue_driver_type * driver = queue_driver_alloc_local(); + job_queue_set_driver(queue, driver); - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack, queue); - arg_pack_append_int(arg_pack, 0); - arg_pack_append_bool(arg_pack, true); - - thread_pool_type * pool = thread_pool_alloc(1, true); - thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack); int job_run_time = 0; for (int i = 0; i < number_of_jobs; i++) { char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i); - util_make_path(runpath); - char * sleeptime = util_alloc_sprintf("%d", job_run_time); - job_queue_add_job_mt(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) { - runpath, sleeptime - }); + util_make_path(runpath); + job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime}); job_run_time += interval_between_jobs; free(sleeptime); free(runpath); } - job_queue_submit_complete(queue); + job_queue_manager_start_queue(queue_manager,0,false,false); + monitor_job_queue( queue , max_job_duration , stop_time , min_realizations ); + job_queue_manager_wait(queue_manager); - monitor_job_queue(queue, max_job_duration, stop_time, min_realizations); + printf("Completed: %d <= %d <= %d ?\n",min_completed , job_queue_get_num_complete(queue) , max_completed); + test_assert_true(job_queue_get_num_complete(queue) >= min_completed); + test_assert_true(job_queue_get_num_complete(queue) <= max_completed); - thread_pool_join(pool); - thread_pool_free(pool); - - - test_assert_int_equal(num_completed, job_queue_get_num_complete(queue)); - test_assert_int_equal(number_of_jobs - num_completed, job_queue_get_num_killed(queue)); + test_assert_int_equal(number_of_jobs - job_queue_get_num_complete( queue ) , job_queue_get_num_killed(queue)); test_assert_bool_equal(false, job_queue_get_open(queue)); job_queue_reset(queue); test_assert_bool_equal(true, job_queue_get_open(queue)); @@ -153,6 +138,7 @@ void run_and_monitor_jobs(char * executable_to_run, int max_job_duration, time_t job_queue_free(queue); queue_driver_free(driver); + job_queue_manager_free( queue_manager ); test_work_area_free(work_area); } @@ -168,12 +154,12 @@ void run_jobs_time_limit_multithreaded(char * executable_to_run, int number_of_j arg_pack_type * arg_pack = arg_pack_alloc(); arg_pack_append_ptr(arg_pack, queue); arg_pack_append_int(arg_pack, 0); - arg_pack_append_bool(arg_pack, true); + arg_pack_append_bool(arg_pack, false); thread_pool_type * pool = thread_pool_alloc(1, true); thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack); - submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, true); + submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); job_queue_submit_complete(queue); thread_pool_join(pool); @@ -191,8 +177,8 @@ void run_jobs_time_limit_multithreaded(char * executable_to_run, int number_of_j test_work_area_free(work_area); } -void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) { - printf("Running JobQueueRunJobs_ReuseQueue_AllOk\n"); +void test1(char ** argv) { + printf("001: Running JobQueueRunJobs_ReuseQueue_AllOk\n"); int number_of_jobs = 20; int number_of_queue_reuse = 10; @@ -204,9 +190,9 @@ void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) { job_queue_set_driver(queue, driver); for (int j = 0; j < number_of_queue_reuse; j++) { - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0", false); + submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0"); - job_queue_run_jobs(queue, number_of_jobs, true); + job_queue_run_jobs(queue, number_of_jobs, false); test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); test_assert_bool_equal(false, job_queue_get_open(queue)); @@ -220,8 +206,8 @@ void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) { } -void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) { - printf("Running JobQueueRunJobs_ReuseQueueWithStopTime_AllOk\n"); +void test2(char ** argv) { + printf("002: Running JobQueueRunJobs_ReuseQueueWithStopTime_AllOk\n"); int number_of_jobs = 3; int number_of_slow_jobs = 2; @@ -234,11 +220,11 @@ void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) { job_queue_set_driver(queue, driver); for (int j = 0; j < number_of_queue_reuse; j++) { - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slow_jobs, "1", "5", false); + submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slow_jobs, "1", "5"); - job_queue_run_jobs(queue, number_of_jobs, true); - time_t current_time = time(NULL); - job_queue_set_job_stop_time(queue, current_time); + job_queue_run_jobs(queue, number_of_jobs, false); + time_t current_time = time(NULL); + job_queue_set_job_stop_time(queue, current_time); test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); test_assert_bool_equal(false, job_queue_get_open(queue)); @@ -253,25 +239,31 @@ void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) { } -void JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun(char ** argv) { - printf("Running JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun\n"); +void test3(char ** argv) { + printf("003: Running JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun\n"); //Use stop_time to to stop jobs after min_realizations are finished + int number_of_jobs = 10; int min_realizations = 5; int num_expected_completed = 5; int max_duration_time = 0; int interval_between_jobs = 2; - time_t currenttime; - time(¤ttime); - time_t stoptime = currenttime; - run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs); + time_t stoptime = time( NULL ); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); } -void JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(char ** argv) { - printf("Running JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun\n"); +void test4(char ** argv) { + printf("004: Running JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); + run_jobs_with_time_limit_test(argv[1], 100, 23, "1", "100", 5); +} + + +void test5(char ** argv) { + printf("005: Running JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun\n"); //Use stop_time to to stop jobs after min_realizations are finished + int number_of_jobs = 10; int min_realizations = 5; int num_expected_completed = 10; int max_duration_time = 0; @@ -279,12 +271,13 @@ void JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(char ** argv) { time_t currenttime; time(¤ttime); time_t stoptime = currenttime + 15; - run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); } -void JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisationsAreRun(char ** argv) { - printf("Running JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLong_MinRealisationsAreRun\n"); +void test6(char ** argv) { + printf("006: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLong_MinRealisationsAreRun\n"); + int number_of_jobs = 10; int min_realizations = 1; int num_expected_completed = 1; int max_duration_time = 1; @@ -292,13 +285,14 @@ void JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisat time_t currenttime; time(¤ttime); time_t stoptime = currenttime + 10; - run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, number_of_jobs , interval_between_jobs); } -void JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun(char ** argv) { - printf("Running JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun\n"); +void test7(char ** argv) { + printf("007: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun\n"); + int number_of_jobs = 10; int min_realizations = 1; int num_expected_completed = 1; int max_duration_time = 10; @@ -306,101 +300,108 @@ void JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisat time_t currenttime; time(¤ttime); time_t stoptime = currenttime + 1; - run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); } -void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun(char ** argv) { - printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun\n"); +void test8(char ** argv) { + printf("008: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun\n"); // Must have one job completed, the rest are then killed due to the max_duration_time gets exceeded. + int number_of_jobs = 10; int min_realizations = 1; int num_expected_completed = 1; int max_duration_time = 1; int interval_between_jobs = 2; time_t currenttime = 0; - run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, 3 , interval_between_jobs); } -void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun(char ** argv) { - printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun\n"); +void test9(char ** argv) { + printf("009: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun\n"); // Min realizations is 1, but the max running time exceeds the time used by any of the jobs, so all run to completion + int number_of_jobs = 10; int min_realizations = 1; int num_expected_completed = 10; int max_duration_time = 12; int interval_between_jobs = 1; time_t currenttime = 0; - run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); } -void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun(char ** argv) { - printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun\n"); - // Min is 3, but max_duration_time allows for one more to be completed +void test10(char ** argv) { + printf("010: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun\n"); + + int number_of_jobs = 10; int min_realizations = 3; - int num_expected_completed = 4; int max_duration_time = 7; int interval_between_jobs = 2; time_t currenttime = 0; - run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, min_realizations , number_of_jobs , interval_between_jobs); } -void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun(char ** argv) { - printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun\n"); +void test11(char ** argv) { + printf("011: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun\n"); // Min is 10, so all run to completion + int number_of_jobs = 10; int min_realizations = 10; int num_expected_completed = 10; int max_duration_time = 1; int interval_between_jobs = 0; time_t currenttime = 0; - run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs); + run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); } -void JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun(char ** argv) { - printf("Running JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun\n"); +void test12(char ** argv) { + printf("012: Running JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun\n"); run_jobs_with_time_limit_test(argv[1], 10, 0, "1", "100", 0); // 0 as limit means no limit*/ } -void JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(char ** argv) { - printf("Running JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); - run_jobs_with_time_limit_test(argv[1], 100, 23, "1", "100", 5); -} - -void JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(char ** argv) { - printf("Running JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); +void test13(char ** argv) { + printf("013: Running JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); run_jobs_time_limit_multithreaded(argv[1], 100, 23, "1", "100", 5); } -void JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(char ** argv) { - printf("Running JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest\n"); +void test14(char ** argv) { + printf("014: Running JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest\n"); int number_of_jobs = 10; test_work_area_type * work_area = test_work_area_alloc("job_queue"); job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR"); queue_driver_type * driver = queue_driver_alloc_local(); + job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); job_queue_set_driver(queue, driver); - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack, queue); - arg_pack_append_int(arg_pack, 0); - arg_pack_append_bool(arg_pack, true); - - thread_pool_type * pool = thread_pool_alloc(1, true); - thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack); int number_of_slowjobs = 7; + int number_of_fastjobs = number_of_jobs - number_of_slowjobs; char * sleep_short = "0"; char * sleep_long = "100"; - - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, false); - - util_usleep(1000000); + submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); job_queue_submit_complete(queue); + job_queue_manager_start_queue( queue_manager , 10 , false , false); + + /* + The jobs are distributed with some very fast, and some quite + long. Here we busy wait until all the fast ones have completed and + then we calculate a stop for the remaining jobs with the + job_queue_set_auto_job_stop_time() function. + */ + + while (true) { + int num_complete = job_queue_get_num_complete(queue); + if (num_complete == number_of_fastjobs) + break; + util_usleep( 100000 ); + } + job_queue_set_auto_job_stop_time(queue); - thread_pool_join(pool); + job_queue_manager_wait(queue_manager); + test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue)); test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue)); @@ -411,14 +412,14 @@ void JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(char ** arg test_assert_int_equal(0, job_queue_get_num_complete(queue)); - thread_pool_free(pool); + job_queue_manager_free( queue_manager ); job_queue_free(queue); queue_driver_free(driver); test_work_area_free(work_area); } -void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv) { - printf("Running JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing\n"); +void test15(char ** argv) { + printf("015: Running JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing\n"); int number_of_jobs = 10; @@ -429,7 +430,7 @@ void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv) char * sleep_long = "100"; - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_jobs, "0", sleep_long, false); + submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_jobs, "0", sleep_long); job_queue_set_auto_job_stop_time(queue); @@ -441,8 +442,8 @@ void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv) test_work_area_free(work_area); } -void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv) { - printf("Running JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing\n"); +void test16(char ** argv) { + printf("016: Running JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing\n"); int number_of_jobs = 10; test_work_area_type * work_area = test_work_area_alloc("job_queue"); @@ -451,9 +452,9 @@ void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv queue_driver_type * driver = queue_driver_alloc_local(); job_queue_set_driver(queue, driver); - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0", false); + submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0"); - job_queue_run_jobs(queue, number_of_jobs, true); + job_queue_run_jobs(queue, number_of_jobs, false); test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); test_assert_bool_equal(false, job_queue_get_open(queue)); @@ -465,28 +466,26 @@ void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv test_work_area_free(work_area); } + int main(int argc, char ** argv) { - JobQueueRunJobs_ReuseQueue_AllOk(argv); - JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(argv); - - JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun(argv); - JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(argv); - JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(argv); + util_install_signals(); - JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun(argv); - JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun(argv); - JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun(argv); - JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun(argv); - - JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun(argv); - JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(argv); - - JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisationsAreRun(argv); - JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun(argv); - - JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(argv); - JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(argv); - JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(argv); + test1(argv); + test2(argv); + test3(argv); + test4(argv); + test5(argv); + test6(argv); + test7(argv); + test8(argv); + test9(argv); + test10(argv); + test11(argv); + test12(argv); + test13(argv); + test14(argv); + test15(argv); + test16(argv); exit(0); } diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_list_test.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_list_test.c new file mode 100644 index 0000000000..9ab24a1b61 --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_list_test.c @@ -0,0 +1,77 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_node_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include +#include + +#include +#include + +#include +#include + + +void test_create() { + job_list_type * list = job_list_alloc(); + test_assert_true( job_list_is_instance( list )); + test_assert_int_equal( 0 , job_list_get_size( list )); + job_list_free( list ); +} + + + +void call_add_job( void * arg ) { + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_list_type * job_list = arg_pack_iget_ptr( arg_pack , 0 ); + job_queue_node_type * node = arg_pack_iget_ptr( arg_pack , 1 ); + job_list_add_job( job_list , node ); +} + + +void call_iget_job( void * arg ) { + job_list_type * job_list = job_list_safe_cast( arg ); + job_list_iget_job( job_list , 10); +} + + + +void test_add_job() { + job_list_type * list = job_list_alloc(); + job_queue_node_type * node = job_queue_node_alloc_simple("name" , "/tmp" , "/bin/ls" , 0 , NULL); + job_list_add_job( list , node ); + test_assert_int_equal( job_list_get_size( list ) , 1 ); + test_assert_int_equal( job_queue_node_get_queue_index(node) , 0 ); + test_assert_ptr_equal( node , job_list_iget_job(list , 0)); + { + arg_pack_type * arg_pack = arg_pack_alloc( ); + arg_pack_append_ptr( arg_pack , list ); + arg_pack_append_ptr( arg_pack , node ); + test_assert_util_abort("job_queue_node_set_queue_index", call_add_job, arg_pack ); + arg_pack_free( arg_pack ); + } + test_assert_util_abort("job_list_iget_job", call_iget_job, list); + job_list_reset( list ); + test_assert_int_equal( 0 , job_list_get_size( list )); + job_list_free( list ); +} + + +int main( int argc , char ** argv) { + util_install_signals(); + test_create(); + test_add_job(); +} diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_node_test.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_node_test.c new file mode 100644 index 0000000000..29f901548e --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_node_test.c @@ -0,0 +1,58 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_node_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ +#include +#include + +#include +#include + + +void test_create() { + job_queue_node_type * node = job_queue_node_alloc_simple("name" , "/tmp" , "/bin/ls" , 0 , NULL); + test_assert_true( job_queue_node_is_instance( node )); + job_queue_node_free( node ); +} + + + +void call_get_queue_index( void * arg ) { + job_queue_node_type * node = job_queue_node_safe_cast( arg ); + job_queue_node_get_queue_index( node ); +} + + + + +void test_queue_index() { + job_queue_node_type * node = job_queue_node_alloc_simple( "name" , "/tmp" , "/bin/ls" , 0 , NULL ); + test_assert_util_abort("job_queue_node_get_queue_index" , call_get_queue_index , node ); +} + + +void test_path_does_not_exist() { + job_queue_node_type * node = job_queue_node_alloc_simple( "name" , "does-not-exist" , "/bin/ls" , 0 , NULL); + test_assert_NULL( node ); +} + + +int main( int argc , char ** argv) { + util_install_signals(); + test_create(); + test_queue_index(); + test_path_does_not_exist(); +} diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_task.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_task.c new file mode 100644 index 0000000000..c08d3f7e0e --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_task.c @@ -0,0 +1,57 @@ +/* + Copyright (C) 2013 Statoil ASA, Norway. + + The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#include + +#include + + +/* + This is a small test job used by the job_queue_stress_test. The job + does the following: + + 0. Chadir to runpath + 1. Create the file @runfile. + 2. Wait with usleep( @usleep_time ). + 3. Remove the @runfile. + 4. Create new file @OK_file + 5. exit. +*/ + +int main(int argc, char ** argv) { + const char * runpath = argv[1]; + const char * runfile = argv[2]; + const char * OK_file = argv[3]; + + int usleep_time; + + util_chdir( runpath ); + util_sscanf_int( argv[4] , &usleep_time ); + { + FILE * stream = util_fopen( runfile , "w"); + fprintf(stream , "Running ... \n"); + fclose( stream ); + } + usleep( usleep_time ); + util_unlink_existing(runfile); + { + FILE * stream = util_fopen( OK_file , "w"); + fprintf(stream , "OK ... \n"); + fclose( stream ); + } +} diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_test.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_test.c new file mode 100644 index 0000000000..e6c797b984 --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_queue_stress_test.c @@ -0,0 +1,261 @@ +/* + Copyright (C) 2013 Statoil ASA, Norway. + + The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. + */ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define JOB_TYPE_ID 77539 +typedef struct { + UTIL_TYPE_ID_DECLARATION; + char * run_path; + bool callback_run; + int queue_index; + int submit_usleep; + int callback_usleep; + int run_usleep; + int argc; + char ** argv; + const char * cmd; +} job_type; + + + +UTIL_SAFE_CAST_FUNCTION( job , JOB_TYPE_ID ) + +job_type * alloc_job( rng_type * rng , const char * cmd) { + const int second = 1000000; + const int submit_min = 0; + const int submit_max = 10 * second; + + const int callback_min = 0.5 * second; + const int callback_max = 2 * second; + + const int run_min = 2 * second; + const int run_max = 10 * second; + + job_type * job = util_malloc( sizeof * job ); + UTIL_TYPE_ID_INIT( job , JOB_TYPE_ID ) + job->callback_run = false; + job->queue_index = -1; + job->submit_usleep = submit_min + rng_get_int( rng , (submit_max - submit_min )); + job->callback_usleep = callback_min + rng_get_int( rng , (callback_max - callback_min )); + job->run_usleep = run_min + rng_get_int( rng , (run_max - run_min )); + job->run_path = util_alloc_sprintf("%08d", rng_get_int(rng , 100000000)); + job->cmd = cmd; + job->argc = 4; + + job->argv = util_malloc( 4 * sizeof * job->argv ); + job->argv[0] = job->run_path; + job->argv[1] = "RUNNING"; + job->argv[2] = "OK"; + job->argv[3] = util_alloc_sprintf("%d", job->run_usleep); + + util_make_path( job->run_path ); + return job; +} + + +job_type ** alloc_jobs( rng_type * rng , int num_jobs , const char * cmd) { + job_type ** jobs = util_malloc( num_jobs * sizeof * jobs ); + for (int i=0; i < num_jobs; i++) { + job_type * job = alloc_job( rng , cmd); + job_safe_cast( job ); + jobs[i] = job; + } + return jobs; +} + + + +bool callback( void * arg ) { + job_type * job = job_safe_cast( arg ); + usleep( job->callback_usleep ); + job->callback_run = true; + return true; +} + + +void * submit_job__( void * arg ) { + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_type * job = job_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ) ); + job_queue_type * queue = arg_pack_iget_ptr( arg_pack , 1 ); + job->queue_index = job_queue_add_job( queue , job->cmd , callback , NULL , NULL , job , 1 , job->run_path , job->run_path , job->argc , (const char **) job->argv ); + usleep( job->submit_usleep ); + return NULL; +} + + +void submit_jobs( job_queue_type * queue , int num_jobs , job_type ** jobs , thread_pool_type * tp) { + for (int i=0; i < num_jobs; i++) { + job_type * job = jobs[i]; + arg_pack_type * arg = arg_pack_alloc(); + arg_pack_append_ptr( arg , job ); + arg_pack_append_ptr( arg , queue ); + thread_pool_add_job(tp , submit_job__ , arg ); + } +} + + +void check_jobs( int num_jobs , job_type ** jobs ) { + for (int i=0; i < num_jobs; i++) { + job_type * job = jobs[i]; + if (!job->callback_run) + fprintf(stderr,"The callback has not been registered on job:%d/%d \n",i,job->queue_index); + test_assert_true( job->callback_run ); + } +} + + +void * global_status( void * arg ) { + job_queue_type * job_queue = job_queue_safe_cast( arg ); + int counter = 0; + while (true) { + util_usleep(100000); + + if (job_queue_get_num_complete(job_queue) == job_queue_get_active_size(job_queue)) + break; + + if ((counter % 10) == 0) + printf("Waiting:%03d Running:%03d Callback:%03d Complete:%03d \n", + job_queue_get_num_waiting(job_queue) , + job_queue_get_num_running(job_queue), + job_queue_get_num_callback( job_queue ) , + job_queue_get_num_complete(job_queue)); + + counter++; + } + return NULL; +} + + +void * status_job__( void * arg ) { + const int usleep_time = 10000; + arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); + job_type * job = job_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ) ); + job_queue_type * queue = arg_pack_iget_ptr( arg_pack , 1 ); + char * run_file = util_alloc_filename( job->run_path , "RUNNING" , NULL); + + while (true) { + if (job->queue_index >= 0) { + job_status_type status; + if (util_is_file(run_file)) { + status = job_queue_iget_job_status(queue, job->queue_index); + if (util_is_file(run_file)) + test_assert_true( (status == JOB_QUEUE_RUNNING) || (status == JOB_QUEUE_SUBMITTED) ); + } + status = job_queue_iget_job_status(queue, job->queue_index); + if (status == JOB_QUEUE_SUCCESS) + break; + } + usleep( usleep_time ); + } + + free( run_file ); + return NULL; +} + + + +void status_jobs( job_queue_type * queue , int num_jobs , job_type ** jobs , thread_pool_type * tp) { + for (int i=0; i < num_jobs; i++) { + job_type * job = jobs[i]; + arg_pack_type * arg = arg_pack_alloc(); + arg_pack_append_ptr( arg , job ); + arg_pack_append_ptr( arg , queue ); + thread_pool_add_job(tp , status_job__ , arg ); + } + thread_pool_add_job( tp , global_status , queue ); +} + + +/* + The purpose of this test is to stress the queue system with a + massively multithreaded workload. The test will submit jobs, let + them run and run a callback. The various elements are pimped with + usleep() calls to ensure that all of these actions: + + 1. Submit + 2. Run callback + 3. Check status + + Are performed concurrently. The total runtime of the test should be + ~ 120 seconds. +*/ + + +int main(int argc , char ** argv) { + const int queue_timeout = 180; + const int submit_timeout = 180; + const int status_timeout = 180; + const int number_of_jobs = 250; + const int submit_threads = number_of_jobs / 10 ; + const int status_threads = number_of_jobs + 1; + const char * job = util_alloc_abs_path(argv[1]); + rng_type * rng = rng_alloc( MZRAN , INIT_CLOCK ); + test_work_area_type * work_area = test_work_area_alloc("job_queue"); + job_type **jobs = alloc_jobs( rng , number_of_jobs , job); + + job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK", "ERROR"); + queue_driver_type * driver = queue_driver_alloc_local(); + job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); + + job_queue_set_driver(queue, driver); + job_queue_manager_start_queue(queue_manager, 0, false , true); + + { + thread_pool_type * status_pool = thread_pool_alloc( status_threads , true ); + thread_pool_type * submit_pool = thread_pool_alloc( submit_threads , true ); + + submit_jobs( queue , number_of_jobs , jobs , submit_pool ); + status_jobs( queue , number_of_jobs , jobs , status_pool ); + + if (!thread_pool_try_join( submit_pool , submit_timeout )) + util_exit("Joining submit pool failed \n"); + thread_pool_free( submit_pool ); + + job_queue_submit_complete(queue); + + if (!thread_pool_try_join( status_pool , status_timeout)) + util_exit("Joining status pool failed \n"); + thread_pool_free( status_pool ); + } + + if (!job_queue_manager_try_wait(queue_manager , queue_timeout)) + util_exit("job_queue never completed \n"); + + job_queue_manager_free(queue_manager); + job_queue_free(queue); + queue_driver_free(driver); + check_jobs( number_of_jobs , jobs ); + test_work_area_free(work_area); + rng_free( rng ); +} diff --git a/ThirdParty/Ert/devel/libjob_queue/tests/job_status_test.c b/ThirdParty/Ert/devel/libjob_queue/tests/job_status_test.c new file mode 100644 index 0000000000..bde1fa9889 --- /dev/null +++ b/ThirdParty/Ert/devel/libjob_queue/tests/job_status_test.c @@ -0,0 +1,111 @@ +/* + Copyright (C) 2015 Statoil ASA, Norway. + + The file 'job_status_test.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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 3 of the License, or + (at your option) any later version. + + ERT 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 at + for more details. +*/ + +#include +#include +#include + +#include +#include +#include + + +void call_get_status( void * arg ) { + job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); + job_queue_status_get_count( job_status , JOB_QUEUE_DONE + JOB_QUEUE_USER_EXIT); +} + + + +void test_create() { + job_queue_status_type * status = job_queue_status_alloc(); + test_assert_true( job_queue_status_is_instance( status )); + test_assert_int_equal( job_queue_status_get_count( status , JOB_QUEUE_DONE ) , 0 ); + test_assert_util_abort( "STATUS_INDEX" , call_get_status , status ); + job_queue_status_free( status ); +} + + +void * add_sim( void * arg ) { + job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); + job_queue_status_inc( job_status , JOB_QUEUE_WAITING ); + return NULL; +} + + +void * user_exit( void * arg ) { + job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); + job_queue_status_transition( job_status , JOB_QUEUE_WAITING , JOB_QUEUE_USER_EXIT); + return NULL; +} + + +void * user_done( void * arg ) { + job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); + job_queue_status_transition( job_status , JOB_QUEUE_WAITING , JOB_QUEUE_DONE); + return NULL; +} + + + +void test_update() { + int N = 15000; + pthread_t * thread_list = util_malloc( 2*N*sizeof * thread_list); + + job_queue_status_type * status = job_queue_status_alloc(); + test_assert_int_equal( 0 , job_queue_status_get_total_count( status )); + for (int i=0; i < 2*N; i++) + pthread_create( &thread_list[i] , NULL , add_sim , status ); + + for (int i=0; i < 2*N; i++) + pthread_join( thread_list[i] , NULL ); + + test_assert_int_equal( 2*N , job_queue_status_get_count( status , JOB_QUEUE_WAITING )); + for (int i=0; i < 2*N; i++) { + if ((i % 2) == 0) + pthread_create( &thread_list[i] , NULL , user_exit , status ); + else + pthread_create( &thread_list[i] , NULL , user_done , status ); + } + for (int i=0; i < 2*N; i++) + pthread_join( thread_list[i] , NULL ); + + test_assert_int_equal( 0 , job_queue_status_get_count( status , JOB_QUEUE_WAITING )); + test_assert_int_equal( N , job_queue_status_get_count( status , JOB_QUEUE_USER_EXIT )); + test_assert_int_equal( N , job_queue_status_get_count( status , JOB_QUEUE_DONE )); + + test_assert_int_equal( 2*N , job_queue_status_get_total_count( status )); + job_queue_status_free( status ); +} + + +void test_name() { + test_assert_string_equal( job_queue_status_name( JOB_QUEUE_NOT_ACTIVE ) , + "JOB_QUEUE_NOT_ACTIVE" ); + test_assert_string_equal( job_queue_status_name( JOB_QUEUE_EXIT ) , + "JOB_QUEUE_EXIT" ); + test_assert_string_equal( job_queue_status_name( JOB_QUEUE_FAILED ) , + "JOB_QUEUE_FAILED" ); +} + + +int main( int argc , char ** argv) { + test_create(); + test_update(); + test_name(); +} diff --git a/ThirdParty/Ert/devel/python/python/ert/config/__init__.py b/ThirdParty/Ert/devel/python/python/ert/config/__init__.py index 0420a73e17..da46f58b29 100644 --- a/ThirdParty/Ert/devel/python/python/ert/config/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert/config/__init__.py @@ -20,6 +20,7 @@ CONFIG_LIB = clib.ert_load("libconfig") from .unrecognized_enum import UnrecognizedEnum from .content_type_enum import ContentTypeEnum +from .config_error import ConfigError from .config_content import ConfigContent , ContentItem, ContentNode from .config_parser import ConfigParser, SchemaItem -from .config_error import ConfigError + diff --git a/ThirdParty/Ert/devel/python/python/ert/config/config_content.py b/ThirdParty/Ert/devel/python/python/ert/config/config_content.py index b9dc960930..99bae616af 100644 --- a/ThirdParty/Ert/devel/python/python/ert/config/config_content.py +++ b/ThirdParty/Ert/devel/python/python/ert/config/config_content.py @@ -16,7 +16,7 @@ import os.path -from ert.config import UnrecognizedEnum, CONFIG_LIB, ContentTypeEnum +from ert.config import UnrecognizedEnum, CONFIG_LIB, ContentTypeEnum,ConfigError from ert.cwrap import BaseCClass, CWrapper class ContentNode(BaseCClass): @@ -47,6 +47,20 @@ class ContentNode(BaseCClass): typed_get = self.typed_get[content_type] return typed_get( self , index ) + def getPath(self , index = 0, absolute = True , relative_start = None): + index = self.__assertIndex(index) + content_type = ContentNode.cNamespace().iget_type(self, index) + if content_type in [ContentTypeEnum.CONFIG_EXISTING_PATH , ContentTypeEnum.CONFIG_PATH]: + if absolute: + return ContentNode.cNamespace().iget_as_abspath(self, index) + else: + if relative_start is None: + return ContentNode.cNamespace().iget_as_relpath(self, index) + else: + abs_path = ContentNode.cNamespace().iget_as_abspath(self, index) + return os.path.relpath( abs_path , relative_start ) + else: + raise TypeError("The getPath() method can only be called on PATH items") def content(self, sep=" "): return ContentNode.cNamespace().get_full_string(self, sep) @@ -84,6 +98,8 @@ class ContentItem(BaseCClass): else: raise TypeError("[] operator must have integer index") + def last(self): + return self[-1] def getValue(self , item_index = -1 , node_index = 0): node = self[item_index] @@ -126,6 +142,8 @@ class ConfigContent(BaseCClass): ConfigContent.cNamespace().free(self) + def getErrors(self): + return ConfigContent.cNamespace().get_errors(self) cwrapper = CWrapper(CONFIG_LIB) @@ -137,6 +155,7 @@ ConfigContent.cNamespace().free = cwrapper.prototype("void config_content_fr ConfigContent.cNamespace().is_valid = cwrapper.prototype("bool config_content_is_valid( config_content )") ConfigContent.cNamespace().has_key = cwrapper.prototype("bool config_content_has_item( config_content , char*)") ConfigContent.cNamespace().get_item = cwrapper.prototype("content_item_ref config_content_get_item( config_content , char*)") +ConfigContent.cNamespace().get_errors = cwrapper.prototype("config_error_ref config_content_get_errors( content_node )") ContentItem.cNamespace().size = cwrapper.prototype("int config_content_item_get_size( content_item )") ContentItem.cNamespace().iget_content_node = cwrapper.prototype("content_node_ref config_content_item_iget_node( content_item , int)") @@ -145,10 +164,14 @@ ContentNode.cNamespace().iget = cwrapper.prototype("char* config_content_node_ig ContentNode.cNamespace().size = cwrapper.prototype("int config_content_node_get_size( content_node )") ContentNode.cNamespace().get_full_string = cwrapper.prototype("char* config_content_node_get_full_string( content_node , char* )") ContentNode.cNamespace().iget_type = cwrapper.prototype("config_content_type_enum config_content_node_iget_type( content_node , int)") +ContentNode.cNamespace().iget_as_abspath = cwrapper.prototype("char* config_content_node_iget_as_abspath( content_node , int)") +ContentNode.cNamespace().iget_as_relpath = cwrapper.prototype("char* config_content_node_iget_as_relpath( content_node , int)") +ContentNode.typed_get[ContentTypeEnum.CONFIG_STRING] = iget_as_string = cwrapper.prototype("char* config_content_node_iget( content_node , int)") ContentNode.typed_get[ContentTypeEnum.CONFIG_INT] = iget_as_int = cwrapper.prototype("int config_content_node_iget_as_int( content_node , int)") -ContentNode.typed_get[ContentTypeEnum.CONFIG_BOOL] = iget_as_bool = cwrapper.prototype("bool config_content_node_iget_as_bool( content_node , int)") ContentNode.typed_get[ContentTypeEnum.CONFIG_FLOAT] = iget_as_double = cwrapper.prototype("double config_content_node_iget_as_double( content_node , int)") ContentNode.typed_get[ContentTypeEnum.CONFIG_PATH] = iget_as_path = cwrapper.prototype("char* config_content_node_iget_as_path( content_node , int)") -ContentNode.typed_get[ContentTypeEnum.CONFIG_STRING] = iget_as_string = cwrapper.prototype("char* config_content_node_iget( content_node , int)") +ContentNode.typed_get[ContentTypeEnum.CONFIG_EXISTING_PATH] = iget_as_path = cwrapper.prototype("char* config_content_node_iget_as_path( content_node , int)") +ContentNode.typed_get[ContentTypeEnum.CONFIG_BOOL] = iget_as_bool = cwrapper.prototype("bool config_content_node_iget_as_bool( content_node , int)") + diff --git a/ThirdParty/Ert/devel/python/python/ert/config/config_error.py b/ThirdParty/Ert/devel/python/python/ert/config/config_error.py index 69ed8eda98..2cbeb17563 100644 --- a/ThirdParty/Ert/devel/python/python/ert/config/config_error.py +++ b/ThirdParty/Ert/devel/python/python/ert/config/config_error.py @@ -43,9 +43,7 @@ class ConfigError(BaseCClass): ################################################################## cwrapper = CWrapper(CONFIG_LIB) -cwrapper.registerType("config_error", ConfigError) -cwrapper.registerType("config_error_obj", ConfigError.createPythonObject) -cwrapper.registerType("config_error_ref", ConfigError.createCReference) +cwrapper.registerObjectType("config_error", ConfigError) ConfigError.cNamespace().free = cwrapper.prototype("void config_error_free(config_error)") ConfigError.cNamespace().count = cwrapper.prototype("int config_error_count(config_error)") diff --git a/ThirdParty/Ert/devel/python/python/ert/config/config_parser.py b/ThirdParty/Ert/devel/python/python/ert/config/config_parser.py index f1d64b72ec..4b118e5e6b 100644 --- a/ThirdParty/Ert/devel/python/python/ert/config/config_parser.py +++ b/ThirdParty/Ert/devel/python/python/ert/config/config_parser.py @@ -14,6 +14,7 @@ # See the GNU General Public License at # for more details. +import sys import os.path from ert.config import UnrecognizedEnum, CONFIG_LIB, ContentTypeEnum , ConfigContent @@ -57,9 +58,13 @@ class ConfigParser(BaseCClass): return ConfigParser.cNamespace().has_schema_item( self , keyword ) - def add(self, keyword, required=False): - return ConfigParser.cNamespace().add(self, keyword, required).setParent( self ) + def add(self, keyword, required=False , value_type = None): + item = ConfigParser.cNamespace().add(self, keyword, required).setParent( self ) + if value_type: + item.iset_type( 0 , value_type ) + return item + def getSchemaItem(self , keyword): if keyword in self: @@ -80,6 +85,10 @@ class ConfigParser(BaseCClass): if config_content.isValid(): return config_content else: + sys.stderr.write("Errors parsing:%s \n" % config_file) + for count,error in enumerate(config_content.getErrors()): + sys.stderr.write(" %02d:%s\n" % (count , error)) + raise Exception("Parsing:%s failed" % config_file) else: raise IOError("File: %s does not exists" % config_file) diff --git a/ThirdParty/Ert/devel/python/python/ert/cwrap/clib.py b/ThirdParty/Ert/devel/python/python/ert/cwrap/clib.py index b599b659c4..11ed71b11f 100644 --- a/ThirdParty/Ert/devel/python/python/ert/cwrap/clib.py +++ b/ThirdParty/Ert/devel/python/python/ert/cwrap/clib.py @@ -46,12 +46,17 @@ so_extension = {"linux" : "so", # Passing None to the CDLL() function means to open a lib handle to # the current runnning process, i.e. like dlopen( NULL ). We must # special case this to avoid creating the bogus argument 'None.so'. -def lib_name(lib , platform_key): +def lib_name(lib , path = None): if lib is None: - so_name = None + return None else: + platform_key = platform.system().lower() so_name = "%s.%s" % (lib , so_extension[ platform_key ]) - return so_name + if path: + return os.path.join( path , so_name ) + else: + return so_name + @@ -73,15 +78,14 @@ def __load( lib_list, ert_prefix): error_list = {} dll = None - platform_key = platform.system().lower() for lib in lib_list: - so_name = lib_name( lib , platform_key ) + if ert_prefix: + lib_file = lib_name( lib , path = ert_lib_path ) + else: + lib_file = lib_name( lib ) + try: - if ert_prefix and so_name: - ert_lib = os.path.join(ert_lib_path , so_name) - dll = ctypes.CDLL(ert_lib, ctypes.RTLD_GLOBAL) - else: - dll = ctypes.CDLL(so_name , ctypes.RTLD_GLOBAL) + dll = ctypes.CDLL(lib_file , ctypes.RTLD_GLOBAL) return dll except Exception, exc: error_list[lib] = exc diff --git a/ThirdParty/Ert/devel/python/python/ert/cwrap/cwrap.py b/ThirdParty/Ert/devel/python/python/ert/cwrap/cwrap.py index d2f1bb19ce..6dd5ea59ca 100644 --- a/ThirdParty/Ert/devel/python/python/ert/cwrap/cwrap.py +++ b/ThirdParty/Ert/devel/python/python/ert/cwrap/cwrap.py @@ -73,8 +73,12 @@ class CWrapper: """Registers the default available types for prototyping.""" cls.registerType("void", None) cls.registerType("void*", ctypes.c_void_p) + cls.registerType("uint", ctypes.c_uint) + cls.registerType("uint*", ctypes.POINTER(ctypes.c_uint)) cls.registerType("int", ctypes.c_int) cls.registerType("int*", ctypes.POINTER(ctypes.c_int)) + cls.registerType("int64", ctypes.c_int64) + cls.registerType("int64*", ctypes.POINTER(ctypes.c_int64)) cls.registerType("size_t", ctypes.c_size_t) cls.registerType("size_t*", ctypes.POINTER(ctypes.c_size_t)) cls.registerType("bool", ctypes.c_bool) diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert/ecl/CMakeLists.txt index 18f8cbfae5..115dd9685c 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/CMakeLists.txt @@ -1,29 +1,30 @@ set(PYTHON_SOURCES __init__.py ecl.py + ecl_3d_file.py + ecl_3dkw.py ecl_case.py ecl_default.py ecl_file.py - ecl_3d_file.py - ecl_init_file.py - ecl_restart_file.py ecl_grav.py ecl_grav_calc.py ecl_grid.py + ecl_init_file.py ecl_kw.py - ecl_3dkw.py ecl_npv.py ecl_region.py + ecl_restart_file.py ecl_rft.py ecl_rft_cell.py ecl_smspec_node.py ecl_subsidence.py ecl_sum.py + ecl_sum_keyword_vector.py ecl_sum_node.py + ecl_sum_tstep.py ecl_sum_vector.py ecl_util.py fortio.py - ecl_sum_keyword_vector.py ) if (BUILD_ERT) diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/__init__.py b/ThirdParty/Ert/devel/python/python/ert/ecl/__init__.py index a534e1d0b6..2b7d718e59 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/__init__.py @@ -77,6 +77,7 @@ import ert.geo ECL_LIB = clib.ert_load("libecl") +from .ecl_sum_tstep import EclSumTStep from .ecl_sum import EclSum #, EclSumVector, EclSumNode, EclSMSPECNode from .ecl_sum_keyword_vector import EclSumKeyWordVector from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclTypeEnum, EclUtil diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl.py index 02b4cc7f1e..5c41880c15 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl.py @@ -117,12 +117,8 @@ class default_wrapper(object): ecl_default = default_wrapper() -from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclTypeEnum, EclUtil - -#make enum values globally available in ert.ecl.ecl -for enum in EclFileEnum.enum_names: - globals()[enum] = getattr(EclFileEnum, enum) - +from .ecl_util import EclFileFlagEnum, EclPhaseEnum, EclTypeEnum, EclUtil + for enum in EclFileFlagEnum.enum_names: globals()[enum] = getattr(EclFileFlagEnum, enum) diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_file.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_file.py index 35a7f61893..e81e3d27c7 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_file.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_file.py @@ -275,11 +275,11 @@ class EclFile(CClass): """ OK = False - if report_step: + if not report_step is None: OK = cfunc.restart_block_step( self , report_step ) - elif sim_time: + elif not sim_time is None: OK = cfunc.restart_block_time( self , CTime( sim_time ) ) - elif index: + elif not index is None: OK = cfunc.restart_block_iselect( self, index ) else: raise TypeError("select_restart_section() requires either dtime or report_step argument - none given") diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_grid.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_grid.py index a2e62a9b64..9cd00974e1 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_grid.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_grid.py @@ -121,8 +121,16 @@ class EclGrid(CClass): return obj + @classmethod + def create_ref(cls , c_ptr , parent = None ): + obj = object.__new__( cls ) + obj.init_cref( c_ptr , parent ) + return obj + + @classmethod def create_rectangular(cls , dims , dV , actnum = None): + warnings.warn("The create_rectangular method is deprecated - use createRectangular( )") return cls.createRectangular( dims , dV , actnum ) @@ -1057,6 +1065,11 @@ class EclGrid(CClass): else: raise ValueError("The input keyword must have nx*n*nz or nactive elements. Size:%d invalid" % len(kw)) + + def exportACTNUMKw(self): + actnum = EclKW.create("ACTNUM" , self.getGlobalSize() , EclTypeEnum.ECL_INT_TYPE) + cfunc.init_actnum( self , actnum.getDataPtr() ) + return actnum # 2. Creating a wrapper object around the libecl library, diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_kw.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_kw.py index d83d816bd5..981afd057d 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_kw.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_kw.py @@ -775,8 +775,11 @@ class EclKW(CClass): return cfunc.get_size( self ) def set_name( self , name ): + if len(name) > 8: + raise ValueError("Sorry: the name property must be max 8 characters long :-(") cfunc.set_header( self , name ) + def get_name( self ): return self.getName() @@ -1016,6 +1019,15 @@ class EclKW(CClass): cfunc.fix_uninitialized( self , dims[0] , dims[1], dims[2] , actnum.getDataPtr() ) + def getDataPtr(self): + if self.ecl_type == EclTypeEnum.ECL_INT_TYPE: + return cfunc.int_ptr( self ) + elif self.ecl_type == EclTypeEnum.ECL_FLOAT_TYPE: + return cfunc.float_ptr( self ) + elif self.ecl_type == EclTypeEnum.ECL_DOUBLE_TYPE: + return cfunc.double_ptr( self ) + else: + raise ValueError("Only numeric types can export data pointer") ################################################################# diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum.py index a93dd9b57a..55b46b8e08 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum.py @@ -30,6 +30,7 @@ import datetime # index as the first argument and the key/key_index as second # argument. In the python code this order has been reversed. from ert.cwrap import BaseCClass, CWrapper, CFILE +from ert.ecl import EclSumTStep from ert.ecl.ecl_sum_vector import EclSumVector from ert.ecl.ecl_smspec_node import EclSMSPECNode from ert.util import StringList, CTime, DoubleVector, TimeVector, IntVector @@ -110,6 +111,7 @@ class EclSum(BaseCClass): def writer(case , start_time , nx,ny,nz , fmt_output = False , unified = True , time_in_days = True , key_join_string = ":"): """ The writer is not generally usable. + @rtype: EclSum """ return EclSum.cNamespace().create_writer( case , fmt_output , unified , key_join_string , CTime(start_time) , time_in_days , nx , ny , nz) @@ -119,8 +121,9 @@ class EclSum(BaseCClass): def addTStep(self , report_step , sim_days): - tstep = EclSum.cNamespace().add_tstep( self , report_step , sim_days ) - return tstep + """ @rtype: EclSumTStep """ + sim_seconds = sim_days * 24 * 60 * 60 + return EclSum.cNamespace().add_tstep(self, report_step, sim_seconds) def _initialize(self): @@ -973,7 +976,9 @@ ime_index. ################################################################# -# 2. Creating a wrapper object around the libecl library, + + +# 2. Creating a wrapper object around the libecl library, # registering the type map : ecl_kw <-> EclKW cwrapper = CWrapper(ECL_LIB) cwrapper.registerType( "ecl_sum" , EclSum ) @@ -1030,9 +1035,10 @@ EclSum.cNamespace().get_var_node = cwrapper.prototype("smspec_n EclSum.cNamespace().create_well_list = cwrapper.prototype("stringlist_obj ecl_sum_alloc_well_list( ecl_sum , char* )") EclSum.cNamespace().create_group_list = cwrapper.prototype("stringlist_obj ecl_sum_alloc_group_list( ecl_sum , char* )") -EclSum.cNamespace().create_writer = cwrapper.prototype("ecl_sum_obj ecl_sum_alloc_writer( char* , bool , bool , char* , time_t , bool , int , int , int)") -EclSum.cNamespace().add_variable = cwrapper.prototype("void ecl_sum_add_var(ecl_sum , char* , char* , int , char*, double)") -EclSum.cNamespace().add_tstep = cwrapper.prototype("c_void_p ecl_sum_add_tstep(ecl_sum , int , double)") +EclSum.cNamespace().create_writer = cwrapper.prototype("ecl_sum_obj ecl_sum_alloc_writer( char* , bool , bool , char* , time_t , bool , int , int , int)") +EclSum.cNamespace().add_variable = cwrapper.prototype("void ecl_sum_add_var(ecl_sum , char* , char* , int , char*, double)") +EclSum.cNamespace().add_tstep = cwrapper.prototype("ecl_sum_tstep_ref ecl_sum_add_tstep(ecl_sum , int , double)") import ert.ecl.ecl_sum_keyword_vector -EclSum.cNamespace().dump_csv_line = cwrapper.prototype("void ecl_sum_dump_line_to_csv_file(ecl_sum , time_t , ecl_sum_vector, FILE)") +EclSum.cNamespace().dump_csv_line = cwrapper.prototype("void ecl_sum_dump_line_to_csv_file(ecl_sum , time_t , ecl_sum_vector, FILE)") +EclSum.cNamespace().get_smspec = cwrapper.prototype("void* ecl_sum_get_smspec(ecl_sum)") diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum_tstep.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum_tstep.py new file mode 100644 index 0000000000..34dcfd7eb8 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_sum_tstep.py @@ -0,0 +1,56 @@ +from ert.cwrap import BaseCClass, CWrapper +from ert.ecl import ECL_LIB + + +class EclSumTStep(BaseCClass): + def __init__(self, report_step, mini_step, sim_days, smspec): + sim_seconds = sim_days * 24 * 60 * 60 + + c_pointer = EclSumTStep.cNamespace().alloc(report_step, mini_step, sim_seconds, smspec) + super(EclSumTStep, self).__init__(c_pointer) + + def getSimDays(self): + """ @rtype: double """ + return EclSumTStep.cNamespace().get_sim_days(self) + + def getReport(self): + """ @rtype: int """ + return EclSumTStep.cNamespace().get_report(self) + + def getMiniStep(self): + """ @rtype: int """ + return EclSumTStep.cNamespace().get_ministep(self) + + def __getitem__(self, key): + """ @rtype: double """ + if not key in self: + raise KeyError("Key '%s' is not available." % key) + + return EclSumTStep.cNamespace().get_from_key(self, key) + + def __setitem__(self, key, value): + if not key in self: + raise KeyError("Key '%s' is not available." % key) + + EclSumTStep.cNamespace().set_from_key(self, key, value) + + def __contains__(self, key): + return EclSumTStep.cNamespace().has_key(self, key) + + def free(self): + EclSumTStep.cNamespace().free(self) + + +cwrapper = CWrapper(ECL_LIB) +cwrapper.registerObjectType("ecl_sum_tstep", EclSumTStep) + +EclSumTStep.cNamespace().alloc = cwrapper.prototype("void* ecl_sum_tstep_alloc_new(int, int, float, void*)") +EclSumTStep.cNamespace().free = cwrapper.prototype("void ecl_sum_tstep_free(ecl_sum_tstep)") + +EclSumTStep.cNamespace().get_sim_days = cwrapper.prototype("double ecl_sum_tstep_get_sim_days(ecl_sum_tstep)") +EclSumTStep.cNamespace().get_report = cwrapper.prototype("int ecl_sum_tstep_get_report(ecl_sum_tstep)") +EclSumTStep.cNamespace().get_ministep = cwrapper.prototype("int ecl_sum_tstep_get_ministep(ecl_sum_tstep)") + +EclSumTStep.cNamespace().set_from_key = cwrapper.prototype("void ecl_sum_tstep_set_from_key(ecl_sum_tstep, char*, float)") +EclSumTStep.cNamespace().get_from_key = cwrapper.prototype("double ecl_sum_tstep_get_from_key(ecl_sum_tstep, char*)") +EclSumTStep.cNamespace().has_key = cwrapper.prototype("bool ecl_sum_tstep_has_key(ecl_sum_tstep)") \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_util.py b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_util.py index 65ca98009c..650593c420 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_util.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/ecl_util.py @@ -24,13 +24,37 @@ ert.cwrap.cenum.create_enum() function in a semi-automagic manner. In addition to the enum definitions there are a few stateless functions from ecl_util.c which are not bound to any class type. """ -from ert.cwrap import create_enum, CWrapper, CWrapperNameSpace - +import ctypes +from ert.cwrap import create_enum, CWrapper, CWrapperNameSpace, BaseCEnum from ert.ecl import ECL_LIB +class EclFileEnum(BaseCEnum): + ECL_OTHER_FILE = None + ECL_RESTART_FILE = None + ECL_UNIFIED_RESTART_FILE = None + ECL_SUMMARY_FILE = None + ECL_UNIFIED_SUMMARY_FILE = None + ECL_GRID_FILE = None + ECL_EGRID_FILE = None + ECL_INIT_FILE = None + ECL_RFT_FILE = None + ECL_DATA_FILE = None + + +EclFileEnum.addEnum("ECL_OTHER_FILE", 0) +EclFileEnum.addEnum("ECL_RESTART_FILE", 1) +EclFileEnum.addEnum("ECL_UNIFIED_RESTART_FILE", 2) +EclFileEnum.addEnum("ECL_SUMMARY_FILE", 4) +EclFileEnum.addEnum("ECL_UNIFIED_SUMMARY_FILE", 8) +EclFileEnum.addEnum("ECL_SUMMARY_HEADER_FILE", 16) +EclFileEnum.addEnum("ECL_GRID_FILE", 32) +EclFileEnum.addEnum("ECL_EGRID_FILE", 64) +EclFileEnum.addEnum("ECL_INIT_FILE", 128) +EclFileEnum.addEnum("ECL_RFT_FILE", 256) +EclFileEnum.addEnum("ECL_DATA_FILE", 512) + +EclFileEnum.registerEnum(ECL_LIB, "ecl_file_enum") -# ecl_file_enum from ecl_util.h -EclFileEnum = create_enum(ECL_LIB, "ecl_util_file_enum_iget", "ecl_file_enum") # ecl_phase_enum from ecl_util.h EclPhaseEnum = create_enum(ECL_LIB, "ecl_util_phase_enum_iget", "ecl_phase_enum") @@ -42,16 +66,16 @@ EclTypeEnum = create_enum(ECL_LIB, "ecl_util_type_enum_iget", "ecl_type_enum") EclFileFlagEnum = create_enum(ECL_LIB, "ecl_util_file_flags_enum_iget", "ecl_file_flag_enum") - - cwrapper = CWrapper(ECL_LIB) cfunc = CWrapperNameSpace("ecl_util") cfunc.get_num_cpu = cwrapper.prototype("int ecl_util_get_num_cpu( char* )") -cfunc.get_file_type = cwrapper.prototype("int ecl_util_get_file_type( char* , bool* , int*)") +cfunc.get_file_type = cwrapper.prototype("ecl_file_enum ecl_util_get_file_type( char* , bool* , int*)") cfunc.get_type_name = cwrapper.prototype("char* ecl_util_get_type_name( int )") cfunc.get_start_date = cwrapper.prototype("time_t ecl_util_get_start_date( char* )") + + class EclUtil(object): @staticmethod def get_num_cpu( datafile ): @@ -69,8 +93,9 @@ class EclUtil(object): """ Will inspect an ECLIPSE filename and return an integer type flag. """ - return cfunc.get_file_type(filename, None, None) - + file_type , fmt , step = EclUtil.inspectExtension( filename ) + return file_type + @staticmethod def type_name(ecl_type): return cfunc.get_type_name(ecl_type) @@ -79,7 +104,24 @@ class EclUtil(object): def get_start_date(datafile): return cfunc.get_start_date(datafile).datetime() + @staticmethod + def inspectExtension( filename ): + """Will inspect an ECLIPSE filename and return a tuple consisting of + file type (EclFileEnum), a bool for formatted or not, and an + integer for the step number. + """ + fmt_file = ctypes.c_bool() + report_step = ctypes.c_int(-1) + file_type = cfunc.get_file_type(filename, ctypes.byref(fmt_file) , ctypes.byref(report_step)) + if report_step.value == -1: + step = None + else: + step = report_step.value + + return (file_type , fmt_file.value , step) + + get_num_cpu = EclUtil.get_num_cpu get_file_type = EclUtil.get_file_type diff --git a/ThirdParty/Ert/devel/python/python/ert/ecl/faults/layer.py b/ThirdParty/Ert/devel/python/python/ert/ecl/faults/layer.py index 95e528a76f..088762dbcb 100644 --- a/ThirdParty/Ert/devel/python/python/ert/ecl/faults/layer.py +++ b/ThirdParty/Ert/devel/python/python/ert/ecl/faults/layer.py @@ -157,7 +157,6 @@ class Layer(BaseCClass): def addIJBarrier(self , ij_list): if len(ij_list) < 2: - print "ij_list:%s" % ij_list raise ValueError("Must have at least two (i,j) points") nx = self.getNX() @@ -227,6 +226,10 @@ class Layer(BaseCClass): return ij_list + def countEqual(self , value): + return Layer.cNamespace().count_equal( self , value ) + + cwrapper = CWrapper(ECL_LIB) CWrapper.registerObjectType("layer", Layer) @@ -248,5 +251,6 @@ Layer.cNamespace().assign = cwrapper.prototype("void layer_assign(layer , int)") Layer.cNamespace().cell_sum = cwrapper.prototype("int layer_get_cell_sum(layer)") Layer.cNamespace().update_connected = cwrapper.prototype("void layer_update_connected_cells(layer,int,int,int,int)") Layer.cNamespace().cells_equal = cwrapper.prototype("void layer_cells_equal( layer, int,int_vector,int_vector)") +Layer.cNamespace().count_equal = cwrapper.prototype("int layer_count_equal( layer, int)") Layer.cNamespace().active_cell = cwrapper.prototype("bool layer_iget_active( layer, int,int)") Layer.cNamespace().update_active = cwrapper.prototype("bool layer_update_active( layer, ecl_grid , int)") diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert/enkf/CMakeLists.txt index ecec6ee9c5..75db4dcdbf 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/CMakeLists.txt @@ -18,9 +18,13 @@ set(PYTHON_SOURCES ert_template.py ert_templates.py ert_workflow_list.py + key_manager.py local_config.py + local_dataset.py + local_ministep.py local_obsdata.py local_obsdata_node.py + local_updatestep.py meas_block.py meas_data.py model_config.py @@ -37,7 +41,7 @@ set(PYTHON_SOURCES summary_key_set.py ) -add_python_package("python.ert.enkf" ${PYTHON_INSTALL_PREFIX}/ert/enkf "${PYTHON_SOURCES}" True) +add_python_package("python.ert.enkf" ${PYTHON_INSTALL_PREFIX}/ert/enkf "${PYTHON_SOURCES}" True) add_subdirectory(data) add_subdirectory(enums) diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/__init__.py b/ThirdParty/Ert/devel/python/python/ert/enkf/__init__.py index 9aa0b9dcb4..6b1f75231d 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/__init__.py @@ -44,8 +44,12 @@ from .ert_workflow_list import ErtWorkflowList from .active_list import ActiveList from .data import * +from .local_dataset import LocalDataset from .local_obsdata_node import LocalObsdataNode from .local_obsdata import LocalObsdata +from .local_ministep import LocalMinistep +from .local_updatestep import LocalUpdateStep + from .observations import * from .obs_block import ObsBlock diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/ecl_config.py b/ThirdParty/Ert/devel/python/python/ert/enkf/ecl_config.py index fe5fe40327..f895155081 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/ecl_config.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/ecl_config.py @@ -13,6 +13,8 @@ # # See the GNU General Public License at # for more details. +from warnings import warn + from ert.cwrap import BaseCClass, CWrapper from ert.enkf import ENKF_LIB from ert.util import StringList @@ -67,7 +69,13 @@ class EclConfig(BaseCClass): return EclConfig.cNamespace().validate_gridfile(self, gridfile) def get_grid(self): - return EclConfig.cNamespace().get_grid(self) + warning_message = "The method get_grid() is deprecated. Use getGrid() instead" + warn(warning_message) + return self.getGrid( ) + + def getGrid(self): + c_ptr = EclConfig.cNamespace().get_grid(self) + return EclGrid.create_ref( c_ptr ) #----------------------------------------------------------------- diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_main.py b/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_main.py index 4c50d5cfb1..30f1a38bdb 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_main.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_main.py @@ -17,6 +17,7 @@ from ert.cwrap import BaseCClass, CWrapper from ert.enkf import AnalysisConfig, EclConfig, EnkfObs, EnKFState, LocalConfig, ModelConfig, EnsembleConfig, PlotConfig, SiteConfig, ENKF_LIB, EnkfSimulationRunner, EnkfFsManager, ErtWorkflowList, PostSimulationHook from ert.enkf.enums import EnkfInitModeEnum +from ert.enkf.key_manager import KeyManager from ert.util import SubstitutionList, Log @@ -36,6 +37,7 @@ class EnKFMain(BaseCClass): self.__fs_manager = EnkfFsManager(self) + self.__key_manager = KeyManager(self) @staticmethod def loadSiteConfig(): @@ -100,10 +102,13 @@ class EnKFMain(BaseCClass): """ @rtype: Log """ return EnKFMain.cNamespace().get_logh(self).setParent(self) - def local_config(self): + def getLocalConfig(self): """ @rtype: LocalConfig """ - return EnKFMain.cNamespace().get_local_config(self).setParent(self) - + config = EnKFMain.cNamespace().get_local_config(self).setParent(self) + config.initAttributes( self.ensembleConfig() , self.getObservations() , self.eclConfig().get_grid() ) + return config + + def siteConfig(self): """ @rtype: SiteConfig """ return EnKFMain.cNamespace().get_site_config(self).setParent(self) @@ -200,6 +205,10 @@ class EnKFMain(BaseCClass): """ @rtype: EnkfFsManager """ return self.__fs_manager + def getKeyManager(self): + """ :rtype: KeyManager """ + return self.__key_manager + def getWorkflowList(self): """ @rtype: ErtWorkflowList """ return EnKFMain.cNamespace().get_workflow_list(self).setParent(self) diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_obs.py b/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_obs.py index bef5c98386..f4cd631a49 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_obs.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/enkf_obs.py @@ -135,6 +135,8 @@ class EnkfObs(BaseCClass): def scaleCorrelatedStd( self , fs , local_obsdata , active_list): return EnkfObs.cNamespace().scale_correlated_std( self , fs , active_list , local_obsdata ) + def localScaleStd( self , local_obsdata , scale_factor): + return EnkfObs.cNamespace().local_scale_std( self , local_obsdata, scale_factor) def load(self , config_file): if not os.path.isfile( config_file ): @@ -170,3 +172,6 @@ EnkfObs.cNamespace().add_obs_vector = cwrapper.prototype("void enkf_obs_add_obs_ EnkfObs.cNamespace().get_obs_and_measure_data = cwrapper.prototype("void enkf_obs_get_obs_and_measure_data(enkf_obs, enkf_fs, local_obsdata, enkf_state_type_enum, int_vector, meas_data, obs_data)") EnkfObs.cNamespace().create_all_active_obs = cwrapper.prototype("local_obsdata_obj enkf_obs_alloc_all_active_local_obs( enkf_obs , char*)"); EnkfObs.cNamespace().scale_correlated_std = cwrapper.prototype("double enkf_obs_scale_correlated_std( enkf_obs , enkf_fs , int_vector , local_obsdata)"); +EnkfObs.cNamespace().local_scale_std = cwrapper.prototype("void enkf_obs_local_scale_std( enkf_obs , local_obsdata , double)"); + + diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/custom_kw_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/custom_kw_collector.py index 74116f2f18..30f78b2067 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/custom_kw_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/custom_kw_collector.py @@ -1,6 +1,7 @@ from pandas import DataFrame from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, CustomKWConfig, EnkfNode, NodeId, \ EnkfStateType +from ert.enkf.key_manager import KeyManager class CustomKWCollector(object): @@ -8,19 +9,8 @@ class CustomKWCollector(object): @staticmethod def getAllCustomKWKeys(ert): """ @rtype: list of str """ - custom_kw_keys = ert.ensembleConfig().getKeylistFromImplType(ErtImplType.CUSTOM_KW) - custom_kw_keys = [key for key in custom_kw_keys] - - custom_kw_list = [] - for name in custom_kw_keys: - enkf_config_node = ert.ensembleConfig().getNode(name) - custom_kw_config = enkf_config_node.getModelConfig() - assert isinstance(custom_kw_config, CustomKWConfig) - - for key in custom_kw_config: - custom_kw_list.append("%s:%s" % (name, key)) - - return custom_kw_list + key_manager = KeyManager(ert) + return key_manager.customKwKeys() @staticmethod def groupKeys(keys): diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_data_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_data_collector.py index 9ee2127d11..867483999c 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_data_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_data_collector.py @@ -8,9 +8,7 @@ from ert.util import BoolVector class GenDataCollector(object): - @staticmethod - def loadGenData(ert, case_name, key, report_step): """@type ert: EnKFMain @type case_name: str @@ -36,10 +34,12 @@ class GenDataCollector(object): data_array.fill( numpy.nan ) for realization_index, realization_number in enumerate(realizations): realization_vector = ensemble_data[realization_number] - for data_index in range(data_size): - if active_mask[data_index]: - value = realization_vector[data_index] - data_array[data_index][realization_index] = value + + if len(realization_vector) > 0: # Must check because of a bug changing between different case with different states + for data_index in range(data_size): + if active_mask[data_index]: + value = realization_vector[data_index] + data_array[data_index][realization_index] = value return DataFrame( data = data_array , columns = realizations ) diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_kw_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_kw_collector.py index f4d40acaaf..00bc1417f5 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_kw_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/gen_kw_collector.py @@ -2,6 +2,7 @@ import math from pandas import DataFrame, MultiIndex import numpy from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, GenKwConfig +from ert.enkf.key_manager import KeyManager from ert.enkf.plot_data import EnsemblePlotGenKW from ert.util import BoolVector @@ -20,22 +21,8 @@ class GenKwCollector(object): @staticmethod def getAllGenKwKeys(ert): """ @rtype: list of str """ - gen_kw_keys = ert.ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW) - gen_kw_keys = [key for key in gen_kw_keys] - - gen_kw_list = [] - for key in gen_kw_keys: - enkf_config_node = ert.ensembleConfig().getNode(key) - gen_kw_config = enkf_config_node.getModelConfig() - assert isinstance(gen_kw_config, GenKwConfig) - - for keyword_index, keyword in enumerate(gen_kw_config): - gen_kw_list.append("%s:%s" % (key, keyword)) - - if gen_kw_config.shouldUseLogScale(keyword_index): - gen_kw_list.append("LOG10_%s:%s" % (key, keyword)) - - return gen_kw_list + key_manager = KeyManager(ert) + return key_manager.genKwKeys() @staticmethod def loadAllGenKwData(ert, case_name, keys=None): diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/misfit_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/misfit_collector.py index 700b7e57f1..275118488d 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/misfit_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/misfit_collector.py @@ -1,6 +1,7 @@ from pandas import DataFrame import numpy from ert.enkf import EnKFMain, EnkfFs, RealizationStateEnum, EnkfStateType +from ert.enkf.key_manager import KeyManager from ert.util import BoolVector @@ -16,16 +17,10 @@ class MisfitCollector(object): return [iens for iens in active_list] @staticmethod - def getAllMisfitKeys(ert): + def getAllMisfitKeys(ert, sort_keys=True): """ @rtype: list of str """ - keys = [] - for obs_vector in ert.getObservations(): - key = "MISFIT:%s" % obs_vector.getObservationKey() - keys.append(key) - - keys.append("MISFIT:TOTAL") - - return keys + key_manager = KeyManager(ert) + return key_manager.misfitKeys(sort_keys=sort_keys) @staticmethod def loadAllMisfitData(ert, case_name): @@ -37,7 +32,7 @@ class MisfitCollector(object): fs = ert.getEnkfFsManager().getFileSystem(case_name) realizations = MisfitCollector.createActiveList(ert, fs) - misfit_keys = MisfitCollector.getAllMisfitKeys(ert) + misfit_keys = MisfitCollector.getAllMisfitKeys(ert, sort_keys=False) misfit_sum_index = len(misfit_keys) - 1 misfit_array = numpy.empty(shape=(len(misfit_keys), len(realizations)), dtype=numpy.float64) diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_collector.py index b82053c1b4..322ad3d946 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_collector.py @@ -1,6 +1,7 @@ from pandas import DataFrame, MultiIndex import numpy from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum +from ert.enkf.key_manager import KeyManager from ert.enkf.plot_data import EnsemblePlotData from ert.util import BoolVector @@ -19,8 +20,8 @@ class SummaryCollector(object): @staticmethod def getAllSummaryKeys(ert): """ @rtype: list of str """ - keys = ert.ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY) - return sorted([key for key in keys], key=lambda k : k.lower()) + key_manager = KeyManager(ert) + return key_manager.summaryKeys() @staticmethod def loadAllSummaryData(ert, case_name, keys=None): diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_observation_collector.py b/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_observation_collector.py index c434f62ddf..7eb9df6f31 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_observation_collector.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/export/summary_observation_collector.py @@ -1,6 +1,7 @@ from pandas import DataFrame, MultiIndex import numpy from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, EnkfObservationImplementationType +from ert.enkf.key_manager import KeyManager from ert.enkf.plot_data import EnsemblePlotData from ert.util import BoolVector @@ -13,10 +14,8 @@ class SummaryObservationCollector(object): @type ert: EnKFMain @rtype: list of str """ - ensemble_config = ert.ensembleConfig() - keys = sorted([key for key in ensemble_config.getKeylistFromImplType(ErtImplType.SUMMARY)]) - observation_keys = [key for key in keys if len(ensemble_config.getNode(key).getObservationKeys()) > 0] - return observation_keys + key_manager = KeyManager(ert) + return key_manager.summaryKeysWithObservations() @staticmethod def loadObservationData(ert, case_name, keys=None): diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/key_manager.py b/ThirdParty/Ert/devel/python/python/ert/enkf/key_manager.py new file mode 100644 index 0000000000..2331ce5080 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/key_manager.py @@ -0,0 +1,154 @@ +from ert.enkf import ErtImplType, GenKwConfig, CustomKWConfig + + +class KeyManager(object): + + def __init__(self, ert): + super(KeyManager, self).__init__() + """ + @type ert: ert.enkf.EnKFMain + """ + self.__ert = ert + + self.__all_keys = None + self.__all_keys_with_observations = None + self.__summary_keys = None + self.__summary_keys_with_observations = None + self.__gen_data_keys = None + self.__gen_kw_keys = None + self.__custom_kw_keys = None + self.__misfit_keys = None + + + def ert(self): + """ :rtype: ert.enkf.EnKFMain """ + return self.__ert + + def ensembleConfig(self): + """ :rtype: ert.enkf.EnsembleConfig """ + return self.ert().ensembleConfig() + + def summaryKeys(self): + """ :rtype: list of str """ + if self.__summary_keys is None: + self.__summary_keys = sorted([key for key in self.ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY)], key=lambda k : k.lower()) + + return self.__summary_keys + + def summaryKeysWithObservations(self): + """ :rtype: list of str """ + if self.__summary_keys_with_observations is None: + self.__summary_keys_with_observations = sorted([key for key in self.summaryKeys() if len(self.ensembleConfig().getNode(key).getObservationKeys()) > 0], key=lambda k : k.lower()) + + return self.__summary_keys_with_observations + + def genKwKeys(self): + """ :rtype: list of str """ + if self.__gen_kw_keys is None: + gen_kw_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW) + gen_kw_keys = [key for key in gen_kw_keys] + + gen_kw_list = [] + for key in gen_kw_keys: + enkf_config_node = self.ert().ensembleConfig().getNode(key) + gen_kw_config = enkf_config_node.getModelConfig() + assert isinstance(gen_kw_config, GenKwConfig) + + for keyword_index, keyword in enumerate(gen_kw_config): + gen_kw_list.append("%s:%s" % (key, keyword)) + + if gen_kw_config.shouldUseLogScale(keyword_index): + gen_kw_list.append("LOG10_%s:%s" % (key, keyword)) + + self.__gen_kw_keys = sorted(gen_kw_list, key=lambda k : k.lower()) + + return self.__gen_kw_keys + + + def customKwKeys(self): + """ :rtype: list of str """ + if self.__custom_kw_keys is None: + custom_kw_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.CUSTOM_KW) + + keys = [] + for name in custom_kw_keys: + enkf_config_node = self.ert().ensembleConfig().getNode(name) + custom_kw_config = enkf_config_node.getModelConfig() + assert isinstance(custom_kw_config, CustomKWConfig) + + for key in custom_kw_config: + keys.append("%s:%s" % (name, key)) + + self.__custom_kw_keys = sorted([key for key in keys], key=lambda k : k.lower()) + + return self.__custom_kw_keys + + + def genDataKeys(self): + """ :rtype: list of str """ + if self.__gen_data_keys is None: + gen_data_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_DATA) + gen_data_list = [] + for key in gen_data_keys: + enkf_config_node = self.ert().ensembleConfig().getNode(key) + gen_data_config = enkf_config_node.getDataModelConfig() + + for report_step in range(self.ert().getHistoryLength() + 1): + if gen_data_config.hasReportStep(report_step): + gen_data_list.append("%s@%d" % (key, report_step)) + self.__gen_data_keys = sorted(gen_data_list, key=lambda k : k.lower()) + + return self.__gen_data_keys + + def misfitKeys(self, sort_keys=True): + """ @rtype: list of str """ + if self.__misfit_keys is None: + keys = [] + for obs_vector in self.ert().getObservations(): + key = "MISFIT:%s" % obs_vector.getObservationKey() + keys.append(key) + + keys.append("MISFIT:TOTAL") + + self.__misfit_keys = sorted(keys, key=lambda k : k.lower()) if sort_keys else keys + + return self.__misfit_keys + + + def allDataTypeKeys(self): + """ :rtype: list of str """ + if self.__all_keys is None: + self.__all_keys = self.summaryKeys() + self.genKwKeys() + self.customKwKeys() + self.genDataKeys() + + return self.__all_keys + + def allDataTypeKeysWithObservations(self): + """ :rtype: list of str """ + if self.__all_keys_with_observations is None: + self.__all_keys_with_observations = self.summaryKeysWithObservations() + + return self.__all_keys_with_observations + + def isKeyWithObservations(self, key): + """ :rtype: bool """ + return key in self.allDataTypeKeysWithObservations() + + def isSummaryKey(self, key): + """ :rtype: bool """ + return key in self.summaryKeys() + + def isGenKwKey(self, key): + """ :rtype: bool """ + return key in self.genKwKeys() + + def isCustomKwKey(self, key): + """ :rtype: bool """ + return key in self.customKwKeys() + + def isGenDataKey(self, key): + """ :rtype: bool """ + return key in self.genDataKeys() + + def isMisfitKey(self, key): + """ :rtype: bool """ + return key in self.misfitKeys() \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/local_config.py b/ThirdParty/Ert/devel/python/python/ert/enkf/local_config.py index 3024634f33..2fed30687a 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/local_config.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/local_config.py @@ -14,36 +14,170 @@ # See the GNU General Public License at # for more details. from ert.cwrap import BaseCClass, CWrapper -from ert.enkf import ENKF_LIB - -from ert.util import StringList +from ert.enkf import ENKF_LIB, LocalUpdateStep +from ert.enkf.local_ministep import LocalMinistep class LocalConfig(BaseCClass): + def __init__(self): raise NotImplementedError("Class can not be instantiated directly!") + - def get_config_files(self): - """ @rtype: StringList """ - return LocalConfig.cNamespace().get_config_files(self).setParent(self) + # The LocalConfig class is created as a reference to an existing + # underlying C structure by the method + # EnkFMain.local_config(). When the pointer to the C + # local_config_type object has been properly wrapped we 'decorate' + # the Python object with references to the ensemble_config , + # observations and grid. + # + # This implies that the Python object LocalConfig is richer than + # the underlying C object local_config_type; the extra attributes + # are only used for validation. + + def initAttributes(self , ensemble_config , obs , grid): + self.ensemble_config = ensemble_config + self.obs = obs + self.grid = grid - def clear_config_files(self): - LocalConfig.cNamespace().clear_config_files(self) - def add_config_file(self, filename): - LocalConfig.cNamespace().add_config_file(self, filename) + def __getObservations(self): + return self.obs + def __getEnsembleConfig(self): + return self.ensemble_config + + def getGrid(self): + # The grid can be None + return self.grid + + def free(self): LocalConfig.cNamespace().free(self) + def clear(self): + LocalConfig.cNamespace().clear(self) + + + def getConfigFiles(self): + """ @rtype: StringList """ + return LocalConfig.cNamespace().get_config_files(self).setParent(self) + + def clearConfigFiles(self): + LocalConfig.cNamespace().clear_config_files(self) + + def addConfigFile(self, filename): + assert isinstance(filename, str) + LocalConfig.cNamespace().add_config_file(self, filename) + + def createMinistep(self, mini_step_key): + """ @rtype: Ministep """ + assert isinstance(mini_step_key, str) + LocalConfig.cNamespace().create_ministep(self, mini_step_key) + return self.getMinistep(mini_step_key) + + def createObsdata(self, obsset_key): + """ @rtype: Obsdata """ + assert isinstance(obsset_key, str) + LocalConfig.cNamespace().create_obsdata(self, obsset_key) + obsdata = self.getObsdata(obsset_key) + obsdata.initObservations( self.__getObservations() ) + return obsdata + + + def copyObsdata(self, src_key, target_key): + """ @rtype: Obsdata """ + assert isinstance(src_key, str) + assert isinstance(target_key, str) + obsdata = LocalConfig.cNamespace().copy_obsdata(self, src_key, target_key) + obsdata.initObservations( self.__getObservations() ) + return obsdata + + + def createDataset(self, dataset_key): + """ @rtype: Dataset """ + assert isinstance(dataset_key, str) + LocalConfig.cNamespace().create_dataset(self, dataset_key) + data = self.getDataset(dataset_key) + data.initEnsembleConfig( self.__getEnsembleConfig() ) + return data + + + def copyDataset(self, src_key, target_key): + """ @rtype: Dataset """ + assert isinstance(src_key, str) + assert isinstance(target_key, str) + data = LocalConfig.cNamespace().copy_dataset(self, src_key, target_key) + data.initEnsembleConfig( self.__getEnsembleConfig() ) + return data + + + def getUpdatestep(self): + """ @rtype: UpdateStep """ + return LocalConfig.cNamespace().get_updatestep(self) + + + def getMinistep(self, mini_step_key): + """ @rtype: Ministep """ + assert isinstance(mini_step_key, str) + return LocalConfig.cNamespace().get_ministep(self, mini_step_key) + + def getObsdata(self, obsset_key): + """ @rtype: Obsdata """ + assert isinstance(obsset_key, str) + return LocalConfig.cNamespace().get_obsdata(self, obsset_key) + + def getDataset(self, dataset_key): + """ @rtype: Dataset """ + assert isinstance(dataset_key, str) + return LocalConfig.cNamespace().get_dataset(self, dataset_key) + + + def attachMinistep(self, update_step, mini_step): + assert isinstance(mini_step, LocalMinistep) + assert isinstance(update_step, LocalUpdateStep) + LocalConfig.cNamespace().attach_ministep(update_step, mini_step) + + def writeLocalConfigFile(self, filename): + assert isinstance(filename, str) + LocalConfig.cNamespace().write_local_config_file(self, filename) + + + def writeSummaryFile(self, filename): + """ + Writes a summary of the local config object + The summary contains the Obsset with their respective + number of observations and the Datasets with the number of active indices + """ + assert isinstance(filename, str) + LocalConfig.cNamespace().write_local_config_summary_file(self, filename) + cwrapper = CWrapper(ENKF_LIB) -cwrapper.registerType("local_config", LocalConfig) -cwrapper.registerType("local_config_obj", LocalConfig.createPythonObject) -cwrapper.registerType("local_config_ref", LocalConfig.createCReference) +cwrapper.registerObjectType("local_config", LocalConfig) + +LocalConfig.cNamespace().free = cwrapper.prototype("void local_config_free( local_config )") +LocalConfig.cNamespace().clear = cwrapper.prototype("void local_config_clear( local_config )") +LocalConfig.cNamespace().get_config_files = cwrapper.prototype("stringlist_ref local_config_get_config_files( local_config )") +LocalConfig.cNamespace().clear_config_files = cwrapper.prototype("void local_config_clear_config_files( local_config )") +LocalConfig.cNamespace().add_config_file = cwrapper.prototype("void local_config_add_config_file( local_config , char*)") +LocalConfig.cNamespace().get_updatestep = cwrapper.prototype("local_updatestep_ref local_config_get_updatestep( local_config )") + +LocalConfig.cNamespace().get_ministep = cwrapper.prototype("local_ministep_ref local_config_get_ministep( local_config, char*)") +LocalConfig.cNamespace().create_ministep = cwrapper.prototype("void local_config_alloc_ministep( local_config, char*)") +LocalConfig.cNamespace().attach_ministep = cwrapper.prototype("void local_updatestep_add_ministep( local_updatestep, local_ministep)") + +LocalConfig.cNamespace().get_obsdata = cwrapper.prototype("local_obsdata_ref local_config_get_obsdata( local_config, char*)") +LocalConfig.cNamespace().create_obsdata = cwrapper.prototype("void local_config_alloc_obsset( local_config, char*)") +LocalConfig.cNamespace().copy_obsdata = cwrapper.prototype("local_obsdata_ref local_config_alloc_obsdata_copy( local_config, char*, char*)") + +LocalConfig.cNamespace().get_dataset = cwrapper.prototype("local_dataset_ref local_config_get_dataset( local_config, char*)") +LocalConfig.cNamespace().create_dataset = cwrapper.prototype("void local_config_alloc_dataset( local_config, char*)") +LocalConfig.cNamespace().copy_dataset = cwrapper.prototype("local_dataset_ref local_config_alloc_dataset_copy( local_config, char*, char*)") + +LocalConfig.cNamespace().write_local_config_file = cwrapper.prototype("void local_config_fprintf( local_config, char*)") +LocalConfig.cNamespace().write_local_config_summary_file = cwrapper.prototype("void local_config_summary_fprintf( local_config, char*)") + + -LocalConfig.cNamespace().free = cwrapper.prototype("void local_config_free( local_config )") -LocalConfig.cNamespace().get_config_files = cwrapper.prototype("stringlist_ref local_config_get_config_files( local_config )") -LocalConfig.cNamespace().clear_config_files = cwrapper.prototype("void local_config_clear_config_files( local_config )") -LocalConfig.cNamespace().add_config_file = cwrapper.prototype("void local_config_add_config_file( local_config , char*)") diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/local_dataset.py b/ThirdParty/Ert/devel/python/python/ert/enkf/local_dataset.py new file mode 100644 index 0000000000..be6c8ebb1e --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/local_dataset.py @@ -0,0 +1,94 @@ +from ert.cwrap import BaseCClass, CWrapper +from ert.enkf import ENKF_LIB +from ert.ecl import EclRegion + +class LocalDataset(BaseCClass): + + def __init__(self, name): + raise NotImplementedError("Class can not be instantiated directly!") + + + def initEnsembleConfig(self , config): + self.ensemble_config = config + + + def __len__(self): + """ @rtype: int """ + return LocalDataset.cNamespace().size(self) + + def __contains__(self , key): + """ @rtype: bool """ + return LocalDataset.cNamespace().has_key(self, key) + + def __delitem__(self, key): + assert isinstance(key, str) + if key in self: + LocalDataset.cNamespace().del_node(self, key) + else: + raise KeyError("Unknown key:%s" % key) + + def getName(self): + """ @rtype: str """ + return LocalDataset.cNamespace().name(self) + + def addNode(self, key): + assert isinstance(key, str) + if key in self.ensemble_config: + if not LocalDataset.cNamespace().has_key(self, key): + LocalDataset.cNamespace().add_node(self, key) + else: + raise KeyError("Tried to add existing data key:%s " % key) + else: + raise KeyError("Tried to add data key:%s - not in ensemble" % key) + + + def addNodeWithIndex(self, key, index): + assert isinstance(key, str) + assert isinstance(index, int) + + self.addNode( key ) + active_list = self.getActiveList(key) + active_list.addActiveIndex(index) + + + def addField(self, key, ecl_region): + assert isinstance(key, str) + assert isinstance(ecl_region, EclRegion) + + self.addNode( key ) + active_list = self.getActiveList(key) + active_region = ecl_region.getActiveList() + for i in active_region: + active_list.addActiveIndex(i) + + + def getActiveList(self, key): + """ @rtype: ActiveList """ + if key in self: + return LocalDataset.cNamespace().active_list(self , key) + else: + raise KeyError("Local key:%s not recognized" % key) + + + def free(self): + LocalDataset.cNamespace().free(self) + + + +cwrapper = CWrapper(ENKF_LIB) +cwrapper.registerObjectType("local_dataset", LocalDataset) + +LocalDataset.cNamespace().alloc = cwrapper.prototype("c_void_p local_dataset_alloc(char*)") +LocalDataset.cNamespace().size = cwrapper.prototype("c_void_p local_dataset_get_size(char*)") +LocalDataset.cNamespace().has_key = cwrapper.prototype("bool local_dataset_has_key(local_dataset, char*)") +LocalDataset.cNamespace().free = cwrapper.prototype("void local_dataset_free(local_dataset)") +LocalDataset.cNamespace().name = cwrapper.prototype("char* local_dataset_get_name(local_dataset)") +LocalDataset.cNamespace().active_list = cwrapper.prototype("active_list_ref local_dataset_get_node_active_list(local_dataset, char*)") +LocalDataset.cNamespace().add_node = cwrapper.prototype("void local_dataset_add_node(local_dataset, char*)") +LocalDataset.cNamespace().del_node = cwrapper.prototype("void local_dataset_del_node(local_dataset, char*)") + + + + + + diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/local_ministep.py b/ThirdParty/Ert/devel/python/python/ert/enkf/local_ministep.py new file mode 100644 index 0000000000..dee6a99d00 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/local_ministep.py @@ -0,0 +1,60 @@ +import ert.util +from ert.cwrap import BaseCClass, CWrapper +from ert.enkf import ENKF_LIB, LocalObsdata, LocalObsdataNode, LocalDataset + +class LocalMinistep(BaseCClass): + + def __init__(self, ministep_key): + raise NotImplementedError("Class can not be instantiated directly!") + + # Will used the data keys; and ignore observation keys. + def __getitem__(self, data_key): + if data_key in self: + return LocalMinistep.cNamespace().get_local_data(self , data_key) + else: + raise KeyError("No such data key: %s" % data_key) + + def __len__(self): + return LocalMinistep.cNamespace().data_size( self ) + + def __contains__(self , data_key): + return LocalMinistep.cNamespace().has_local_data(self , data_key) + + def addNode(self, node): + assert isinstance(node, LocalObsdataNode) + LocalMinistep.cNamespace().add_node(self,node) + + def attachObsset(self, obs_set): + assert isinstance(obs_set, LocalObsdata) + LocalMinistep.cNamespace().attach_obsset(self,obs_set) + + + def attachDataset(self, dataset): + assert isinstance(dataset, LocalDataset) + LocalMinistep.cNamespace().attach_dataset(self,dataset) + + def getLocalObsData(self): + """ @rtype: LocalObsdata """ + return LocalMinistep.cNamespace().get_local_obs_data(self) + + def getName(self): + """ @rtype: str """ + return LocalMinistep.cNamespace().name(self) + + def free(self): + LocalMinistep.cNamespace().free(self) + +cwrapper = CWrapper(ENKF_LIB) +cwrapper.registerObjectType("local_ministep", LocalMinistep) + +LocalMinistep.cNamespace().alloc = cwrapper.prototype("c_void_p local_ministep_alloc(char*)") +LocalMinistep.cNamespace().add_node = cwrapper.prototype("void local_ministep_add_obsdata_node(local_ministep,local_obsdata_node)") +LocalMinistep.cNamespace().get_local_obs_data = cwrapper.prototype("local_obsdata_ref local_ministep_get_obsdata(local_ministep)") +LocalMinistep.cNamespace().get_local_data = cwrapper.prototype("local_dataset_ref local_ministep_get_dataset(local_ministep , char*)") +LocalMinistep.cNamespace().has_local_data = cwrapper.prototype("bool local_ministep_has_dataset(local_ministep , char*)") +LocalMinistep.cNamespace().free = cwrapper.prototype("void local_ministep_free(local_ministep)") +LocalMinistep.cNamespace().attach_obsset = cwrapper.prototype("void local_ministep_add_obsdata(local_ministep,local_obsdata)") +LocalMinistep.cNamespace().attach_dataset = cwrapper.prototype("void local_ministep_add_dataset(local_ministep,local_dataset)") +LocalMinistep.cNamespace().name = cwrapper.prototype("char* local_ministep_get_name(local_ministep)") +LocalMinistep.cNamespace().data_size = cwrapper.prototype("int local_ministep_get_num_dataset(local_ministep)") + diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/local_obsdata.py b/ThirdParty/Ert/devel/python/python/ert/enkf/local_obsdata.py index fa4b20292b..cfce87a01e 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/local_obsdata.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/local_obsdata.py @@ -1,18 +1,42 @@ from ert.cwrap import BaseCClass, CWrapper -from ert.enkf import ENKF_LIB, LocalObsdataNode +from ert.enkf import ENKF_LIB, LocalObsdataNode class LocalObsdata(BaseCClass): - def __init__(self, name): - assert isinstance(name, str) + + def __init__(self, name , obs = None): + # The obs instance should be a EnkFObs instance; some circular dependency problems + # by importing it right away. It is not really optional, but it is made optional + # here to be able to give a decent error message for old call sites which did not + # supply the obs argument. + if obs is None: + msg = """ +The LocalObsdata constructor has recently changed, as a second +argument you should pass the EnkFObs instance with all the +observations. You can typically get this instance from the ert main +object as: + + obs = ert.getObservations() + local_obs = LocalObsData("YOUR-KEY" , obs) + +""" + raise Exception( msg ) + + assert isinstance(name, str) + c_pointer = LocalObsdata.cNamespace().alloc(name) super(LocalObsdata, self).__init__(c_pointer) + self.initObservations( obs ) + + def initObservations(self , obs): + self.obs = obs + def __len__(self): - """ @rtype: int """ - return LocalObsdata.cNamespace().size(self) + """ @rtype: int """ + return LocalObsdata.cNamespace().size(self) def __getitem__(self, key): @@ -27,27 +51,13 @@ class LocalObsdata(BaseCClass): return LocalObsdata.cNamespace().get_node(self, key).setParent(self) else: raise KeyError("Unknown key:%s" % key) - def __iter__(self): cur = 0 while cur < len(self): - yield self[cur] - cur += 1 - - - def addNode(self, node): - """ @rtype: bool """ - assert isinstance(node, LocalObsdataNode) - node.convertToCReference(self) - already_exists_node_for_key = LocalObsdata.cNamespace().add_node(self, node) - return already_exists_node_for_key - - - def addObsVector(self , obs_vector): - self.addNode( obs_vector.createLocalObs() ) - - + yield self[cur] + cur += 1 + def __contains__(self, item): """ @rtype: bool """ if isinstance(item, str): @@ -56,7 +66,43 @@ class LocalObsdata(BaseCClass): return LocalObsdata.cNamespace().has_node(self, item.getKey()) return False + + def __delitem__(self, key): + assert isinstance(key, str) + if key in self: + LocalObsdata.cNamespace().del_node(self, key) + else: + raise KeyError("Unknown key:%s" % key) + + def addNode(self, node): + assert isinstance(node, LocalObsdataNode) + if node.getKey() in self.obs: + if node not in self: + node.convertToCReference(self) + LocalObsdata.cNamespace().add_node(self, node) + else: + raise KeyError("Tried to add existing observation key:%s " % node.getKey()) + + else: + raise KeyError("The observation node: %s is not recognized observation key" % node.getKey()) + def addNodeAndRange(self, key, step_1, step_2): + assert isinstance(key, str) + assert isinstance(step_1, int) + assert isinstance(step_2, int) + node = LocalObsdataNode(key) + self.addNode( node ) + node.addRange(step_1, step_2) + + + def clear(self): + LocalObsdata.cNamespace().clear(self) + + + def addObsVector(self , obs_vector): + self.addNode( obs_vector.createLocalObs() ) + + def getName(self): """ @rtype: str """ return LocalObsdata.cNamespace().name(self) @@ -67,18 +113,18 @@ class LocalObsdata(BaseCClass): cwrapper = CWrapper(ENKF_LIB) -cwrapper.registerType("local_obsdata", LocalObsdata) -cwrapper.registerType("local_obsdata_obj", LocalObsdata.createPythonObject) -cwrapper.registerType("local_obsdata_ref", LocalObsdata.createCReference) +cwrapper.registerObjectType("local_obsdata", LocalObsdata) -LocalObsdata.cNamespace().alloc = cwrapper.prototype("c_void_p local_obsdata_alloc(char*)") -LocalObsdata.cNamespace().free = cwrapper.prototype("void local_obsdata_free(local_obsdata)") -LocalObsdata.cNamespace().size = cwrapper.prototype("int local_obsdata_get_size(local_obsdata)") -LocalObsdata.cNamespace().has_node = cwrapper.prototype("bool local_obsdata_has_node(local_obsdata, char*)") -LocalObsdata.cNamespace().add_node = cwrapper.prototype("bool local_obsdata_add_node(local_obsdata, local_obsdata_node)") +LocalObsdata.cNamespace().alloc = cwrapper.prototype("c_void_p local_obsdata_alloc(char*)") +LocalObsdata.cNamespace().free = cwrapper.prototype("void local_obsdata_free(local_obsdata)") +LocalObsdata.cNamespace().size = cwrapper.prototype("int local_obsdata_get_size(local_obsdata)") +LocalObsdata.cNamespace().has_node = cwrapper.prototype("bool local_obsdata_has_node(local_obsdata, char*)") +LocalObsdata.cNamespace().add_node = cwrapper.prototype("bool local_obsdata_add_node(local_obsdata, local_obsdata_node)") +LocalObsdata.cNamespace().del_node = cwrapper.prototype("void local_obsdata_del_node(local_obsdata, char*)") +LocalObsdata.cNamespace().clear = cwrapper.prototype("void local_dataset_clear(local_obsdata)") LocalObsdata.cNamespace().iget_node = cwrapper.prototype("local_obsdata_node_ref local_obsdata_iget(local_obsdata, int)") -LocalObsdata.cNamespace().get_node = cwrapper.prototype("local_obsdata_node_ref local_obsdata_get(local_obsdata, char*)") -LocalObsdata.cNamespace().name = cwrapper.prototype("char* local_obsdata_get_name(local_obsdata)") +LocalObsdata.cNamespace().get_node = cwrapper.prototype("local_obsdata_node_ref local_obsdata_get(local_obsdata, char*)") +LocalObsdata.cNamespace().name = cwrapper.prototype("char* local_obsdata_get_name(local_obsdata)") diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/local_updatestep.py b/ThirdParty/Ert/devel/python/python/ert/enkf/local_updatestep.py new file mode 100644 index 0000000000..67c8ec3ba2 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/local_updatestep.py @@ -0,0 +1,42 @@ +from ert.cwrap import BaseCClass, CWrapper +from ert.enkf import ENKF_LIB, LocalMinistep + +class LocalUpdateStep(BaseCClass): + + def __init__(self, updatestep_key): + raise NotImplementedError("Class can not be instantiated directly!") + + def __len__(self): + """ @rtype: int """ + return LocalUpdateStep.cNamespace().size(self) + + def __getitem__(self, index): + """ @rtype: LocalMinistep """ + assert isinstance(index, int) + if index < len(self): + return LocalUpdateStep.cNamespace().iget_ministep(self, index) + else: + raise IndexError("Invalid index") + + def attachMinistep(self, ministep): + assert isinstance(ministep, LocalMinistep) + LocalUpdateStep.cNamespace().attach_ministep(self,ministep) + + def getName(self): + """ @rtype: str """ + return LocalUpdateStep.cNamespace().name(self) + + def free(self): + LocalUpdateStep.cNamespace().free(self) + +cwrapper = CWrapper(ENKF_LIB) +cwrapper.registerObjectType("local_updatestep", LocalUpdateStep) + +LocalUpdateStep.cNamespace().alloc = cwrapper.prototype("c_void_p local_updatestep_alloc(char*)") +LocalUpdateStep.cNamespace().size = cwrapper.prototype("int local_updatestep_get_num_ministep(local_updatestep)") +LocalUpdateStep.cNamespace().iget_ministep = cwrapper.prototype("local_ministep_ref local_updatestep_iget_ministep(local_updatestep, int)") +LocalUpdateStep.cNamespace().free = cwrapper.prototype("void local_updatestep_free(local_updatestep)") +LocalUpdateStep.cNamespace().attach_ministep = cwrapper.prototype("void local_updatestep_add_ministep(local_updatestep,local_ministep)") +LocalUpdateStep.cNamespace().name = cwrapper.prototype("char* local_updatestep_get_name(local_updatestep)") + + diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/obs_data.py b/ThirdParty/Ert/devel/python/python/ert/enkf/obs_data.py index e692b2f831..716cd66055 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/obs_data.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/obs_data.py @@ -12,9 +12,21 @@ class ObsData(BaseCClass): def __len__(self): """ @rtype: int """ - return ObsData.cNamespace().active_size(self) + return ObsData.cNamespace().total_size(self) + + def __getitem__(self , index): + if index < 0: + index += len(self) + + if index >= len(self): + raise IndexError("Invalid index:%d valid range: [0,%d)" % (index , len(self))) + + value = ObsData.cNamespace().iget_value( self , index ) + std = ObsData.cNamespace().iget_std( self , index ) + return (value,std) + def addBlock(self , obs_key , obs_size): error_covar = None error_covar_owner = False @@ -64,7 +76,9 @@ cwrapper.registerObjectType("obs_data", ObsData) ObsData.cNamespace().alloc = cwrapper.prototype("c_void_p obs_data_alloc(double)") ObsData.cNamespace().free = cwrapper.prototype("void obs_data_free(obs_data)") -ObsData.cNamespace().active_size = cwrapper.prototype("int obs_data_get_active_size(obs_data)") +ObsData.cNamespace().total_size = cwrapper.prototype("int obs_data_get_total_size(obs_data)") +ObsData.cNamespace().iget_value = cwrapper.prototype("double obs_data_iget_value(obs_data)") +ObsData.cNamespace().iget_std = cwrapper.prototype("double obs_data_iget_std(obs_data)") ObsData.cNamespace().add_block = cwrapper.prototype("obs_block_ref obs_data_add_block(obs_data , char* , int , matrix , bool)") ObsData.cNamespace().allocdObs = cwrapper.prototype("matrix_obj obs_data_allocdObs(obs_data)") diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/run_arg.py b/ThirdParty/Ert/devel/python/python/ert/enkf/run_arg.py index 6a91bde787..3f86c22500 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/run_arg.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/run_arg.py @@ -23,7 +23,7 @@ from ert.enkf.enums import EnkfRunType, EnkfStateType class RunArg(BaseCClass): def __init__(self , c_ptr , parent = None , is_reference = False ): - super(RunArg , self).__init__( c_ptr , parent = None , is_reference = is_reference ) + super(RunArg , self).__init__( c_ptr , parent = parent , is_reference = is_reference ) @classmethod @@ -37,7 +37,8 @@ class RunArg(BaseCClass): def getQueueIndex(self): return RunArg.cNamespace().get_queue_index( self ) - + def isSubmitted(self): + return RunArg.cNamespace().is_submitted( self ) @@ -48,3 +49,4 @@ cwrapper.registerObjectType("run_arg", RunArg) RunArg.cNamespace().alloc_ENSEMBLE_EXPERIMENT = cwrapper.prototype("c_void_p run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs , int, int, char*)") RunArg.cNamespace().free = cwrapper.prototype("void run_arg_free(run_arg)") RunArg.cNamespace().get_queue_index = cwrapper.prototype("int run_arg_get_queue_index(run_arg)") +RunArg.cNamespace().is_submitted = cwrapper.prototype("bool run_arg_is_submitted(run_arg)") diff --git a/ThirdParty/Ert/devel/python/python/ert/enkf/site_config.py b/ThirdParty/Ert/devel/python/python/ert/enkf/site_config.py index ecb98e6e5f..e4955a14d8 100644 --- a/ThirdParty/Ert/devel/python/python/ert/enkf/site_config.py +++ b/ThirdParty/Ert/devel/python/python/ert/enkf/site_config.py @@ -29,7 +29,9 @@ class SiteConfig(BaseCClass): return SiteConfig.cNamespace().get_queue_name( self ) def setJobQueue(self, queue): - SiteConfig.cNamespace().set_job_queue( self , queue) + raise Exception("The function setJobQueue() is not properly implemented") + + def getLsfQueue(self): """ @rtype: str """ @@ -141,6 +143,11 @@ class SiteConfig(BaseCClass): def addRshHost(self, host, max_running): SiteConfig.cNamespace().add_rsh_host(self, host, max_running) + def getLocation(self): + """ @rtype: str """ + return SiteConfig.cNamespace().get_location(self) + + def free(self): SiteConfig.cNamespace().free(self) @@ -152,7 +159,6 @@ cwrapper.registerType( "site_config_ref" , SiteConfig.createCReference) SiteConfig.cNamespace().free = cwrapper.prototype("void site_config_free( site_config )") SiteConfig.cNamespace().get_queue_name = cwrapper.prototype("char* site_config_get_queue_name(site_config)") -SiteConfig.cNamespace().set_job_queue = cwrapper.prototype("void site_config_set_job_queue(site_config, char*)") SiteConfig.cNamespace().get_lsf_queue = cwrapper.prototype("char* site_config_get_lsf_queue(site_config)") SiteConfig.cNamespace().set_lsf_queue = cwrapper.prototype("void site_config_set_lsf_queue(site_config, char*)") SiteConfig.cNamespace().get_max_running_lsf = cwrapper.prototype("int site_config_get_max_running_lsf(site_config)") @@ -186,3 +192,4 @@ SiteConfig.cNamespace().clear_pathvar = cwrapper.prototype("void site_co SiteConfig.cNamespace().update_pathvar = cwrapper.prototype("void site_config_update_pathvar(site_config, char*, char*)") SiteConfig.cNamespace().get_job_queue = cwrapper.prototype("job_queue_ref site_config_get_job_queue(site_config)") SiteConfig.cNamespace().queue_is_running = cwrapper.prototype("bool site_config_queue_is_running(site_config)") +SiteConfig.cNamespace().get_location = cwrapper.prototype("char* site_config_get_location(site_config)") diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/driver.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/driver.py index 075c7243bb..fe379e33a9 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/driver.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/driver.py @@ -141,7 +141,7 @@ cfunc.set_driver_option = cwrapper.prototype("void queue_driver_set_optio cfunc.free_driver = cwrapper.prototype("void queue_driver_free( driver )") cfunc.submit = cwrapper.prototype("c_void_p queue_driver_submit_job( driver , char* , int , char* , char* , int , char**)") cfunc.free_job = cwrapper.prototype("void queue_driver_free_job( driver , job )") -cfunc.cget_status = cwrapper.prototype("int job_queue_get_status( driver , job)") +cfunc.cget_status = cwrapper.prototype("int queue_driver_get_status( driver , job)") cfunc.kill_job = cwrapper.prototype("void queue_driver_kill_job( driver , job )") cfunc.set_max_running = cwrapper.prototype("void queue_driver_set_max_running( driver , int )") cfunc.get_max_running = cwrapper.prototype("int queue_driver_get_max_running( driver )") diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/ert_script.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/ert_script.py index 1cc3119be7..12e3f9b07e 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/ert_script.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/ert_script.py @@ -38,6 +38,12 @@ class ErtScript(object): def cancel(self): self.__is_cancelled = True + def cleanup(self): + """ + Override to perform cleanup after a run. + """ + pass + def initializeAndRun(self, argument_types, argument_values, verbose=False): """ @type argument_types: list of type @@ -66,10 +72,11 @@ class ErtScript(object): return self.run(*arguments) except Exception as e: sys.stderr.write("The script '%s' caused an error while running:\n" % self.__class__.__name__) - traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) self.__failed = True stack_trace = traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) return "".join(stack_trace) + finally: + self.cleanup() __module_count = 0 # Need to have unique modules in case of identical object naming in scripts diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/job_queue_manager.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/job_queue_manager.py index 9840b13a8f..afc1118dd9 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/job_queue_manager.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/job_queue_manager.py @@ -33,15 +33,18 @@ class JobQueueManager(BaseCClass): super(JobQueueManager, self).__init__(c_ptr) - def startQueue(self , total_size , verbose = False): - JobQueueManager.cNamespace().start_queue( self , total_size , verbose ) + def startQueue(self , total_size , verbose = False , reset_queue = True): + JobQueueManager.cNamespace().start_queue( self , total_size , verbose , reset_queue) def getNumRunning(self): return JobQueueManager.cNamespace().get_num_running( self ) - def getNumComplete(self): - return JobQueueManager.cNamespace().get_num_complete( self ) + def getNumSuccess(self): + return JobQueueManager.cNamespace().get_num_success( self ) + def getNumFailed(self): + return JobQueueManager.cNamespace().get_num_failed( self ) + def isRunning(self): return JobQueueManager.cNamespace().is_running( self ) @@ -50,8 +53,18 @@ class JobQueueManager(BaseCClass): def jobComplete(self , job_index): return JobQueueManager.cNamespace().job_complete( self , job_index ) - - + + def jobRunning(self , job_index): + return JobQueueManager.cNamespace().job_running( self , job_index ) + + def jobWaiting(self , job_index): + return JobQueueManager.cNamespace().job_waiting( self , job_index ) + + def jobFailed(self , job_index): + return JobQueueManager.cNamespace().job_failed( self , job_index ) + + def jobSuccess(self , job_index): + return JobQueueManager.cNamespace().job_success( self , job_index ) ################################################################# @@ -61,8 +74,13 @@ cwrapper.registerObjectType("job_queue_manager", JobQueueManager) JobQueueManager.cNamespace().alloc = cwrapper.prototype("c_void_p job_queue_manager_alloc( job_queue) ") JobQueueManager.cNamespace().free = cwrapper.prototype("void job_queue_manager_free( job_queue_manager )") -JobQueueManager.cNamespace().start_queue = cwrapper.prototype("void job_queue_manager_start_queue( job_queue_manager , int , bool)") +JobQueueManager.cNamespace().start_queue = cwrapper.prototype("void job_queue_manager_start_queue( job_queue_manager , int , bool, bool)") JobQueueManager.cNamespace().get_num_running = cwrapper.prototype("int job_queue_manager_get_num_running( job_queue_manager )") -JobQueueManager.cNamespace().get_num_complete = cwrapper.prototype("int job_queue_manager_get_num_complete( job_queue_manager )") +JobQueueManager.cNamespace().get_num_success = cwrapper.prototype("int job_queue_manager_get_num_success( job_queue_manager )") +JobQueueManager.cNamespace().get_num_failed = cwrapper.prototype("int job_queue_manager_get_num_failed( job_queue_manager )") JobQueueManager.cNamespace().is_running = cwrapper.prototype("bool job_queue_manager_is_running( job_queue_manager )") -JobQueueManager.cNamespace().job_complete = cwrapper.prototype("bool job_queue_manager_job_complete( job_queue_manager , int)") +JobQueueManager.cNamespace().job_complete = cwrapper.prototype("bool job_queue_manager_job_success( job_queue_manager , int)") +JobQueueManager.cNamespace().job_running = cwrapper.prototype("bool job_queue_manager_job_running( job_queue_manager , int)") +JobQueueManager.cNamespace().job_failed = cwrapper.prototype("bool job_queue_manager_job_failed( job_queue_manager , int)") +JobQueueManager.cNamespace().job_waiting = cwrapper.prototype("bool job_queue_manager_job_waiting( job_queue_manager , int)") +JobQueueManager.cNamespace().job_success = cwrapper.prototype("bool job_queue_manager_job_success( job_queue_manager , int)") diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/queue.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/queue.py index efed10d231..8832073896 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/queue.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/queue.py @@ -174,7 +174,7 @@ class JobQueue(BaseCClass): exit_callback = None - queue_index = JobQueue.cNamespace().add_job_mt(self, + queue_index = JobQueue.cNamespace().add_job(self, cmd, done_callback, retry_callback, @@ -186,8 +186,8 @@ class JobQueue(BaseCClass): len(argv), c_argv) - job = Job(self.driver, JobQueue.cNamespace().get_job_ptr(self, queue_index), queue_index, False) - + job_ptr = None + job = Job(self.driver, job_ptr , queue_index, False) self.jobs.add_job(job, job_name) return job @@ -287,8 +287,7 @@ JobQueue.cNamespace().free = cwrapper.prototype("void job_queue_free( JobQueue.cNamespace().set_max_running = cwrapper.prototype("void job_queue_set_max_running( job_queue , int)") JobQueue.cNamespace().get_max_running = cwrapper.prototype("int job_queue_get_max_running( job_queue )") JobQueue.cNamespace().set_driver = cwrapper.prototype("void job_queue_set_driver( job_queue , c_void_p )") -JobQueue.cNamespace().add_job_mt = cwrapper.prototype("int job_queue_add_job_mt( job_queue , char* , c_void_p , c_void_p , c_void_p , c_void_p , int , char* , char* , int , char**)") -JobQueue.cNamespace().add_job_st = cwrapper.prototype("int job_queue_add_job_st( job_queue , char* , c_void_p , c_void_p , c_void_p , c_void_p , int , char* , char* , int , char**)") +JobQueue.cNamespace().add_job = cwrapper.prototype("int job_queue_add_job( job_queue , char* , c_void_p , c_void_p , c_void_p , c_void_p , int , char* , char* , int , char**)") JobQueue.cNamespace().start_queue = cwrapper.prototype("void job_queue_run_jobs( job_queue , int , bool)") JobQueue.cNamespace().run_jobs = cwrapper.prototype("void job_queue_run_jobs_threaded(job_queue , int , bool)") @@ -299,7 +298,6 @@ JobQueue.cNamespace().num_pending = cwrapper.prototype("int job_queue_get_n JobQueue.cNamespace().is_running = cwrapper.prototype("int job_queue_is_running( job_queue )") JobQueue.cNamespace().submit_complete = cwrapper.prototype("void job_queue_submit_complete( job_queue )") -JobQueue.cNamespace().get_job_ptr = cwrapper.prototype("c_void_p job_queue_iget_job( job_queue , int)") #warn fix return type JobQueue.cNamespace().iget_sim_start = cwrapper.prototype("time_t job_queue_iget_sim_start( job_queue , int)") JobQueue.cNamespace().get_active_size = cwrapper.prototype("int job_queue_get_active_size( job_queue )") JobQueue.cNamespace().get_pause = cwrapper.prototype("bool job_queue_get_pause(job_queue)") diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow.py index 98fe8feead..5f3ceb73b1 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow.py @@ -49,6 +49,10 @@ class Workflow(BaseCClass): self.__current_job = job if not self.__cancelled: return_value = job.run(ert, args, verbose) + + if job.hasFailed(): + print(return_value) + #todo store results? self.__current_job = None diff --git a/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow_job.py b/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow_job.py index b58dfc2d9f..cab00a8710 100644 --- a/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow_job.py +++ b/ThirdParty/Ert/devel/python/python/ert/job_queue/workflow_job.py @@ -53,7 +53,7 @@ class WorkflowJob(BaseCClass): """ @rtype: bool """ if self.isInternalScript(): script_obj = ErtScript.loadScriptFromFile(self.getInternalScriptPath()) - return issubclass(script_obj, ErtPlugin) + return script_obj is not None and issubclass(script_obj, ErtPlugin) return False diff --git a/ThirdParty/Ert/devel/python/python/ert/sched/sched_file.py b/ThirdParty/Ert/devel/python/python/ert/sched/sched_file.py index bbe5e16e34..4cf8a835c1 100644 --- a/ThirdParty/Ert/devel/python/python/ert/sched/sched_file.py +++ b/ThirdParty/Ert/devel/python/python/ert/sched/sched_file.py @@ -13,6 +13,8 @@ # # See the GNU General Public License at # for more details. +import os.path + from ert.cwrap import BaseCClass, CWrapper from ert.sched import SCHED_LIB from ert.util import CTime @@ -20,8 +22,11 @@ from ert.util import CTime class SchedFile(BaseCClass): def __init__(self, filename, start_time): - c_ptr = SchedFile.cNamespace().parse(filename, CTime(start_time)) - super(SchedFile, self).__init__(c_ptr) + if os.path.isfile(filename): + c_ptr = SchedFile.cNamespace().parse(filename, CTime(start_time)) + super(SchedFile, self).__init__(c_ptr) + else: + raise IOError("No such file: %s" % filename) @property def length(self): diff --git a/ThirdParty/Ert/devel/python/python/ert/server/ert_client.py b/ThirdParty/Ert/devel/python/python/ert/server/ert_client.py index 6e15ac136c..7452483237 100644 --- a/ThirdParty/Ert/devel/python/python/ert/server/ert_client.py +++ b/ThirdParty/Ert/devel/python/python/ert/server/ert_client.py @@ -18,8 +18,14 @@ import sys import socket import json import datetime +import time from ert.server import ErtServer +class ServerReturnedNoneException(Exception): + pass + +class ConnectionErrorException(Exception): + pass class ErtClient(object): def __init__(self , port , host): @@ -30,7 +36,8 @@ class ErtClient(object): try: self.socket.connect((self.host , self.port)) except socket.error: - sys.exit("Failed to connect to port:%d at %s." % (port , host)) + raise Exception("Failed to connect to port:%d at %s." % (port , host)) + @staticmethod def convert_to_datetime(data): @@ -43,11 +50,19 @@ class ErtClient(object): return result def sendRecv(self , data): - self.socket.sendall( json.dumps(data) + "\n" ) - recv = self.socket.recv(4096) + + try: + self.socket.sendall( json.dumps(data) + "\n" ) + recv = self.socket.recv(4096) + except: + raise ConnectionErrorException() + result = json.loads(recv) + if result is not None: + result0 = result[0] + else: + raise ServerReturnedNoneException() - result0 = result[0] if result0 == "OK": result = result[1:] if data == ["TIME_STEP"]: @@ -60,8 +75,19 @@ class ErtClient(object): raise Exception("Ert server returned result[0] == %s - must have OK|ERROR as first element in return list" % result[0]) - @staticmethod def runCommand( cmd , port , host): - client = ErtClient( port , host ) - return client.sendRecv( cmd ) + while True: + client = ErtClient(port, host) + try: + result = client.sendRecv(cmd) + return result + except ServerReturnedNoneException: + print("The server returned null on command %s, the command will be resent." % cmd) + time.sleep(3) + except ConnectionErrorException: + print("Connection dropped unexpectedly on command %s, the command will be resent." % cmd) + time.sleep(3) + except: + print("Unhandled exception on command %s - this will be raised to a higher place." % cmd) + raise diff --git a/ThirdParty/Ert/devel/python/python/ert/server/ert_server.py b/ThirdParty/Ert/devel/python/python/ert/server/ert_server.py index 0a3662af08..9cef1048a1 100644 --- a/ThirdParty/Ert/devel/python/python/ert/server/ert_server.py +++ b/ThirdParty/Ert/devel/python/python/ert/server/ert_server.py @@ -12,7 +12,8 @@ # FITNESS FOR A PARTICULAR PURPOSE. # # See the GNU General Public License at -# for more details. +# for more details. +import logging import sys import threading @@ -51,16 +52,18 @@ class ErtServer(object): DATE_FORMAT = '%Y-%m-%d %H:%M:%S' site_config = None - def __init__(self , config_file , logger): + def __init__(self , config , logger=None): installAbortSignals() self.queue_lock = threading.Lock() self.ert_handle = None + + if logger is None: + logger = logging + self.logger = logger - if os.path.exists(config_file): - self.open( config_file ) - else: - raise IOError("The config file:%s does not exist" % config_file) + + self.open(config) self.initCmdTable() self.run_context = None @@ -87,9 +90,18 @@ class ErtServer(object): "TIME_STEP": self.handleTIMESTEP } - def open(self , config_file): + def open(self , config): + if isinstance(config, EnKFMain): + config_file = config.getUserConfigFile() + else: + if os.path.exists(config): + config_file = config + config = EnKFMain( config ) + else: + raise IOError("The config file:%s does not exist" % config) + self.config_file = config_file - self.ert_handle = EnKFMain( config_file ) + self.ert_handle = config self.logger.info("Have connect ert handle to:%s" , config_file) @@ -123,22 +135,33 @@ class ErtServer(object): raise KeyError("The command:%s was not recognized" % cmd) + + # The STATUS action can either report results for the complete + # simulation set, or it can report the status of one particular + # realisation. If the function is called with zero arguments it + # will return the global status, if called with one argument it + # will return the status for that realisation. + def handleSTATUS(self , args): if self.isConnected(): if self.run_context is None: return self.SUCCESS(["READY"]) else: - if self.run_context.isRunning(): - if len(args) == 0: - return self.SUCCESS(["RUNNING" , self.run_context.getNumRunning() , self.run_context.getNumComplete()]) + if len(args) == 0: + if self.run_context.isRunning(): + return self.SUCCESS(["RUNNING" , self.run_context.getNumRunning() , self.run_context.getNumSuccess() , self.run_context.getNumFailed()]) else: - iens = args[0] - if self.run_context.realisationComplete(iens): - return self.SUCCESS(["COMPLETE"]) - else: - return self.SUCCESS(["RUNNING"]) + return self.SUCCESS(["COMPLETE" , self.run_context.getNumRunning() , self.run_context.getNumSuccess() , self.run_context.getNumFailed()]) else: - return self.SUCCESS(["COMPLETE"]) + iens = args[0] + + if self.run_context.realisationRunning(iens): + return self.SUCCESS(["RUNNING"]) + elif self.run_context.realisationFailed(iens): + return self.SUCCESS(["FAILED"]) + elif self.run_context.realisationSuccess(iens): + return self.SUCCESS(["SUCCESS"]) + else: return self.SUCCESS(["CLOSED"]) diff --git a/ThirdParty/Ert/devel/python/python/ert/server/ert_socket.py b/ThirdParty/Ert/devel/python/python/ert/server/ert_socket.py index 351edc6fba..411fea81fa 100644 --- a/ThirdParty/Ert/devel/python/python/ert/server/ert_socket.py +++ b/ThirdParty/Ert/devel/python/python/ert/server/ert_socket.py @@ -21,13 +21,12 @@ import threading import json import traceback import socket +import fcntl from ert.server import ErtServer, SUCCESS , ERROR class ErtHandler(SocketServer.StreamRequestHandler): ert_server = None - config_file = None - logger = None def handle(self): string_data = self.rfile.readline().strip() @@ -52,12 +51,12 @@ class ErtHandler(SocketServer.StreamRequestHandler): try: result = self.ert_server.evalCmd( data ) except Exception,e: - result = ERROR( "Exception raised" , exception = e) + tb = traceback.format_exc() + result = ERROR( "Exception raised:" , exception = tb) self.returnToClient( result ) - def handleQuit(self): shutdown_thread = threading.Thread( target = self.server.shutdown ) shutdown_thread.start() @@ -71,18 +70,26 @@ class ErtSocketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): class ErtSocket(object): - def __init__(self , config_file , port , host , logger): + def __init__(self , config , port , host , logger): + self.host = host + self.port = port self.server = ErtSocketServer((host , port) , ErtHandler) - self.open(config_file , logger) + self._setupSocketCloseOnExec() + self.open(config , logger) + self.__is_listening = False + def _setupSocketCloseOnExec(self): + fd = self.server.fileno() + old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) + fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) @staticmethod - def connect(config_file , port , host , logger , info_callback = None , timeout = 60 , sleep_time = 5): + def connect(config , port , host , logger = None, info_callback = None , timeout = 60 , sleep_time = 5): start_time = time.time() ert_socket = None while True: try: - ert_socket = ErtSocket(config_file , port, host , logger) + ert_socket = ErtSocket(config , port, host , logger) break except socket.error: if info_callback: @@ -95,17 +102,16 @@ class ErtSocket(object): return ert_socket - - def open(self , config_file , logger): - ErtHandler.ert_server = ErtServer( config_file , logger ) - - + def open(self , config , logger): + ErtHandler.ert_server = ErtServer( config , logger ) def evalCmd(self , cmd): return ErtHandler.ert_server.evalCmd( cmd ) - def listen(self): + self.__is_listening = True self.server.serve_forever( ) - - + + def shutdown(self): + if self.__is_listening: + self.server.shutdown() diff --git a/ThirdParty/Ert/devel/python/python/ert/server/run_context.py b/ThirdParty/Ert/devel/python/python/ert/server/run_context.py index b122dc193c..c981888104 100644 --- a/ThirdParty/Ert/devel/python/python/ert/server/run_context.py +++ b/ThirdParty/Ert/devel/python/python/ert/server/run_context.py @@ -15,8 +15,8 @@ # for more details. from ert.job_queue import JobQueueManager -from ert.enkf import RunArg -from ert.util import BoolVector +from ert.enkf import RunArg, ENKF_LIB +from ert.util import BoolVector, ArgPack, CThreadPool class RunContext(object): def __init__(self , ert_handle , size , run_fs , run_count): @@ -33,8 +33,10 @@ class RunContext(object): self.ert_handle.addDataKW("" , "%s" % run_count) self.ert_run_context = self.ert_handle.getRunContextENSEMPLE_EXPERIMENT( run_fs , mask ) - + self.thread_pool = CThreadPool( 8 ) + self.submit_func = CThreadPool.lookupCFunction( ENKF_LIB , "enkf_main_isubmit_job__" ) + def isRunning(self): return self.queue_manager.isRunning() @@ -43,15 +45,45 @@ class RunContext(object): return self.queue_manager.getNumRunning() - def getNumComplete(self): - return self.queue_manager.getNumComplete() - + def getNumSuccess(self): + return self.queue_manager.getNumSuccess() + + + def getNumFailed(self): + return self.queue_manager.getNumFailed() + def startSimulation(self , iens): - self.ert_handle.submitSimulation( self.ert_run_context.iensGet( iens )) + member_context = self.ert_run_context.iensGet( iens ) + arg = ArgPack( self.ert_handle , member_context ) + self.thread_pool.addTask( self.submit_func , arg ) + - - def realisationComplete(self, iens): + def realisationSuccess(self, iens): run_arg = self.ert_run_context.iensGet( iens ) queue_index = run_arg.getQueueIndex() - return self.queue_manager.jobComplete( queue_index ) + return self.queue_manager.jobSuccess( queue_index ) + + + def realisationFailed(self, iens): + run_arg = self.ert_run_context.iensGet( iens ) + queue_index = run_arg.getQueueIndex() + return self.queue_manager.jobFailed( queue_index ) + + + # Running is slightly misleading; we have three catogories: + # Complete, Failed, and "Running". Running in this context is + # actually the 'the rest', and includes jobs in all sorts of + # waiting. + + def realisationRunning(self, iens): + run_arg = self.ert_run_context.iensGet( iens ) + if run_arg.isSubmitted(): + queue_index = run_arg.getQueueIndex() + if self.queue_manager.jobRunning( queue_index ) or self.queue_manager.jobWaiting( queue_index ): + return True + else: + return False + else: + return True + diff --git a/ThirdParty/Ert/devel/python/python/ert/test/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert/test/CMakeLists.txt index 62ac811f64..94c3fa2e77 100644 --- a/ThirdParty/Ert/devel/python/python/ert/test/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert/test/CMakeLists.txt @@ -6,6 +6,7 @@ set(PYTHON_SOURCES test_run.py source_enumerator.py test_area.py + path_context.py ) add_python_package("python.ert.test" ${PYTHON_INSTALL_PREFIX}/ert/test "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/devel/python/python/ert/test/__init__.py b/ThirdParty/Ert/devel/python/python/ert/test/__init__.py index da9a6f283d..66efef55bf 100644 --- a/ThirdParty/Ert/devel/python/python/ert/test/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert/test/__init__.py @@ -4,6 +4,7 @@ from .extended_testcase import ExtendedTestCase from .source_enumerator import SourceEnumerator from .test_area import TestArea , TestAreaContext from .ert_test_runner import ErtTestRunner +from .path_context import PathContext try: from .ert_test_context import ErtTestContext, ErtTest except ImportError: diff --git a/ThirdParty/Ert/devel/python/python/ert/test/extended_testcase.py b/ThirdParty/Ert/devel/python/python/ert/test/extended_testcase.py index 3445ab9d12..01a8383bc5 100644 --- a/ThirdParty/Ert/devel/python/python/ert/test/extended_testcase.py +++ b/ThirdParty/Ert/devel/python/python/ert/test/extended_testcase.py @@ -147,24 +147,7 @@ class ExtendedTestCase(TestCase): def createSharePath(self, path, share_root=None): if share_root is None and self.__share_root is None: - file_path = os.path.realpath(__file__) - build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../devel/share/")) - site_packages_build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../../../devel/share/")) - src_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../share/")) - env_root = os.getenv("ERT_TEST_ROOT_PATH") - - if env_root is not None and os.path.exists(env_root): - root = os.path.realpath(env_root) - elif os.path.exists(build_root): - root = os.path.realpath(build_root) - elif os.path.exists(site_packages_build_root): - root = os.path.realpath(site_packages_build_root) - elif os.path.exists(src_root): - root = os.path.realpath(src_root) - else: - root = None - - self.setShareRoot(root) + self.setShareRoot(ExtendedTestCase.findShareRoot()) root_path = self.__share_root if share_root is not None: @@ -175,15 +158,34 @@ class ExtendedTestCase(TestCase): return os.path.realpath(os.path.join(root_path , path)) - + + @staticmethod + def findShareRoot(): + file_path = os.path.realpath(__file__) + build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../devel/share/")) + site_packages_build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../../../devel/share/")) + src_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../share/")) + env_root = os.getenv("ERT_SHARE_PATH") + + if env_root is not None and os.path.exists(env_root): + root = os.path.realpath(env_root) + elif os.path.exists(build_root): + root = os.path.realpath(build_root) + elif os.path.exists(site_packages_build_root): + root = os.path.realpath(site_packages_build_root) + elif os.path.exists(src_root): + root = os.path.realpath(src_root) + else: + root = None + + return root + def assertNotRaises(self, func): try: func() except: self.fail() - - @staticmethod def slowTestShouldNotRun(): """ diff --git a/ThirdParty/Ert/devel/python/python/ert/test/path_context.py b/ThirdParty/Ert/devel/python/python/ert/test/path_context.py new file mode 100644 index 0000000000..0db2fc320b --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/test/path_context.py @@ -0,0 +1,46 @@ +import os +import shutil + +class PathContext(object): + def __init__(self , path , store = False): + self.path = path + self.cwd = os.getcwd() + self.store = store + self.path_list = [ ] + + if not os.path.exists(path): + work_path = path + + while True: + work_path , base = os.path.split(work_path) + if work_path: + if os.path.isdir(work_path): + break + else: + self.path_list.append( work_path ) + else: + break + + os.makedirs( path ) + else: + if not self.store: + raise OSError("Entry %s already exists" % path) + os.chdir( path ) + + + + def __exit__(self , exc_type , exc_val , exc_tb): + os.chdir( self.cwd ) + if self.store == False: + shutil.rmtree( self.path ) + for path in self.path_list: + try: + os.rmdir( path ) + except OSError: + break + + return False + + + def __enter__(self): + return self diff --git a/ThirdParty/Ert/devel/python/python/ert/util/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert/util/CMakeLists.txt index e8a7ae9876..f0c3f86924 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert/util/CMakeLists.txt @@ -17,11 +17,13 @@ set(PYTHON_SOURCES stringlist.py substitution_list.py thread_pool.py + cthread_pool.py time_vector.py ui_return.py util_func.py vector_template.py version.py + arg_pack.py ) add_python_package("python.ert.util" ${PYTHON_INSTALL_PREFIX}/ert/util "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/devel/python/python/ert/util/__init__.py b/ThirdParty/Ert/devel/python/python/ert/util/__init__.py index 6299f5b8d8..9311f5ebdd 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/__init__.py @@ -73,8 +73,10 @@ from .hash import Hash, StringHash, DoubleHash, IntegerHash from .substitution_list import SubstitutionList from .ui_return import UIReturn from .thread_pool import ThreadPool +from .cthread_pool import CThreadPool , startCThreadPool from .install_abort_signals import installAbortSignals from .profiler import Profiler +from .arg_pack import ArgPack # Check if latex functionality exists in libert_util if hasattr(UTIL_LIB, "latex_alloc"): diff --git a/ThirdParty/Ert/devel/python/python/ert/util/arg_pack.py b/ThirdParty/Ert/devel/python/python/ert/util/arg_pack.py new file mode 100644 index 0000000000..befb03e0a7 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/util/arg_pack.py @@ -0,0 +1,63 @@ +# Copyright (C) 2015 Statoil ASA, Norway. +# +# The file 'arg_pack.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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 3 of the License, or +# (at your option) any later version. +# +# ERT 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 at +# for more details. + +from ert.util import UTIL_LIB +from ert.cwrap import CWrapper, BaseCClass + + +class ArgPack(BaseCClass): + + def __init__(self , *args): + c_ptr = ArgPack.cNamespace().alloc() + super(ArgPack, self).__init__(c_ptr) + self.child_list = [] + for arg in args: + self.append( arg ) + + + + def append(self , data): + if isinstance(data , int): + ArgPack.cNamespace().append_int( self , data ) + elif isinstance(data , float): + ArgPack.cNamespace().append_double( self , data ) + elif isinstance(data , BaseCClass): + ArgPack.cNamespace().append_ptr( self , BaseCClass.from_param( data ) ) + self.child_list.append( data ) + else: + raise TypeError("Can only add int/double/basecclass") + + + def __len__(self): + return ArgPack.cNamespace().size(self) + + + + def free(self): + ArgPack.cNamespace().free(self) + + + +CWrapper.registerObjectType("arg_pack", ArgPack) + +cwrapper = CWrapper(UTIL_LIB) + +ArgPack.cNamespace().alloc = cwrapper.prototype("c_void_p arg_pack_alloc( )") +ArgPack.cNamespace().free = cwrapper.prototype("void arg_pack_free(arg_pack )") +ArgPack.cNamespace().size = cwrapper.prototype("int arg_pack_size(arg_pack )") +ArgPack.cNamespace().append_int = cwrapper.prototype("void arg_pack_append_int(arg_pack , int)") +ArgPack.cNamespace().append_double = cwrapper.prototype("void arg_pack_append_double(arg_pack ,double)") +ArgPack.cNamespace().append_ptr = cwrapper.prototype("void arg_pack_append_ptr(arg_pack , c_void_p)") diff --git a/ThirdParty/Ert/devel/python/python/ert/util/cthread_pool.py b/ThirdParty/Ert/devel/python/python/ert/util/cthread_pool.py new file mode 100644 index 0000000000..74190de652 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert/util/cthread_pool.py @@ -0,0 +1,83 @@ +# Copyright (C) 2015 Statoil ASA, Norway. +# +# The file 'cthread_pool.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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 3 of the License, or +# (at your option) any later version. +# +# ERT 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 at +# for more details. + +import ctypes +from ert.util import UTIL_LIB +from ert.cwrap import CWrapper, BaseCClass + +class CThreadPool(BaseCClass): + def __init__(self , pool_size , start = True): + c_ptr = CThreadPool.cNamespace().alloc( pool_size , start ) + super(CThreadPool, self).__init__(c_ptr) + self.arg_list = [] + + def addTask(self , cfunc , arg): + """ + The function should come from CThreadPool.lookupCFunction(). + """ + if isinstance(arg, BaseCClass): + arg_ptr = BaseCClass.from_param( arg ) + else: + arg_ptr = arg + + self.arg_list.append( arg ) + CThreadPool.cNamespace().add_job( self , cfunc , arg_ptr ) + + + def join(self): + CThreadPool.cNamespace().join( self ) + + + def free(self): + self.join( ) + CThreadPool.cNamespace().free( self ) + + + @staticmethod + def lookupCFunction(lib , name): + if isinstance(lib , ctypes.CDLL): + func = getattr(lib , name) + return func + else: + raise TypeError("The lib argument must of type ctypes.CDLL") + + + +class CThreadPoolContextManager(object): + + def __init__(self , tp): + self.__tp = tp + + def __enter__(self): + return self.__tp + + def __exit__(self, exc_type, exc_val, exc_tb): + self.__tp.join() + return False + + +def startCThreadPool( size ): + return CThreadPoolContextManager( CThreadPool( size , start = True )) + + + +CWrapper.registerObjectType("thread_pool", CThreadPool) + +cwrapper = CWrapper(UTIL_LIB) +CThreadPool.cNamespace().alloc = cwrapper.prototype("c_void_p thread_pool_alloc( int , bool )") +CThreadPool.cNamespace().free = cwrapper.prototype("void thread_pool_free( thread_pool )") +CThreadPool.cNamespace().add_job = cwrapper.prototype("void thread_pool_add_job( thread_pool , c_void_p , c_void_p)") +CThreadPool.cNamespace().join = cwrapper.prototype("void thread_pool_join( thread_pool )") diff --git a/ThirdParty/Ert/devel/python/python/ert/util/ctime.py b/ThirdParty/Ert/devel/python/python/ert/util/ctime.py index 11498654e5..3f7a434725 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/ctime.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/ctime.py @@ -15,12 +15,11 @@ # for more details. -import math import ctypes import datetime import time -from types import NoneType from ert.cwrap import CWrapper, BaseCValue +from ert.util import UTIL_LIB class CTime(BaseCValue): @@ -32,9 +31,9 @@ class CTime(BaseCValue): elif isinstance(value, CTime): value = value.value() elif isinstance(value, datetime.datetime): - value = int(math.floor(time.mktime((value.year, value.month, value.day, value.hour, value.minute, value.second, 0, 0, -1 )))) + value = CTime._mktime(value.second, value.minute, value.hour, value.day, value.month, value.year) elif isinstance(value, datetime.date): - value = int(math.floor(time.mktime((value.year, value.month, value.day, 0, 0, 0, 0, 0, -1 )))) + value = CTime._mktime(0, 0, 0, value.day, value.month, value.year) else: raise NotImplementedError("Can not convert class %s to CTime" % value.__class__) @@ -57,7 +56,7 @@ class CTime(BaseCValue): return datetime.datetime(*self.time()[0:6]) def __str__(self): - return "%s" % (str(self.datetime())) + return self.datetime().strftime("%Y-%m-%d %H:%M:%S%z") def __ge__(self, other): return self > other or self == other @@ -131,11 +130,26 @@ class CTime(BaseCValue): # this function is a requirement for comparing against datetime objects where the CTime is on the right side pass + def __repr__(self): + return "time_t value: %d [%s]" % (self.value(), str(self)) + + @property def stripped(self): return time.strptime(self, "%Y-%m-%d %H:%M:S%") + @classmethod + def timezone(cls): + """ + Returns the current timezone "in" C + @rtype: str + """ + return CTime._timezone() -cwrapper = CWrapper(None) + +cwrapper = CWrapper(UTIL_LIB) cwrapper.registerType("time_t", CTime) +CTime._timezone = cwrapper.prototype("char* util_get_timezone()") +CTime._mktime = cwrapper.prototype("long util_make_datetime(int, int, int, int, int, int)") + diff --git a/ThirdParty/Ert/devel/python/python/ert/util/int_vector.py b/ThirdParty/Ert/devel/python/python/ert/util/int_vector.py index 86362269de..2eb97c1cb3 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/int_vector.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/int_vector.py @@ -25,9 +25,8 @@ class IntVector(VectorTemplate): super(IntVector, self).__init__(default_value, initial_size) @classmethod - def active_list(cls , range_string): - """ - Will create a IntVector instance with the values from @range_string. + def active_list(cls , range_string ): + """Will create a IntVector instance with the values from @range_string. The range_string input should be of the type "1,3-5,9,17", i.e. integer values separated by commas, and dashes to @@ -37,10 +36,26 @@ class IntVector(VectorTemplate): "1,4-7,10" => {1,4,5,6,7,10} "1,4-7,10X" => {} - The empty list will evaluate to false + The empty list will evaluate to false. The values in the input + string are meant to indicate "active values", i.e. the output + values are sorted and repeated values are only counted once: + + "1,1,7,2" => {1,2,7} + """ return cls.cNamespace().create_active_list(range_string) - + + @classmethod + def valueList(cls , range_string): + """Will create a IntVecter of all the values in the @range_string. + + Will not sort the values, and not uniquiefy - in contrast to + the active_list() method. + + """ + return cls.cNamespace().create_value_list(range_string) + + def count(self, value): """ @rtype: int """ return IntVector.cNamespace().count_equal(self, value) @@ -84,7 +99,8 @@ IntVector.cNamespace().memcpy = cwrapper.prototype("void int_vect IntVector.cNamespace().set_default = cwrapper.prototype("void int_vector_set_default( int_vector , int)") IntVector.cNamespace().get_default = cwrapper.prototype("int int_vector_get_default( int_vector )") IntVector.cNamespace().element_size = cwrapper.prototype("int int_vector_element_size( int_vector )") -IntVector.cNamespace().create_active_list = cwrapper.prototype("int_vector_obj string_util_alloc_active_list( char* )") +IntVector.cNamespace().create_active_list = cwrapper.prototype("int_vector_obj string_util_alloc_active_list( char*)") +IntVector.cNamespace().create_value_list = cwrapper.prototype("int_vector_obj string_util_alloc_value_list( char*)") IntVector.cNamespace().permute = cwrapper.prototype("void int_vector_permute(int_vector, permutation_vector)") IntVector.cNamespace().sort_perm = cwrapper.prototype("permutation_vector_obj int_vector_alloc_sort_perm(int_vector)") diff --git a/ThirdParty/Ert/devel/python/python/ert/util/rng.py b/ThirdParty/Ert/devel/python/python/ert/util/rng.py index 536a67ded3..c5f00a6d94 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/rng.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/rng.py @@ -45,9 +45,12 @@ class RandomNumberGenerator(BaseCClass): return RandomNumberGenerator.cNamespace().get_double(self) - def getInt(self): + def getInt(self, max=None): """ @rtype: float """ - return RandomNumberGenerator.cNamespace().get_int(self) + if max is None: + max = RandomNumberGenerator.cNamespace().get_max_int(self) + + return RandomNumberGenerator.cNamespace().get_int(self, max) def free(self): @@ -64,6 +67,7 @@ CWrapper.registerType("rng_ref", RandomNumberGenerator.createCReference) RandomNumberGenerator.cNamespace().rng_alloc = cwrapper.prototype("c_void_p rng_alloc(rng_alg_type_enum, rng_init_mode_enum)") RandomNumberGenerator.cNamespace().free = cwrapper.prototype("void rng_free(rng)") RandomNumberGenerator.cNamespace().get_double = cwrapper.prototype("double rng_get_double(rng)") -RandomNumberGenerator.cNamespace().get_int = cwrapper.prototype("int rng_get_int(rng)") +RandomNumberGenerator.cNamespace().get_int = cwrapper.prototype("int rng_get_int(rng, int)") +RandomNumberGenerator.cNamespace().get_max_int = cwrapper.prototype("uint rng_get_max_int(rng)") RandomNumberGenerator.cNamespace().state_size = cwrapper.prototype("int rng_state_size(rng)") RandomNumberGenerator.cNamespace().set_state = cwrapper.prototype("void rng_set_state(rng , char*)") diff --git a/ThirdParty/Ert/devel/python/python/ert/util/stat.py b/ThirdParty/Ert/devel/python/python/ert/util/stat.py index d32b79d33d..f552a7acd5 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/stat.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/stat.py @@ -18,7 +18,7 @@ from ert.util import UTIL_LIB from ert.util import Matrix from ert.util import LLSQResultEnum -from ert.cwrap import CWrapper, CWrapperNameSpace +from ert.cwrap import CWrapper, CWrapperNameSpace, CWrapError def quantile( data, q ): @@ -30,6 +30,9 @@ def quantile_sorted( data, q ): def polyfit(n,x,y,s = None): + if cfunc.polyfit is None: + raise NotImplementedError("Sorry - your ert distribution has been built without lapack support") + if isinstance(x,Matrix): xm = x else: @@ -79,5 +82,8 @@ cfunc = CWrapperNameSpace("stat") cfunc.quantile = cwrapper.prototype("double statistics_empirical_quantile( double_vector , double )") cfunc.quantile_sorted = cwrapper.prototype("double statistics_empirical_quantile( double_vector , double )") -cfunc.polyfit = cwrapper.prototype("llsq_result_enum matrix_stat_polyfit(matrix , matrix , matrix , matrix)") +try: + cfunc.polyfit = cwrapper.prototype("llsq_result_enum matrix_stat_polyfit(matrix , matrix , matrix , matrix)") +except CWrapError: + cfunc.polyfit = None diff --git a/ThirdParty/Ert/devel/python/python/ert/util/stringlist.py b/ThirdParty/Ert/devel/python/python/ert/util/stringlist.py index 143dfcae8d..1bb2ecd837 100644 --- a/ThirdParty/Ert/devel/python/python/ert/util/stringlist.py +++ b/ThirdParty/Ert/devel/python/python/ert/util/stringlist.py @@ -69,6 +69,21 @@ class StringList(BaseCClass): raise TypeError("Item: %s not a string" % s) + def __eq__(self , other): + if len(self) == len(other): + if isinstance( other , StringList): + return StringList.cNamespace().equal(self, other) + else: + equal = True + for index,s2 in enumerate(other): + if self[index] != s2: + equal = False + break + return equal + else: + return False + + def __setitem__(self, index, value): if isinstance(index, IntType): length = self.__len__() @@ -240,6 +255,7 @@ StringList.cNamespace().iget_copy = cwrapper.prototype("char* stringlist_iget_c StringList.cNamespace().iset = cwrapper.prototype("void stringlist_iset_copy( stringlist , int , char* )") StringList.cNamespace().get_size = cwrapper.prototype("int stringlist_get_size( stringlist )") StringList.cNamespace().contains = cwrapper.prototype("bool stringlist_contains(stringlist , char*)") +StringList.cNamespace().equal = cwrapper.prototype("bool stringlist_equal(stringlist , stringlist)") StringList.cNamespace().sort = cwrapper.prototype("void stringlist_python_sort( stringlist , int)") StringList.cNamespace().pop = cwrapper.prototype("char* stringlist_pop(stringlist)") StringList.cNamespace().last = cwrapper.prototype("char* stringlist_get_last(stringlist)") diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/CMakeLists.txt index f119b0ad23..643fad617b 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert_gui/CMakeLists.txt @@ -1,21 +1,21 @@ set(PYTHON_SOURCES __init__.py + about_dialog.py ert_splash.py gert_main.py ide_test.py main_window.py newconfig.py - about_dialog.py ) -add_python_package("python.ert_gui" ${PYTHON_INSTALL_PREFIX}/ert_gui "${PYTHON_SOURCES}" True) +add_python_package("python.ert_gui" ${PYTHON_INSTALL_PREFIX}/ert_gui "${PYTHON_SOURCES}" True) add_subdirectory(ide) add_subdirectory(models) add_subdirectory(pages) +add_subdirectory(plottery) add_subdirectory(shell) add_subdirectory(simulation) add_subdirectory(tools) add_subdirectory(viewer) add_subdirectory(widgets) - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/gert_main.py b/ThirdParty/Ert/devel/python/python/ert_gui/gert_main.py index db2a86090e..7741834032 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/gert_main.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/gert_main.py @@ -247,7 +247,7 @@ def main(argv): window.addDock("Configuration Summary", SummaryPanel(), area=Qt.BottomDockWidgetArea) window.addTool(IdeTool(os.path.basename(config_file), ert.reloadERT, help_tool)) - window.addTool(PlotTool()) + window.addTool(PlotTool(ert.ert())) window.addTool(ExportTool()) window.addTool(WorkflowsTool()) window.addTool(ManageCasesTool()) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/models/connectors/init/case_list.py b/ThirdParty/Ert/devel/python/python/ert_gui/models/connectors/init/case_list.py index 340dc7a97a..f3ab98c067 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/models/connectors/init/case_list.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/models/connectors/init/case_list.py @@ -34,6 +34,15 @@ class CaseList(ErtConnector, ListModelMixin): return cases_with_data_and_not_running + def getAllCasesNotRunning(self): + cases = self.getList() + cases_not_running = [] + for case in cases: + if not self.ert().getEnkfFsManager().isCaseRunning(case): + cases_not_running.append(case) + + return cases_not_running + def getCaseRealizationStates(self, case_name): state_map = self.ert().getEnkfFsManager().getStateMapForCase(case_name) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/CMakeLists.txt index f48937f005..c5b3f552cc 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/CMakeLists.txt @@ -1,6 +1,7 @@ set(PYTHON_SOURCES __init__.py default_boolean_model.py + default_choice_list_model.py default_name_format_model.py default_path_model.py function_button_model.py diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/__init__.py b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/__init__.py index 1e4cbfe915..612e817818 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/__init__.py @@ -3,3 +3,4 @@ from .default_path_model import DefaultPathModel from .default_boolean_model import DefaultBooleanModel from .string_model import StringModel from .default_name_format_model import DefaultNameFormatModel +from .default_choice_list_model import DefaultChoiceListModel diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/default_choice_list_model.py b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/default_choice_list_model.py new file mode 100644 index 0000000000..890ea767fc --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/models/mixins/connectorless/default_choice_list_model.py @@ -0,0 +1,26 @@ +from ert_gui.models.mixins import ChoiceModelMixin, ListModelMixin + + +class DefaultChoiceListModel(ListModelMixin, ChoiceModelMixin): + + def __init__(self, choices, default_choice=None): + assert choices is not None and len(choices) > 0 + self.__choices = choices + self.__value = None if not default_choice in choices else default_choice + super(DefaultChoiceListModel, self).__init__() + + def getList(self): + return self.__choices + + def getChoices(self): + return self.getList() + + def getCurrentChoice(self): + if self.__value is None: + return self.getList()[0] + return self.__value + + def setCurrentChoice(self, value): + self.__value = value + self.observable().notify(self.CURRENT_CHOICE_CHANGED_EVENT) + diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/pages/run_dialog.py b/ThirdParty/Ert/devel/python/python/ert_gui/pages/run_dialog.py index dc37053900..d8569eb3b0 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/pages/run_dialog.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/pages/run_dialog.py @@ -2,6 +2,7 @@ from threading import Thread from PyQt4.QtCore import Qt, pyqtSignal, QTimer, QSize from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QMessageBox, QPushButton, QHBoxLayout, QColor, QLabel from ert_gui.models.connectors.run import SimulationsTracker +from ert_gui.models.ert_connector import ErtConnector from ert_gui.models.mixins.run_model import RunModelMixin from ert_gui.tools.plot.plot_tool import PlotTool from ert_gui.widgets import util @@ -57,11 +58,16 @@ class RunDialog(QDialog): self.running_time = QLabel("") - self.plot_tool = PlotTool() + ert = None + if isinstance(run_model, ErtConnector): + ert = run_model.ert() + + self.plot_tool = PlotTool(ert) self.plot_tool.setParent(self) self.plot_button = QPushButton(self.plot_tool.getName()) self.plot_button.clicked.connect(self.plot_tool.trigger) - + self.plot_button.setEnabled(ert is not None) + self.kill_button = QPushButton("Kill simulations") self.done_button = QPushButton("Done") self.done_button.setHidden(True) @@ -194,4 +200,4 @@ class RunDialog(QDialog): self.__update_timer.stop() self.processing_animation.hide() self.kill_button.setHidden(True) - self.done_button.setHidden(False) \ No newline at end of file + self.done_button.setHidden(False) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/CMakeLists.txt new file mode 100644 index 0000000000..138639ecd0 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/CMakeLists.txt @@ -0,0 +1,10 @@ +set(PYTHON_SOURCES + __init__.py + plot_config.py + plot_context.py + plot_data_gatherer.py +) + +add_python_package("python.ert_gui.plottery" ${PYTHON_INSTALL_PREFIX}/ert_gui/plottery "${PYTHON_SOURCES}" True) + +add_subdirectory(plots) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/__init__.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/__init__.py new file mode 100644 index 0000000000..20003f6e23 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/__init__.py @@ -0,0 +1,4 @@ +from .plot_data_gatherer import PlotDataGatherer +from .plot_config import PlotConfig +from .plot_context import PlotContext + diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_config.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_config.py new file mode 100644 index 0000000000..1dcef021a5 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_config.py @@ -0,0 +1,143 @@ +import itertools + + +class PlotConfig(object): + + def __init__(self, title="Unnamed", x_label=None, y_label=None): + super(PlotConfig, self).__init__() + self.__title = title + + self.__line_color_cycle = itertools.cycle(["#000000"]) #Black + # Blueish, Greenlike, Beigeoid, Pinkness, Orangy-Brown + self.setLineColorCycle(["#386CB0", "#7FC97F", "#FDC086", "#F0027F", "#BF5B17"]) + + self.__legend_items = [] + self.__legend_labels = [] + + self.__x_label = x_label + self.__y_label = y_label + + + self.__line_color = None + self.__line_style = "-" + self.__line_alpha = 0.8 + self.__line_marker = None + + self.__observations_enabled = True + self.__observations_color = "#000000" #Black + self.__observations_alpha = 1.0 + + self.__refcase_enabled = True + self.__refcase_color = "#000000" #Black + self.__refcase_alpha = 0.8 + self.__refcase_style = "-" + self.__refcase_marker = "x" + self.__refcase_width = 2.0 + + self.__legend_enabled = True + self.__grid_enabled = True + self.__date_support_active = True + + + def lineColor(self): + if self.__line_color is None: + self.nextColor() + + return self.__line_color + + def nextColor(self): + self.__line_color = self.__line_color_cycle.next() + return self.__line_color + + def setLineColorCycle(self, color_list): + self.__line_color_cycle = itertools.cycle(color_list) + + def addLegendItem(self, label, item): + self.__legend_items.append(item) + self.__legend_labels.append(label) + + def title(self): + """ :rtype: str """ + return self.__title + + def lineStyle(self): + return self.__line_style + + def lineAlpha(self): + return self.__line_alpha + + def lineMarker(self): + return self.__line_marker + + def xLabel(self): + return self.__x_label + + def yLabel(self): + return self.__y_label + + def legendItems(self): + return self.__legend_items + + def legendLabels(self): + return self.__legend_labels + + def setXLabel(self, label): + self.__x_label = label + + def setYLabel(self, label): + self.__y_label = label + + + def setObservationsEnabled(self, enabled): + self.__observations_enabled = enabled + + def isObservationsEnabled(self): + return self.__observations_enabled + + def observationsColor(self): + return self.__observations_color + + def observationsAlpha(self): + return self.__observations_alpha + + + def setRefcaseEnabled(self, enabled): + self.__refcase_enabled = enabled + + def isRefcaseEnabled(self): + return self.__refcase_enabled + + def refcaseColor(self): + return self.__refcase_color + + def refcaseAlpha(self): + return self.__refcase_alpha + + def refcaseStyle(self): + return self.__refcase_style + + def refcaseMarker(self): + return self.__refcase_marker + + def refcaseWidth(self): + return self.__refcase_width + + + def isLegendEnabled(self): + return self.__legend_enabled + + def setLegendEnabled(self, enabled): + self.__legend_enabled = enabled + + + def isGridEnabled(self): + return self.__grid_enabled + + def setGridEnabled(self, enabled): + self.__grid_enabled = enabled + + def deactiveDateSupport(self): + self.__date_support_active = False + + def isDateSupportActive(self): + return self.__date_support_active diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_context.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_context.py new file mode 100644 index 0000000000..9a6b02790c --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_context.py @@ -0,0 +1,39 @@ +from .plot_config import PlotConfig +from .plot_data_gatherer import PlotDataGatherer + +class PlotContext(object): + + def __init__(self, ert, figure, plot_config, cases, key, data_gatherer): + super(PlotContext, self).__init__() + self.__data_gatherer = data_gatherer + self.__key = key + self.__cases = cases + self.__figure = figure + self.__ert = ert + self.__plot_config = plot_config + + def figure(self): + """ :rtype: matplotlib.figure.Figure""" + return self.__figure + + def plotConfig(self): + """ :rtype: PlotConfig """ + return self.__plot_config + + def ert(self): + """ :rtype: ert.enkf.EnKFMain""" + return self.__ert + + def cases(self): + """ :rtype: list of str """ + return self.__cases + + def key(self): + """ :rtype: str """ + return self.__key + + def dataGatherer(self): + """ :rtype: PlotDataGatherer """ + return self.__data_gatherer + + diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_data_gatherer.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_data_gatherer.py new file mode 100644 index 0000000000..7c60ddfe3b --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plot_data_gatherer.py @@ -0,0 +1,132 @@ +from pandas import DataFrame +from ert.enkf.export import GenKwCollector, SummaryCollector, GenDataCollector, SummaryObservationCollector, \ + GenDataObservationCollector, CustomKWCollector + + +class PlotDataGatherer(object): + + def __init__(self, dataGatherFunc, conditionFunc, refcaseGatherFunc=None, observationGatherFunc=None): + super(PlotDataGatherer, self).__init__() + + self.__dataGatherFunction = dataGatherFunc + self.__conditionFunction = conditionFunc + self.__refcaseGatherFunction = refcaseGatherFunc + self.__observationGatherFunction = observationGatherFunc + + def hasRefcaseGatherFunction(self): + """ :rtype: bool """ + return self.__refcaseGatherFunction is not None + + def hasObservationGatherFunction(self): + """ :rtype: bool """ + return self.__observationGatherFunction is not None + + def canGatherDataForKey(self, key): + """ :rtype: bool """ + return self.__conditionFunction(key) + + def gatherData(self, ert, case, key): + """ :rtype: pandas.DataFrame """ + if not self.canGatherDataForKey(key): + raise UserWarning("Unable to gather data for key: %s" % key) + + return self.__dataGatherFunction(ert, case, key) + + def gatherRefcaseData(self, ert, key): + """ :rtype: pandas.DataFrame """ + if not self.canGatherDataForKey(key) or not self.hasRefcaseGatherFunction(): + raise UserWarning("Unable to gather refcase data for key: %s" % key) + + return self.__refcaseGatherFunction(ert, key) + + def gatherObservationData(self, ert, case, key): + """ :rtype: pandas.DataFrame """ + if not self.canGatherDataForKey(key) or not self.hasObservationGatherFunction(): + raise UserWarning("Unable to gather observation data for key: %s" % key) + + return self.__observationGatherFunction(ert, case, key) + + + @staticmethod + def gatherGenKwData(ert, case, key): + """ :rtype: pandas.DataFrame """ + data = GenKwCollector.loadAllGenKwData(ert, case, [key]) + return data[key].dropna() + + @staticmethod + def gatherSummaryData(ert, case, key): + """ :rtype: pandas.DataFrame """ + data = SummaryCollector.loadAllSummaryData(ert, case, [key]) + if not data.empty: + data = data.reset_index() + data = data.pivot(index="Date", columns="Realization", values=key) + + return data #.dropna() + + @staticmethod + def gatherSummaryRefcaseData(ert, key): + refcase = ert.eclConfig().getRefcase() + + if not key in refcase: + return DataFrame() + + vector = refcase.get_vector(key, report_only=False) + + rows = [] + for index in range(1, len(vector)): + node = vector[index] + row = { + "Date": node.date, + key: node.value + } + rows.append(row) + + data = DataFrame(rows) + data = data.set_index("Date") + + return data + + @staticmethod + def gatherSummaryObservationData(ert, case, key): + if ert.getKeyManager().isKeyWithObservations(key): + return SummaryObservationCollector.loadObservationData(ert, case, [key]).dropna() + else: + return DataFrame() + + + @staticmethod + def gatherGenDataData(ert, case, key): + """ :rtype: pandas.DataFrame """ + key, report_step = key.split("@", 1) + report_step = int(report_step) + try: + data = GenDataCollector.loadGenData(ert, case, key, report_step) + except ValueError: + data = DataFrame() + + return data.dropna() # removes all rows that has a NaN + + + @staticmethod + def gatherGenDataObservationData(ert, case, key_with_report_step): + """ :rtype: pandas.DataFrame """ + key, report_step = key_with_report_step.split("@", 1) + report_step = int(report_step) + + obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, key, report_step) + + if obs_key is not None: + obs_data = GenDataObservationCollector.loadGenDataObservations(ert, case, [obs_key]) + columns = {obs_key: key_with_report_step, "STD_%s" % obs_key: "STD_%s" % key_with_report_step} + obs_data = obs_data.rename(columns=columns) + else: + obs_data = DataFrame() + + return obs_data.dropna() + + @staticmethod + def gatherCustomKwData(ert, case, key): + """ :rtype: pandas.DataFrame """ + data = CustomKWCollector.loadAllCustomKWData(ert, case, [key]) + + return data diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/CMakeLists.txt new file mode 100644 index 0000000000..31fc925843 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/CMakeLists.txt @@ -0,0 +1,14 @@ +set(PYTHON_SOURCES + __init__.py + ensemble.py + gaussian_kde.py + histogram.py + observations.py + overview.py + plot_tools.py + refcase.py + statistics.py +) + +add_python_package("python.ert_gui.plottery.plots" ${PYTHON_INSTALL_PREFIX}/ert_gui/plottery/plots "${PYTHON_SOURCES}" True) + diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/__init__.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/__init__.py new file mode 100644 index 0000000000..2cc576334d --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/__init__.py @@ -0,0 +1,9 @@ +from .histogram import plotHistogram +from .gaussian_kde import plotGaussianKDE + +from .refcase import plotRefcase +from .observations import plotObservations + +from .ensemble import plotEnsemble +from .statistics import plotStatistics +from .overview import plotOverview \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/ensemble.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/ensemble.py new file mode 100644 index 0000000000..63b37ebf52 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/ensemble.py @@ -0,0 +1,52 @@ +from .refcase import plotRefcase +from .observations import plotObservations +from .plot_tools import PlotTools + +def plotEnsemble(plot_context): + """ + @type plot_context: PlotContext + """ + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + axes = plot_context.figure().add_subplot(111) + """:type: matplotlib.axes.Axes """ + + case_list = plot_context.cases() + + for case in case_list: + data = plot_context.dataGatherer().gatherData(ert, case, key) + if not data.empty: + if not data.index.is_all_dates: + config.deactiveDateSupport() + + _plotLines(axes, config, data, case) + config.nextColor() + + plotRefcase(plot_context, axes) + plotObservations(plot_context, axes) + + default_x_label = "Date" if config.isDateSupportActive() else "Index" + PlotTools.finalizePlot(plot_context, axes, default_x_label=default_x_label, default_y_label="Value") + + +def _plotLines(axes, plot_config, data, ensemble_label): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type ensemble_label: Str + """ + + line_color = plot_config.lineColor() + line_alpha = plot_config.lineAlpha() + line_marker = plot_config.lineMarker() + line_style = plot_config.lineStyle() + + if plot_config.isDateSupportActive(): + lines = axes.plot_date(x=data.index.values, y=data, color=line_color, alpha=line_alpha, marker=line_marker, linestyle=line_style) + else: + lines = axes.plot(data.index.values, data, color=line_color, alpha=line_alpha, marker=line_marker, linestyle=line_style) + + if len(lines) > 0: + plot_config.addLegendItem(ensemble_label, lines[0]) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/gaussian_kde.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/gaussian_kde.py new file mode 100644 index 0000000000..0f864be7b3 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/gaussian_kde.py @@ -0,0 +1,65 @@ +import numpy +from scipy.stats import gaussian_kde +from .plot_tools import PlotTools + + +def plotGaussianKDE(plot_context): + """ + @type plot_context: PlotContext + """ + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + axes = plot_context.figure().add_subplot(111) + """:type: matplotlib.axes.Axes """ + + config.deactiveDateSupport() + + if key.startswith("LOG10_"): + key = key[6:] + axes.set_xscale("log") + + case_list = plot_context.cases() + for case in case_list: + data = plot_context.dataGatherer().gatherData(ert, case, key) + + if not data.empty and data.nunique() > 1: + _plotGaussianKDE(axes, config, data, case) + config.nextColor() + + PlotTools.finalizePlot(plot_context, axes, default_x_label="Value", default_y_label="Density") + + +def _plotGaussianKDE(axes, plot_config, data, label): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type label: Str + """ + + # axes.set_xlabel(plot_config.xLabel()) + # axes.set_ylabel(plot_config.yLabel()) + + line_color = plot_config.lineColor() + line_alpha = plot_config.lineAlpha() + line_marker = plot_config.lineMarker() + line_style = plot_config.lineStyle() + line_width = 2 + + if data.dtype == "object": + data = data.convert_objects(convert_numeric=True) + + if data.dtype == "object": + pass + + else: + sample_range = data.max() - data.min() + indexes = numpy.linspace(data.min() - 0.5 * sample_range, data.max() + 0.5 * sample_range, 1000) + gkde = gaussian_kde(data.values) + evaluated_gkde = gkde.evaluate(indexes) + + lines = axes.plot(indexes, evaluated_gkde, linewidth=line_width, color=line_color, alpha=line_alpha) + + if len(lines) > 0: + plot_config.addLegendItem(label, lines[0]) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/histogram.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/histogram.py new file mode 100644 index 0000000000..8ba9250373 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/histogram.py @@ -0,0 +1,141 @@ +from math import sqrt, ceil, floor, log10 +from matplotlib.patches import Rectangle +import numpy +from .plot_tools import PlotTools + + + +def plotHistogram(plot_context): + """ + @type plot_context: ert_gui.plottery.PlotContext + """ + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + case_list = plot_context.cases() + case_count = len(case_list) + + if config.xLabel() is None: + config.setXLabel("Value") + + if config.yLabel() is None: + config.setYLabel("Count") + + use_log_scale = False + if key.startswith("LOG10_"): + key = key[6:] + use_log_scale = True + + data = {} + minimum = None + maximum = None + for case in case_list: + data[case] = plot_context.dataGatherer().gatherData(ert, case, key) + + if minimum is None: + minimum = data[case].min() + else: + minimum = min(minimum, data[case].min()) + + if maximum is None: + maximum = data[case].max() + else: + maximum = max(maximum, data[case].max()) + + #todo: bin count must also be determined across all cases... + + axes = {} + """:type: dict of (str, matplotlib.axes.Axes) """ + for index, case in enumerate(case_list): + axes[case] = plot_context.figure().add_subplot(case_count, 1, index + 1) + + axes[case].set_title("%s (%s)" % (config.title(), case)) + + if use_log_scale: + axes[case].set_xscale("log") + + if not data[case].empty: + _plotHistogram(axes[case], config, data[case], case, use_log_scale, minimum, maximum) + + config.nextColor() + PlotTools.showGrid(axes[case], plot_context) + + max_count = max([subplot.get_ylim()[1] for subplot in axes.values()]) + + for subplot in axes.values(): + subplot.set_ylim(0, max_count) + + +def _plotHistogram(axes, plot_config, data, label, use_log_scale=False, minimum=None, maximum=None): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type label: Str + """ + + axes.set_xlabel(plot_config.xLabel()) + axes.set_ylabel(plot_config.yLabel()) + + line_color = plot_config.lineColor() + line_alpha = plot_config.lineAlpha() + line_marker = plot_config.lineMarker() + line_style = plot_config.lineStyle() + line_width = 2 + + if data.dtype == "object": + data = data.convert_objects(convert_numeric=True) + + if data.dtype == "object": + counts = data.value_counts() + x = counts.index.values + freq = counts.values + pos = numpy.arange(len(x)) + width = 1.0 + axes.set_xticks(pos + (width / 2.0)) + axes.set_xticklabels(x) + axes.bar(pos, freq, alpha=line_alpha, color=line_color, width=width) + else: + bins = int(ceil(sqrt(len(data.index)))) + + if use_log_scale: + bins = _histogramLogBins(data, bins, minimum, maximum) + elif minimum is not None and maximum is not None: + bins = numpy.linspace(minimum, maximum, bins) + + axes.hist(data.values, alpha=line_alpha, bins=bins, color=line_color) + + rectangle = Rectangle((0, 0), 1, 1, color=line_color) # creates rectangle patch for legend use.' + plot_config.addLegendItem(label, rectangle) + + + +def _histogramLogBins(data, bin_count, minimum=None, maximum=None): + """ + @type data: pandas.DataFrame + @rtype: int + """ + + if minimum is None: + minimum = data.min() + + if maximum is None: + maximum = data.max() + + minimum = log10(float(minimum)) + maximum = log10(float(maximum)) + + min_value = int(floor(minimum)) + max_value = int(ceil(maximum)) + + log_bin_count = max_value - min_value + + if log_bin_count < bin_count: + next_bin_count = log_bin_count * 2 + + if bin_count - log_bin_count > next_bin_count - bin_count: + log_bin_count = next_bin_count + else: + log_bin_count = bin_count + + return 10 ** numpy.linspace(minimum, maximum, log_bin_count) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/observations.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/observations.py new file mode 100644 index 0000000000..6df1291480 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/observations.py @@ -0,0 +1,29 @@ +def plotObservations(plot_context, axes): + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + case_list = plot_context.cases() + data_gatherer = plot_context.dataGatherer() + + if config.isObservationsEnabled() and data_gatherer.hasObservationGatherFunction(): + if len(case_list) > 0: + observation_data = data_gatherer.gatherObservationData(ert, case_list[0], key) + + if not observation_data.empty: + _plotObservations(axes, config, observation_data, value_column=key) + + + +def _plotObservations(axes, plot_config, data, value_column): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type value_column: Str + """ + + error_color = plot_config.observationsColor() + error_alpha = plot_config.observationsAlpha() + + errorbars = axes.errorbar(x=data.index.values, y=data[value_column], yerr=data["STD_%s" % value_column], + fmt=' ', ecolor=error_color, alpha=error_alpha) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/overview.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/overview.py new file mode 100644 index 0000000000..93686dbdba --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/overview.py @@ -0,0 +1,54 @@ +from matplotlib.patches import Rectangle +from pandas import DataFrame +from .refcase import plotRefcase +from .observations import plotObservations +from .plot_tools import PlotTools + + +def plotOverview(plot_context): + """ + @type plot_context: ert_gui.plottery.PlotContext + """ + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + axes = plot_context.figure().add_subplot(111) + """:type: matplotlib.axes.Axes """ + + case_list = plot_context.cases() + for case in case_list: + data = plot_context.dataGatherer().gatherData(ert, case, key) + if not data.empty: + if not data.index.is_all_dates: + config.deactiveDateSupport() + + min_max_data = DataFrame() + min_max_data["Minimum"] = data.min(axis=1) + min_max_data["Maximum"] = data.max(axis=1) + + _plotArea(axes, config, min_max_data, case) + config.nextColor() + + plotRefcase(plot_context, axes) + plotObservations(plot_context, axes) + + default_x_label = "Date" if config.isDateSupportActive() else "Index" + PlotTools.finalizePlot(plot_context, axes, default_x_label=default_x_label, default_y_label="Value") + + +def _plotArea(axes, plot_config, data, ensemble_label): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type ensemble_label: Str + """ + + line_color = plot_config.lineColor() + line_alpha = plot_config.lineAlpha() * 0.5 + + poly_collection = axes.fill_between(data.index.values, data["Minimum"].values, data["Maximum"].values, alpha=line_alpha, color=line_color) + + rectangle = Rectangle((0, 0), 1, 1, color=line_color) # creates rectangle patch for legend use. + + plot_config.addLegendItem(ensemble_label, rectangle) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/plot_tools.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/plot_tools.py new file mode 100644 index 0000000000..1e8a4a09e3 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/plot_tools.py @@ -0,0 +1,48 @@ +class PlotTools(object): + @staticmethod + def showGrid(axes, plot_context): + config = plot_context.plotConfig() + if config.isGridEnabled(): + axes.grid() + + + @staticmethod + def showLegend(axes, plot_context): + config = plot_context.plotConfig() + if config.isLegendEnabled() and len(config.legendItems()) > 0: + axes.legend(config.legendItems(), config.legendLabels()) + + + @staticmethod + def finalizePlot(plot_context, axes, default_x_label="Unnamed", default_y_label="Unnamed"): + PlotTools.showLegend(axes, plot_context) + PlotTools.showGrid(axes, plot_context) + + PlotTools.__setupLabels(plot_context, default_x_label, default_y_label) + + plot_config = plot_context.plotConfig() + axes.set_xlabel(plot_config.xLabel()) + axes.set_ylabel(plot_config.yLabel()) + + axes.set_title(plot_config.title()) + + if plot_config.isDateSupportActive(): + plot_context.figure().autofmt_xdate() + + + @staticmethod + def __setupLabels(plot_context, default_x_label, default_y_label): + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + + if config.xLabel() is None: + config.setXLabel(default_x_label) + + if config.yLabel() is None: + config.setYLabel(default_y_label) + + if ert.eclConfig().hasRefcase() and key in ert.eclConfig().getRefcase(): + unit = ert.eclConfig().getRefcase().unit(key) + if unit != "": + config.setYLabel(unit) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/refcase.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/refcase.py new file mode 100644 index 0000000000..bab0d828b9 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/refcase.py @@ -0,0 +1,30 @@ +def plotRefcase(plot_context, axes): + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + data_gatherer = plot_context.dataGatherer() + + if config.isRefcaseEnabled() and data_gatherer.hasRefcaseGatherFunction(): + refcase_data = data_gatherer.gatherRefcaseData(ert, key) + + if not refcase_data.empty: + _plotRefcase(axes, config, refcase_data) + + +def _plotRefcase(axes, plot_config, data): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + """ + + line_color = plot_config.refcaseColor() + line_alpha = plot_config.refcaseAlpha() + line_marker = plot_config.refcaseMarker() + line_style = plot_config.refcaseStyle() + line_width = plot_config.refcaseWidth() + + lines = axes.plot_date(x=data.index.values, y=data, color=line_color, alpha=line_alpha, marker=line_marker, linestyle=line_style, linewidth=line_width) + + if len(lines) > 0: + plot_config.addLegendItem("Refcase", lines[0]) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/statistics.py b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/statistics.py new file mode 100644 index 0000000000..72e08c36f7 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/plottery/plots/statistics.py @@ -0,0 +1,71 @@ +from matplotlib.patches import Rectangle +from pandas import DataFrame +from .refcase import plotRefcase +from .observations import plotObservations +from .plot_tools import PlotTools + + +def plotStatistics(plot_context): + """ + @type plot_context: PlotContext + """ + ert = plot_context.ert() + key = plot_context.key() + config = plot_context.plotConfig() + axes = plot_context.figure().add_subplot(111) + """:type: matplotlib.axes.Axes """ + + case_list = plot_context.cases() + for case in case_list: + data = plot_context.dataGatherer().gatherData(ert, case, key) + if not data.empty: + if not data.index.is_all_dates: + config.deactiveDateSupport() + + statistics_data = DataFrame() + + statistics_data["Minimum"] = data.min(axis=1) + statistics_data["Maximum"] = data.max(axis=1) + statistics_data["Mean"] = data.mean(axis=1) + statistics_data["p10"] = data.quantile(0.1, axis=1) + statistics_data["p33"] = data.quantile(0.33, axis=1) + statistics_data["p50"] = data.quantile(0.50, axis=1) + statistics_data["p67"] = data.quantile(0.67, axis=1) + statistics_data["p90"] = data.quantile(0.90, axis=1) + + _plotPercentiles(axes, config, statistics_data, case) + config.nextColor() + + plotRefcase(plot_context, axes) + plotObservations(plot_context, axes) + + default_x_label = "Date" if config.isDateSupportActive() else "Index" + PlotTools.finalizePlot(plot_context, axes, default_x_label=default_x_label, default_y_label="Value") + + +def _plotPercentiles(axes, plot_config, data, ensemble_label): + """ + @type axes: matplotlib.axes.Axes + @type plot_config: PlotConfig + @type data: DataFrame + @type ensemble_label: Str + """ + + line_color = plot_config.lineColor() + line_alpha = plot_config.lineAlpha() + + minimum_line = axes.plot(data.index.values, data["Minimum"].values, alpha=line_alpha, linestyle="--", color=line_color) + maximum_line = axes.plot(data.index.values, data["Maximum"].values, alpha=line_alpha, linestyle="--", color=line_color) + p50_line = axes.plot(data.index.values, data["p50"].values, alpha=line_alpha, linestyle="--", color=line_color, marker="x") + mean_line = axes.plot(data.index.values, data["Mean"].values, alpha=line_alpha, linestyle="-", color=line_color, marker="") + axes.fill_between(data.index.values, data["p10"].values, data["p90"].values, alpha=line_alpha * 0.3, color=line_color) + axes.fill_between(data.index.values, data["p33"].values, data["p67"].values, alpha=line_alpha * 0.5, color=line_color) + + rectangle_p10_p90 = Rectangle((0, 0), 1, 1, color=line_color, alpha=line_alpha * 0.3) # creates rectangle patch for legend use. + rectangle_p33_p67 = Rectangle((0, 0), 1, 1, color=line_color, alpha=line_alpha * 0.5) # creates rectangle patch for legend use. + + plot_config.addLegendItem("Minimum/Maximum", minimum_line[0]) + plot_config.addLegendItem("P50", p50_line[0]) + plot_config.addLegendItem("Mean", mean_line[0]) + plot_config.addLegendItem("P10-P90", rectangle_p10_p90) + plot_config.addLegendItem("P33-P67", rectangle_p33_p67) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/shell/debug.py b/ThirdParty/Ert/devel/python/python/ert_gui/shell/debug.py index 54eee75d37..2ad45b402a 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/shell/debug.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/shell/debug.py @@ -1,9 +1,15 @@ +from ert import Version from ert_gui.shell import ShellFunction, assertConfigLoaded class Debug(ShellFunction): def __init__(self, shell_context): super(Debug, self).__init__("debug", shell_context) + self.addHelpFunction("site_config", None, "Show the path to the current site_config") + self.addHelpFunction("version", None, "Show the internalized ert version number") + self.addHelpFunction("timestamp", None, "Show the build timestamp") + self.addHelpFunction("git_commit", None, "Show the git commit") + self.addHelpFunction("info", None, "Shows site_config, version, timestamp and Git Commit") self.addHelpFunction("last_plugin_result", None, "Shows the last plugin result.") self.addHelpFunction("eval", "", "Evaluate a Python expression. " "The last plugin result is defined as: x") @@ -16,6 +22,26 @@ class Debug(ShellFunction): def setLastPluginResult(self, result): self.__last_plugin_result = result + @assertConfigLoaded + def do_site_config(self, line): + print("Site Config: %s" % self.ert().siteConfig().getLocation()) + + def do_version(self, line): + print("Version: %s" % Version.getVersion()) + + def do_timestamp(self, line): + print("Timestamp: %s" % Version.getBuildTime()) + + def do_git_commit(self, line): + print("Git Commit: %s" % Version.getGitCommit(True)) + + @assertConfigLoaded + def do_info(self, line): + print("Site Config: %s" % self.ert().siteConfig().getLocation()) + print("Version: %s" % Version.getVersion()) + print("Timestamp: %s" % Version.getBuildTime()) + print("Git Commit: %s" % Version.getGitCommit(True)) + def do_last_plugin_result(self, line): print("Last plugin result: %s" % self.__last_plugin_result) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/shell/shell_plot.py b/ThirdParty/Ert/devel/python/python/ert_gui/shell/shell_plot.py index 3293ce7c05..9f0ef96cca 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/shell/shell_plot.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/shell/shell_plot.py @@ -16,6 +16,7 @@ class ShellPlot(object): def __init__(self, name): super(ShellPlot, self).__init__() clist = plt.rcParams['axes.color_cycle'] + clist = ["#386CB0", "#7FC97F", "#FDC086", "#F0027F", "#BF5B17"] self.__color_cycle = itertools.cycle(clist) self.figure = plt.figure() diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/tools/CMakeLists.txt index b321023f01..80bcd31456 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/CMakeLists.txt @@ -4,7 +4,7 @@ set(PYTHON_SOURCES tool.py ) -add_python_package("python.ert_gui.tools" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools "${PYTHON_SOURCES}" True) +add_python_package("python.ert_gui.tools" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools "${PYTHON_SOURCES}" True) add_subdirectory(export) add_subdirectory(help) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/CMakeLists.txt index 55d30a0e4d..c8593cf313 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/CMakeLists.txt @@ -5,21 +5,13 @@ set(PYTHON_SOURCES data_type_keys_list_model.py data_type_keys_widget.py data_type_proxy_model.py - export_plot.py filter_popup.py - plot_bridge.py plot_case_model.py plot_case_selection_widget.py - plot_metrics_tracker.py - plot_panel.py - plot_panel_tracker.py - plot_scale_widget.py plot_tool.py - plot_tool_bar.py + plot_widget.py plot_window.py - report_step_widget.py ) -add_python_package("python.ert_gui.tools.plot" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot "${PYTHON_SOURCES}" True) +add_python_package("python.ert_gui.tools.plot" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot "${PYTHON_SOURCES}" True) -add_subdirectory(data) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/__init__.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/__init__.py index b31e60ab3e..18b18ef513 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/__init__.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/__init__.py @@ -1,7 +1,6 @@ -from .plot_bridge import PlotBridge -from .export_plot import ExportPlot -from .filter_popup import FilterPopup +from .plot_widget import PlotWidget +from .filter_popup import FilterPopup from .data_type_keys_list_model import DataTypeKeysListModel from .data_type_proxy_model import DataTypeProxyModel @@ -9,19 +8,12 @@ from .data_type_keys_widget import DataTypeKeysWidget from .plot_case_model import PlotCaseModel from .plot_case_selection_widget import CaseSelectionWidget -from .report_step_widget import ReportStepWidget -from .plot_scale_widget import PlotScalesWidget - -from .plot_tool_bar import PlotToolBar from .color_chooser import ColorChooser from .customize_plot_widget import CustomizePlotWidget -from .plot_panel_tracker import PlotPanelTracker -from .plot_metrics_tracker import PlotMetricsTracker - -from .plot_panel import PlotPanel from .plot_window import PlotWindow from .plot_tool import PlotTool + diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/customize_plot_widget.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/customize_plot_widget.py index 4dae2928ed..e68e2bf89e 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/customize_plot_widget.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/customize_plot_widget.py @@ -5,34 +5,36 @@ from ert_gui.tools.plot import ColorChooser class CustomizePlotWidget(QWidget): - customPlotSettingsChanged = pyqtSignal(dict) + customPlotSettingsChanged = pyqtSignal() def __init__(self): QWidget.__init__(self) self.__custom = { } self.__layout = QVBoxLayout() - self.addCheckBox("error_bar_only", "Show only error bars", False) + self.addCheckBox("show_observations", "Show observations", True) self.addCheckBox("show_refcase", "Show refcase", True) + self.addCheckBox("show_legend", "Show legend", True) + self.addCheckBox("show_grid", "Show grid", True) self.__layout.addSpacing(20) - self.addColorChooser("observation", "Observation", QColor(0, 0, 0, 255)) - self.addColorChooser("observation_area", "Observation Error", QColor(0, 0, 0, 38)) - self.addColorChooser("observation_error_bar", "Observation Error Bar", QColor(0, 0, 0, 255)) - self.addColorChooser("refcase", "Refcase", QColor(0, 0, 0, 178)) - self.addColorChooser("ensemble_1", "Case #1", QColor(56, 108, 176, 204)) - self.addColorChooser("ensemble_2", "Case #2", QColor(127, 201, 127, 204)) - self.addColorChooser("ensemble_3", "Case #3", QColor(253, 192, 134, 204)) - self.addColorChooser("ensemble_4", "Case #4", QColor(240, 2, 127, 204)) - self.addColorChooser("ensemble_5", "Case #5", QColor(191, 91, 23, 204)) + # self.addColorChooser("observation", "Observation", QColor(0, 0, 0, 255)) + # self.addColorChooser("observation_area", "Observation Error", QColor(0, 0, 0, 38)) + # self.addColorChooser("observation_error_bar", "Observation Error Bar", QColor(0, 0, 0, 255)) + # self.addColorChooser("refcase", "Refcase", QColor(0, 0, 0, 178)) + # self.addColorChooser("ensemble_1", "Case #1", QColor(56, 108, 176, 204)) + # self.addColorChooser("ensemble_2", "Case #2", QColor(127, 201, 127, 204)) + # self.addColorChooser("ensemble_3", "Case #3", QColor(253, 192, 134, 204)) + # self.addColorChooser("ensemble_4", "Case #4", QColor(240, 2, 127, 204)) + # self.addColorChooser("ensemble_5", "Case #5", QColor(191, 91, 23, 204)) self.__layout.addStretch() self.setLayout(self.__layout) def emitChange(self): - self.customPlotSettingsChanged.emit(self.__custom) + self.customPlotSettingsChanged.emit() def addCheckBox(self, name, description, default_value): checkbox = QCheckBox(description) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/CMakeLists.txt b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/CMakeLists.txt deleted file mode 100644 index 46c21eebf6..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ensemble_plot_data.py - histogram_plot_data.py - histogram_plot_data_factory.py - observation_plot_data.py - plot_data.py - plot_data_fetcher.py - refcase_plot_data.py -) - -add_python_package("python.ert_gui.tools.plot.data" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot/data "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/__init__.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/__init__.py deleted file mode 100644 index e5778b3bd6..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .histogram_plot_data import CaseHistogramPlotData, HistogramPlotData -from .histogram_plot_data_factory import HistogramPlotDataFactory, ReportStepLessHistogramPlotDataFactory -from .observation_plot_data import ObservationPlotData -from .refcase_plot_data import RefcasePlotData -from .ensemble_plot_data import EnsemblePlotData -from .plot_data import PlotData -from .plot_data_fetcher import PlotDataFetcher \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/ensemble_plot_data.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/ensemble_plot_data.py deleted file mode 100644 index 1f909d6c22..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/ensemble_plot_data.py +++ /dev/null @@ -1,143 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSlot, QString -import math - - -class EnsemblePlotData(QObject): - def __init__(self, name, case_name, parent=None): - QObject.__init__(self, parent) - - self.__name = name - self.__case_name = case_name - - self.__x_values = None - self.__y_values = None - self.__y_min_values = None - self.__y_max_values = None - - self.__has_data = False - - self.__min_x = None - self.__max_x = None - self.__min_y = None - self.__max_y = None - - - - def setEnsembleData(self, x_values, y_values, y_min_values, y_max_values): - if x_values is not None and y_values is not None and y_min_values is not None and y_max_values is not None: - self.__x_values = x_values - self.__y_values = y_values - - self.__y_min_values = y_min_values - self.__y_max_values = y_max_values - - self.__has_data = True - - - def updateBoundaries(self, min_x, max_x, min_y, max_y): - if min_x is not None and (self.__min_x is None or self.__min_x > min_x): - self.__min_x = min_x - - if max_x is not None and (self.__max_x is None or self.__max_x < max_x): - self.__max_x = max_x - - if min_y is not None and (self.__min_y is None or self.__min_y > min_y): - self.__min_y = min_y - - if max_y is not None and (self.__max_y is None or self.__max_y < max_y): - self.__max_y = max_y - - - - @pyqtSlot(result=str) - def name(self): - return self.__name - - @pyqtSlot(result=str) - def caseName(self): - return self.__case_name - - @pyqtSlot(result="QVariantList") - def xValues(self): - return self.__x_values - - @pyqtSlot(result="QVariantList") - def yValues(self): - return self.__y_values - - @pyqtSlot(result="QVariantList") - def yMinValues(self): - return self.__y_min_values - - @pyqtSlot(result="QVariantList") - def yMaxValues(self): - return self.__y_max_values - - @pyqtSlot(QString, result=int) - def realizationCount(self): - return len(self.__y_values) - - @pyqtSlot(result=float) - def minX(self): - return self.__min_x - - @pyqtSlot(result=float) - def maxX(self): - return self.__max_x - - @pyqtSlot(result=float) - def minY(self): - return self.__min_y - - @pyqtSlot(result=float) - def maxY(self): - return self.__max_y - - @pyqtSlot(result=bool) - def isValid(self): - return self.hasBoundaries() and self.hasData() - - @pyqtSlot(result=bool) - def hasBoundaries(self): - return self.__min_x is not None and self.__max_x is not None and self.__min_y is not None and self.__max_y is not None - - @pyqtSlot(result=bool) - def hasData(self): - return self.__has_data - - - - @pyqtSlot(float, result="QVariantList") - def xPercentile(self, percentile): - values = [] - transposed_data = map(list, map(None, *self.__y_values)) - for row in transposed_data: - row = sorted(row) - values.append(self.percentile(row, percentile)) - - return values - - - def percentile(self, N, percent, key=lambda x:x): - """ - Find the percentile of a list of values. - - @parameter N - is a list of values. Note N MUST BE already sorted. - @parameter percent - a float value from 0.0 to 1.0. - @parameter key - optional key function to compute value from each element of N. - - @return - the percentile of the values - """ - if not N: - return None - k = (len(N) - 1) * percent - f = math.floor(k) - c = math.ceil(k) - - if f == c: - return key(N[int(k)]) - - d0 = key(N[int(f)]) * (c - k) - d1 = key(N[int(c)]) * (k - f) - - return d0 + d1 \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data.py deleted file mode 100644 index 759c058e65..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data.py +++ /dev/null @@ -1,167 +0,0 @@ -from math import ceil, sqrt -from PyQt4.QtCore import QObject, pyqtSlot, QString - - -class CaseHistogramPlotData(QObject): - def __init__(self, case_name, report_step_time, parent=None): - QObject.__init__(self, parent) - - self.__case_name = case_name - self.__report_step_time = report_step_time - - self.__min = None - self.__max = None - - self.__samples = [] - - - def addSample(self, sample): - self.__samples.append(sample) - - if self.__min is None or self.__min > sample: - self.__min = sample - - if self.__max is None or self.__max < sample: - self.__max = sample - - def __len__(self): - return len(self.__samples) - - - @pyqtSlot(result=float) - def min(self): - return self.__min - - - @pyqtSlot(result=float) - def max(self): - return self.__max - - - @pyqtSlot(result="QVariantList") - def samples(self): - return self.__samples - - -class HistogramPlotData(QObject): - def __init__(self, name, report_step_time, parent=None): - QObject.__init__(self, parent) - - self.__name = name - self.__report_step_time = report_step_time - - self.__min = None - self.__max = None - - self.__case_list = [] - self.__case_histograms = {} - - self.__observation = None - self.__observation_error = None - self.__refcase = None - - - def addCase(self, case_name): - if not case_name in self.__case_histograms: - self.__case_histograms[case_name] = CaseHistogramPlotData(case_name, self.__report_step_time, parent=self) - self.__case_list.append(case_name) - - - def addSample(self, case_name, sample): - self.addCase(case_name) - - self.__case_histograms[case_name].addSample(sample) - - if self.__min is None or self.__min > sample: - self.__min = sample - - if self.__max is None or self.__max < sample: - self.__max = sample - - - def setRefcase(self, value): - self.__refcase = value - - if self.__min is None or self.__min > value: - self.__min = value - - if self.__max is None or self.__max < value: - self.__max = value - - def setObservation(self, value, error): - self.__observation = value - self.__observation_error = error - - if value >= 0: - error_value = max(0, value - error) - else: - error_value = value - error - - if self.__min is None or self.__min > error_value: - self.__min = error_value - - if self.__max is None or self.__max < value + error: - self.__max = value + error - - - @pyqtSlot(result=str) - def name(self): - return self.__name - - - @pyqtSlot(result=bool) - def hasRefcase(self): - return self.__refcase is not None - - @pyqtSlot(result=bool) - def hasObservation(self): - return self.__observation is not None - - @pyqtSlot(result=float) - def refcase(self): - return self.__refcase - - @pyqtSlot(result=float) - def observation(self): - return self.__observation - - @pyqtSlot(result=float) - def observationError(self): - return self.__observation_error - - @pyqtSlot(QString, result=bool) - def hasCaseHistogram(self, case_name): - return str(case_name) in self.__case_histograms - - @pyqtSlot(QString, result=QObject) - def caseHistogram(self, case_name): - return self.__case_histograms[str(case_name)] - - @pyqtSlot(result=float) - def min(self): - return self.__min - - @pyqtSlot(result=float) - def max(self): - return self.__max - - @pyqtSlot(result=int) - def reportStepTime(self): - return self.__report_step_time - - @pyqtSlot(result=int) - def maxCount(self): - max_sample_count = 0 - for histogram in self.__case_histograms.values(): - max_sample_count = max(max_sample_count, len(histogram)) - - return max_sample_count - - @pyqtSlot(QString, result=bool) - def isValid(self, case_name): - return self.hasObservation() or self.hasRefcase() or self.hasCaseHistogram(case_name) - - @pyqtSlot(result=int) - def numberOfBins(self): - return ceil(sqrt(self.maxCount())) - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data_factory.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data_factory.py deleted file mode 100644 index 5a942bee59..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/histogram_plot_data_factory.py +++ /dev/null @@ -1,149 +0,0 @@ -from ert_gui.tools.plot.data import HistogramPlotData - - -class HistogramPlotDataFactory(object): - def __init__(self, name): - super(HistogramPlotDataFactory, self).__init__() - self.__name = name - - self.__observations = None - self.__refcase = None - self.__case_names = [] - self.__ensemble_data = {} - - def setObservations(self, x_values, y_values, std_values, min_y, max_y): - if x_values is not None: - self.__observations = {"x_values": x_values, - "y_values": y_values, - "std_values": std_values, - "min_y": min_y, - "max_y": max_y, - "reverse_lookup": {}} - - rl = self.__observations["reverse_lookup"] - - for index in range(len(x_values)): - x = x_values[index] - rl[x] = index - - - def hasObservationSample(self, x_value): - return x_value in self.__observations["reverse_lookup"] - - - def setRefcase(self, x_values, y_values, min_y, max_y): - if x_values is not None and y_values is not None: - self.__refcase = {"x_values": x_values, - "y_values": y_values, - "min_y": min_y, - "max_y": max_y, - "reverse_lookup": {}} - - rl = self.__refcase["reverse_lookup"] - - for index in range(len(x_values)): - x = x_values[index] - rl[x] = index - - - def hasRefcaseSample(self, x_value): - return x_value in self.__refcase["reverse_lookup"] - - def addEnsembleData(self, case_name, x_values, y_values, min_y, max_y): - self.__case_names.append(case_name) - - ensemble_data = {"x_values": x_values, - "y_values": y_values, - "min_y": min_y, - "max_y": max_y, - "reverse_lookup": {}} - - rl = ensemble_data["reverse_lookup"] - - for index in range(len(x_values)): - x = x_values[index] - rl[x] = index - - self.__ensemble_data[case_name] = ensemble_data - - def hasEnsembleSample(self, case_name, x_value): - ensemble_data = self.__ensemble_data[case_name] - return x_value in ensemble_data["reverse_lookup"] - - def hasEnsembleData(self): - return len(self.__case_names) > 0 - - def hasObservations(self): - """ @rtype: bool """ - return self.__observations is not None - - def hasRefcaseData(self): - """ @rtype: bool """ - return self.__refcase is not None - - def hasRefcase(self): - """ @rtype: bool """ - return self.__refcase is not None - - - def observationIndex(self, x_value): - return self.__observations["reverse_lookup"][x_value] - - def refcaseIndex(self, x_value): - return self.__refcase["reverse_lookup"][x_value] - - def ensembleIndex(self, case_name, x_value): - ensemble = self.__ensemble_data[case_name] - return ensemble["reverse_lookup"][x_value] - - def ensembleData(self, case_name): - """ @rtype: EnsemblePlotData """ - return self.__ensemble_data[case_name] - - def getEnsembleSamples(self, case_name, x_value): - """ @rtype: list of float """ - index = self.ensembleIndex(case_name, x_value) - ensemble = self.ensembleData(case_name) - result = [] - for realization in ensemble["y_values"]: - if len(realization) > 0 and index < len(realization): - result.append(realization[index]) - - return result - - - def getHistogramData(self, x_value): - """ @rtype: HistogramPlotData """ - histogram_data = HistogramPlotData(self.__name, x_value) - - if self.hasObservations(): - if self.hasObservationSample(x_value): - index = self.observationIndex(x_value) - value = self.__observations["y_values"][index] - std = self.__observations["std_values"][index] - histogram_data.setObservation(value, std) - - if self.hasRefcase(): - if self.hasRefcaseSample(x_value): - index = self.refcaseIndex(x_value) - value = self.__refcase["y_values"][index] - histogram_data.setRefcase(value) - - for case_name in self.__case_names: - histogram_data.addCase(case_name) - - if self.hasEnsembleSample(case_name, x_value): - for sample in self.getEnsembleSamples(case_name, x_value): - histogram_data.addSample(case_name, sample) - - return histogram_data - - -class ReportStepLessHistogramPlotDataFactory(HistogramPlotDataFactory): - def __init__(self, name): - super(ReportStepLessHistogramPlotDataFactory, self).__init__(name) - - def getHistogramData(self, x_value): - return super(ReportStepLessHistogramPlotDataFactory, self).getHistogramData(0) - - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/observation_plot_data.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/observation_plot_data.py deleted file mode 100644 index 37fc4685e9..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/observation_plot_data.py +++ /dev/null @@ -1,91 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSlot - - -class ObservationPlotData(QObject): - def __init__(self, name, parent=None): - QObject.__init__(self, parent) - - self.__name = name - self.__x_values = [] - self.__y_values = [] - self.__std_values = [] - self.__is_continuous = True - self.__has_data = False - - self.__min_x = None - self.__max_x = None - self.__min_y = None - self.__max_y = None - - - def setObservationData(self, x_values, y_values, std_values, continuous): - if x_values is not None and y_values is not None and std_values is not None: - self.__x_values = x_values - self.__y_values = y_values - self.__std_values = std_values - self.__is_continuous = continuous - self.__has_data = True - - - def updateBoundaries(self, min_x, max_x, min_y, max_y): - if min_x is not None and (self.__min_x is None or self.__min_x > min_x): - self.__min_x = min_x - - if max_x is not None and (self.__max_x is None or self.__max_x < max_x): - self.__max_x = max_x - - if min_y is not None and (self.__min_y is None or self.__min_y > min_y): - self.__min_y = min_y - - if max_y is not None and (self.__max_y is None or self.__max_y < max_y): - self.__max_y = max_y - - - - @pyqtSlot(result=str) - def name(self): - return self.__name - - @pyqtSlot(result="QVariantList") - def xValues(self): - return self.__x_values - - @pyqtSlot(result="QVariantList") - def yValues(self): - return self.__y_values - - @pyqtSlot(result="QVariantList") - def stdValues(self): - return self.__std_values - - @pyqtSlot(result=bool) - def isContinuous(self): - return self.__is_continuous - - @pyqtSlot(result=float) - def minX(self): - return self.__min_x - - @pyqtSlot(result=float) - def maxX(self): - return self.__max_x - - @pyqtSlot(result=float) - def minY(self): - return self.__min_y - - @pyqtSlot(result=float) - def maxY(self): - return self.__max_y - - @pyqtSlot(result=bool) - def isValid(self): - return self.hasBoundaries() and self.hasData() - - @pyqtSlot(result=bool) - def hasBoundaries(self): - return self.__min_x is not None and self.__max_x is not None and self.__min_y is not None and self.__max_y is not None - - @pyqtSlot(result=bool) - def hasData(self): - return self.__has_data diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data.py deleted file mode 100644 index 09c25c9168..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data.py +++ /dev/null @@ -1,195 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSlot, QString -from ert_gui.tools.plot.data import HistogramPlotDataFactory, HistogramPlotData, ObservationPlotData, RefcasePlotData, EnsemblePlotData - - -class PlotData(QObject): - def __init__(self, name, parent=None): - QObject.__init__(self, parent) - - self.__name = name - - #: :type: ObservationPlotData - self.__observation_data = None - #: :type: RefcasePlotData - self.__refcase_data = None - #: :type: EnsemblePlotData - self.__ensemble_data = {} - - self.__user_data = {} - - #: :type: HistogramPlotDataFactory - self.__histogram_factory = None - - self.__unit_x = "Unknown" - self.__unit_y = "Unknown" - - self.__min_x = None - self.__max_x = None - self.__min_y = None - self.__max_y = None - - self.__use_log_scale = False - - self.__case_list = [] - - - def setObservationData(self, observation_data): - if observation_data.isValid(): - observation_data.setParent(self) - self.__observation_data = observation_data - self.updateBoundaries(observation_data.minX(), observation_data.maxX(), observation_data.minY(), observation_data.maxY()) - - - def setRefcaseData(self, refcase_data): - refcase_data.setParent(self) - self.__refcase_data = refcase_data - self.updateBoundaries(refcase_data.minX(), refcase_data.maxX(), refcase_data.minY(), refcase_data.maxY()) - - def setHistogramFactory(self, histogram_factory): - assert isinstance(histogram_factory, HistogramPlotDataFactory) - self.__histogram_factory = histogram_factory - - def setUnitX(self, unit): - self.__unit_x = unit - - def setUnitY(self, unit): - self.__unit_y = unit - - def addEnsembleData(self, ensemble_data): - if ensemble_data.isValid(): - ensemble_data.setParent(self) - case_name = ensemble_data.caseName() - self.__case_list.append(case_name) - self.__ensemble_data[case_name] = ensemble_data - self.updateBoundaries(ensemble_data.minX(), ensemble_data.maxX(), ensemble_data.minY(), ensemble_data.maxY()) - - def setUserData(self, name, data): - data.setParent(self) - self.__user_data[name] = data - - def updateBoundaries(self, min_x, max_x, min_y, max_y): - if min_x is not None and (self.__min_x is None or self.__min_x > min_x): - self.__min_x = min_x - - if max_x is not None and (self.__max_x is None or self.__max_x < max_x): - self.__max_x = max_x - - if min_y is not None and (self.__min_y is None or self.__min_y > min_y): - self.__min_y = min_y - - if max_y is not None and (self.__max_y is None or self.__max_y < max_y): - self.__max_y = max_y - - def setShouldUseLogScale(self, use_log_scale): - self.__use_log_scale = use_log_scale - - @pyqtSlot(result=str) - def name(self): - """ @rtype: str """ - return self.__name - - @pyqtSlot(result=str) - def unitX(self): - """ @rtype: str """ - return self.__unit_x - - @pyqtSlot(result=str) - def unitY(self): - """ @rtype: str """ - return self.__unit_y - - @pyqtSlot(result=QObject) - def observationData(self): - """ @rtype: ObservationPlotData """ - return self.__observation_data - - @pyqtSlot(result=bool) - def hasObservationData(self): - """ @rtype: bool """ - return self.__observation_data is not None and self.__observation_data.isValid() - - @pyqtSlot(result=QObject) - def refcaseData(self): - """ @rtype: RefcasePlotData """ - return self.__refcase_data - - @pyqtSlot(result=bool) - def hasRefcaseData(self): - """ @rtype: bool """ - return self.__refcase_data is not None and self.__refcase_data.isValid() - - @pyqtSlot(QString, result=QObject) - def ensembleData(self, case_name): - """ @rtype: EnsemblePlotData """ - return self.__ensemble_data[str(case_name)] - - @pyqtSlot(result=bool) - def hasEnsembleData(self): - """ @rtype: bool """ - return len(self.__ensemble_data.keys()) > 0 - - @pyqtSlot(QString, result=bool) - def hasEnsembleDataForCase(self, case_name): - """ @rtype: bool """ - return str(case_name) in self.__ensemble_data - - @pyqtSlot(QString, result=bool) - def hasUserData(self, name): - """ @rtype: bool """ - return str(name) in self.__user_data - - @pyqtSlot(QString, result=int) - def realizationCount(self, case): - """ @rtype: int """ - return self.__ensemble_data[str(case)].realizationCount() - - @pyqtSlot(result=bool) - def hasHistogram(self): - """ @rtype: bool """ - return self.__histogram_factory is not None - - @pyqtSlot(result=float) - def minX(self): - return self.__min_x - - @pyqtSlot(result=float) - def maxX(self): - return self.__max_x - - @pyqtSlot(result=float) - def minY(self): - return self.__min_y - - @pyqtSlot(result=float) - def maxY(self): - return self.__max_y - - @pyqtSlot(result=bool) - def isValid(self): - return self.hasBoundaries() and (self.hasObservationData() or self.hasRefcaseData() or self.hasEnsembleData() or self.hasHistogram()) - - @pyqtSlot(result=bool) - def hasBoundaries(self): - return self.__min_x is not None and self.__max_x is not None and self.__min_y is not None and self.__max_y is not None - - @pyqtSlot(result="QStringList") - def caseList(self): - return self.__case_list - - @pyqtSlot(result=bool) - def shouldUseLogScale(self): - return self.__use_log_scale - - @pyqtSlot(int, result=QObject) - def histogramData(self, report_step_time): - if self.__histogram_factory is not None: - data = self.__histogram_factory.getHistogramData(report_step_time) - data.setParent(self) - - return data - return None - - @pyqtSlot("QString", result=QObject) - def getUserData(self, name): - return self.__user_data[str(name)] - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data_fetcher.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data_fetcher.py deleted file mode 100644 index d0be283efd..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/plot_data_fetcher.py +++ /dev/null @@ -1,232 +0,0 @@ -from ert.enkf.plot import EnsembleDataFetcher, ObservationDataFetcher, RefcaseDataFetcher, BlockObservationDataFetcher, EnsembleGenKWFetcher, EnsembleGenDataFetcher, ObservationGenDataFetcher -from ert.enkf.plot import EnsembleBlockDataFetcher, PcaDataFetcher -from ert_gui.models.connectors.plot import DataTypeKeysModel -from ert_gui.tools.plot.data import PlotData, ObservationPlotData, EnsemblePlotData, RefcasePlotData, HistogramPlotDataFactory, ReportStepLessHistogramPlotDataFactory -from ert_gui.models import ErtConnector - - -class PlotDataFetcher(ErtConnector): - - def getPlotDataForKeyAndCases(self, key, cases): - observation_data_fetcher = ObservationDataFetcher(self.ert()) - block_observation_data_fetcher = BlockObservationDataFetcher(self.ert()) - gen_kw_fetcher = EnsembleGenKWFetcher(self.ert()) - gen_data_fetcher = EnsembleGenDataFetcher(self.ert()) - - if self.isBlockObservationKey(key): - return self.fetchBlockObservationData(block_observation_data_fetcher, key, cases) - - elif self.isSummaryKey(key): - return self.fetchSummaryData(observation_data_fetcher, key, cases) - - elif self.isGenKWKey(key): - return self.fetchGenKWData(gen_kw_fetcher, key, cases) - - elif self.isGenDataKey(key): - return self.fetchGenData(gen_data_fetcher, key, cases) - - elif self.isPcaDataKey(key): - plot_data = PlotData(key) - pca_plot_data = self.fetchPcaData(key, cases) - plot_data.setUserData("PCA", pca_plot_data) - return plot_data - - else: - raise NotImplementedError("Key %s not supported." % key) - - - def isSummaryKey(self, key): - ensemble_data_fetcher = ObservationDataFetcher(self.ert()) - return ensemble_data_fetcher.supportsKey(key) - - - def isBlockObservationKey(self, key): - block_observation_data_fetcher = BlockObservationDataFetcher(self.ert()) - return block_observation_data_fetcher.supportsKey(key) - - - def isGenKWKey(self, key): - gen_kw_fetcher = EnsembleGenKWFetcher(self.ert()) - return gen_kw_fetcher.supportsKey(key) - - - def isGenDataKey(self, key): - obs_gen_data_fetcher = ObservationGenDataFetcher(self.ert()) - return obs_gen_data_fetcher.supportsKey(key) - - - def isPcaDataKey(self, key): - pca_data_fetcher = PcaDataFetcher(self.ert()) - return pca_data_fetcher.supportsKey(key) or DataTypeKeysModel().isCustomPcaKey(key) - - def isCustomPcaDataKey(self, key): - return DataTypeKeysModel().isCustomPcaKey(key) - - def dataTypeKeySupportsReportSteps(self, key): - return self.isSummaryKey(key) - - def fetchGenData(self, gen_data_fetcher, key, cases): - plot_data = PlotData(key) - - gen_data_observation_fetcher = ObservationGenDataFetcher(self.ert()) - - if gen_data_observation_fetcher.hasData(key): - self.addObservationData(plot_data, key, gen_data_observation_fetcher) - self.addEnsembleData(plot_data, key, cases, gen_data_fetcher) - self.addPcaData(plot_data, key, cases) - - return plot_data - - - def fetchGenKWData(self, gen_kw_fetcher, key, cases): - plot_data = PlotData(key) - - histogram_factory = ReportStepLessHistogramPlotDataFactory(key) - self.addEnsembleData(plot_data, key, cases, gen_kw_fetcher, histogram_factory) - plot_data.setHistogramFactory(histogram_factory) - - return plot_data - - - def fetchBlockObservationData(self, block_observation_data_fetcher, key, cases): - plot_data = PlotData(key) - - plot_data.setUnitY(self.ert().eclConfig().getDepthUnit()) - plot_data.setUnitX(self.ert().eclConfig().getPressureUnit()) - - if block_observation_data_fetcher.hasData(key): - block_observation_data_fetcher.setSelectedReportStepIndex(0) - self.addObservationData(plot_data, key, block_observation_data_fetcher) - - ensemble_block_data_fetcher = EnsembleBlockDataFetcher(self.ert()) - ensemble_block_data_fetcher.setSelectedReportStepIndex(0) - self.addEnsembleData(plot_data, key, cases, ensemble_block_data_fetcher) - - self.addPcaData(plot_data, key, cases) - - return plot_data - - - def fetchSummaryData(self, observation_data_fetcher, key, cases): - plot_data = PlotData(key) - - histogram_factory = HistogramPlotDataFactory(key) - refcase_fetcher = RefcaseDataFetcher(self.ert()) - - self.addObservationData(plot_data, key, observation_data_fetcher, histogram_factory) - - self.addRefcaseData(plot_data, key, refcase_fetcher, histogram_factory) - - self.addEnsembleData(plot_data, key, cases, EnsembleDataFetcher(self.ert()), histogram_factory) - - self.addPcaData(plot_data, key, cases) - - if refcase_fetcher.hasRefcase(): - unit = refcase_fetcher.getRefCase().unit(key) - if unit != "": - plot_data.setUnitY(unit) - - plot_data.setHistogramFactory(histogram_factory) - - return plot_data - - - def addEnsembleData(self, plot_data, key, cases, fetcher, histogram_factory=None): - for case in cases: - ensemble_data = fetcher.fetchData(key, case) - - if "use_log_scale" in ensemble_data: - plot_data.setShouldUseLogScale(ensemble_data["use_log_scale"]) - - if len(ensemble_data) > 0: - ensemble_plot_data = EnsemblePlotData(key, case) - - if "min_y_values" in ensemble_data: - min_values = ensemble_data["min_y_values"] - elif "min_x_values" in ensemble_data: - min_values = ensemble_data["min_x_values"] - else: - min_values = [] - - - if "max_y_values" in ensemble_data: - max_values = ensemble_data["max_y_values"] - elif "max_x_values" in ensemble_data: - max_values = ensemble_data["max_x_values"] - else: - max_values = [] - - ensemble_plot_data.setEnsembleData(ensemble_data["x"], ensemble_data["y"], min_values, max_values) - ensemble_plot_data.updateBoundaries(ensemble_data["min_x"], ensemble_data["max_x"], ensemble_data["min_y"], ensemble_data["max_y"]) - plot_data.addEnsembleData(ensemble_plot_data) - - if histogram_factory is not None: - histogram_factory.addEnsembleData(case, ensemble_data["x"], ensemble_data["y"], ensemble_data["min_y"], ensemble_data["max_y"]) - - - def addObservationData(self, plot_data, key, fetcher, histogram_factory=None): - observation_data = fetcher.fetchData(key) - - observation_plot_data = ObservationPlotData(key) - observation_plot_data.setObservationData(observation_data["x"], observation_data["y"], observation_data["std"], observation_data["continuous"]) - observation_plot_data.updateBoundaries(observation_data["min_x"], observation_data["max_x"], observation_data["min_y"], observation_data["max_y"]) - - plot_data.setObservationData(observation_plot_data) - - if histogram_factory is not None: - histogram_factory.setObservations(observation_data["x"], observation_data["y"], observation_data["std"], observation_data["min_y"], observation_data["max_y"]) - - - def addRefcaseData(self, plot_data, key, fetcher, histogram_factory=None): - refcase_data = fetcher.fetchData(key) - refcase_plot_data = RefcasePlotData(key) - refcase_plot_data.setRefcaseData(refcase_data["x"], refcase_data["y"]) - refcase_plot_data.updateBoundaries(refcase_data["min_x"], refcase_data["max_x"], refcase_data["min_y"], refcase_data["max_y"]) - plot_data.setRefcaseData(refcase_plot_data) - - if histogram_factory is not None: - histogram_factory.setRefcase(refcase_data["x"], refcase_data["y"], refcase_data["min_y"], refcase_data["max_y"]) - - - def addPcaData(self, plot_data, key, cases): - if plot_data.hasObservationData() and plot_data.hasEnsembleData(): - plot_data.setUserData("PCA", self.fetchPcaData(key, cases)) - else: - plot_data.setUserData("PCA", PlotData("No ensemble data available for %s" % key)) - - - def fetchPcaData(self, key, cases): - """ @rtype: PlotData """ - if key.startswith("PCA:"): - pca_name = key - else: - pca_name ="PCA:%s" % key - - pca_data_fetcher = PcaDataFetcher(self.ert()) - pca_plot_data = PlotData(pca_name) - - if DataTypeKeysModel().isCustomPcaKey(key): - obs_keys = DataTypeKeysModel().getCustomPcaKeyObsKeys(key) - else: - obs_keys = pca_data_fetcher.getObsKeys(key) - - for case in cases: - - pca_data = pca_data_fetcher.fetchData(obs_keys, case) - - if pca_data["x"] is not None: - - if not pca_plot_data.hasObservationData(): - pca_observation_plot_data = ObservationPlotData(pca_name) - pca_observation_plot_data.setObservationData(pca_data["x"], pca_data["obs_y"], [0.0 for x in pca_data["x"]], False) - pca_observation_plot_data.updateBoundaries(pca_data["min_x"], pca_data["max_x"], pca_data["min_y"], pca_data["max_y"]) - pca_plot_data.setObservationData(pca_observation_plot_data) - - pca_ensemble_plot_data = EnsemblePlotData(key, case) - pca_ensemble_plot_data.setEnsembleData(pca_data["x"], pca_data["y"], [], []) - pca_ensemble_plot_data.updateBoundaries(pca_data["min_x"], pca_data["max_x"], pca_data["min_y"], pca_data["max_y"]) - pca_plot_data.addEnsembleData(pca_ensemble_plot_data) - - return pca_plot_data - - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/refcase_plot_data.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/refcase_plot_data.py deleted file mode 100644 index 2375f2b51d..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data/refcase_plot_data.py +++ /dev/null @@ -1,89 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSlot - - -class RefcasePlotData(QObject): - def __init__(self, name, parent=None): - QObject.__init__(self, parent) - - self.__name = name - - self.__x_values = [] - self.__y_values = [] - self.__has_data = False - - self.__min_x = None - self.__max_x = None - self.__min_y = None - self.__max_y = None - - - - def setRefcaseData(self, x_values, y_values): - if x_values is not None and y_values is not None: - self.__x_values = x_values - self.__y_values = y_values - self.__has_data = True - - - def updateBoundaries(self, min_x, max_x, min_y, max_y): - if min_x is not None and (self.__min_x is None or self.__min_x > min_x): - self.__min_x = min_x - - if max_x is not None and (self.__max_x is None or self.__max_x < max_x): - self.__max_x = max_x - - if min_y is not None and (self.__min_y is None or self.__min_y > min_y): - self.__min_y = min_y - - if max_y is not None and (self.__max_y is None or self.__max_y < max_y): - self.__max_y = max_y - - - - @pyqtSlot(result=str) - def name(self): - return self.__name - - - - @pyqtSlot(result="QVariantList") - def xValues(self): - return self.__x_values - - @pyqtSlot(result="QVariantList") - def yValues(self): - return self.__y_values - - - @pyqtSlot(result=float) - def minX(self): - return self.__min_x - - @pyqtSlot(result=float) - def maxX(self): - return self.__max_x - - @pyqtSlot(result=float) - def minY(self): - return self.__min_y - - @pyqtSlot(result=float) - def maxY(self): - return self.__max_y - - - @pyqtSlot(result=bool) - def isValid(self): - return self.hasBoundaries() and self.hasData() - - @pyqtSlot(result=bool) - def hasBoundaries(self): - return self.__min_x is not None and self.__max_x is not None and self.__min_y is not None and self.__max_y is not None - - - @pyqtSlot(result=bool) - def hasData(self): - return self.__has_data - - - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_list_model.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_list_model.py index 417a610ef1..478444c5c5 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_list_model.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_list_model.py @@ -1,6 +1,5 @@ from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant from PyQt4.QtGui import QColor -from ert_gui.models.connectors.plot import DataTypeKeysModel from ert_gui.widgets import util @@ -9,11 +8,16 @@ class DataTypeKeysListModel(QAbstractItemModel): HAS_OBSERVATIONS = QColor(237, 218, 116) GROUP_ITEM = QColor(64, 64, 64) - def __init__(self): + def __init__(self, ert): + """ + @type ert: ert.enkf.EnKFMain + """ QAbstractItemModel.__init__(self) + self.__ert = ert self.__icon = util.resourceIcon("ide/small/bullet_star") - self.__items = DataTypeKeysModel().getAllKeys() + def keyManager(self): + return self.__ert.getKeyManager() def index(self, row, column, parent=None, *args, **kwargs): return self.createIndex(row, column, parent) @@ -22,7 +26,7 @@ class DataTypeKeysListModel(QAbstractItemModel): return QModelIndex() def rowCount(self, parent=None, *args, **kwargs): - return len(self.__items) + return len(self.keyManager().allDataTypeKeys()) def columnCount(self, QModelIndex_parent=None, *args, **kwargs): return 1 @@ -31,14 +35,14 @@ class DataTypeKeysListModel(QAbstractItemModel): assert isinstance(index, QModelIndex) if index.isValid(): - items = self.__items + items = self.keyManager().allDataTypeKeys() row = index.row() item = items[row] if role == Qt.DisplayRole: return item elif role == Qt.BackgroundRole: - if DataTypeKeysModel().isObservationKey(item): + if self.keyManager().isKeyWithObservations(item): return self.HAS_OBSERVATIONS return QVariant() @@ -48,28 +52,25 @@ class DataTypeKeysListModel(QAbstractItemModel): if index.isValid(): row = index.row() - return self.__items[row] + return self.keyManager().allDataTypeKeys()[row] return None def isSummaryKey(self, key): - return DataTypeKeysModel().isSummaryKey(str(key)) + return self.keyManager().isSummaryKey(key) def isBlockKey(self, key): - return DataTypeKeysModel().isBlockKey(str(key)) + return False def isGenKWKey(self, key): - return DataTypeKeysModel().isGenKWKey(str(key)) + return self.keyManager().isGenKwKey(key) def isGenDataKey(self, key): - return DataTypeKeysModel().isGenDataKey(str(key)) + return self.keyManager().isGenDataKey(key) + + def isCustomKwKey(self, key): + return self.keyManager().isCustomKwKey(key) def isCustomPcaKey(self, key): - return DataTypeKeysModel().isCustomPcaKey(str(key)) - - - - - - + return False diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_widget.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_widget.py index af3c1fc743..8bc8b78c2b 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_widget.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_keys_widget.py @@ -7,9 +7,9 @@ from ert_gui.widgets.search_box import SearchBox class DataTypeKeysWidget(QWidget): - dataTypeKeySelected = pyqtSignal(str) + dataTypeKeySelected = pyqtSignal() - def __init__(self): + def __init__(self, model): QWidget.__init__(self) self.__filter_popup = FilterPopup(self) @@ -17,7 +17,7 @@ class DataTypeKeysWidget(QWidget): layout = QVBoxLayout() - self.model = DataTypeKeysListModel() + self.model = model self.filter_model = DataTypeProxyModel(self.model) filter_layout = QHBoxLayout() @@ -46,17 +46,18 @@ class DataTypeKeysWidget(QWidget): self.setLayout(layout) def onItemChanged(self, item): - self.filter_model.setShowBlockKeys(item["block"]) + # self.filter_model.setShowBlockKeys(item["block"]) self.filter_model.setShowSummaryKeys(item["summary"]) self.filter_model.setShowGenKWKeys(item["gen_kw"]) self.filter_model.setShowGenDataKeys(item["gen_data"]) - self.filter_model.setShowCustomPcaKeys(item["custom_pca"]) + self.filter_model.setShowCustomKwKeys(item["custom_kw"]) + # self.filter_model.setShowCustomPcaKeys(item["custom_pca"]) def itemSelected(self): selected_item = self.getSelectedItem() if selected_item is not None: - self.dataTypeKeySelected.emit(selected_item) + self.dataTypeKeySelected.emit() def getSelectedItem(self): diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_proxy_model.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_proxy_model.py index 9d67fb51b1..059762f9ef 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_proxy_model.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/data_type_proxy_model.py @@ -27,6 +27,7 @@ class DataTypeProxyModel(QSortFilterProxyModel): self.__show_block_keys = True self.__show_gen_kw_keys = True self.__show_gen_data_keys = True + self.__show_custom_kw_keys = True self.__show_custom_pca_keys = True self.setFilterCaseSensitivity(Qt.CaseInsensitive) @@ -52,6 +53,9 @@ class DataTypeProxyModel(QSortFilterProxyModel): elif not self.__show_gen_data_keys and source_model.isGenDataKey(key): show = False + elif not self.__show_custom_kw_keys and source_model.isCustomKwKey(key): + show = False + elif not self.__show_custom_pca_keys and source_model.isCustomPcaKey(key): show = False @@ -78,6 +82,10 @@ class DataTypeProxyModel(QSortFilterProxyModel): self.__show_gen_data_keys = visible self.invalidateFilter() + def setShowCustomKwKeys(self, visible): + self.__show_custom_kw_keys = visible + self.invalidateFilter() + def setShowCustomPcaKeys(self, visible): self.__show_custom_pca_keys = visible self.invalidateFilter() diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/export_plot.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/export_plot.py deleted file mode 100644 index c9ce40b24a..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/export_plot.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'export_plot.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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 3 of the License, or -# (at your option) any later version. -# -# ERT 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 at -# for more details. -import os -from PyQt4.QtCore import QSize, QSizeF, Qt, QStringList, QFileInfo -from PyQt4.QtGui import QPrinter, QImage, QPainter, QFileDialog, QApplication, QCursor - -from ert_gui.models.connectors.plot.plot_settings import PlotSettingsModel -from ert_gui.tools.plot.plot_bridge import PlotWebPage, PlotBridge -from ert_gui.tools.plot.plot_panel import PlotPanel - - -class ExportPlot(object): - def __init__(self, active_plot_panel, settings, custom_settings, path=None): - super(ExportPlot, self).__init__() - assert isinstance(active_plot_panel, PlotPanel) - self.__active_plot_panel = active_plot_panel - self.__settings = settings - self.__custom_settings = custom_settings - self.__bridge = None - """:type: PlotBridge """ - self.__plot_bridge_org = active_plot_panel.getPlotBridge() - self.__width = self.__plot_bridge_org.getPrintWidth() - self.__height = self.__plot_bridge_org.getPrintHeight() + 20 - self.__file_name = None - self.__selected_file_type = None - self.__path = path - - - def export(self): - if self.__path is not None: - default_export_path = self.__path - else: - default_export_path = PlotSettingsModel().getDefaultPlotPath() - - dialog = QFileDialog(self.__active_plot_panel) - dialog.setFileMode(QFileDialog.AnyFile) - #dialog.setNameFilter("Image (*.png);; PDF (*.pdf)") - dialog.setNameFilter("Image (*.png)") - dialog.setWindowTitle("Export plot") - dialog.setDirectory(default_export_path) - dialog.setOption(QFileDialog.DontUseNativeDialog, True) - dialog.setLabelText(QFileDialog.FileType, "Select file type: ") - dialog.setAcceptMode(QFileDialog.AcceptSave) - dialog.selectFile(self.getDefaultFileName()) - - if dialog.exec_(): - result = dialog.selectedFiles() - assert isinstance(result, QStringList) - if len(result) == 1: - file_info = QFileInfo(result[0]) - self.__file_name = file_info.fileName() - self.__path = file_info.path() - self.__selected_file_type = dialog.selectedNameFilter() - name = self.__active_plot_panel.getName() - url = self.__active_plot_panel.getUrl() - - - web_page = PlotWebPage("export - %s" % name) - web_page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) - web_page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) - web_page.setViewportSize(QSize(self.__width, self.__height)) - self.__bridge = PlotBridge(web_page, url) - self.__bridge.plotReady.connect(self.plotReady) - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - - - def plotReady(self): - data = self.__plot_bridge_org.getPlotData() - self.__bridge.setPlotData(data) - self.__bridge.updatePlotSize(QSize(self.__width, self.__height)) - self.__bridge.setCustomSettings(self.__custom_settings) - - self.__bridge.setReportStepTime(self.__settings["report_step"]) - - x_min = self.__settings["x_min"] - x_max = self.__settings["x_max"] - y_min = self.__settings["y_min"] - y_max = self.__settings["y_max"] - self.__bridge.setScales(x_min, x_max, y_min, y_max) - - self.__bridge.renderingFinished.connect(self.performExport) - - - def performExport(self): - file_name = os.path.join(str(self.__path), str(self.__file_name)) - view = self.__bridge.getPage() - if not self.__file_name.isEmpty(): - if str(self.__selected_file_type) == "PDF (*.pdf)": - if not file_name.endswith(".pdf"): - file_name += ".pdf" - self.exportPDF(view, file_name, self.__width, self.__height) - elif str(self.__selected_file_type) == "Image (*.png)": - if not file_name.endswith(".png"): - file_name += ".png" - self.exportPNG(view, file_name, self.__width, self.__height) - - - def exportPDF(self, view, file_name, width, height): - pdf = QPrinter() - pdf.setOutputFormat(QPrinter.PdfFormat) - pdf.setPrintRange(QPrinter.AllPages) - pdf.setOrientation(QPrinter.Portrait) - pdf.setResolution(QPrinter.HighResolution) - pdf.setPaperSize(QSizeF(width,height),QPrinter.Point) - pdf.setFullPage(True) - pdf.setOutputFileName(file_name) - view.mainFrame().print_(pdf) - - QApplication.restoreOverrideCursor() - - - def exportPNG(self, view, file_name, width, height): - image = QImage(QSize(width, height), QImage.Format_ARGB32_Premultiplied) - paint = QPainter(image) - paint.setRenderHint(QPainter.Antialiasing, True) - paint.setRenderHint(QPainter.HighQualityAntialiasing, True) - paint.setRenderHint(QPainter.TextAntialiasing, True) - paint.setRenderHint(QPainter.SmoothPixmapTransform, True) - view.mainFrame().render(paint) - image.save(file_name) - paint.end() - - QApplication.restoreOverrideCursor() - - - def getDefaultFileName(self): - name = str(self.__plot_bridge_org.getPlotTitle()) - name = name.replace(":"," ") - name = name.replace("@", "-") - type = self.__active_plot_panel.getName() - - name = type + " " + name + ".png" - - return name - - def getCurrentPath(self): - return self.__path \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/filter_popup.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/filter_popup.py index 20ebbf21d4..d66dc12768 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/filter_popup.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/filter_popup.py @@ -23,10 +23,11 @@ class FilterPopup(QDialog): self.__layout.addWidget(QLabel("Filter by data type:")) self.addFilterItem("Summary", "summary") - self.addFilterItem("Block", "block") + # self.addFilterItem("Block", "block") self.addFilterItem("Gen KW", "gen_kw") self.addFilterItem("Gen Data", "gen_data") - self.addFilterItem("Custom PCA", "custom_pca") + self.addFilterItem("Custom KW", "custom_kw") + # self.addFilterItem("Custom PCA", "custom_pca") frame.setLayout(self.__layout) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_bridge.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_bridge.py deleted file mode 100644 index 8631c620fe..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_bridge.py +++ /dev/null @@ -1,224 +0,0 @@ -import json -import os -from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QUrl, QVariant -from PyQt4.QtWebKit import QWebPage -from ert.util import CTime -from ert_gui.tools.plot.data import PlotData - -class PlotWebPage(QWebPage): - def __init__(self, name): - QWebPage.__init__(self) - self.name = name - - def javaScriptConsoleMessage(self, message, line_number, source_id): - print("[%s] Source: %s at line: %d -> %s" % (self.name, source_id, line_number, message)) - - -class PlotBridge(QObject): - plotReady = pyqtSignal() - renderingFinished = pyqtSignal() - - def __init__(self, web_page, plot_url): - QObject.__init__(self) - assert isinstance(web_page, QWebPage) - - self.__web_page = web_page - self.__ready = False - self.__html_ready = False - self.__data = PlotData("invalid", parent=self) - self.__size = None - self.__temporary_data_object = None - - self.applyContextObject() - - root_path = os.getenv("ERT_SHARE_PATH") - path = os.path.join(root_path, plot_url) - self.__web_page.mainFrame().load(QUrl("file://%s" % path)) - self.__web_page.loadFinished.connect(self.loadFinished) - - - def applyContextObject(self): - self.__web_page.mainFrame().addToJavaScriptWindowObject("plot_data_source", self) - - def updatePlotSize(self, size): - self.__size = size - if self.isReady(): - self.__web_page.mainFrame().evaluateJavaScript("setSize(%d,%d);" % (size.width(), size.height())) - self.renderNow() - - def supportsPlotProperties(self, time=False, value=False, depth=False, index=False, histogram=False, pca=False): - time = str(time).lower() - value = str(value).lower() - depth = str(depth).lower() - index = str(index).lower() - histogram = str(histogram).lower() - pca = str(pca).lower() - return self.__web_page.mainFrame().evaluateJavaScript("supportsPlotProperties(%s,%s,%s,%s,%s,%s);" % (time, value, depth, index, histogram, pca)).toBool() - - def setPlotData(self, data): - self.__data = data - self.__web_page.mainFrame().evaluateJavaScript("updatePlot();") - - def setReportStepTime(self, report_step_time): - if report_step_time is None: - report_step_time = "null" - - if isinstance(report_step_time, CTime): - report_step_time = report_step_time.ctime() - - self.__web_page.mainFrame().evaluateJavaScript("setReportStepTime(%s);" % report_step_time) - - - def setScales(self, x_min, x_max, y_min, y_max): - if x_min is None: - x_min = "null" - - if x_max is None: - x_max = "null" - - if y_min is None: - y_min = "null" - - if y_max is None: - y_max = "null" - - if isinstance(x_min, CTime): - x_min = x_min.ctime() - - if isinstance(x_max, CTime): - x_max = x_max.ctime() - - if isinstance(y_min, CTime): - y_min = y_min.ctime() - - if isinstance(y_max, CTime): - y_max = y_max.ctime() - - scales = (x_min, x_max, y_min, y_max) - self.__web_page.mainFrame().evaluateJavaScript("setScales(%s,%s,%s,%s);" % scales) - - @pyqtSlot(result=QObject) - def getPlotData(self): - return self.__data - - - @pyqtSlot() - def htmlInitialized(self): - # print("[%s] Initialized!" % self.__name) - self.__html_ready = True - self.checkStatus() - - def loadFinished(self, ok): - self.__ready = True - self.checkStatus() - - def checkStatus(self): - if self.__ready and self.__html_ready: - # print("[%s] Ready!" % self.__name) - self.plotReady.emit() - if self.__size is not None: - self.updatePlotSize(self.__size) - - def isReady(self): - return self.__ready and self.__html_ready - - def getPrintWidth(self): - return self.__web_page.mainFrame().evaluateJavaScript("getPrintWidth();").toInt()[0] - - def getPrintHeight(self): - return self.__web_page.mainFrame().evaluateJavaScript("getPrintHeight();").toInt()[0] - - def getPage(self): - return self.__web_page - - def setCustomSettings(self, settings): - json_settings = json.dumps(settings) - self.__web_page.mainFrame().evaluateJavaScript("setCustomSettings(%s);" % json_settings) - - def renderNow(self): - self.__web_page.mainFrame().evaluateJavaScript("renderNow()") - - - def getPlotTitle(self): - return self.__web_page.mainFrame().evaluateJavaScript("getPlotTitle();" ).toString() - - - def xAxisType(self): - """ @rtype: str """ - axis_type = self.__web_page.mainFrame().evaluateJavaScript("xAxisType();") - - if axis_type.isNull(): - return None - - return str(axis_type.toString()) - - - def yAxisType(self): - """ @rtype: str """ - axis_type = self.__web_page.mainFrame().evaluateJavaScript("yAxisType();") - - if axis_type.isNull(): - return None - - return str(axis_type.toString()) - - - def isReportStepCapable(self): - """ @rtype: bool """ - return self.__web_page.mainFrame().evaluateJavaScript("isReportStepCapable();" ).toBool() - - - @pyqtSlot(result=QObject) - def getTemporaryData(self): - return self.__temporary_data_object - - - def getXScales(self, data): - """ @rtype: (float, float) """ - self.__temporary_data_object = data - x_min = self.__web_page.mainFrame().evaluateJavaScript("getXMin();") - x_max = self.__web_page.mainFrame().evaluateJavaScript("getXMax();") - - if x_min.isNull(): - x_min = None - elif x_min.typeName() == "double": - x_min = x_min.toDouble()[0] - else: - raise TypeError("Unknown type %s for x_min" % x_min.typeName()) - - if x_max.isNull(): - x_max = None - elif x_max.typeName() == "double": - x_max = x_max.toDouble()[0] - else: - raise TypeError("Unknown type %s for x_max" % x_max.typeName()) - - return x_min, x_max - - - def getYScales(self, data): - """ @rtype: (float, float) """ - self.__temporary_data_object = data - y_min = self.__web_page.mainFrame().evaluateJavaScript("getYMin();") - y_max = self.__web_page.mainFrame().evaluateJavaScript("getYMax();") - - if y_min.isNull(): - y_min = None - elif y_min.typeName() == "double": - y_min = y_min.toDouble()[0] - else: - raise TypeError("Unknown type %s for y_min" % y_min.typeName()) - - if y_max.isNull(): - y_max = None - elif y_max.typeName() == "double": - y_max = y_max.toDouble()[0] - else: - raise TypeError("Unknown type %s for y_max" % y_max.typeName()) - - return y_min, y_max - - - - - diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_case_model.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_case_model.py index fcb59930c3..2bf2b56b02 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_case_model.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_case_model.py @@ -47,7 +47,7 @@ class PlotCaseModel(QAbstractItemModel): def getAllItems(self): if self.__data is None: - self.__data = CaseList().getAllCasesWithDataAndNotRunning() + self.__data = CaseList().getAllCasesNotRunning() return self.__data diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_metrics_tracker.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_metrics_tracker.py deleted file mode 100644 index 80b4883e35..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_metrics_tracker.py +++ /dev/null @@ -1,84 +0,0 @@ -class PlotMetricsTracker(object): - def __init__(self): - super(PlotMetricsTracker, self).__init__() - - self.__data_type_key = None - self.__data_type_key_support_report_steps = False - self.__scale_types = {} - - self.__scales = {} - - def addScaleType(self, scale_name, scale_type): - """ - @type scale_name: str - @type scale_type: int or float or CTime - """ - self.__scale_types[scale_name] = scale_type - - - def getType(self, scale_name): - """ - @type scale_name: str - @rtype: int or float or CTime or None - """ - - if scale_name is None: - return None - - if not scale_name in self.__scale_types: - raise KeyError("Scale type with name: '%s' does not exist!" % scale_name) - - return self.__scale_types[scale_name] - - - def __createScaleTracker(self): - scale_tracker = {} - - for scale_name in self.__scale_types.keys(): - scale_tracker[scale_name] = (None, None) - - return scale_tracker - - def setDataTypeKey(self, data_type_key): - """ @type data_type_key: str """ - self.__data_type_key = data_type_key - - if not data_type_key in self.__scales: - self.__scales[data_type_key] = self.__createScaleTracker() - - def getDataTypeKey(self): - """ @rtype: str """ - return self.__data_type_key - - - def setScalesForType(self, scale_name, min_value, max_value): - if scale_name is not None: - if not scale_name in self.__scales[self.__data_type_key]: - raise KeyError("Scale name '%s' not registered!" % scale_name) - - self.__scales[self.__data_type_key][scale_name] = (min_value, max_value) - - - def getScalesForType(self, scale_name): - """ @rtype: tuple of (int, int) or tuple of (float, float) or tuple of (CTime, CTime) """ - scale_tracker = self.__scales[self.__data_type_key] - if not scale_name in scale_tracker: - return None, None - - return scale_tracker[scale_name] - - def setDataTypeKeySupportsReportSteps(self, supports_report_steps): - self.__data_type_key_support_report_steps = supports_report_steps - - def dataTypeSupportsReportStep(self): - return self.__data_type_key_support_report_steps - - def resetScaleType(self, scale_name): - self.setScalesForType(scale_name, None, None) - - def hasScale(self, scale_name): - if scale_name is None: - return True - - scale_tracker = self.__scales[self.__data_type_key] - return not scale_tracker[scale_name] == (None, None) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel.py deleted file mode 100644 index 78d16ea506..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel.py +++ /dev/null @@ -1,124 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal -from PyQt4.QtGui import QWidget, QGridLayout, QPainter, QShortcut, QMainWindow -from PyQt4.QtWebKit import QWebView, QWebSettings, QWebInspector - -from ert_gui.tools.plot import PlotBridge -from ert_gui.tools.plot.plot_bridge import PlotWebPage - - -class PlotWebView(QWebView): - def __init__(self, name): - QWebView.__init__(self) - self.setPage(PlotWebPage(name)) - self.setRenderHint(QPainter.Antialiasing, True) - self.setContextMenuPolicy(Qt.NoContextMenu) - self.settings().setAttribute(QWebSettings.JavascriptEnabled, True) - self.settings().setAttribute(QWebSettings.LocalContentCanAccessFileUrls, True) - self.settings().setAttribute(QWebSettings.LocalContentCanAccessRemoteUrls, True) - self.settings().clearMemoryCaches() - - self.__inspector_window = None - - shortcut = QShortcut(self) - shortcut.setKey(Qt.Key_F12) - shortcut.activated.connect(self.toggleInspector) - - - def toggleInspector(self): - if self.__inspector_window is None: - self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) - web_inspector = QWebInspector() - web_inspector.setPage(self.page()) - - self.__inspector_window = QMainWindow(self) - self.__inspector_window.setCentralWidget(web_inspector) - self.__inspector_window.resize(900, 600) - self.__inspector_window.setVisible(False) - - self.__inspector_window.setVisible(not self.__inspector_window.isVisible()) - - -class PlotPanel(QWidget): - plotReady = pyqtSignal() - - def __init__(self, name, debug_name, plot_url): - QWidget.__init__(self) - - self.__name = name - self.__debug_name = debug_name - self.__plot_url = plot_url - - layout = QGridLayout() - - self.web_view = PlotWebView(debug_name) - - layout.addWidget(self.web_view) - self.setLayout(layout) - - self.__plot_is_visible = True - self.__plot_bridge = PlotBridge(self.getWebView().page(), plot_url) - self.__plot_bridge.plotReady.connect(self.plotReady) - - - def getName(self): - return self.__name - - def getUrl(self): - return self.__plot_url - - def getWebView(self): - return self.web_view - - def setSettings(self, settings): - if self.isPlotVisible(): - self.__plot_bridge.setPlotSettings(settings) - - def isReady(self): - return self.__plot_bridge.isReady() - - - def resizeEvent(self, event): - QWidget.resizeEvent(self, event) - if self.isPlotVisible(): - self.__plot_bridge.updatePlotSize(size = self.size()) - - - def supportsPlotProperties(self, time=False, value=False, depth=False, index=False, histogram=False, pca=False): - return self.__plot_bridge.supportsPlotProperties(time, value, depth, index, histogram, pca) - - def isPlotVisible(self): - return self.__plot_is_visible - - def setPlotIsVisible(self, visible): - self.__plot_is_visible = visible - - def getPlotBridge(self): - """ @rtype: PlotBridge """ - return self.__plot_bridge - - def renderNow(self): - if self.isPlotVisible(): - self.__plot_bridge.renderNow() - - - def xAxisType(self): - """ @rtype: str """ - return self.__plot_bridge.xAxisType() - - - def yAxisType(self): - """ @rtype: str """ - return self.__plot_bridge.yAxisType() - - def getXScales(self, data): - """ @rtype: (float, float) """ - return self.__plot_bridge.getXScales(data) - - def getYScales(self, data): - """ @rtype: (float, float) """ - return self.__plot_bridge.getYScales(data) - - - def isReportStepCapable(self): - """ @rtype: bool """ - return self.__plot_bridge.isReportStepCapable() \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel_tracker.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel_tracker.py deleted file mode 100644 index e518e06ae1..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_panel_tracker.py +++ /dev/null @@ -1,56 +0,0 @@ -from PyQt4.QtGui import QTabWidget - -class PlotPanelTracker(object): - def __init__(self, tab_widget): - """@type tab_widget: QTabWidget""" - super(PlotPanelTracker, self).__init__() - - self.__selected_widget_for_type = {} - self.__tab_widget = tab_widget - - self.__key_type_tester_map = {} - - def addKeyTypeTester(self, key_type, tester_function): - if key_type in self.__key_type_tester_map: - raise KeyError("Key type '%s' already exists!" % key_type) - - self.__key_type_tester_map[key_type] = tester_function - - - def storePlotType(self, fetcher, key): - """ - @type fetcher: PlotDataFetcher - @type key: str - """ - if key is not None: - for key_type in self.__key_type_tester_map: - data_type_tester_function = self.__key_type_tester_map[key_type] - - if data_type_tester_function(fetcher, key): - self.__selected_widget_for_type[key_type] = self.__tab_widget.currentWidget() - return - - raise NotImplementedError("Key '%s' not supported." % key) - - - def restorePlotType(self, fetcher, key): - """ - @type fetcher: PlotDataFetcher - @type key: str - """ - if key is not None: - for key_type in self.__key_type_tester_map: - data_type_tester_function = self.__key_type_tester_map[key_type] - - if data_type_tester_function(fetcher, key): - - if key_type in self.__selected_widget_for_type: - widget = self.__selected_widget_for_type[key_type] - self.__tab_widget.setCurrentWidget(widget) - else: - if self.__tab_widget.count() > 0: - self.__tab_widget.setCurrentIndex(0) - - return - - raise NotImplementedError("Key '%s' not supported." % key) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_scale_widget.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_scale_widget.py deleted file mode 100644 index 20bb964f88..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_scale_widget.py +++ /dev/null @@ -1,143 +0,0 @@ -from PyQt4.QtCore import pyqtSignal, Qt -from PyQt4.QtGui import QWidget, QVBoxLayout, QCheckBox, QDoubleSpinBox, QSpinBox, QStackedWidget, QSizePolicy, QLabel - -from ert.util import CTime -from ert_gui.models.connectors.plot import ReportStepsModel -from ert_gui.widgets.list_spin_box import ListSpinBox - - -class PlotScalesWidget(QWidget): - plotScaleChanged = pyqtSignal() - - def __init__(self, type_key, title, select_min_time_value=False): - QWidget.__init__(self) - - self.__type_key = type_key - self.__type = None - - self.__double_spinner = self.createDoubleSpinner(minimum=-1e15, maximum=1e15) - self.__integer_spinner = self.createIntegerSpinner(minimum=0, maximum=1e10) - - self.__time_map = ReportStepsModel().getList() - self.__time_index_map = {} - for index in range(len(self.__time_map)): - time = self.__time_map[index] - self.__time_index_map[time] = index - - self.__time_spinner = self.createTimeSpinner(select_minimum_value=select_min_time_value) - - layout = QVBoxLayout() - self.setLayout(layout) - - self.__label = QLabel(title) - self.__label.setAlignment(Qt.AlignHCenter) - - self.__stack = QStackedWidget() - self.__stack.setSizePolicy(QSizePolicy(QSizePolicy.Preferred)) - self.__stack.addWidget(self.__integer_spinner) - self.__stack.addWidget(self.__double_spinner) - self.__stack.addWidget(self.__time_spinner) - - layout.addWidget(self.__stack) - layout.addWidget(self.__label) - - self.setLayout(layout) - - def createDoubleSpinner(self, minimum, maximum): - spinner = QDoubleSpinBox() - spinner.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) - spinner.setMinimumWidth(105) - spinner.setRange(minimum, maximum) - spinner.setKeyboardTracking(False) - spinner.setDecimals(8) - - spinner.editingFinished.connect(self.plotScaleChanged) - spinner.valueChanged.connect(self.plotScaleChanged) - - return spinner - - def createIntegerSpinner(self, minimum, maximum): - spinner = QSpinBox() - spinner.setMinimumWidth(75) - spinner.setRange(minimum, maximum) - spinner.setKeyboardTracking(False) - - spinner.editingFinished.connect(self.plotScaleChanged) - spinner.valueChanged.connect(self.plotScaleChanged) - - return spinner - - def createTimeSpinner(self, select_minimum_value): - def converter(item): - return "%s" % (str(item.date())) - - spinner = ListSpinBox(self.__time_map) - spinner.setMinimumWidth(75) - - if select_minimum_value: - spinner.setValue(0) - - spinner.valueChanged[int].connect(self.plotScaleChanged) - spinner.editingFinished.connect(self.plotScaleChanged) - spinner.setStringConverter(converter) - - return spinner - - - def getValue(self): - if self.__type is int: - return self.__integer_spinner.value() - elif self.__type is float: - return self.__double_spinner.value() - elif self.__type is CTime: - index = self.__time_spinner.value() - return self.__time_map[index] - else: - raise TypeError("Unsupported spinner type: %s" % self.__type) - - - def setValue(self, value): - if value is not None: - if self.__type is int: - self.__integer_spinner.setValue(int(value)) - elif self.__type is float: - self.__double_spinner.setValue(value) - elif self.__type is CTime: - index = self.__time_index_map[value] - self.__time_spinner.setValue(index) - else: - raise TypeError("Unsupported spinner type: %s" % self.__type) - - - def setFontSize(self, size): - font = self.__double_spinner.font() - font.setPointSize(size) - self.__double_spinner.setFont(font) - - font = self.__integer_spinner.font() - font.setPointSize(size) - self.__integer_spinner.setFont(font) - - font = self.__time_spinner.font() - font.setPointSize(size) - self.__time_spinner.setFont(font) - - font = self.__label.font() - font.setPointSize(size) - self.__label.setFont(font) - - - def setType(self, spinner_type): - self.__type = spinner_type - if spinner_type is int: - self.__stack.setCurrentWidget(self.__integer_spinner) - elif spinner_type is float: - self.__stack.setCurrentWidget(self.__double_spinner) - elif spinner_type is CTime: - self.__stack.setCurrentWidget(self.__time_spinner) - else: - raise TypeError("Unsupported spinner type: %s" % spinner_type) - - - def getType(self): - return self.__type diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool.py index 8a4497f383..4dc34e3784 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool.py @@ -4,11 +4,12 @@ from ert_gui.widgets import util class PlotTool(Tool): - def __init__(self): + def __init__(self, ert): super(PlotTool, self).__init__("Create Plot", "tools/plot", util.resourceIcon("ide/chart_curve_add")) + self.__ert = ert def trigger(self): - plot_window = PlotWindow(self.parent()) + plot_window = PlotWindow(self.__ert, self.parent()) plot_window.show() diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool_bar.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool_bar.py deleted file mode 100644 index d549c4b8ad..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_tool_bar.py +++ /dev/null @@ -1,105 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal -from PyQt4.QtGui import QToolBar -from ert.util import CTime -from ert_gui.tools.plot import ReportStepWidget, PlotScalesWidget -from ert_gui.widgets import util - - -class PlotToolBar(QToolBar): - FONT_SIZE = 11 - - exportClicked = pyqtSignal() - resetScalesClicked = pyqtSignal() - reportStepChanged = pyqtSignal() - plotScalesChanged = pyqtSignal() - - def __init__(self): - QToolBar.__init__(self, "PlotTools") - - self.setObjectName("PlotToolBar") - self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - - self.__reset_scales = self.createAction("Reset Scales", util.resourceIcon("ide/transform_scale")) - self.__reset_scales.triggered.connect(self.resetScalesClicked) - - self.__x_min, self.__x_min_action = self.addScaler("x_min", "X Minimum", spinner_type=CTime, select_min_time_value=True) - self.__x_max, self.__x_max_action = self.addScaler("x_max", "X Maximum", spinner_type=CTime) - self.__y_min, self.__y_min_action = self.addScaler("y_min", "Y Minimum", spinner_type=float, select_min_time_value=True) - self.__y_max, self.__y_max_action = self.addScaler("y_max", "Y Maximum", spinner_type=float) - - self.__report_step_widget = ReportStepWidget() - self.__report_step_widget.reportStepTimeSelected.connect(self.reportStepChanged) - self.__report_step_widget.setFontSize(PlotToolBar.FONT_SIZE) - - self.__report_step_widget_action = self.addWidget(self.__report_step_widget) - - self.addSeparator() - - export_action = self.createAction("Export Plot", util.resourceIcon("ide/table_export")) - export_action.triggered.connect(self.exportClicked) - - - def createAction(self, title, icon): - action = self.addAction(title) - action.setIcon(icon) - - w = self.widgetForAction(action) - font = w.font() - font.setPointSize(PlotToolBar.FONT_SIZE) - w.setFont(font) - - return action - - def addScaler(self, type_key, title, spinner_type, select_min_time_value=False): - scaler = PlotScalesWidget(type_key, title, select_min_time_value=select_min_time_value) - scaler.setFontSize(PlotToolBar.FONT_SIZE) - scaler.plotScaleChanged.connect(self.plotScalesChanged) - scaler.setType(spinner_type) - - action = self.addWidget(scaler) - - return scaler, action - - - def setToolBarOptions(self, x_type, y_type, report_step_capable): - self.blockSignals(True) - self.__x_min_action.setVisible(x_type is not None) - self.__x_max_action.setVisible(x_type is not None) - - self.__y_min_action.setVisible(y_type is not None) - self.__y_max_action.setVisible(y_type is not None) - - if x_type is not None: - self.__x_min.setType(x_type) - self.__x_max.setType(x_type) - - if y_type is not None: - self.__y_min.setType(y_type) - self.__y_max.setType(y_type) - - self.__report_step_widget_action.setVisible(report_step_capable) - self.blockSignals(False) - - - def getXScales(self): - return (self.__x_min.getValue()), (self.__x_max.getValue()) - - - def getYScales(self): - return (self.__y_min.getValue()), (self.__y_max.getValue()) - - - def getReportStep(self): - """ @rtype: CTime """ - return self.__report_step_widget.getSelectedValue() - - - def setScales(self, x_min, x_max, y_min, y_max): - self.blockSignals(True) - - self.__x_min.setValue(x_min) - self.__x_max.setValue(x_max) - self.__y_min.setValue(y_min) - self.__y_max.setValue(y_max) - - self.blockSignals(False) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_widget.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_widget.py new file mode 100644 index 0000000000..d745039192 --- /dev/null +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_widget.py @@ -0,0 +1,68 @@ +from PyQt4.QtCore import Qt +from PyQt4.QtGui import QWidget, QVBoxLayout + +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar + +class PlotWidget(QWidget): + def __init__(self, name, plotFunction, plot_condition_function_list, plotContextFunction, parent=None): + QWidget.__init__(self, parent) + + self.__name = name + self.__plotFunction = plotFunction + self.__plotContextFunction = plotContextFunction + self.__plot_conditions = plot_condition_function_list + """:type: list of functions """ + self.__figure = Figure() + self.__figure.set_tight_layout(True) + self.__canvas = FigureCanvas(self.__figure) + self.__canvas.setParent(self) + self.__canvas.setFocusPolicy(Qt.StrongFocus) + self.__canvas.setFocus() + + vbox = QVBoxLayout() + vbox.addWidget(self.__canvas) + self.__toolbar = NavigationToolbar(self.__canvas, self) + vbox.addWidget(self.__toolbar) + self.setLayout(vbox) + + self.__dirty = True + self.__active = False + self.resetPlot() + + + + def getFigure(self): + """ :rtype: matplotlib.figure.Figure""" + return self.__figure + + + def resetPlot(self): + self.__figure.clear() + + + def updatePlot(self): + if self.isDirty() and self.isActive(): + print("Drawing: %s" % self.__name) + self.resetPlot() + plot_context = self.__plotContextFunction(self.getFigure()) + self.__plotFunction(plot_context) + self.__canvas.draw() + + self.setDirty(False) + + + def setDirty(self, dirty=True): + self.__dirty = dirty + + def isDirty(self): + return self.__dirty + + def setActive(self, active=True): + self.__active = active + + def isActive(self): + return self.__active + + def canPlotKey(self, key): + return any([plotConditionFunction(key) for plotConditionFunction in self.__plot_conditions]) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_window.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_window.py index 394cea0d3e..18dda0476a 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_window.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/plot_window.py @@ -1,251 +1,123 @@ from PyQt4.QtCore import Qt from PyQt4.QtGui import QMainWindow, QDockWidget, QTabWidget, QWidget, QVBoxLayout -from ert.util import CTime + from ert_gui.models.connectors.init import CaseSelectorModel -from ert_gui.tools.plot import PlotPanel, DataTypeKeysWidget, CaseSelectionWidget, ExportPlot, CustomizePlotWidget, PlotToolBar, PlotMetricsTracker, PlotPanelTracker -from ert_gui.tools.plot.data import PlotDataFetcher +from ert_gui.plottery import PlotContext, PlotDataGatherer, PlotConfig, plots + + +from ert_gui.tools.plot import DataTypeKeysWidget, CaseSelectionWidget, CustomizePlotWidget, PlotWidget +from ert_gui.tools.plot import DataTypeKeysListModel from ert_gui.widgets.util import may_take_a_long_time class PlotWindow(QMainWindow): - def __init__(self, parent): + def __init__(self, ert, parent): QMainWindow.__init__(self, parent) + self.__ert = ert + """:type: ert.enkf.enkf_main.EnKFMain""" + self.setMinimumWidth(750) self.setMinimumHeight(500) self.setWindowTitle("Plotting") self.activateWindow() - self.__plot_data = None - - self.__plot_metrics_tracker = PlotMetricsTracker() - self.__plot_metrics_tracker.addScaleType("value", float) - self.__plot_metrics_tracker.addScaleType("depth", float) - self.__plot_metrics_tracker.addScaleType("pca", float) - self.__plot_metrics_tracker.addScaleType("index", int) - self.__plot_metrics_tracker.addScaleType("count", int) - self.__plot_metrics_tracker.addScaleType("time", CTime) - self.__central_tab = QTabWidget() self.__central_tab.currentChanged.connect(self.currentPlotChanged) - self.__plot_panel_tracker = PlotPanelTracker(self.__central_tab) - self.__plot_panel_tracker.addKeyTypeTester("summary", PlotDataFetcher.isSummaryKey) - self.__plot_panel_tracker.addKeyTypeTester("block", PlotDataFetcher.isBlockObservationKey) - self.__plot_panel_tracker.addKeyTypeTester("gen_kw", PlotDataFetcher.isGenKWKey) - self.__plot_panel_tracker.addKeyTypeTester("gen_data", PlotDataFetcher.isGenDataKey) - self.__plot_panel_tracker.addKeyTypeTester("custom_pca", PlotDataFetcher.isCustomPcaDataKey) - - central_widget = QWidget() central_layout = QVBoxLayout() central_layout.setContentsMargins(0, 0, 0, 0) central_widget.setLayout(central_layout) - self.__toolbar = PlotToolBar() - self.__toolbar.resetScalesClicked.connect(self.resetCurrentScales) - - central_layout.addWidget(self.__toolbar) central_layout.addWidget(self.__central_tab) self.setCentralWidget(central_widget) + key_manager = ert.getKeyManager() + """:type: ert.enkf.key_manager.KeyManager """ - self.__plot_panels = [] - """:type: list of PlotPanel""" + self.__plot_widgets = [] + """:type: list of PlotWidget""" - self.addPlotPanel("Ensemble plot", "gui/plots/simple_plot.html", short_name="EP") - self.addPlotPanel("Ensemble overview plot", "gui/plots/simple_overview_plot.html", short_name="EOP") - self.addPlotPanel("Ensemble statistics", "gui/plots/ensemble_statistics_plot.html", short_name="ES") - self.addPlotPanel("Histogram", "gui/plots/histogram.html", short_name="Histogram") - self.addPlotPanel("Distribution", "gui/plots/gen_kw.html", short_name="Distribution") - self.addPlotPanel("RFT plot", "gui/plots/rft.html", short_name="RFT") - self.addPlotPanel("RFT overview plot", "gui/plots/rft_overview.html", short_name="oRFT") - self.addPlotPanel("Ensemble plot", "gui/plots/gen_data.html", short_name="epGenData") - self.addPlotPanel("Ensemble overview plot", "gui/plots/gen_data_overview.html", short_name="eopGenData") - self.addPlotPanel("Ensemble statistics", "gui/plots/gen_data_statistics_plot.html", short_name="esGenData") - self.addPlotPanel("PCA plot", "gui/plots/pca.html", short_name="PCA") + self.__data_gatherers = [] + """:type: list of PlotDataGatherer """ - self.__data_type_keys_widget = DataTypeKeysWidget() + PDG = PlotDataGatherer + summary_gatherer = self.createDataGatherer(PDG.gatherSummaryData, key_manager.isSummaryKey, refcaseGatherFunc=PDG.gatherSummaryRefcaseData, observationGatherFunc=PDG.gatherSummaryObservationData) + gen_data_gatherer = self.createDataGatherer(PDG.gatherGenDataData, key_manager.isGenDataKey, observationGatherFunc=PDG.gatherGenDataObservationData) + gen_kw_gatherer = self.createDataGatherer(PDG.gatherGenKwData, key_manager.isGenKwKey) + custom_kw_gatherer = self.createDataGatherer(PDG.gatherCustomKwData, key_manager.isCustomKwKey) + + + self.addPlotWidget("Ensemble", plots.plotEnsemble, [summary_gatherer, gen_data_gatherer]) + self.addPlotWidget("Overview", plots.plotOverview, [summary_gatherer, gen_data_gatherer]) + self.addPlotWidget("Statistics", plots.plotStatistics, [summary_gatherer, gen_data_gatherer]) + self.addPlotWidget("Histogram", plots.plotHistogram, [gen_kw_gatherer, custom_kw_gatherer]) + self.addPlotWidget("Gaussian KDE", plots.plotGaussianKDE, [gen_kw_gatherer, custom_kw_gatherer]) + + + self.__data_types_key_model = DataTypeKeysListModel(ert) + + self.__data_type_keys_widget = DataTypeKeysWidget(self.__data_types_key_model) self.__data_type_keys_widget.dataTypeKeySelected.connect(self.keySelected) self.addDock("Data types", self.__data_type_keys_widget) current_case = CaseSelectorModel().getCurrentChoice() self.__case_selection_widget = CaseSelectionWidget(current_case) - self.__case_selection_widget.caseSelectionChanged.connect(self.caseSelectionChanged) + self.__case_selection_widget.caseSelectionChanged.connect(self.keySelected) plot_case_dock = self.addDock("Plot case", self.__case_selection_widget) self.__customize_plot_widget = CustomizePlotWidget() - self.__customize_plot_widget.customPlotSettingsChanged.connect(self.plotSettingsChanged) + self.__customize_plot_widget.customPlotSettingsChanged.connect(self.keySelected) customize_plot_dock = self.addDock("Customize", self.__customize_plot_widget) - self.__toolbar.exportClicked.connect(self.exportActivePlot) - self.__toolbar.plotScalesChanged.connect(self.plotSettingsChanged) - self.__toolbar.reportStepChanged.connect(self.plotSettingsChanged) - self.__exporter = None self.tabifyDockWidget(plot_case_dock, customize_plot_dock) plot_case_dock.show() plot_case_dock.raise_() - self.__plot_cases = self.__case_selection_widget.getPlotCaseNames() + self.__plot_widgets[self.__central_tab.currentIndex()].setActive() + self.__data_type_keys_widget.selectDefault() - def fetchDefaultXScales(self): - if self.__plot_data is not None: - active_plot = self.getActivePlot() - x_axis_type_name = active_plot.xAxisType() - - x_axis_type = self.__plot_metrics_tracker.getType(x_axis_type_name) - - if x_axis_type is not None: - x_min, x_max = active_plot.getXScales(self.__plot_data) - - if x_axis_type is CTime and x_min is not None and x_max is not None: - x_min = int(x_min) - x_max = int(x_max) - - self.__plot_metrics_tracker.setScalesForType(x_axis_type_name, x_min, x_max) - - - - def fetchDefaultYScales(self): - if self.__plot_data is not None: - active_plot = self.getActivePlot() - y_axis_type_name = active_plot.yAxisType() - - y_axis_type = self.__plot_metrics_tracker.getType(y_axis_type_name) - - if y_axis_type is not None: - y_min, y_max = active_plot.getYScales(self.__plot_data) - - if y_axis_type is CTime and y_min is not None and y_max is not None: - y_min = int(y_min) - y_max = int(y_max) - - self.__plot_metrics_tracker.setScalesForType(y_axis_type_name, y_min, y_max) - - - def resetCurrentScales(self): - active_plot = self.getActivePlot() - x_axis_type_name = active_plot.xAxisType() - y_axis_type_name = active_plot.yAxisType() - - self.__plot_metrics_tracker.resetScaleType(x_axis_type_name) - self.__plot_metrics_tracker.resetScaleType(y_axis_type_name) - - self.currentPlotChanged() - self.plotSettingsChanged() - - - def getActivePlot(self): - """ @rtype: PlotPanel """ - if not self.__central_tab.currentIndex() > -1: - raise AssertionError("No plot selected!") - - active_plot = self.__central_tab.currentWidget() - assert isinstance(active_plot, PlotPanel) - - return active_plot + def createDataGatherer(self, dataGatherFunc, gatherConditionFunc, refcaseGatherFunc=None, observationGatherFunc=None): + data_gatherer = PlotDataGatherer(dataGatherFunc, gatherConditionFunc, refcaseGatherFunc=refcaseGatherFunc, observationGatherFunc=observationGatherFunc) + self.__data_gatherers.append(data_gatherer) + return data_gatherer def currentPlotChanged(self): - active_plot = self.getActivePlot() + for plot_widget in self.__plot_widgets: + plot_widget.setActive(False) + index = self.__central_tab.indexOf(plot_widget) - if active_plot.isReady(): - x_axis_type_name = active_plot.xAxisType() - x_axis_type = self.__plot_metrics_tracker.getType(x_axis_type_name) - - y_axis_type_name = active_plot.yAxisType() - y_axis_type = self.__plot_metrics_tracker.getType(y_axis_type_name) - - if not self.__plot_metrics_tracker.hasScale(x_axis_type_name): - self.fetchDefaultXScales() - - if not self.__plot_metrics_tracker.hasScale(y_axis_type_name): - self.fetchDefaultYScales() - - x_min, x_max = self.__plot_metrics_tracker.getScalesForType(x_axis_type_name) - y_min, y_max = self.__plot_metrics_tracker.getScalesForType(y_axis_type_name) - - self.__toolbar.setToolBarOptions(x_axis_type, y_axis_type, active_plot.isReportStepCapable() and self.__plot_metrics_tracker.dataTypeSupportsReportStep()) - self.__toolbar.setScales(x_min, x_max, y_min, y_max) + if index == self.__central_tab.currentIndex() and plot_widget.canPlotKey(self.getSelectedKey()): + plot_widget.setActive() + plot_widget.updatePlot() - def plotSettingsChanged(self): - x_min, x_max = self.__toolbar.getXScales() - y_min, y_max = self.__toolbar.getYScales() + def createPlotContext(self, figure): + key = self.getSelectedKey() + cases = self.__case_selection_widget.getPlotCaseNames() + data_gatherer = next((data_gatherer for data_gatherer in self.__data_gatherers if data_gatherer.canGatherDataForKey(key)), None) + plot_config = PlotConfig(key) + self.applyCustomization(plot_config) + return PlotContext(self.__ert, figure, plot_config, cases, key, data_gatherer) - active_plot = self.getActivePlot() + def getSelectedKey(self): + key = str(self.__data_type_keys_widget.getSelectedItem()) + return key - x_axis_type_name = active_plot.xAxisType() - y_axis_type_name = active_plot.yAxisType() + def addPlotWidget(self, name, plotFunction, data_gatherers, enabled=True): + plot_condition_function_list = [data_gatherer.canGatherDataForKey for data_gatherer in data_gatherers] + plot_widget = PlotWidget(name, plotFunction, plot_condition_function_list, self.createPlotContext) - self.__plot_metrics_tracker.setScalesForType(x_axis_type_name, x_min, x_max) - self.__plot_metrics_tracker.setScalesForType(y_axis_type_name, y_min, y_max) - - self.updatePlots() - - - def updatePlots(self): - report_step = self.__toolbar.getReportStep() - - for plot_panel in self.__plot_panels: - if plot_panel.isPlotVisible(): - model = plot_panel.getPlotBridge() - model.setPlotData(self.__plot_data) - model.setCustomSettings(self.__customize_plot_widget.getCustomSettings()) - model.setReportStepTime(report_step) - - x_axis_type_name = plot_panel.xAxisType() - y_axis_type_name = plot_panel.yAxisType() - - x_min, x_max = self.__plot_metrics_tracker.getScalesForType(x_axis_type_name) - y_min, y_max = self.__plot_metrics_tracker.getScalesForType(y_axis_type_name) - - model.setScales(x_min, x_max, y_min, y_max) - - plot_panel.renderNow() - - - def exportActivePlot(self): - active_plot = self.getActivePlot() - - if self.__exporter is None: - path = None - else: - path = self.__exporter.getCurrentPath() - - - report_step = self.__toolbar.getReportStep() - - x_axis_type_name = active_plot.xAxisType() - y_axis_type_name = active_plot.yAxisType() - - x_min, x_max = self.__plot_metrics_tracker.getScalesForType(x_axis_type_name) - y_min, y_max = self.__plot_metrics_tracker.getScalesForType(y_axis_type_name) - - settings = {"x_min": x_min, - "x_max": x_max, - "y_min": y_min, - "y_max": y_max, - "report_step": report_step} - - self.__exporter = ExportPlot(active_plot, settings, self.__customize_plot_widget.getCustomSettings(), path) - - self.__exporter.export() - - - def addPlotPanel(self, name, path, short_name=None): - if short_name is None: - short_name = name - - plot_panel = PlotPanel(name, short_name, path) - plot_panel.plotReady.connect(self.plotReady) - self.__plot_panels.append(plot_panel) - self.__central_tab.addTab(plot_panel, name) + index = self.__central_tab.addTab(plot_widget, name) + self.__plot_widgets.append(plot_widget) + self.__central_tab.setTabEnabled(index, enabled) def addDock(self, name, widget, area=Qt.LeftDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): @@ -259,87 +131,24 @@ class PlotWindow(QMainWindow): return dock_widget - def checkPlotStatus(self): - for plot_panel in self.__plot_panels: - if not plot_panel.isReady(): - return False + def applyCustomization(self, plot_config): + custom = self.__customize_plot_widget.getCustomSettings() - if len(self.__plot_cases) == 0: - return False - - return True - - def plotReady(self): - if self.checkPlotStatus(): - self.__data_type_keys_widget.selectDefault() - self.currentPlotChanged() - self.__customize_plot_widget.emitChange() - - - def caseSelectionChanged(self): - self.__plot_cases = self.__case_selection_widget.getPlotCaseNames() - self.keySelected(self.__plot_metrics_tracker.getDataTypeKey()) - - - def showOrHidePlotTab(self, plot_panel, is_visible, show_plot): - plot_panel.setPlotIsVisible(show_plot) - if show_plot and not is_visible: - index = self.__plot_panels.index(plot_panel) - self.__central_tab.insertTab(index, plot_panel, plot_panel.getName()) - elif not show_plot and is_visible: - index = self.__central_tab.indexOf(plot_panel) - self.__central_tab.removeTab(index) + plot_config.setObservationsEnabled(custom["show_observations"]) + plot_config.setRefcaseEnabled(custom["show_refcase"]) + plot_config.setLegendEnabled(custom["show_legend"]) + plot_config.setGridEnabled(custom["show_grid"]) @may_take_a_long_time - def keySelected(self, key): - key = str(key) - old_data_type_key = self.__plot_metrics_tracker.getDataTypeKey() - self.__plot_metrics_tracker.setDataTypeKey(key) + def keySelected(self): + key = self.getSelectedKey() - plot_data_fetcher = PlotDataFetcher() - self.__plot_data = plot_data_fetcher.getPlotDataForKeyAndCases(key, self.__plot_cases) - self.__plot_data.setParent(self) + for plot_widget in self.__plot_widgets: + plot_widget.setDirty() + index = self.__central_tab.indexOf(plot_widget) + self.__central_tab.setTabEnabled(index, plot_widget.canPlotKey(key)) - self.__central_tab.blockSignals(True) - - self.__plot_panel_tracker.storePlotType(plot_data_fetcher, old_data_type_key) - - for plot_panel in self.__plot_panels: - self.showOrHidePlotTab(plot_panel, False, True) - - self.__plot_metrics_tracker.setDataTypeKeySupportsReportSteps(plot_data_fetcher.dataTypeKeySupportsReportSteps(key)) - show_pca = plot_data_fetcher.isPcaDataKey(key) - for plot_panel in self.__plot_panels: - visible = self.__central_tab.indexOf(plot_panel) > -1 - - if plot_data_fetcher.isSummaryKey(key): - show_plot = plot_panel.supportsPlotProperties(time=True, value=True, histogram=True, pca=show_pca) - self.showOrHidePlotTab(plot_panel, visible, show_plot) - - elif plot_data_fetcher.isBlockObservationKey(key): - show_plot = plot_panel.supportsPlotProperties(depth=True, value=True, pca=show_pca) - self.showOrHidePlotTab(plot_panel, visible, show_plot) - - elif plot_data_fetcher.isGenKWKey(key): - show_plot = plot_panel.supportsPlotProperties(value=True, histogram=True, pca=show_pca) - self.showOrHidePlotTab(plot_panel, visible, show_plot) - - elif plot_data_fetcher.isGenDataKey(key): - show_plot = plot_panel.supportsPlotProperties(index=True, pca=show_pca) - self.showOrHidePlotTab(plot_panel, visible, show_plot) - - elif plot_data_fetcher.isPcaDataKey(key): - show_plot = plot_panel.supportsPlotProperties(pca=show_pca) - self.showOrHidePlotTab(plot_panel, visible, show_plot) - - else: - raise NotImplementedError("Key %s not supported." % key) - - self.__plot_panel_tracker.restorePlotType(plot_data_fetcher, key) - - self.__central_tab.blockSignals(False) - self.currentPlotChanged() - - if self.checkPlotStatus(): - self.plotSettingsChanged() + for plot_widget in self.__plot_widgets: + if plot_widget.canPlotKey(key): + plot_widget.updatePlot() diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/report_step_widget.py b/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/report_step_widget.py deleted file mode 100644 index e16176470e..0000000000 --- a/ThirdParty/Ert/devel/python/python/ert_gui/tools/plot/report_step_widget.py +++ /dev/null @@ -1,45 +0,0 @@ -from PyQt4.QtCore import pyqtSignal, Qt -from PyQt4.QtGui import QWidget, QVBoxLayout, QLabel -from ert_gui.models.connectors.plot.report_steps import ReportStepsModel -from ert_gui.widgets.list_spin_box import ListSpinBox - - -class ReportStepWidget(QWidget): - reportStepTimeSelected = pyqtSignal(int) - def __init__(self): - QWidget.__init__(self) - - layout = QVBoxLayout() - self.setLayout(layout) - - def converter(item): - return "%s" % (str(item.date())) - - self.__items = ReportStepsModel().getList() - self.__time_spinner = ListSpinBox(self.__items) - self.__time_spinner.valueChanged[int].connect(self.valueSelected) - self.__time_spinner.setStringConverter(converter) - layout.addWidget(self.__time_spinner) - - self.__label = QLabel("Report Step") - - layout.addWidget(self.__label, 0, Qt.AlignHCenter) - layout.addStretch() - - - def valueSelected(self, index): - self.reportStepTimeSelected.emit(self.__items[index]) - - def getSelectedValue(self): - """ @rtype: CTime """ - index = self.__time_spinner.value() - return self.__items[index] - - def setFontSize(self, size): - font = self.__time_spinner.font() - font.setPointSize(size) - self.__time_spinner.setFont(font) - - font = self.__label.font() - font.setPointSize(size) - self.__label.setFont(font) diff --git a/ThirdParty/Ert/devel/python/python/ert_gui/widgets/custom_dialog.py b/ThirdParty/Ert/devel/python/python/ert_gui/widgets/custom_dialog.py index 9abc952aeb..fb969f41cc 100644 --- a/ThirdParty/Ert/devel/python/python/ert_gui/widgets/custom_dialog.py +++ b/ThirdParty/Ert/devel/python/python/ert_gui/widgets/custom_dialog.py @@ -83,6 +83,10 @@ class CustomDialog(QDialog): return qw + def addSpace(self, size=10): + """ Add some vertical spacing """ + space_widget = self.createSpace(size) + self.layout.addRow("", space_widget) def addOption(self, option_widget): """ @@ -93,6 +97,11 @@ class CustomDialog(QDialog): option_widget.validationChanged.connect(self.optionValidationChanged) self.layout.addRow(option_widget.getLabel(), option_widget) + def addWidget(self, widget, label=""): + if not label.endswith(":"): + label = "%s:" % label + self.layout.addRow(label, widget) + def addButtons(self): buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) diff --git a/ThirdParty/Ert/devel/python/tests/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/CMakeLists.txt index 23067e8a1f..f0cc9487fa 100644 --- a/ThirdParty/Ert/devel/python/tests/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/tests/CMakeLists.txt @@ -32,6 +32,7 @@ endfunction(addPythonTest) add_subdirectory(core) +add_subdirectory(share) if(BUILD_ERT) add_subdirectory(ert) diff --git a/ThirdParty/Ert/devel/python/tests/core/cwrap/test_basecvalue.py b/ThirdParty/Ert/devel/python/tests/core/cwrap/test_basecvalue.py index 572c023519..31acefcd16 100644 --- a/ThirdParty/Ert/devel/python/tests/core/cwrap/test_basecvalue.py +++ b/ThirdParty/Ert/devel/python/tests/core/cwrap/test_basecvalue.py @@ -1,4 +1,4 @@ -from ctypes import c_ubyte, c_long +from ctypes import c_ubyte, c_double from ert.cwrap import BaseCValue, clib, CWrapper from ert.test import ExtendedTestCase @@ -7,8 +7,8 @@ class UnsignedByteValue(BaseCValue): DATA_TYPE = c_ubyte -class TimeTValue(BaseCValue): - DATA_TYPE = c_long +class MaxDouble(BaseCValue): + DATA_TYPE = c_double class BaseCValueTest(ExtendedTestCase): @@ -17,8 +17,8 @@ class BaseCValueTest(ExtendedTestCase): self.ert_wrapper = CWrapper(ert) - self.ert_wrapper.registerType("time_t", TimeTValue) - self.make_date = self.ert_wrapper.prototype("time_t util_make_date(int, int, int)") + self.ert_wrapper.registerType("pow_double", MaxDouble) + self.double_max = self.ert_wrapper.prototype("pow_double util_double_max(double, double)") def test_illegal_type(self): @@ -62,8 +62,8 @@ class BaseCValueTest(ExtendedTestCase): UnsignedByteValue.from_param("exception") - def test_time_t(self): - future = self.make_date(1, 1, 2050) + def test_double_max(self): + double_max = self.double_max(2.97, 2.98) - self.assertIsInstance(future, TimeTValue) - self.assertEqual(future.value(), 2524604400) + self.assertIsInstance(double_max, MaxDouble) + self.assertEqual(double_max.value(), 2.98) diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/core/ecl/CMakeLists.txt index 67cc33090b..ff37b91ddc 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/CMakeLists.txt @@ -31,6 +31,7 @@ set(TEST_SOURCES test_rft_cell.py test_statoil_faults.py test_sum.py + test_ecl_util.py ) add_python_package("python.tests.ecl" ${PYTHON_INSTALL_PREFIX}/tests/ecl "${TEST_SOURCES}" False) @@ -62,6 +63,7 @@ addPythonTest(ecl.fault_blocks ecl.test_fault_blocks.FaultBlockTest ) addPythonTest(ecl.fault_blocks_statoil ecl.test_fault_blocks_statoil.FaultBlockTest LABELS StatoilData) addPythonTest(ecl.ecl_npv ecl.test_npv.NPVTest LABELS StatoilData) addPythonTest(ecl.ecl_deprecation ecl.test_deprecation.DeprecationTest ) +addPythonTest(ecl.ecl_util ecl.test_ecl_util.EclUtilTest ) addPythonTest(ecl.indexed_read ecl.test_indexed_read.EclIndexedReadTest LABELS StatoilData) @@ -74,4 +76,4 @@ if (NOT ${NFS_RUNPATH} STREQUAL "") if (NOT ${RSH_SERVERS} STREQUAL "") addPythonTest(ert.ecl.ecl_queue_RSH tests.ecl.test_ecl_submit.RSHSubmitTest ARGUMENTS ${NFS_RUNPATH} ${RSH_SERVERS} LABELS StatoilData:Slow) endif() -endif() \ No newline at end of file +endif() diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_deprecation.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_deprecation.py index 966ffce403..f4aaf00bb7 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/test_deprecation.py +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_deprecation.py @@ -25,7 +25,7 @@ from ert.util import BoolVector class DeprecationTest(ExtendedTestCase): def test_EclGrid_get_corner_xyz(self): - grid = EclGrid.create_rectangular( (10,20,30) , (1,1,1) ) + grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) with warnings.catch_warnings(): grid.get_corner_xyz(0 , global_index = 10) @@ -33,13 +33,20 @@ class DeprecationTest(ExtendedTestCase): with warnings.catch_warnings(): import ert.ecl.ecl as ecl + # Added in 1.8.x development def test_EclGrid_dims_property(self): - grid = EclGrid.create_rectangular( (10,20,30) , (1,1,1) ) + grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) with warnings.catch_warnings(): d = grid.dims + # Added in 1.9.x development + def test_EclGrid_dims_property(self): + with warnings.catch_warnings(): + grid = EclGrid.create_rectangular( (10,20,30) , (1,1,1) ) + + # Added in 1.8.x development @@ -56,7 +63,7 @@ class DeprecationTest(ExtendedTestCase): # Added in 1.8.x development def test_EclRegion_properties(self): - grid = EclGrid.create_rectangular( (10,10,10) , (1,1,1)) + grid = EclGrid.createRectangular( (10,10,10) , (1,1,1)) region = EclRegion( grid , False ) with warnings.catch_warnings(): @@ -76,4 +83,7 @@ class DeprecationTest(ExtendedTestCase): # Deprecated method from 1.8.4 def test_BoolVector_active_mask(self): with warnings.catch_warnings(): - active_vector = BoolVector.active_mask("1,1,1,1,1,1") \ No newline at end of file + active_vector = BoolVector.active_mask("1,1,1,1,1,1") + + + diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_sum_tstep.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_sum_tstep.py new file mode 100644 index 0000000000..ddcdcaa609 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_sum_tstep.py @@ -0,0 +1,41 @@ +from datetime import datetime +import random +from ert.ecl import EclSumTStep, EclSum +from ert.test import ExtendedTestCase + + +class EclSumTStepTest(ExtendedTestCase): + + def test_creation(self): + ecl_sum = EclSum.writer("TEST", datetime(2010, 1, 1), 10, 10, 10) + ecl_sum.addVariable("FOPT") + ecl_sum.addVariable("FOPR") + + smspec = ecl_sum.cNamespace().get_smspec(ecl_sum) + + test_data = [(1, 0, 10), (1, 1, 20), (1, 2, 30), (2, 0, 40)] + + for report_step, mini_step, sim_days in test_data: + ecl_sum_tstep = EclSumTStep(report_step, mini_step, sim_days, smspec) + + self.assertEqual(ecl_sum_tstep.getSimDays(), sim_days) + self.assertEqual(ecl_sum_tstep.getReport(), report_step) + self.assertEqual(ecl_sum_tstep.getMiniStep(), mini_step) + + self.assertTrue("FOPT" in ecl_sum_tstep) + self.assertTrue("FOPR" in ecl_sum_tstep) + self.assertFalse("WWCT" in ecl_sum_tstep) + + random_float = random.random() + ecl_sum_tstep["FOPT"] = random_float + ecl_sum_tstep["FOPR"] = random_float + 1 + + self.assertAlmostEqual(random_float, ecl_sum_tstep["FOPT"], places=5) + self.assertAlmostEqual(random_float + 1, ecl_sum_tstep["FOPR"], places=5) + + with self.assertRaises(KeyError): + ecl_sum_tstep["FROPR"] = 2 + + with self.assertRaises(KeyError): + value = ecl_sum_tstep["FROPR"] + diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_util.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_util.py new file mode 100644 index 0000000000..5e174aa353 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_ecl_util.py @@ -0,0 +1,31 @@ +# Copyright (C) 2015 Statoil ASA, Norway. +# +# The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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 3 of the License, or +# (at your option) any later version. +# +# ERT 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 at +# for more details. + +from ert.ecl import EclUtil, EclTypeEnum , EclFileEnum +from ert.test import ExtendedTestCase + + +class EclUtilTest(ExtendedTestCase): + + def test_enums(self): + source_file_path = "libecl/include/ert/ecl/ecl_util.h" + self.assertEnumIsFullyDefined(EclFileEnum, "ecl_file_enum", source_file_path) + + + def test_file_type(self): + file_type , fmt , report = EclUtil.inspectExtension("CASE.X0078") + self.assertEqual( file_type , EclFileEnum.ECL_RESTART_FILE ) + diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_faults.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_faults.py index f0576dd69d..0407f4a65b 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/test_faults.py +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_faults.py @@ -17,19 +17,24 @@ from unittest import skipIf import time +from ert import util from ert.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment,FaultBlockLayer from ert.ecl import EclGrid, EclKW, EclTypeEnum from ert.test import ExtendedTestCase, TestAreaContext from ert.geo import Polyline , CPolyline + class FaultTest(ExtendedTestCase): + @classmethod + def setUpClass(cls): + cls.grid = EclGrid.create_rectangular( (151,100,50) , (1,1,1)) + def setUp(self): self.faults1 = self.createTestPath("local/ECLIPSE/FAULTS/fault1.grdecl") self.faults2 = self.createTestPath("local/ECLIPSE/FAULTS/fault2.grdecl") - self.grid = EclGrid.create_rectangular( (151,100,50) , (1,1,1)) - - + + def test_PolylineIJ(self): nx = 10 ny = 10 @@ -506,10 +511,9 @@ class FaultTest(ExtendedTestCase): \'F\' 110 110 49 49 1 43 \'X\' / \'F\' 111 111 48 48 1 43 \'Y\' / / -""") - with open("faults.grdecl") as f: - faults = FaultCollection( grid , "faults.grdecl" ) - +""") + faults = FaultCollection( grid , "faults.grdecl" ) + fault = faults["F"] layer = fault[29] self.assertEqual(len(layer) , 2) @@ -518,7 +522,7 @@ class FaultTest(ExtendedTestCase): line2 = layer[1] self.assertEqual(len(line1) , 4) self.assertEqual(len(line2) , 2) - + seg0 = line1[0] seg1 = line1[1] seg2 = line1[2] @@ -527,7 +531,7 @@ class FaultTest(ExtendedTestCase): self.assertEqual( seg1.getCorners() , (50 * (nx + 1) + 107 , 50 * (nx + 1) + 108)) self.assertEqual( seg2.getCorners() , (50 * (nx + 1) + 108 , 49 * (nx + 1) + 108)) self.assertEqual( seg3.getCorners() , (49 * (nx + 1) + 108 , 49 * (nx + 1) + 109)) - + @@ -647,8 +651,7 @@ class FaultTest(ExtendedTestCase): \'F2\' 1 8 2 2 1 1 \'Y\' / / """) - with open("faults.grdecl") as f: - faults = FaultCollection( grid , "faults.grdecl" ) + faults = FaultCollection( grid , "faults.grdecl" ) f1 = faults["F1"] f2 = faults["F2"] diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_grid.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_grid.py index 006fc8b747..db07243322 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/test_grid.py +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_grid.py @@ -132,6 +132,10 @@ class GridTest(ExtendedTestCase): self.assertEqual( actnum[0] , 1 ) self.assertEqual( actnum[nx*ny*nz - 1] , 1 ) + actnum_kw = grid.exportACTNUMKw( ) + self.assertEqual(len(actnum_kw) , len(actnum)) + for a1,a2 in zip(actnum, actnum_kw): + self.assertEqual(a1, a2) diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_kw.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_kw.py index e29562f32d..9e2c16a473 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/test_kw.py +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_kw.py @@ -259,8 +259,16 @@ class KWTest(ExtendedTestCase): self.assertEqual(kw[4] , 66) self.assertEqual(kw[5] , 99) + + def test_long_name(self): + with self.assertRaises(ValueError): + EclKW.create("LONGLONGNAME" , 10 , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.create("REGIONS" , 10 , EclTypeEnum.ECL_INT_TYPE) + with self.assertRaises(ValueError): + kw.set_name("LONGLONGNAME") + #def cutoff( x , arg ): # if x < arg: # return 0 diff --git a/ThirdParty/Ert/devel/python/tests/core/ecl/test_layer.py b/ThirdParty/Ert/devel/python/tests/core/ecl/test_layer.py index 713dac5a4f..26a176288f 100644 --- a/ThirdParty/Ert/devel/python/tests/core/ecl/test_layer.py +++ b/ThirdParty/Ert/devel/python/tests/core/ecl/test_layer.py @@ -259,7 +259,6 @@ class LayerTest(ExtendedTestCase): pl = CPolyline( init_points = [(0 , 0) , (d/2 , d/2) , (d,d)]) layer.addPolylineBarrier( pl , grid , 0) for i in range(d): - print i self.assertTrue( layer.bottomBarrier(i,i) ) if i < (d - 1): self.assertTrue( layer.leftBarrier(i+1,i) ) @@ -296,3 +295,12 @@ class LayerTest(ExtendedTestCase): layer.assign(10) self.assertEqual( layer.cellSum() , 500 ) + + + def test_count_equal(self): + layer = Layer(10,10) + self.assertEqual( 100 , layer.countEqual( 0 )) + self.assertEqual( 0 , layer.countEqual( 1 )) + + layer[3,3] = 3 + self.assertEqual( 1 , layer.countEqual( 3 )) diff --git a/ThirdParty/Ert/devel/python/tests/core/util/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/core/util/CMakeLists.txt index 962c7bf8f8..99f023ad3f 100644 --- a/ThirdParty/Ert/devel/python/tests/core/util/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/tests/core/util/CMakeLists.txt @@ -10,10 +10,13 @@ set(TEST_SOURCES test_string_list.py test_substitution_list.py test_thread_pool.py + test_cthread_pool.py test_ui_return.py test_vectors.py test_version.py test_work_area.py + test_path_context.py + test_arg_pack.py ) add_python_package("python.tests.core.util" ${PYTHON_INSTALL_PREFIX}/tests/core/util "${TEST_SOURCES}" False) @@ -29,7 +32,11 @@ addPythonTest(core.util.tvector core.util.test_vectors.UtilTest) addPythonTest(core.util.ui_return core.util.test_ui_return.UIReturnTest) addPythonTest(core.util.work_area core.util.test_work_area.WorkAreaTest) addPythonTest(core.util.version core.util.test_version.VersionTest) +addPythonTest(core.util.path_context core.util.test_path_context.PathContextTest) +addPythonTest(core.util.thread_pool core.util.test_thread_pool.ThreadPoolTest) +addPythonTest(core.util.cthread_pool core.util.test_cthread_pool.CThreadPoolTest) +addPythonTest(core.util.arg_pack core.util.test_arg_pack.ArgPackTest) #add_test( NAME python.tests.ert.util.latex # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -# COMMAND ctest_run.py ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} core.util.test_latex.LatexTest ) \ No newline at end of file +# COMMAND ctest_run.py ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX} core.util.test_latex.LatexTest ) diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_arg_pack.py b/ThirdParty/Ert/devel/python/tests/core/util/test_arg_pack.py new file mode 100644 index 0000000000..3c6c003c58 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_arg_pack.py @@ -0,0 +1,39 @@ +import ctypes +from ert.cwrap import clib +from ert.util import ArgPack, StringList +from ert.test import ExtendedTestCase + +TEST_LIB = clib.ert_load("libtest_util") + +class ArgPackTest(ExtendedTestCase): + + def test_create(self): + arg = ArgPack() + self.assertEqual( len(arg) , 0 ) + + arg.append( StringList( ) ) + self.assertEqual( len(arg) , 1 ) + + arg.append(3.14) + self.assertEqual( len(arg) , 2 ) + + o = object() + with self.assertRaises(TypeError): + arg.append( o ) + + + def test_args(self): + arg = ArgPack(1,2,3) + self.assertEqual( len(arg) , 3) + + + def test_append_ptr(self): + arg = ArgPack( StringList() ) + self.assertEqual( len(arg) , 1) + + func = getattr( TEST_LIB , "test_argpack_is_stringlist" ) + func.restype = None + func.argtypes = [ ArgPack ] + + func( arg ) + diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_cthread_pool.py b/ThirdParty/Ert/devel/python/tests/core/util/test_cthread_pool.py new file mode 100644 index 0000000000..999aecfcd6 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_cthread_pool.py @@ -0,0 +1,41 @@ +import time +import ctypes +from ert.cwrap import clib +from ert.util import CThreadPool , startCThreadPool +from ert.test import ExtendedTestCase + +TEST_LIB = clib.ert_load("libtest_util") + + +class CThreadPoolTest(ExtendedTestCase): + + def test_cfunc(self): + with self.assertRaises( TypeError ): + func = CThreadPool.lookupCFunction( "WRONG-TYPE" , "no-this-does-not-exist") + + with self.assertRaises( AttributeError ): + func = CThreadPool.lookupCFunction( TEST_LIB , "no-this-does-not-exist") + + + + def test_create(self): + pool = CThreadPool(32 , start = True) + job = CThreadPool.lookupCFunction( TEST_LIB , "thread_pool_test_func1") + arg = ctypes.c_int(0) + + N = 256 + for i in range(N): + pool.addTask( job , ctypes.byref( arg ) ) + pool.join() + self.assertEqual( arg.value , N ) + + + def test_context(self): + N = 256 + arg = ctypes.c_int(0) + job = CThreadPool.lookupCFunction( TEST_LIB , "thread_pool_test_func1") + with startCThreadPool( 16 ) as tp: + for i in range(N): + tp.addTask( job , ctypes.byref( arg ) ) + self.assertEqual( arg.value , N ) + diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_ctime.py b/ThirdParty/Ert/devel/python/tests/core/util/test_ctime.py index 380497efa8..70e48820f9 100644 --- a/ThirdParty/Ert/devel/python/tests/core/util/test_ctime.py +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_ctime.py @@ -1,8 +1,13 @@ from datetime import datetime, date - +import time +from pytz import timezone from ert.util import CTime +def timezoneOffsetInSeconds(dt): + local_timezone = timezone(CTime.timezone()) + return int(local_timezone.utcoffset(dt).total_seconds()) + try: from unittest2 import TestCase except ImportError: @@ -11,13 +16,15 @@ except ImportError: class CTimeTest(TestCase): + def test_creation(self): - t0 = CTime(-60 * 60) + delta = timezoneOffsetInSeconds(datetime(1970, 1, 1)) + t0 = CTime(-delta) t1 = CTime(t0) self.assertEqual(t0, t1) - t2 = CTime(datetime(1970, 1, 1, 0)) + t2 = CTime(datetime(1970, 1, 1)) self.assertEqual(t0, t2) t3 = CTime(date(1970, 1, 1)) @@ -28,10 +35,13 @@ class CTimeTest(TestCase): def test_c_time(self): - c_time = CTime(0) - self.assertEqual(str(c_time), "1970-01-01 01:00:00") + delta = timezoneOffsetInSeconds(datetime(1970, 1, 1)) + c_time = CTime(-delta) + py_time = datetime(1970, 1, 1) - date_time = CTime(datetime(1970, 1, 1, 1, 0, 0)) + self.assertEqual(str(c_time), py_time.strftime("%Y-%m-%d %H:%M:%S%z")) + + date_time = CTime(py_time) self.assertEqual(c_time, date_time) date_time_after = CTime(datetime(1970, 1, 1, 1, 0, 5)) @@ -127,3 +137,21 @@ class CTimeTest(TestCase): self.assertTrue(c0 <= c2 <= d2) self.assertTrue(dt0 <= c2 <= c2) + + + def test_conversion(self): + t = CTime(0) + + self.assertEqual(t.value(), 0) + self.assertEqual(t.ctime(), 0) + self.assertEqual(t.time(), time.localtime(0)) + + # These conversions depend on timezone + utc = timezone('utc') + local_timezone = timezone(CTime.timezone()) + + localized_dt = local_timezone.localize(t.datetime()) + self.assertEqual(localized_dt.astimezone(utc), datetime(1970, 1, 1, 0, tzinfo=utc)) + + localized_d = datetime(1970, 1, 1, 0, tzinfo=utc).astimezone(local_timezone) + self.assertEqual(t.date(), localized_d.date()) diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_path_context.py b/ThirdParty/Ert/devel/python/tests/core/util/test_path_context.py new file mode 100644 index 0000000000..06cb537574 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_path_context.py @@ -0,0 +1,40 @@ +import os +from ert.test import ExtendedTestCase, PathContext,TestAreaContext + + +class PathContextTest(ExtendedTestCase): + def test_error(self): + with self.assertRaises(OSError): + with PathContext("/usr/lib/testing"): + pass + + with open("/tmp/file" , "w") as f: + f.write("xx") + + with self.assertRaises(OSError): + with PathContext("/tmp/file"): + pass + + + def test_chdir(self): + with PathContext("/tmp/pc"): + self.assertEqual( os.getcwd() , "/tmp/pc") + + + def test_cleanup(self): + with TestAreaContext("pathcontext"): + os.makedirs("path/1") + + with self.assertRaises(OSError): + with PathContext("path/1"): + pass + + with PathContext("path/1/next/2/level"): + with open("../../file" , "w") as f: + f.write("Crap") + + self.assertTrue(os.path.isdir("path/1")) + self.assertTrue(os.path.isdir("path/1/next")) + self.assertFalse(os.path.isdir("path/1/next/2")) + + diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_string_list.py b/ThirdParty/Ert/devel/python/tests/core/util/test_string_list.py index 95796c1e27..c8d8947fc6 100644 --- a/ThirdParty/Ert/devel/python/tests/core/util/test_string_list.py +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_string_list.py @@ -74,10 +74,16 @@ class StringListTest(TestCase): self.assertTrue("Bjarne" not in s) def test_append(self): - s = StringList(["A", "B"]) - s.append("C") - self.assertEqual(list(s), ["A", "B", "C"]) + s1 = StringList(["A", "B"]) + s1.append("C") + s2 = StringList(["A","B","C"]) + self.assertEqual(s1, ["A", "B", "C"]) + self.assertEqual(s1, s2) + self.assertFalse(s1 == ["A","B","D"]) + self.assertFalse(s1 == ["A","B","C" , "D"]) + + def test_append_not_string(self): s = StringList() s.append(10) diff --git a/ThirdParty/Ert/devel/python/tests/core/util/test_vectors.py b/ThirdParty/Ert/devel/python/tests/core/util/test_vectors.py index 7762b9827f..10a1faaa68 100644 --- a/ThirdParty/Ert/devel/python/tests/core/util/test_vectors.py +++ b/ThirdParty/Ert/devel/python/tests/core/util/test_vectors.py @@ -128,7 +128,16 @@ class UtilTest(TestCase): active_list = IntVector.active_list("1,10,100-105X") self.assertFalse(active_list) + + def test_value_list(self): + list2 = IntVector.valueList("3,10-12,0,1") + self.assertTrue( len(list2) == 6 ) + expected = [3,10,11,12,0,1] + for v1,v2 in zip(list2,expected): + self.assertEqual( v1 , v2) + + def test_contains_int(self): iv = IntVector() diff --git a/ThirdParty/Ert/devel/python/tests/ctest_run.py b/ThirdParty/Ert/devel/python/tests/ctest_run.py index ceeafa47bf..1ab2bb37a6 100644 --- a/ThirdParty/Ert/devel/python/tests/ctest_run.py +++ b/ThirdParty/Ert/devel/python/tests/ctest_run.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +import os import sys try: @@ -7,27 +8,21 @@ except ImportError: from unittest import TextTestRunner -def runTestCase(tests): - test_result = TextTestRunner(verbosity=0).run(tests) - if test_result.errors or test_result.failures: - for (test, trace_back) in test_result.errors: - sys.stderr.write("=================================================================\n") - sys.stderr.write("Test:%s error \n" % test.id()) - sys.stderr.write("%s\n" % trace_back) - - for (test, trace_back) in test_result.failures: - sys.stderr.write("=================================================================\n") - sys.stderr.write("Test:%s failure \n" % test.id()) - sys.stderr.write("%s\n" % trace_back) +def runTestCase(tests, verbosity=0): + test_result = TextTestRunner(verbosity=verbosity).run(tests) + if len(test_result.errors) or len(test_result.failures): + test_result.printErrors() return False else: return True if __name__ == '__main__': - PYTHONPATH = sys.argv[1] - sys.path.insert(0, PYTHONPATH) + TEST_PYTHONPATH = sys.argv[1] + os.environ["PYTHONPATH"] = TEST_PYTHONPATH + os.pathsep + os.getenv("PYTHONPATH", "") + for path_element in reversed(TEST_PYTHONPATH.split(os.pathsep)): + sys.path.insert(0, path_element) test_class_path = sys.argv[2] argv = [] @@ -38,9 +33,11 @@ if __name__ == '__main__': pass from ert.test import ErtTestRunner + tests = ErtTestRunner.getTestsFromTestClass(test_class_path, argv) - if runTestCase(tests): + # Set verbosity to 2 to see which test method in a class that fails. + if runTestCase(tests, verbosity=0): sys.exit(0) else: sys.exit(1) diff --git a/ThirdParty/Ert/devel/python/tests/ert/config/test_config.py b/ThirdParty/Ert/devel/python/tests/ert/config/test_config.py index a348289dc7..80cf5f389b 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/config/test_config.py +++ b/ThirdParty/Ert/devel/python/tests/ert/config/test_config.py @@ -14,6 +14,7 @@ # # See the GNU General Public License at # for more details. +import os from ert.config import ContentTypeEnum, UnrecognizedEnum, SchemaItem, ContentItem, ContentNode, ConfigParser, ConfigContent from ert.test import ExtendedTestCase, TestAreaContext @@ -123,12 +124,16 @@ class ConfigTest(ExtendedTestCase): schema_item.iset_type(2 , ContentTypeEnum.CONFIG_INT ) schema_item.iset_type(3 , ContentTypeEnum.CONFIG_BOOL ) schema_item.iset_type(4 , ContentTypeEnum.CONFIG_FLOAT ) - + schema_item.iset_type(5 , ContentTypeEnum.CONFIG_PATH ) + with TestAreaContext("config/parse2"): with open("config","w") as fileH: - fileH.write("KEY VALUE1 VALUE2 100 True 3.14\n") - - content = conf.parse("config") + fileH.write("KEY VALUE1 VALUE2 100 True 3.14 path/file.txt\n") + + cwd0 = os.getcwd( ) + os.makedirs("tmp") + os.chdir("tmp") + content = conf.parse("../config") self.assertTrue( content.isValid() ) self.assertTrue( "KEY" in content ) self.assertFalse( "NOKEY" in content ) @@ -139,11 +144,30 @@ class ConfigTest(ExtendedTestCase): item = content["KEY"] self.assertEqual(len(item) , 1) + line = item[0] + with self.assertRaises(TypeError): + line.getPath(4) + + with self.assertRaises(TypeError): + line.getPath() + + + rel_path = line.getPath(index = 5, absolute = False) + self.assertEqual( rel_path , "../path/file.txt" ) + get = line[5] + self.assertEqual( get , "../path/file.txt") + abs_path = line.getPath(index = 5) + self.assertEqual( abs_path , os.path.join(cwd0 , "path/file.txt")) + + rel_path = line.getPath(index = 5, absolute = False , relative_start = "../") + self.assertEqual( rel_path , "path/file.txt" ) + + with self.assertRaises(IndexError): item[10] node = item[0] - self.assertEqual(len(node) , 5) + self.assertEqual(len(node) , 6) with self.assertRaises(IndexError): node[6] @@ -152,7 +176,7 @@ class ConfigTest(ExtendedTestCase): self.assertEqual( node[2] , 100 ) self.assertEqual( node[3] , True ) self.assertEqual( node[4] , 3.14) - + self.assertEqual( content.getValue( "KEY" , 0 , 1 ) , "VALUE2" ) self.assertEqual( content.cNamespace().iget( content , "KEY" , 0 , 1) , "VALUE2") @@ -171,7 +195,7 @@ class ConfigTest(ExtendedTestCase): self.assertEqual( content.cNamespace().get_occurences( content , "KEY" ) , 1) self.assertEqual( content.cNamespace().get_occurences( content , "MISSING-KEY" ) , 0) - + def test_schema(self): schema_item = SchemaItem("TestItem") diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/ert/enkf/CMakeLists.txt index 2fe35a5ac7..7784525f43 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/enkf/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/CMakeLists.txt @@ -19,6 +19,7 @@ set(TEST_SOURCES test_labscale.py test_linalg.py test_local_obsdata_node.py + test_local_config.py test_meas_block.py test_meas_data.py test_obs_block.py @@ -32,12 +33,14 @@ set(TEST_SOURCES test_time_map.py test_update.py test_ensemble_config.py + test_deprecation.py ) add_python_package("python.tests.ert.enkf" ${PYTHON_INSTALL_PREFIX}/tests/ert/enkf "${TEST_SOURCES}" False) addPythonTest(ert.enkf.enkf tests.ert.enkf.test_enkf.EnKFTest LABELS StatoilData) addPythonTest(ert.enkf.enkf_obs tests.ert.enkf.test_enkf_obs.EnKFObsTest LABELS StatoilData) +addPythonTest(ert.enkf.deprecation tests.ert.enkf.test_deprecation.DeprecationTest) addPythonTest(ert.enkf.meas_block tests.ert.enkf.test_meas_block.MeasBlockTest) addPythonTest(ert.enkf.meas_data tests.ert.enkf.test_meas_data.MeasDataTest) addPythonTest(ert.enkf.obs_data tests.ert.enkf.test_obs_data.ObsDataTest) @@ -66,6 +69,7 @@ addPythonTest(ert.enkf.update tests.ert.enkf.test_update.UpdateTest LABELS Stato addPythonTest(ert.enkf.labscale tests.ert.enkf.test_labscale.LabScaleTest LABELS StatoilData) addPythonTest(ert.enkf.active_list tests.ert.enkf.test_active_list.ActiveListTest) addPythonTest(ert.enkf.local_obsdata_node tests.ert.enkf.test_local_obsdata_node.LocalObsdataNodeTest) +addPythonTest(ert.enkf.local_config tests.ert.enkf.test_local_config.LocalConfigTest) addPythonTest(ert.enkf.ensemble_config tests.ert.enkf.test_ensemble_config.EnsembleConfigTest) add_subdirectory(data) diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/export/test_numpy_and_pandas.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/export/test_numpy_and_pandas.py index f83ddfcfcb..e3763467ff 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/enkf/export/test_numpy_and_pandas.py +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/export/test_numpy_and_pandas.py @@ -1,5 +1,6 @@ import numpy -from pandas import MultiIndex, DataFrame, pandas +from pandas import MultiIndex, DataFrame +import pandas as pandas from ert.test import ExtendedTestCase diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_deprecation.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_deprecation.py new file mode 100644 index 0000000000..3a09b9f5e5 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_deprecation.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'test_deprecation.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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 3 of the License, or +# (at your option) any later version. +# +# ERT 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 at +# for more details. +import warnings + +from ert.test import ErtTestContext, ExtendedTestCase + + +class DeprecationTest(ExtendedTestCase): + def setUp(self): + self.config_file = self.createTestPath("local/simple_config/minimum_config") + self.obs_file = self.createTestPath("local/simple_config/minimum_config") + + + # Added in 1.10 development + def test(self): + with ErtTestContext("enkf_deprecation", self.config_file) as test_context: + ert = test_context.getErt() + + ecl_config = ert.eclConfig() + with warnings.catch_warnings(): + ecl_config.get_grid( ) + + diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_enkf_obs.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_enkf_obs.py index f647aadc1f..6d579e4c9b 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_enkf_obs.py +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_enkf_obs.py @@ -6,7 +6,8 @@ from ert.sched import History from ert.util import BoolVector,IntVector from ert.enkf import ActiveMode, EnsembleConfig -from ert.enkf import ObsVector , LocalObsdata, EnkfObs, TimeMap +from ert.enkf.enums import EnkfStateType +from ert.enkf import ObsVector , LocalObsdata, EnkfObs, TimeMap, LocalObsdataNode , ObsData , MeasData, ActiveList class EnKFObsTest(ExtendedTestCase): @@ -17,13 +18,78 @@ class EnKFObsTest(ExtendedTestCase): self.refcase = self.createTestPath("Statoil/config/obs_testing/EXAMPLE_01_BASE") self.grid = self.createTestPath("Statoil/config/obs_testing/EXAMPLE_01_BASE.EGRID") + + def test_scale_obs(self): + with ErtTestContext("obs_test", self.config_file) as test_context: + ert = test_context.getErt() + obs = ert.getObservations() + + obs1 = obs["WWCT:OP_1"].getNode( 50 ) + obs2 = obs["WWCT:OP_1_50"].getNode( 50 ) + + self.assertEqual( obs1.getStandardDeviation( ) , obs2.getStandardDeviation( )) + std0 = obs1.getStandardDeviation( ) + + local_obsdata = LocalObsdata("obs" , obs) + node1 = LocalObsdataNode( "WWCT:OP_1" ) + node1.addRange( 50 , 50 ) + node2 = LocalObsdataNode( "WWCT:OP_1_50" ) + node2.addRange( 50 , 50 ) + local_obsdata.addNode( node1 ) + local_obsdata.addNode( node2 ) + + mask = BoolVector( default_value = True ) + mask[2] = True + meas_data = MeasData(mask) + obs_data = ObsData( ) + fs = ert.getEnkfFsManager().getCurrentFileSystem() + active_list = IntVector() + active_list.initRange(0,2,1) + obs.getObservationAndMeasureData( fs , local_obsdata , EnkfStateType.FORECAST , active_list , meas_data , obs_data ) + self.assertEqual( 2 , len(obs_data) ) + + v1 = obs_data[0] + v2 = obs_data[1] + + self.assertEqual( v1[1] , std0 ) + self.assertEqual( v2[1] , std0 ) + + meas_data = MeasData(mask) + obs_data = ObsData( 10 ) + obs.getObservationAndMeasureData( fs , local_obsdata , EnkfStateType.FORECAST , active_list , meas_data , obs_data ) + self.assertEqual( 2 , len(obs_data) ) + + v1 = obs_data[0] + v2 = obs_data[1] + + self.assertEqual( v1[1] , std0*10) + self.assertEqual( v2[1] , std0*10 ) + + actl = ActiveList() + obs1.updateStdScaling( 10 , actl) + obs2.updateStdScaling( 20 , actl) + meas_data = MeasData(mask) + obs_data = ObsData( ) + obs.getObservationAndMeasureData( fs , local_obsdata , EnkfStateType.FORECAST , active_list , meas_data , obs_data ) + self.assertEqual( 2 , len(obs_data) ) + + v1 = obs_data[0] + v2 = obs_data[1] + + self.assertEqual( v1[1] , std0*10) + self.assertEqual( v2[1] , std0*20) + + + + + def testObs(self): with ErtTestContext("obs_test", self.config_file) as test_context: ert = test_context.getErt() obs = ert.getObservations() - self.assertEqual(31, len(obs)) + self.assertEqual(32, len(obs)) for v in obs: self.assertTrue(isinstance(v, ObsVector)) @@ -59,7 +125,7 @@ class EnKFObsTest(ExtendedTestCase): active_list.initRange(0 , ert.getEnsembleSize() , 1 ) obs = ert.getObservations() - obs_data = LocalObsdata( "OBSxx" ) + obs_data = LocalObsdata( "OBSxx" , obs ) obs_vector = obs["WWCT:OP_1"] obs_data.addObsVector( obs_vector ) scale_factor = obs.scaleCorrelatedStd( fs , obs_data , active_list ) @@ -111,15 +177,15 @@ class EnKFObsTest(ExtendedTestCase): obs.load("/does/not/exist") self.assertTrue( obs.load(self.obs_config) ) - self.assertEqual( len(obs) , 32 ) + self.assertEqual( len(obs) , 33 ) obs.clear() self.assertEqual( len(obs) , 0 ) obs.load(self.obs_config) - self.assertEqual( len(obs) , 32 ) + self.assertEqual( len(obs) , 33 ) self.assertFalse( "RFT2" in obs ) obs.load(self.obs_config2) - self.assertEqual( len(obs) , 33 ) + self.assertEqual( len(obs) , 35 ) self.assertTrue( "RFT2" in obs ) @@ -127,11 +193,30 @@ class EnKFObsTest(ExtendedTestCase): def test_ert_obs_reload(self): with ErtTestContext("obs_test_reload", self.config_file) as test_context: ert = test_context.getErt() - obs = ert.getObservations() - self.assertEqual( len(obs) , 31 ) - ert.loadObservations("observations2") - self.assertEqual( len(obs) , 1 ) - - ert.loadObservations("observations" , clear = False) - self.assertEqual( len(obs) , 32 ) + ens_config = ert.ensembleConfig( ) + wwct_op1 = ens_config["WWCT:OP_1"] + wopr_op5 = ens_config["WOPR:OP_5"] + obs = ert.getObservations() + self.assertEqual( len(obs) , 32 ) + + keys = wwct_op1.getObservationKeys() + self.assertEqual( len(keys) , 2 ) + self.assertTrue( "WWCT:OP_1" in keys ) + self.assertTrue( "WWCT:OP_1_50" in keys ) + + self.assertEqual( wopr_op5.getObservationKeys() , [] ) + + ert.loadObservations("observations2") + self.assertEqual( len(obs) , 2 ) + self.assertEqual( wwct_op1.getObservationKeys() , [] ) + self.assertEqual( wopr_op5.getObservationKeys() , ["WOPR:OP_5"] ) + + ert.loadObservations("observations" , clear = False) + self.assertEqual( len(obs) , 34 ) + keys = wwct_op1.getObservationKeys() + self.assertEqual( len(keys) , 2 ) + self.assertTrue( "WWCT:OP_1" in keys ) + self.assertTrue( "WWCT:OP_1_50" in keys ) + + self.assertEqual( wopr_op5.getObservationKeys() , ["WOPR:OP_5"] ) diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_local_config.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_local_config.py new file mode 100644 index 0000000000..d1805c369e --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_local_config.py @@ -0,0 +1,163 @@ +import os.path +from ert.ecl import EclGrid + +from ert.test import ExtendedTestCase +from ert.test import ErtTestContext +from ert.enkf.local_ministep import LocalMinistep +from ert.enkf.active_list import ActiveList +from ert.enkf.local_obsdata import LocalObsdata +from ert.enkf.local_updatestep import LocalUpdateStep +from ert.enkf.local_obsdata_node import LocalObsdataNode +from ert.enkf import local_config + +class LocalConfigTest(ExtendedTestCase): + + def setUp(self): + + self.config = self.createTestPath("local/custom_kw/mini_config") + + def testLocalConfig(self): + + with ErtTestContext("python/enkf/data/local_config", self.config) as test_context: + + main = test_context.getErt() + self.assertTrue(main, "Load failed") + + local_config = main.getLocalConfig() + self.AllActive(local_config) + + self.MiniStep(local_config) + + self.AttachMinistep(local_config) + + self.LocalDataset(local_config) + + self.LocalObsdata(local_config) + + sfile = "local_config.txt" + local_config.writeLocalConfigFile( sfile ) + self.assertTrue( os.path.isfile( sfile )) + + self.clear(local_config) + + grid = local_config.getGrid() + self.assertTrue( isinstance( grid , EclGrid )) + + + def clear(self, local_config): + local_config.clear() + updateStep = local_config.getUpdatestep( ) + self.assertEqual( len(updateStep) , 0 ) + + + + def AllActive(self , local_config): + updateStep = local_config.getUpdatestep( ) + ministep = updateStep[0] + self.assertEqual( 1 , len(ministep) ) + dataset = ministep["ALL_DATA"] + + self.assertTrue( "PERLIN_PARAM" in dataset ) + self.assertTrue( "PERLIN" in dataset ) + + obsdata = ministep.getLocalObsData() + self.assertEqual( len(obsdata) , 3 ) + + + def MiniStep( self, local_config ): + + # Ministep + ministep = local_config.createMinistep("MINISTEP") + self.assertTrue(isinstance(ministep, LocalMinistep)) + + self.assertFalse( "DATA" in ministep ) + with self.assertRaises(KeyError): + ministep["DATA"] + + + def AttachMinistep( self, local_config): + + # Update step + updatestep = local_config.getUpdatestep( ) + self.assertTrue(isinstance(updatestep, LocalUpdateStep)) + n1 = len(updatestep) + + # Ministep + ministep = local_config.createMinistep("MINISTEP") + self.assertTrue(isinstance(ministep, LocalMinistep)) + + # Attach + updatestep.attachMinistep(ministep) + self.assertTrue(isinstance(updatestep[0], LocalMinistep)) + + self.assertEqual( len(updatestep) , n1 + 1 ) + + + def LocalDataset( self, local_config ): + # Data + data_scale = local_config.createDataset("DATA_SCALE") + with self.assertRaises(KeyError): + data_scale.addNode("MISSING") + + data_scale.addNode("PERLIN_PARAM") + active_list = data_scale.getActiveList("PERLIN_PARAM") + self.assertTrue(isinstance(active_list, ActiveList)) + active_list.addActiveIndex(0) + + self.assertTrue("PERLIN_PARAM" in data_scale) + self.assertFalse("MISSING" in data_scale) + + ministep = local_config.createMinistep("MINISTEP") + ministep.attachDataset( data_scale ) + self.assertTrue( "DATA_SCALE" in ministep ) + data_scale_get = ministep["DATA_SCALE"] + self.assertTrue( "PERLIN_PARAM" in data_scale_get ) + + + + + def LocalObsdata( self, local_config ): + + + # Creating + local_obs_data_1 = local_config.createObsdata("OBSSET_1") + self.assertTrue(isinstance(local_obs_data_1, LocalObsdata)) + + with self.assertRaises(KeyError): + local_obs_data_1.addNodeAndRange("MISSING_KEY" , 0 , 1 ) + + local_obs_data_1.addNodeAndRange("GEN_PERLIN_1", 0, 1) + local_obs_data_1.addNodeAndRange("GEN_PERLIN_2", 0, 1) + + self.assertEqual( len(local_obs_data_1) , 2 ) + + # Delete node + del local_obs_data_1["GEN_PERLIN_1"] + self.assertEqual( len(local_obs_data_1) , 1 ) + + # Get node + node = local_obs_data_1["GEN_PERLIN_2"] + self.assertTrue(isinstance(node, LocalObsdataNode)) + + + + def AttachObsData( self , local_config): + + local_obs_data_1 = local_config.createObsdata("OBSSET_1") + self.assertTrue(isinstance(local_obs_data_1, LocalObsdata)) + + # Obsdata + local_obs_data_1.addNodeAndRange("GEN_PERLIN_1", 0, 1) + local_obs_data_1.addNodeAndRange("GEN_PERLIN_2", 0, 1) + + # Ministep + ministep = local_config.createMinistep("MINISTEP") + self.assertTrue(isinstance(ministep, LocalMinistep)) + + # Attach obsset + ministep.attachObsset(local_obs_data_1) + + # Retrieve attached obsset + local_obs_data_new = ministep.getLocalObsData() + self.assertEqual( len(local_obs_data_new) , 2 ) + diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_obs_data.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_obs_data.py index 85dc2ff6f7..d5136a6e53 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_obs_data.py +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_obs_data.py @@ -33,7 +33,17 @@ class ObsDataTest(ExtendedTestCase): R = obs_data.createR() self.assertEqual( (2,2) , R.dims() ) - - + with self.assertRaises(IndexError): + obs_data[10] + + v,s = obs_data[0] + self.assertEqual( v , 10 ) + self.assertEqual( s , 10 ) + + + v,s = obs_data[1] + self.assertEqual( v , 12 ) + self.assertEqual( s , 12 ) + diff --git a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_run_arg.py b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_run_arg.py index b4e234f79f..8f5f00fbf3 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/enkf/test_run_arg.py +++ b/ThirdParty/Ert/devel/python/tests/ert/enkf/test_run_arg.py @@ -19,11 +19,14 @@ import os from ert.enkf import RunArg from ert.enkf.enums import EnkfRunType from ert.test import ExtendedTestCase - +from ert.util import ArgPack class RunArgTest(ExtendedTestCase): def test_create(self): run_arg = RunArg.ENSEMBLE_EXPERIMENT(fs , 10 , 10 , "/path/to/run") + arg_pack = ArgPack( run_arg , 10 ) + + self.assertFalse( run_arg.isSubmitted( ) ) diff --git a/ThirdParty/Ert/devel/python/tests/ert/sched/test_sched.py b/ThirdParty/Ert/devel/python/tests/ert/sched/test_sched.py index e5bd6a9d0c..9e803d1073 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/sched/test_sched.py +++ b/ThirdParty/Ert/devel/python/tests/ert/sched/test_sched.py @@ -30,13 +30,18 @@ class SchedFileTest(ExtendedTestCase): self.sched_file = SchedFile(src_file, self.start_time) self.file_list = [] + def test_missing(self): + with self.assertRaises(IOError): + SchedFile("/does/not/exist", datetime.date(2000 , 1 , 1)) + + def addFile( self, filename ): self.file_list.append(filename) def tearDown(self): for f in self.file_list: if os.path.exists(f): - os.unlink(f) + os.unlink(f) def test_load(self): self.assertTrue(self.sched_file, "Load failed") diff --git a/ThirdParty/Ert/devel/python/tests/ert/server/test_socket.py b/ThirdParty/Ert/devel/python/tests/ert/server/test_socket.py index 0cc865d40e..1e9ebdfc29 100644 --- a/ThirdParty/Ert/devel/python/tests/ert/server/test_socket.py +++ b/ThirdParty/Ert/devel/python/tests/ert/server/test_socket.py @@ -95,12 +95,25 @@ class SocketTest(ExtendedTestCase): self.runCommand( ["MISSING_COMMAND"] , port ) self.runCommand( ["QUIT"] , port , expected = ["QUIT"] ) - - # Server is closed - with self.assertRaises(Exception): - self.runCommand( ["STATUS"] , port ) + start_time = time.time() + exception_raised = False + while True: + try: + self.runCommand( ["STATUS"] , port ) + time.sleep( 1 ) + except Exception: + exception_raised = True + break + + if time.time() - start_time > 10: + break + + if not exception_raised: + raise Exception("Expected exception when connecting to closed server") + + def test_time_map(self): port = self.base_port + 1 diff --git a/ThirdParty/Ert/devel/python/tests/gui/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/gui/CMakeLists.txt index 61c7dfc1da..3895f93989 100644 --- a/ThirdParty/Ert/devel/python/tests/gui/CMakeLists.txt +++ b/ThirdParty/Ert/devel/python/tests/gui/CMakeLists.txt @@ -11,5 +11,5 @@ addPythonTest(gui.observable tests.gui.test_observable.ObservableTest) add_subdirectory(ertshell) add_subdirectory(ide) -add_subdirectory(plot) + diff --git a/ThirdParty/Ert/devel/python/tests/gui/plot/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/gui/plot/CMakeLists.txt deleted file mode 100644 index dc5af18069..0000000000 --- a/ThirdParty/Ert/devel/python/tests/gui/plot/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_plot_metrics_tracker.py -) - -add_python_package("python.tests.gui.plot" ${PYTHON_INSTALL_PREFIX}/tests/gui/plot "${TEST_SOURCES}" False) - -addPythonTest(gui.plot.plot_metrics_tracker tests.gui.plot.test_plot_metrics_tracker.PlotMetricTrackerTest) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/tests/gui/plot/__init__.py b/ThirdParty/Ert/devel/python/tests/gui/plot/__init__.py deleted file mode 100644 index 284bf2e772..0000000000 --- a/ThirdParty/Ert/devel/python/tests/gui/plot/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'jpb' diff --git a/ThirdParty/Ert/devel/python/tests/gui/plot/test_plot_metrics_tracker.py b/ThirdParty/Ert/devel/python/tests/gui/plot/test_plot_metrics_tracker.py deleted file mode 100644 index 845dbb5d64..0000000000 --- a/ThirdParty/Ert/devel/python/tests/gui/plot/test_plot_metrics_tracker.py +++ /dev/null @@ -1,60 +0,0 @@ -from ert.test.extended_testcase import ExtendedTestCase -from ert_gui.tools.plot.plot_metrics_tracker import PlotMetricsTracker - - -class PlotMetricTrackerTest(ExtendedTestCase): - - def test_creation(self): - pmt = PlotMetricsTracker() - - self.assertIsNone(pmt.getType(None)) - - with self.assertRaises(KeyError): - pmt.getType("type") - - - self.assertIsNone(pmt.getDataTypeKey()) - - pmt.setDataTypeKey("test data type") - self.assertEqual(pmt.getDataTypeKey(), "test data type") - - - - def test_scale_types(self): - pmt = PlotMetricsTracker() - - pmt.addScaleType("index", int) - self.assertEqual(pmt.getType("index"), int) - - pmt.addScaleType("value", float) - self.assertEqual(pmt.getType("value"), float) - - - with self.assertRaises(KeyError): - pmt.getScalesForType("index") - - - pmt.setDataTypeKey("TestData1") - self.assertEqual(pmt.getScalesForType("index"), (None, None)) - self.assertEqual(pmt.getScalesForType("value"), (None, None)) - - pmt.setDataTypeKey("TestData2") - self.assertEqual(pmt.getScalesForType("index"), (None, None)) - self.assertEqual(pmt.getScalesForType("value"), (None, None)) - - pmt.setScalesForType("index", 1, 2) - pmt.setScalesForType("value", 1.5, 2.9) - self.assertEqual(pmt.getScalesForType("index"), (1, 2)) - self.assertEqual(pmt.getScalesForType("value"), (1.5, 2.9)) - - pmt.setDataTypeKey("TestData1") - self.assertEqual(pmt.getScalesForType("index"), (None, None)) - self.assertEqual(pmt.getScalesForType("value"), (None, None)) - - pmt.setScalesForType("index", 10, 20) - pmt.setScalesForType("value", 2.5, 3.9) - self.assertEqual(pmt.getScalesForType("index"), (10, 20)) - self.assertEqual(pmt.getScalesForType("value"), (2.5, 3.9)) - - with self.assertRaises(KeyError): - pmt.setScalesForType("time", 99, 999) diff --git a/ThirdParty/Ert/devel/python/tests/share/CMakeLists.txt b/ThirdParty/Ert/devel/python/tests/share/CMakeLists.txt new file mode 100644 index 0000000000..572d5d0c4e --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/share/CMakeLists.txt @@ -0,0 +1,8 @@ +set(TEST_SOURCES + __init__.py + test_synthesizer.py +) + +add_python_package("python.tests.share" ${PYTHON_INSTALL_PREFIX}/tests/share "${TEST_SOURCES}" False) + +addPythonTest(share.synthesizer share.test_synthesizer.SynthesizerTest) \ No newline at end of file diff --git a/ThirdParty/Ert/devel/python/tests/share/__init__.py b/ThirdParty/Ert/devel/python/tests/share/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ThirdParty/Ert/devel/python/tests/share/test_synthesizer.py b/ThirdParty/Ert/devel/python/tests/share/test_synthesizer.py new file mode 100644 index 0000000000..805d0d3ba9 --- /dev/null +++ b/ThirdParty/Ert/devel/python/tests/share/test_synthesizer.py @@ -0,0 +1,46 @@ +import sys +import os +from ert.test import ExtendedTestCase + +try: + from synthesizer import OilSimulator +except ImportError as e: + share_lib_path = os.path.join(ExtendedTestCase.findShareRoot(), "lib") + + sys.path.insert(0, share_lib_path) + synthesizer_module = __import__("synthesizer") + OilSimulator = synthesizer_module.OilSimulator + sys.path.pop(0) + + +class SynthesizerTest(ExtendedTestCase): + + def test_oil_simulator(self): + sim = OilSimulator() + sim.addWell("OP1", seed=1) + sim.addBlock("6,6,6", seed=2) + + expected_values = [ + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0], + [0.3359771423145687, 0.3359771423145687, 0.25672494192349865, 0.25672494192349865, 0.010039005455891323, 0.010039005455891323, 0.029013112597713192, 0.7641143089523995, 0.3359771423145687, 0.25672494192349865, 0.010039005455891323, 0.7641143089523995, 0.029013112597713192, 0.8462347957619747], + [0.7252470407619624, 1.0612241830765312, 0.5175173529594699, 0.7742422948829686, 0.017973831236885583, 0.028012836692776905, 0.02418370085402209, 0.7135738912023045, 0.7252470407619624, 0.5175173529594699, 0.017973831236885583, 0.7135738912023045, 0.02418370085402209, 0.6888364145396828], + [0.7723163496234255, 1.8335405326999568, 0.5742386073607806, 1.3484809022437492, 0.11041673583737899, 0.1384295725301559, 0.12508507685507134, 0.7435277106858791, 0.7723163496234255, 0.5742386073607806, 0.11041673583737899, 0.7435277106858791, 0.12508507685507134, 0.6403046565762696], + [0.6038799675664164, 2.437420500266373, 0.6888868738548185, 2.037367776098568, 0.267892132439122, 0.4063217049692779, 0.3072960610203287, 1.140767885762087, 0.6038799675664164, 0.6888868738548185, 0.267892132439122, 1.140767885762087, 0.3072960610203287, 0.5205364945011657], + [0.23016535126253962, 2.6675858515289126, 0.721655666522216, 2.7590234426207836, 0.35552466124555465, 0.7618463662148325, 0.6070184801736589, 3.135379250454838, 0.23016535126253962, 0.721655666522216, 0.35552466124555465, 3.135379250454838, 0.6070184801736589, 0.4800677649914682], + [0.026293782934652718, 2.693879634463565, 0.7131990780527108, 3.4722225206734945, 0.6392372725163122, 1.4010836387311447, 0.8647254356377257, 7.131990780527107, 0.026293782934652718, 0.7131990780527108, 0.6392372725163122, 7.131990780527107, 0.8647254356377257, 0.3872974839053025], + [0.0, 2.693879634463565, 0.8676997908824122, 4.339922311555907, 0.8580356376693129, 2.2591192764004577, 0.8956197493411856, 8.676997908824122, 0.0, 0.8676997908824122, 0.8580356376693129, 8.676997908824122, 0.8956197493411856, 0.22557165737149715], + [0.10560669451549878, 2.799486328979064, 0.869082212788759, 5.209004524344666, 0.8903674796589355, 3.1494867560593933, 0.8939664328113363, 8.229423492288294, 0.10560669451549878, 0.869082212788759, 0.8903674796589355, 8.229423492288294, 0.8939664328113363, 0.1340241573819292], + [0.08615885630000791, 2.885645185279072, 0.44074890315982446, 5.64975342750449, 0.9425699260811738, 4.0920566821405675, 0.9040831722665535, 4.407489031598244, 0.08615885630000791, 0.44074890315982446, 0.9425699260811738, 4.407489031598244, 0.9040831722665535, 0.13404047971467026] + ] + + for report_step in range(10): + sim.step(scale=1.0 / 10.0) + + values = [sim.fopr(), sim.fopt(), sim.fgpr(), sim.fgpt(), sim.fwpr(), sim.fwpt(), sim.fwct(), sim.fgor(), + sim.opr("OP1"), sim.gpr("OP1"), sim.wpr("OP1"), sim.gor("OP1"), sim.wct("OP1"), sim.bpr("6,6,6")] + + self.assertAlmostEqual(values[0], values[8]) # fopr = opr:op1 + self.assertAlmostEqual(values[2], values[9]) # fgpr = gpr:op1 + self.assertAlmostEqual(values[4], values[10]) # fwpr = wpr:op1 + + self.assertAlmostEqualList(values, expected_values[report_step]) diff --git a/ThirdParty/Ert/devel/redhat/ert.ecl.spec b/ThirdParty/Ert/devel/redhat/ert.ecl.spec index e50ca7a0fe..1ae33fa569 100644 --- a/ThirdParty/Ert/devel/redhat/ert.ecl.spec +++ b/ThirdParty/Ert/devel/redhat/ert.ecl.spec @@ -5,7 +5,7 @@ %define tag final2 Name: ert.ecl -Version: 2013.10 +Version: 2015.10 Release: 0 Summary: ERT - Ensemble based Reservoir Tool - ECL library License: GPL-3+ @@ -14,7 +14,9 @@ Url: http://ert.nr.no Source0: https://github.com/OPM/%{name}/archive/release/%{version}/%{tag}.tar.gz#/%{name}-%{version}.tar.gz BuildRequires: lapack-devel zlib-devel iputils BuildRequires: gcc -BuildRequires: cmake28 +%{?!el6:BuildRequires: python-devel} +%{?el6:BuildRequires: cmake28} +%{?!el6:BuildRequires: cmake} BuildRoot: %{_tmppath}/%{name}-%{version}-build Requires: libert.ecl1 = %{version} @@ -27,7 +29,19 @@ tool to do assisted history matching with Ensemble Kalman Filter %package -n libert.ecl1 Summary: ERT - Ensemble based Reservoir Tool - ECL library Group: System/Libraries -%{?el5:BuildArch: %{_arch}} + +%{?!el6: +%package -n python-ert.ecl +Summary: ERT - Ensemble based Reservoir Tool - Python bindings +Group: Python/Libraries +Requires: libert.ecl1 + +%description -n python-ert.ecl +ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble +of reservoir models. The initial motivation for creating ERT was a as +tool to do assisted history matching with Ensemble Kalman Filter +(EnKF). This package contains the Python bindings. +} %description -n libert.ecl1 ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble @@ -41,7 +55,6 @@ Group: Development/Libraries/C and C++ Requires: %{name} = %{version} Requires: lapack-devel Requires: libert.ecl1 = %{version} -%{?el5:BuildArch: %{_arch}} %description devel This package contains the development and header files for ert.ecl @@ -51,7 +64,7 @@ This package contains the development and header files for ert.ecl %build cd devel -cmake28 -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%{_prefix} -DBUILD_ECL_SUMMARY=1 +DESTDIR=${RPM_BUILD_ROOT} %{?el6:cmake28} %{?!el6:cmake} -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%{_prefix} -DBUILD_ECL_SUMMARY=1 %{?el6:-DBUILD_PYTHON=0} make %install @@ -77,3 +90,9 @@ rm -rf %{buildroot} %defattr(-,root,root,-) %{_libdir}/*.so %{_includedir}/* + +%{?!el6: +%files -n python-ert.ecl +%defattr(-,root,root,-) +/usr/lib/python2.7/site-packages/ert/* +} diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html index d2786f5659..7fd6807ce1 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_static_kw.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_static_kw.html~HEAD deleted file mode 100644 index f69dbd13cf..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/add_static_kw.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_copy.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_copy.html index 4d0e042fef..bb65f45d44 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_copy.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_copy.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_enkf_update.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_enkf_update.html index 580c4dcb7d..ba92057398 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_enkf_update.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_enkf_update.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_load.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_load.html index 5e3a647ebc..0439e95c26 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_load.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_load.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_select.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_select.html index bd37b1c6ef..5be06c89cb 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_select.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_select.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_set_var.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_set_var.html index 66ef1fb449..7513aae255 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_set_var.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_set_var.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_update.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_update.html index 2667d60c1c..be8ec82a19 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_update.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/analysis_update.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/create_case.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/create_case.html index 363483fc44..7a634a6b3a 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/create_case.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/create_case.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_file.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_file.html~HEAD deleted file mode 100644 index 67263b1346..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_file.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_kw.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_kw.html~HEAD deleted file mode 100644 index e21da1043e..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_kw.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_ranking.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_ranking.html index 7d171050bf..9336015252 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_ranking.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/data_ranking.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/define.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/define.html index 4721ab3a19..b1f1a19e61 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/define.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/define.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/delete_runpath.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/delete_runpath.html index a5557b5943..397ba46143 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/delete_runpath.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/delete_runpath.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/eclbase.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/eclbase.html~HEAD deleted file mode 100644 index a15ca207e0..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/eclbase.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/end_date.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/end_date.html index e8b0961967..13ea1a5f5b 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/end_date.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/end_date.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_alpha.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_alpha.html~HEAD deleted file mode 100644 index b5c5becbca..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_alpha.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_bootstrap.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_bootstrap.html index aaac93ede6..62c4d5e1e0 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_bootstrap.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_bootstrap.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_cv_folds.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_cv_folds.html index 41946518ad..8d32df09a6 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_cv_folds.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_cv_folds.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_force_ncomp.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_force_ncomp.html index 9a55eeb2f0..bff2df9366 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_force_ncomp.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_force_ncomp.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_local_cv.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_local_cv.html index e0d8eb8719..7ea90f84f9 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_local_cv.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_local_cv.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_merge_observations.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_merge_observations.html~HEAD deleted file mode 100644 index 43efa8bd55..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_merge_observations.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_mode.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_mode.html~HEAD deleted file mode 100644 index e119f6ee21..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_mode.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_ncomp.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_ncomp.html index f62fbaa777..438e8b761d 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_ncomp.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_ncomp.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_pen_press.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_pen_press.html index f172c3ccbf..7385cf5292 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_pen_press.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_pen_press.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_rerun.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_rerun.html~HEAD deleted file mode 100644 index 9913097265..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_rerun.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_scaling.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_scaling.html index f0b940597c..26f232374d 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_scaling.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_scaling.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_sched_file.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_sched_file.html~HEAD deleted file mode 100644 index 9c7e1d7e88..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_sched_file.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_truncation.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_truncation.html~HEAD deleted file mode 100644 index f433135ed0..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enkf_truncation.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/ensemble_run.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/ensemble_run.html index 7132b849cc..d0c173a933 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/ensemble_run.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/ensemble_run.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enspath.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enspath.html index 9efc6d3dc8..cc2d44680e 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/enspath.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/enspath.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field.html index 0f067b9ecd..e1cf6dddec 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_ecl_grdecl.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_ecl_grdecl.html index 8572b67c02..256e994c04 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_ecl_grdecl.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_ecl_grdecl.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_rms_roff.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_rms_roff.html index 6de0a005d6..69b24e56a4 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_rms_roff.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_field_rms_roff.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_ranking.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_ranking.html index 4f426d65cc..82e3807b97 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_ranking.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/export_ranking.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/field.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/field.html index 3bead91bbd..7002f52e4e 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/field.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/field.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/forward_model.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/forward_model.html~HEAD deleted file mode 100644 index 4eea6b1a6a..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/forward_model.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_data.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_data.html index 98cee9a9b9..4225d803d4 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_data.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_data.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_kw.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_kw.html index 183aa965f7..92666c8c31 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_kw.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_kw.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_param.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_param.html index 0a1e12cab4..d8ac1acef5 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_param.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/gen_param.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/grid.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/grid.html~HEAD deleted file mode 100644 index 845ada5e0f..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/grid.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/history_source.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/history_source.html~HEAD deleted file mode 100644 index 517e473e65..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/history_source.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_type.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_type.html~HEAD deleted file mode 100644 index 810637150b..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_type.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_viewer.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_viewer.html~HEAD deleted file mode 100644 index a0c251aa26..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/image_viewer.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_case_from_existing.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_case_from_existing.html index ae84aa20f7..ba679851bf 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_case_from_existing.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_case_from_existing.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_misfit_table.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_misfit_table.html index 3276ffe504..a242e1e5ce 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_misfit_table.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_misfit_table.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_section.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_section.html~HEAD deleted file mode 100644 index dc04b799ef..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/init_section.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/install_job.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/install_job.html index 4714a44773..8c97722da7 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/install_job.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/install_job.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/job_script.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/job_script.html~HEAD deleted file mode 100644 index 5eb1ca0e6f..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/job_script.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/jobname.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/jobname.html index 2163b6831d..c1b4e7290e 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/jobname.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/jobname.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/keep_runpath.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/keep_runpath.html index 6c98c30642..5cdc840fcc 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/keep_runpath.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/keep_runpath.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/keywords.txt b/ThirdParty/Ert/devel/share/gui/help/config/keywords/keywords.txt index 3ecbc5a4d4..79d5fc80ea 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/keywords.txt +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/keywords.txt @@ -1,100 +1,100 @@ -data_file http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#DATA_FILE -eclbase http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ECLBASE -jobname http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#JOBNAME -grid http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#GRID -init_section http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#INIT_SECTION -num_realizations http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#NUM_REALIZATIONS -schedule_file http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_FILE -data_kw http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#DATA_KW -delete_runpath http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#DELETE_RUNPATH -enkf_sched_file http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCHED_FILE -end_date http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#END_DATE -enspath http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENSPATH -select_case http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE -history_source http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#HISTORY_SOURCE -refcase http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REFCASE -install_job http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#INSTALL_JOB -keep_runpath http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#KEEP_RUNPATH -obs_config http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#OBS_CONFIG -result_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RESULT_PATH -runpath http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RUNPATH -runpath_file http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RUNPATH_FILE -min_realizations http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#MIN_REALIZATIONS -stop_long_running http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#STOP_LONG_RUNNING -max_runtime http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNTIME -field http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#FIELD -gen_data http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#GEN_DATA -gen_kw http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#GEN_KW -gen_param http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#GEN_PARAM -surface http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SURFACE -summary http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SUMMARY -enkf_alpha http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_ALPHA -enkf_bootstrap http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_BOOTSTRAP -enkf_cv_folds http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_CV_FOLDS -enkf_force_ncomp http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_FORCE_NCOMP -enkf_local_cv http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_LOCAL_CV -enkf_pen_press http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_PEN_PRESS -enkf_mode http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_MODE -enkf_merge_observations http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_MERGE_OBSERVATIONS -enkf_ncomp http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_NCOMP -enkf_rerun http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_RERUN -enkf_scaling http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCALING -enkf_truncation http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENKF_TRUNCATION -update_log_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#UPDATE_LOG_PATH -analysis_load http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_LOAD -analysis_select http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SELECT -analysis_set_var http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SET_VAR -analysis_copy http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_COPY -add_fixed_length_schedule_kw http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ADD_FIXED_LENGTH_SCHEDULE_KW -add_static_kw http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ADD_STATIC_KW -define http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#DEFINE -schedule_prediction_file http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_PREDICTION_FILE -forward_model http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#FORWARD_MODEL -job_script http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#JOB_SCRIPT -queue_system http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#QUEUE_SYSTEM -lsf_server http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#LSF_SERVER -lsf_queue http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#LSF_QUEUE -max_running_lsf http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LSF -max_running_local http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LOCAL -rsh_host http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RSH_HOST -rsh_command http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RSH_COMMAND -max_running_rsh http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_RSH -image_viewer http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#IMAGE_VIEWER -image_type http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#IMAGE_TYPE -plot_driver http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_DRIVER -plot_errorbar http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR -plot_errorbar_max http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR_MAX -plot_height http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_HEIGHT -plot_refcase http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_REFCASE -refcase_list http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REFCASE_LIST -plot_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_PATH -plot_width http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#PLOT_WIDTH -rft_config http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RFT_CONFIG -rftpath http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RFTPATH -select_case http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE -create_case http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#CREATE_CASE -init_case_from_existing http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#INIT_CASE_FROM_EXISTING -export_field http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD -export_field_rms_roff http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_RMS_ROFF -export_field_ecl_grdecl http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_ECL_GRDECL -analysis_update http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_UPDATE -analysis_enkf_update http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_ENKF_UPDATE -run_smoother http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER -run_smoother_with_iter http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER_WITH_ITER -ensemble_run http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#ENSEMBLE_RUN -load_results http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS -load_results_iter http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS_ITER -observation_ranking http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#OBSERVATION_RANKING -data_ranking http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#DATA_RANKING -export_ranking http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#EXPORT_RANKING -init_misfit_table http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#INIT_MISFIT_TABLE -qc_workflow http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#QC_WORKFLOW -qc_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#QC_PATH -report_context http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_CONTEXT -report_list http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_LIST -report_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_PATH -report_search_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_SEARCH_PATH -report_well_list http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_WELL_LIST -report_group_list http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#REPORT_GROUP_LIST -setenv http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#SETENV -update_path http://ert.nr.no/wiki/index.php/Creating_a_configuration_file_for_ERT#UPDATE_PATH \ No newline at end of file +data_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_FILE +eclbase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ECLBASE +jobname http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#JOBNAME +grid http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GRID +init_section http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_SECTION +num_realizations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#NUM_REALIZATIONS +schedule_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_FILE +data_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_KW +delete_runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DELETE_RUNPATH +enkf_sched_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCHED_FILE +end_date http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#END_DATE +enspath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENSPATH +select_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE +history_source http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#HISTORY_SOURCE +refcase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REFCASE +install_job http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INSTALL_JOB +keep_runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#KEEP_RUNPATH +obs_config http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#OBS_CONFIG +result_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RESULT_PATH +runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUNPATH +runpath_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUNPATH_FILE +min_realizations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MIN_REALIZATIONS +stop_long_running http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#STOP_LONG_RUNNING +max_runtime http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNTIME +field http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#FIELD +gen_data http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_DATA +gen_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_KW +gen_param http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_PARAM +surface http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SURFACE +summary http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SUMMARY +enkf_alpha http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_ALPHA +enkf_bootstrap http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_BOOTSTRAP +enkf_cv_folds http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_CV_FOLDS +enkf_force_ncomp http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_FORCE_NCOMP +enkf_local_cv http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_LOCAL_CV +enkf_pen_press http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_PEN_PRESS +enkf_mode http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_MODE +enkf_merge_observations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_MERGE_OBSERVATIONS +enkf_ncomp http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_NCOMP +enkf_rerun http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_RERUN +enkf_scaling http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCALING +enkf_truncation http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_TRUNCATION +update_log_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#UPDATE_LOG_PATH +analysis_load http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_LOAD +analysis_select http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SELECT +analysis_set_var http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SET_VAR +analysis_copy http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_COPY +add_fixed_length_schedule_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ADD_FIXED_LENGTH_SCHEDULE_KW +add_static_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ADD_STATIC_KW +define http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DEFINE +schedule_prediction_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_PREDICTION_FILE +forward_model http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#FORWARD_MODEL +job_script http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#JOB_SCRIPT +queue_system http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QUEUE_SYSTEM +lsf_server http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LSF_SERVER +lsf_queue http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LSF_QUEUE +max_running_lsf http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LSF +max_running_local http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LOCAL +rsh_host http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RSH_HOST +rsh_command http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RSH_COMMAND +max_running_rsh http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_RSH +image_viewer http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#IMAGE_VIEWER +image_type http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#IMAGE_TYPE +plot_driver http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_DRIVER +plot_errorbar http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR +plot_errorbar_max http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR_MAX +plot_height http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_HEIGHT +plot_refcase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_REFCASE +refcase_list http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REFCASE_LIST +plot_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_PATH +plot_width http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_WIDTH +rft_config http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RFT_CONFIG +rftpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RFTPATH +select_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE +create_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#CREATE_CASE +init_case_from_existing http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_CASE_FROM_EXISTING +export_field http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD +export_field_rms_roff http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_RMS_ROFF +export_field_ecl_grdecl http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_ECL_GRDECL +analysis_update http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_UPDATE +analysis_enkf_update http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_ENKF_UPDATE +run_smoother http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER +run_smoother_with_iter http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER_WITH_ITER +ensemble_run http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENSEMBLE_RUN +load_results http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS +load_results_iter http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS_ITER +observation_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#OBSERVATION_RANKING +data_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_RANKING +export_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_RANKING +init_misfit_table http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_MISFIT_TABLE +qc_workflow http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QC_WORKFLOW +qc_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QC_PATH +report_context http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_CONTEXT +report_list http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_LIST +report_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_PATH +report_search_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_SEARCH_PATH +report_well_list http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_WELL_LIST +report_group_list http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REPORT_GROUP_LIST +setenv http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SETENV +update_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#UPDATE_PATH \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results.html index 1510767b99..2def17d6d9 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results_iter.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results_iter.html index 04d868798c..11a79d6e59 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results_iter.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/load_results_iter.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_queue.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_queue.html~HEAD deleted file mode 100644 index 9a294d649f..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_queue.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_server.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_server.html index bc158ce4c1..fd9aac3cc2 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_server.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/lsf_server.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_local.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_local.html~HEAD deleted file mode 100644 index fc4f5d6c5e..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_local.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_lsf.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_lsf.html~HEAD deleted file mode 100644 index 5ac5df8bb4..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_lsf.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_rsh.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_rsh.html~HEAD deleted file mode 100644 index c219d781eb..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_running_rsh.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_runtime.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_runtime.html index 749e5b5437..3e1de4739b 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_runtime.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/max_runtime.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/min_realizations.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/min_realizations.html index a3ddc94425..4f54035717 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/min_realizations.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/min_realizations.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/num_realizations.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/num_realizations.html~HEAD deleted file mode 100644 index 3314abdc98..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/num_realizations.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/obs_config.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/obs_config.html~HEAD deleted file mode 100644 index 58b2087624..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/obs_config.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/observation_ranking.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/observation_ranking.html index 1cce3fd21f..be2ff2fe01 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/observation_ranking.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/observation_ranking.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_driver.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_driver.html~HEAD deleted file mode 100644 index 8d596aa2bf..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_driver.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar.html index 8dc1f04c64..0568bb659d 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar_max.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar_max.html~HEAD deleted file mode 100644 index 11d2e0d3a0..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_errorbar_max.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_height.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_height.html~HEAD deleted file mode 100644 index 7e8e70a614..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_height.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_path.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_path.html~HEAD deleted file mode 100644 index 88ba65eb41..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_path.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_refcase.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_refcase.html index 8d20e136b0..a7d3d67fb9 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_refcase.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_refcase.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_width.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_width.html~HEAD deleted file mode 100644 index 26cc77a710..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/plot_width.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_path.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_path.html index b291a46a71..26029f50f1 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_path.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_path.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_workflow.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_workflow.html index 38901e8394..61ebf75d26 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_workflow.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/qc_workflow.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html index e06952bf8b..d23625073f 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html @@ -5,4 +5,4 @@ Controls where the simulation jobs are executed.
LOCAL: Submits the jobs to your local workstation.
-More information in the wiki. +More information in the wiki. diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html~HEAD deleted file mode 100644 index 99018f9949..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/queue_system.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase.html~HEAD deleted file mode 100644 index 08d1a76fb5..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase_list.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase_list.html index 37b3d471f3..9fa95da112 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase_list.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/refcase_list.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_context.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_context.html index 332754b50b..552263e58a 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_context.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_context.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_group_list.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_group_list.html index e253eb0ef7..77e6854c9b 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_group_list.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_group_list.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_list.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_list.html index 512e8cdd08..c256814c55 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_list.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_list.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_path.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_path.html index 711aa8c825..d2dc8e7d4a 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_path.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_path.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_search_path.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_search_path.html index c7c0ac1f5d..0840bb7e1c 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_search_path.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_search_path.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_well_list.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_well_list.html index e8579adc7b..094fa02b36 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_well_list.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/report_well_list.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/result_path.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/result_path.html index 242f708267..5ca7fa5241 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/result_path.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/result_path.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rft_config.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rft_config.html index c5f8cc80dc..fa68edbb47 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rft_config.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rft_config.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rftpath.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rftpath.html index 863dec10b9..ca1df0aa92 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rftpath.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rftpath.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_command.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_command.html~HEAD deleted file mode 100644 index 5b4b606c61..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_command.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_host.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_host.html~HEAD deleted file mode 100644 index 49ba3b46a4..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/rsh_host.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother.html index 305fc0b1d2..5d61059e82 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother_with_iter.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother_with_iter.html index 14d805f1a9..f71187c49e 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother_with_iter.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/run_smoother_with_iter.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath.html~HEAD deleted file mode 100644 index 89303eaa37..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath_file.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath_file.html index 2e83b4513f..e5839c9695 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath_file.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/runpath_file.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_file.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_file.html~HEAD deleted file mode 100644 index 8d94d5d2ab..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_file.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_prediction_file.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_prediction_file.html~HEAD deleted file mode 100644 index 0f3c2a29ac..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/schedule_prediction_file.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/select_case.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/select_case.html index 877772b866..68f628f3c3 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/select_case.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/select_case.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/setenv.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/setenv.html~HEAD deleted file mode 100644 index aaa34ca9ae..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/setenv.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/stop_long_running.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/stop_long_running.html index 4bc741bf20..0abd696273 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/stop_long_running.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/stop_long_running.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/summary.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/summary.html index f4cf208cce..8083f8729b 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/summary.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/summary.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/surface.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/surface.html index 9ea333c494..c26f69080a 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/surface.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/surface.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_log_path.html b/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_log_path.html index af497a446a..c321b261c8 100644 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_log_path.html +++ b/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_log_path.html @@ -1 +1 @@ -Click here to view help on the wiki page. \ No newline at end of file +Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_path.html~HEAD b/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_path.html~HEAD deleted file mode 100644 index 0763a2e9f1..0000000000 --- a/ThirdParty/Ert/devel/share/gui/help/config/keywords/update_path.html~HEAD +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/ensemble_statistics_plot.html b/ThirdParty/Ert/devel/share/gui/plots/ensemble_statistics_plot.html deleted file mode 100644 index ed551a1ec0..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/ensemble_statistics_plot.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/gen_data.html b/ThirdParty/Ert/devel/share/gui/plots/gen_data.html deleted file mode 100644 index b186896624..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/gen_data.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/gen_data_overview.html b/ThirdParty/Ert/devel/share/gui/plots/gen_data_overview.html deleted file mode 100644 index 7498115052..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/gen_data_overview.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/gen_data_statistics_plot.html b/ThirdParty/Ert/devel/share/gui/plots/gen_data_statistics_plot.html deleted file mode 100644 index 0569fb6253..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/gen_data_statistics_plot.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/gen_kw.html b/ThirdParty/Ert/devel/share/gui/plots/gen_kw.html deleted file mode 100644 index b705a1867f..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/gen_kw.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/histogram.html b/ThirdParty/Ert/devel/share/gui/plots/histogram.html deleted file mode 100644 index a414542cbc..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/histogram.html +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.js b/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.js deleted file mode 100644 index b0cb637255..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.js +++ /dev/null @@ -1,9274 +0,0 @@ -!function() { - var d3 = { - version: "3.4.1" - }; - if (!Date.now) Date.now = function() { - return +new Date(); - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window; - try { - d3_array(d3_documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - try { - d3_document.createElement("div").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - d3.ascending = function(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - }; - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined; - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (!isNaN(a = +array[i])) s += a; - } else { - while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - function d3_number(x) { - return x != null && !isNaN(x); - } - d3.mean = function(array, f) { - var n = array.length, a, m = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; - } else { - while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; - } - return j ? m : undefined; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - if (arguments.length > 1) array = array.map(f); - array = array.filter(d3_number); - return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; - }; - d3.bisector = function(f) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - }; - var d3_bisector = d3.bisector(function(d) { - return d; - }); - d3.bisectLeft = d3_bisector.left; - d3.bisect = d3.bisectRight = d3_bisector.right; - d3.shuffle = function(array) { - var m = array.length, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m], array[m] = array[i], array[i] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.zip = function() { - if (!(n = arguments.length)) return []; - for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { - for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { - zip[j] = arguments[j][i]; - } - } - return zips; - }; - function d3_zipLength(d) { - return d.length; - } - d3.transpose = function(matrix) { - return d3.zip.apply(d3, matrix); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - try { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } catch (e) { - ctor.prototype = properties; - } - } - d3.map = function(object) { - var map = new d3_Map(); - if (object instanceof d3_Map) object.forEach(function(key, value) { - map.set(key, value); - }); else for (var key in object) map.set(key, object[key]); - return map; - }; - function d3_Map() {} - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this[d3_map_prefix + key]; - }, - set: function(key, value) { - return this[d3_map_prefix + key] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - this.forEach(function(key, value) { - values.push(value); - }); - return values; - }, - entries: function() { - var entries = []; - this.forEach(function(key, value) { - entries.push({ - key: key, - value: value - }); - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) f.call(this, key.substring(1), this[key]); - } - }); - var d3_map_prefix = "\x00", d3_map_prefixCode = d3_map_prefix.charCodeAt(0); - function d3_map_has(key) { - return d3_map_prefix + key in this; - } - function d3_map_remove(key) { - key = d3_map_prefix + key; - return key in this && delete this[key]; - } - function d3_map_keys() { - var keys = []; - this.forEach(function(key) { - keys.push(key); - }); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) ++size; - return size; - } - function d3_map_empty() { - for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() {} - d3_class(d3_Set, { - has: d3_map_has, - add: function(value) { - this[d3_map_prefix + value] = true; - return value; - }, - remove: function(value) { - value = d3_map_prefix + value; - return value in this && delete this[value]; - }, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1)); - } - }); - d3.behavior = {}; - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.substring(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.substring(i + 1); - type = type.substring(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatcher = d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = function(s, n) { - return Sizzle.uniqueSort(Sizzle(s, n)); - }; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3_selectionRoot; - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: "http://www.w3.org/1999/xhtml", - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0) { - prefix = name.substring(0, i); - name = name.substring(i + 1); - } - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return name.trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name); - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() { - return this.ownerDocument.createElementNS(name.space, name.local); - } : function() { - return this.ownerDocument.createElementNS(this.namespaceURI, name); - }; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(function() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - }); - }; - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue; - for (i = -1; ++i < n; ) { - keyValue = key.call(node = group[i], node.__data__, i); - if (nodeByKeyValue.has(keyValue)) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues.push(keyValue); - } - for (i = -1; ++i < m; ) { - keyValue = key.call(groupData, nodeData = groupData[i], i); - if (node = nodeByKeyValue.get(keyValue)) { - updateNodes[i] = node; - node.__data__ = nodeData; - } else if (!dataByKeyValue.has(keyValue)) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - dataByKeyValue.set(keyValue, nodeData); - nodeByKeyValue.remove(keyValue); - } - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.has(keyValues[i])) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3.ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - this.each(function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3_selectionPrototype.transition = function() { - var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, id); - }; - d3_selectionPrototype.interrupt = function() { - return this.each(d3_selection_interrupt); - }; - function d3_selection_interrupt() { - var lock = this.__transition__; - if (lock) ++lock.active; - } - d3.select = function(node) { - var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ]; - group.parentNode = d3_documentElement; - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes); - group.parentNode = d3_documentElement; - return d3_selection([ group ]); - }; - var d3_selectionRoot = d3.select(d3_documentElement); - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.substring(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0; - function d3_event_dragSuppress() { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect) { - var style = d3_documentElement.style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - function off() { - w.on(click, null); - } - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touches = function(container, touches) { - if (arguments.length < 2) touches = d3_eventSource().touches; - return touches ? d3_array(touches).map(function(touch) { - var point = d3_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, "mousemove", "mouseup"), touchstart = dragstart(touchid, touchposition, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function touchid() { - return d3.event.changedTouches[0].identifier; - } - function touchposition(parent, id) { - return d3.touches(parent).filter(function(p) { - return p.identifier === id; - })[0]; - } - function dragstart(id, position, move, end) { - return function() { - var target = this, parent = target.parentNode, event_ = event.of(target, arguments), eventTarget = d3.event.target, eventId = id(), drag = eventId == null ? "drag" : "drag-" + eventId, origin_ = position(parent, eventId), dragged = 0, offset, w = d3.select(d3_window).on(move + "." + drag, moved).on(end + "." + drag, ended), dragRestore = d3_event_dragSuppress(); - if (origin) { - offset = origin.apply(target, arguments); - offset = [ offset.x - origin_[0], offset.y - origin_[1] ]; - } else { - offset = [ 0, 0 ]; - } - event_({ - type: "dragstart" - }); - function moved() { - var p = position(parent, eventId), dx = p[0] - origin_[0], dy = p[1] - origin_[1]; - dragged |= dx | dy; - origin_ = p; - event_({ - type: "drag", - x: p[0] + offset[0], - y: p[1] + offset[1], - dx: dx, - dy: dy - }); - } - function ended() { - w.on(move + "." + drag, null).on(end + "." + drag, null); - dragRestore(dragged && d3.event.target === eventTarget); - event_({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π; - function d3_sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2]; - var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ; - function interpolate(t) { - var s = t * S; - if (dr) { - var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - } - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ]; - } - interpolate.duration = S * 1e3; - return interpolate; - }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on(mousemove, mousewheelreset).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(event_); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(event_); - }; - }).each("end.zoom", function() { - zoomended(event_); - }); - } else { - this.__chart__ = view; - zoomstarted(event_); - zoomed(event_); - zoomended(event_); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: +_ - }; - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(event) { - event({ - type: "zoomstart" - }); - } - function zoomed(event) { - rescale(); - event({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); - } - function zoomended(event) { - event({ - type: "zoomend" - }); - } - function mousedowned() { - var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, dragged = 0, w = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), l = location(d3.mouse(target)), dragRestore = d3_event_dragSuppress(); - d3_selection_interrupt.call(target); - zoomstarted(event_); - function moved() { - dragged = 1; - translateTo(d3.mouse(target), l); - zoomed(event_); - } - function ended() { - w.on(mousemove, d3_window === target ? mousewheelreset : null).on(mouseup, null); - dragRestore(dragged && d3.event.target === eventTarget); - zoomended(event_); - } - } - function touchstarted() { - var target = this, event_ = event.of(target, arguments), locations0 = {}, distance0 = 0, scale0, eventId = d3.event.changedTouches[0].identifier, touchmove = "touchmove.zoom-" + eventId, touchend = "touchend.zoom-" + eventId, w = d3.select(d3_window).on(touchmove, moved).on(touchend, ended), t = d3.select(target).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress(); - d3_selection_interrupt.call(target); - started(); - zoomstarted(event_); - function relocate() { - var touches = d3.touches(target); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; - } - function started() { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0], l = locations0[p.identifier]; - scaleTo(view.k * 2); - translateTo(p, l); - d3_eventPreventDefault(); - zoomed(event_); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } - } - function moved() { - var touches = d3.touches(target), p0, l0, p1, l1; - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(event_); - } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - w.on(touchmove, null).on(touchend, null); - t.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(event_); - } - } - function mousewheeled() { - var event_ = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), - zoomstarted(event_); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(event_); - }, 50); - d3_eventPreventDefault(); - var point = center || d3.mouse(this); - if (!translate0) translate0 = location(point); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(point, translate0); - zoomed(event_); - } - function mousewheelreset() { - translate0 = null; - } - function dblclicked() { - var event_ = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2; - zoomstarted(event_); - scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); - translateTo(p, l); - zoomed(event_); - zoomended(event_); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ]; - var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - function d3_Color() {} - d3_Color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.hsl = function(h, s, l) { - return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l); - }; - function d3_hsl(h, s, l) { - return new d3_Hsl(h, s, l); - } - function d3_Hsl(h, s, l) { - this.h = h; - this.s = s; - this.l = l; - } - var d3_hslPrototype = d3_Hsl.prototype = new d3_Color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return d3_hsl(this.h, this.s, k * this.l); - }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); - }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - return d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = function(h, c, l) { - return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l); - }; - function d3_hcl(h, c, l) { - return new d3_Hcl(h, c, l); - } - function d3_Hcl(h, c, l) { - this.h = h; - this.c = c; - this.l = l; - } - var d3_hclPrototype = d3_Hcl.prototype = new d3_Color(); - d3_hclPrototype.brighter = function(k) { - return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); - }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = function(l, a, b) { - return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b); - }; - function d3_lab(l, a, b) { - return new d3_Lab(l, a, b); - } - function d3_Lab(l, a, b) { - this.l = l; - this.a = a; - this.b = b; - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_Lab.prototype = new d3_Color(); - d3_labPrototype.brighter = function(k) { - return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); - }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = function(r, g, b) { - return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b); - }; - function d3_rgbNumber(value) { - return d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; - } - function d3_rgb(r, g, b) { - return new d3_Rgb(r, g, b); - } - function d3_Rgb(r, g, b) { - this.r = r; - this.g = g; - this.b = b; - } - var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return d3_rgb(Math.min(255, ~~(r / k)), Math.min(255, ~~(g / k)), Math.min(255, ~~(b / k))); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return d3_rgb(~~(k * this.r), ~~(k * this.g), ~~(k * this.b)); - }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); - }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); - }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - var r = 0, g = 0, b = 0, m1, m2, name; - m1 = /([a-z]+)\((.*)\)/i.exec(format); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } - } - } - if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b); - if (format != null && format.charAt(0) === "#") { - if (format.length === 4) { - r = format.charAt(1); - r += r; - g = format.charAt(2); - g += g; - b = format.charAt(3); - b += b; - } else if (format.length === 7) { - r = format.substring(1, 3); - g = format.substring(3, 5); - b = format.substring(5, 7); - } - r = parseInt(r, 16); - g = parseInt(g, 16); - b = parseInt(b, 16); - } - return rgb(r, g, b); - } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; - } - return d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - function d3_identity(d) { - return d; - } - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; - } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && request.responseText || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } - } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.substring(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.substring(j, I - k); - } - return text.substring(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && !(a = f(a, n++))) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } - }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); - }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); - }; - d3.timer = function(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - f: false, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - }; - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); - }; - function d3_timer_mark() { - var now = Date.now(); - d3_timer_active = d3_timer_queueHead; - while (d3_timer_active) { - if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t); - d3_timer_active = d3_timer_active.n; - } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.f) { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } else { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; - } - } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping ? function(value) { - var i = value.length, t = [], j = 0, g = locale_grouping[0]; - while (i > 0 && g > 0) { - t.push(value.substring(i -= g, i + g)); - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - if (comma) width -= Math.floor((width - 1) / 4); - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - suffix = unit.symbol; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before = i < 0 ? value : value.substring(0, i), after = i < 0 ? "" : locale_decimal + value.substring(i + 1); - if (!zfill && comma) before = formatGroup(before); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix; - }; - }; - } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); - } - }); - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); - } - }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; - } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; - } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } - } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; - } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; - } - }; - } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); - }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); - }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.substring(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; - } - } - string.push(template.substring(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) { - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; - } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; - } - } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; - }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); - }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; - } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.substring(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.substring(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.substring(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.substring(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); - } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); - } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); - } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = +string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.substring(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; - } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(abs(z) / 60), zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.substring(i, i + 1)); - return n ? i + n[0].length : -1; - } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); - }; - } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) - }; - }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; - } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); - } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); - } - }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); - } - }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); - } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } - }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; - } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; - } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; - } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; - } - function compareRanges(a, b) { - return a[0] - b[0]; - } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; - } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; - } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; - }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; - } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); - } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - listener.polygonStart(); - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - listener.polygonEnd(); - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); - } - function ringStart() { - ringListener.lineStart(); - ring = []; - } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); - return; - } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); - } - return clip; - }; - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; - } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); - } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, antimeridian = abs(dλ) > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(dλ), cosφ0 * cosφ + k * Math.cos(dλ))); - polarAngle += antimeridian ? dλ + (dλ >= 0 ? τ : -τ) : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } - } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; - } - } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; - } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; - } - } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; - } - } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy - }; - return line; - }; - } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } - }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); - } - listener.polygonEnd(); - } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; - } - } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); - } - } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); - } - clip.point = point; - if (v_) listener.lineEnd(); - } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - return clip; - }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); - } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); - }; - return p; - } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; - } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); - }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; - } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; - } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); - }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); - } - }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); - }; - } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; - } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; - }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - context.closePath(); - } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); - } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); - } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; - } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); - } - return resample; - } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } - } - } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; - } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); - } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); - }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); - }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; - } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); - } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); - } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); - } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; - } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; - } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; - } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; - } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; - } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); - }; - } - function d3_source(d) { - return d.source; - } - function d3_target(d) { - return d.target; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; - } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; - }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); - }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; - } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; - }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, - point: d3_noop, - lineStart: d3_geo_lengthLineStart, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; - }; - function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; - } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; - }; - return azimuthal; - } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - var ρ = abs(abs(φ) - halfπ) < ε ? 0 : F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; - } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; - } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); - } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; - } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ -_[1], _[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return projection.rotate([ 0, 0 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; - } - function d3_geom_pointY(d) { - return d[1]; - } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); - } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; - }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; - } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - c = d; - } - if (closed) subject.push(subject[0]); - a = b; - } - return subject; - }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); - } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; - } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; - } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); - } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; - } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; - } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; - } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; - } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; - } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; - } - } - } - } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; - } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; - } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; - } - } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; - } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } - } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } - } - } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; - } - } - } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; - } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; - } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; - } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; - } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; - } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; - } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; - } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; - } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; - } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges - }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; - } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); - } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); - }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); - } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } - return quadtree(points); - } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = sx; else x2 = sx; - if (bottom) y1 = sy; else y2 = sy; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; - }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null - }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); - }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; - } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - b -= a = +a; - return function(t) { - return a + b * t; - }; - } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o; - a = a + "", b = b + ""; - d3_interpolate_number.lastIndex = 0; - for (i = 0; m = d3_interpolate_number.exec(b); ++i) { - if (m.index) s.push(b.substring(s0, s1 = m.index)); - q.push({ - i: s.length, - x: m[0] - }); - s.push(null); - s0 = d3_interpolate_number.lastIndex; - } - if (s0 < b.length) s.push(b.substring(s0)); - for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) { - o = q[i]; - if (o.x == m[0]) { - if (o.i) { - if (s[o.i + 1] == null) { - s[o.i - 1] += o.x; - s.splice(o.i, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } else { - s[o.i - 1] += o.x + s[o.i + 1]; - s.splice(o.i, 2); - for (j = i + 1; j < n; ++j) q[j].i -= 2; - } - } else { - if (s[o.i + 1] == null) { - s[o.i] = o.x; - } else { - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } - } - q.splice(i, 1); - n--; - i--; - } else { - o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x)); - } - } - while (i < n) { - o = q.pop(); - if (s[o.i + 1] == null) { - s[o.i] = o.x; - } else { - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - } - n--; - } - if (s.length === 1) { - return s[0] == null ? (o = q[0].x, function(t) { - return o(t) + ""; - }) : function() { - return b; - }; - } - return function(t) { - for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_Color ? d3_interpolateRgb : t === "object" ? Array.isArray(b) ? d3_interpolateArray : d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; - } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; - }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); - } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); - }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); - } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); - }; - } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; - }; - } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; - }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; - }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; - } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; - }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; - } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; - } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; - } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransform(a, b) { - var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; - if (ta[0] != tb[0] || ta[1] != tb[1]) { - s.push("translate(", null, ",", null, ")"); - q.push({ - i: 1, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: 3, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } else { - s.push(""); - } - if (ra != rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(s.pop() + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(s.pop() + "rotate(" + rb + ")"); - } - if (wa != wb) { - q.push({ - i: s.push(s.pop() + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(s.pop() + "skewX(" + wb + ")"); - } - if (ka[0] != kb[0] || ka[1] != kb[1]) { - n = s.push(s.pop() + "scale(", null, ",", null, ")"); - q.push({ - i: n - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: n - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] != 1 || kb[1] != 1) { - s.push(s.pop() + "scale(" + kb + ")"); - } - n = q.length; - return function(t) { - var i = -1, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - function d3_uninterpolateNumber(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { - return (x - a) * b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { - return Math.max(0, Math.min(1, (x - a) * b)); - }; - } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; - }; - }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; - } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; - } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); - } - return sharedNode; - } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: (x - x0) / k - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } - } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); - }); - } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - force.tick = function() { - if ((alpha *= .99) < .005) { - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight / (t.weight + s.weight)); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha - }); - }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; - }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) alpha = x; else alpha = 0; - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - d3.timer(force.tick); - } - return force; - }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, m = candidates.length, x; - while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); - }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); - }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; - } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; - } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; - } - } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; - } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; - } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function recurse(node, depth, nodes) { - var childs = children.call(hierarchy, node, depth); - node.depth = depth; - nodes.push(node); - if (childs && (n = childs.length)) { - var i = -1, n, c = node.children = new Array(n), v = 0, j = depth + 1, d; - while (++i < n) { - d = c[i] = recurse(childs[i], j, nodes); - d.parent = node; - v += d.value; - } - if (sort) c.sort(sort); - if (value) node.value = v; - } else { - delete node.children; - if (value) { - node.value = +value.call(hierarchy, node, depth) || 0; - } - } - return node; - } - function revalue(node, depth) { - var children = node.children, v = 0; - if (children && (n = children.length)) { - var i = -1, n, j = depth + 1; - while (++i < n) v += revalue(children[i], j); - } else if (value) { - v = +value.call(hierarchy, node, depth) || 0; - } - if (value) node.value = v; - return v; - } - function hierarchy(d) { - var nodes = []; - recurse(d, 0, nodes); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - revalue(root, 0); - return root; - }; - return hierarchy; - }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; - } - function d3_layout_hierarchyChildren(d) { - return d.children; - } - function d3_layout_hierarchyValue(d) { - return d.value; - } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; - } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); - } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; - } - } - } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; - } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; - } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; - }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ; - function pie(data) { - var values = data.map(function(d, i) { - return +value.call(pie, d, i); - }); - var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle); - var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values); - var index = d3.range(data.length); - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - var arcs = []; - index.forEach(function(i) { - var d; - arcs[i] = { - data: data[i], - value: d = values[i], - startAngle: a, - endAngle: a += d * k - }; - }); - return arcs; - } - pie.value = function(x) { - if (!arguments.length) return value; - value = x; - return pie; - }; - pie.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return pie; - }; - pie.startAngle = function(x) { - if (!arguments.length) return startAngle; - startAngle = x; - return pie; - }; - pie.endAngle = function(x) { - if (!arguments.length) return endAngle; - endAngle = x; - return pie; - }; - return pie; - }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var n = series.length, m = series[0].length, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); - } - } - return data; - } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; - } - function d3_layout_stackY(d) { - return d.y; - } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; - } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); - } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; - } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; - } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; - } - } - return j; - } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); - } - function d3_layout_stackSum(p, d) { - return p + d[1]; - } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); - } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; - } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0]; - function firstWalk(node, previousSibling) { - var children = node.children, layout = node._tree; - if (children && (n = children.length)) { - var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1; - while (++i < n) { - child = children[i]; - firstWalk(child, previousChild); - ancestor = apportion(child, previousChild, ancestor); - previousChild = child; - } - d3_layout_treeShift(node); - var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim); - if (previousSibling) { - layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); - layout.mod = layout.prelim - midpoint; - } else { - layout.prelim = midpoint; - } - } else { - if (previousSibling) { - layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); - } - } - } - function secondWalk(node, x) { - node.x = node._tree.prelim + x; - var children = node.children; - if (children && (n = children.length)) { - var i = -1, n; - x += node._tree.mod; - while (++i < n) { - secondWalk(children[i], x); - } - } - } - function apportion(node, previousSibling, ancestor) { - if (previousSibling) { - var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop._tree.ancestor = node; - shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift); - sip += shift; - sop += shift; - } - sim += vim._tree.mod; - sip += vip._tree.mod; - som += vom._tree.mod; - sop += vop._tree.mod; - } - if (vim && !d3_layout_treeRight(vop)) { - vop._tree.thread = vim; - vop._tree.mod += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom._tree.thread = vip; - vom._tree.mod += sip - som; - ancestor = node; - } - } - return ancestor; - } - d3_layout_treeVisitAfter(root, function(node, previousSibling) { - node._tree = { - ancestor: node, - prelim: 0, - mod: 0, - change: 0, - shift: 0, - number: previousSibling ? previousSibling._tree.number + 1 : 0 - }; - }); - firstWalk(root); - secondWalk(root, -root._tree.prelim); - var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1; - d3_layout_treeVisitAfter(root, nodeSize ? function(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; - delete node._tree; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = node.depth / y1 * size[1]; - delete node._tree; - }); - return nodes; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); - }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(node) { - var children = node.children; - return children && children.length ? children[0] : node._tree.thread; - } - function d3_layout_treeRight(node) { - var children = node.children, n; - return children && (n = children.length) ? children[n - 1] : node._tree.thread; - } - function d3_layout_treeSearch(node, compare) { - var children = node.children; - if (children && (n = children.length)) { - var child, n, i = -1; - while (++i < n) { - if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) { - node = child; - } - } - } - return node; - } - function d3_layout_treeRightmost(a, b) { - return a.x - b.x; - } - function d3_layout_treeLeftmost(a, b) { - return b.x - a.x; - } - function d3_layout_treeDeepest(a, b) { - return a.depth - b.depth; - } - function d3_layout_treeVisitAfter(node, callback) { - function visit(node, previousSibling) { - var children = node.children; - if (children && (n = children.length)) { - var child, previousChild = null, i = -1, n; - while (++i < n) { - child = children[i]; - visit(child, previousChild); - previousChild = child; - } - } - callback(node, previousSibling); - } - visit(node, null); - } - function d3_layout_treeShift(node) { - var shift = 0, change = 0, children = node.children, i = children.length, child; - while (--i >= 0) { - child = children[i]._tree; - child.prelim += shift; - child.mod += shift; - shift += child.shift + (change += child.change); - } - } - function d3_layout_treeMove(ancestor, node, shift) { - ancestor = ancestor._tree; - node = node._tree; - var change = shift / (node.number - ancestor.number); - ancestor.change += change; - node.change -= change; - node.shift += shift; - node.prelim += shift; - node.mod += shift; - } - function d3_layout_treeAncestor(vim, node, ancestor) { - return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor; - } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_treeVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_treeVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_treeVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_treeVisitAfter(root, d3_layout_packSiblings); - d3_layout_treeVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; - } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); - }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; - } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; - } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } - } - } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; - } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); - } - } - } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_treeVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_treeVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; - }); - return nodes; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; - }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; - }; - return d3_layout_hierarchyRebind(cluster, hierarchy); - }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; - } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; - } - } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; - } - children.forEach(squarify); - } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; - } - } - children.forEach(stickify); - } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); - } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = 0; - root.y = 0; - root.dx = size[0]; - root.dy = size[1]; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; - }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; - }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; - } - }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); - } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; - } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; - } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; - } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity - }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); - }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - return d3.format(format ? format.replace(d3_format_re, function(a, b, c, d, e, f, g, h, i, j) { - return [ b, c, d, e, f, g, h, i || "." + d3_scale_linearFormatPrecision(j, range), j ].join(""); - }) : ",." + d3_scale_linearPrecision(range[2]) + "f"); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(Math.abs(range[0]), Math.abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); - }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); - } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); - } - return ticks; - }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, - Math.floor), e; - return function(d) { - return d / pow(f(log(d) + e)) <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || ranger.t === "range" && index.set(x, domain.push(x))) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding); - range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; - }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; - }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step; - range = steps(start + Math.round(error / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; - }; - scale.rangeBand = function() { - return rangeBand; - }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); - }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.filter(function(d) { - return !isNaN(d); - }).sort(d3.ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); - } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); - }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; - } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function arc() { - var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, - a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1); - return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z"; - } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; - }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.join("L"); - } - function d3_svg_lineLinearClosed(points) { - return d3_svg_lineLinear(points) + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); - } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); - } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - } - } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; - } - return path; - } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); - } - return tangents; - } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - points.pop(); - path.push("L", pi); - return path.join(""); - } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); - } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; - } - m[i] = d; - return m; - } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); - } - return tangents; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] + d3_svg_arcOffset; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; - } - } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; - } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - return area; - } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; - } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; - } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; - }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; - } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; - } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - function d3_transition(groups, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection) { - return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition(); - }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, id, node.__transition__[id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node.__transition__[id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, id); - }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.id); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id; - if (arguments.length < 2) return this.node().__transition__[id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node.__transition__[id].tween.remove(name); - } : function(node) { - node.__transition__[id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node.__transition__[id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); - } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); - }); - } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); - }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); - }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; - }; - } - d3_transitionPrototype.remove = function() { - return this.each("end.transition", function() { - var p; - if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id; - if (arguments.length < 1) return this.node().__transition__[id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node.__transition__[id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node.__transition__[id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node.__transition__[id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node.__transition__[id]; - type.call(node, node.__data__, i, j); - }); - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } else { - d3_selection_each(this, function(node) { - var transition = node.__transition__[id]; - (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = Object.create(node.__transition__[id0]); - transition.delay += transition.duration; - d3_transitionNode(node, i, id1, transition); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, id1); - }; - function d3_transitionNode(node, i, id, inherit) { - var lock = node.__transition__ || (node.__transition__ = { - active: 0, - count: 0 - }), transition = lock[id]; - if (!transition) { - var time = inherit.time; - transition = lock[id] = { - tween: new d3_Map(), - time: time, - ease: inherit.ease, - delay: inherit.delay, - duration: inherit.duration - }; - ++lock.count; - d3.timer(function(elapsed) { - var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = []; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - function start(elapsed) { - if (lock.active > id) return stop(); - lock.active = id; - transition.event && transition.event.start.call(node, d, i); - transition.tween.forEach(function(key, value) { - if (value = value.call(node, d, i)) { - tweened.push(value); - } - }); - d3.timer(function() { - timer.c = tick(elapsed || 1) ? d3_true : tick; - return 1; - }, 0, time); - } - function tick(elapsed) { - if (lock.active !== id) return stop(); - var t = elapsed / duration, e = ease(t), n = tweened.length; - while (n > 0) { - tweened[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, d, i); - return stop(); - } - } - function stop() { - if (--lock.count) delete lock[id]; else delete node.__transition__; - return 1; - } - }, 0, time); - } - } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"); - switch (orient) { - case "bottom": - { - tickTransform = d3_svg_axisX; - lineEnter.attr("y2", innerTickSize); - textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding); - lineUpdate.attr("x2", 0).attr("y2", innerTickSize); - textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding); - text.attr("dy", ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize); - break; - } - - case "top": - { - tickTransform = d3_svg_axisX; - lineEnter.attr("y2", -innerTickSize); - textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); - lineUpdate.attr("x2", 0).attr("y2", -innerTickSize); - textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); - text.attr("dy", "0em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize); - break; - } - - case "left": - { - tickTransform = d3_svg_axisY; - lineEnter.attr("x2", -innerTickSize); - textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)); - lineUpdate.attr("x2", -innerTickSize).attr("y2", 0); - textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", 0); - text.attr("dy", ".32em").style("text-anchor", "end"); - pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize); - break; - } - - case "right": - { - tickTransform = d3_svg_axisY; - lineEnter.attr("x2", innerTickSize); - textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding); - lineUpdate.attr("x2", innerTickSize).attr("y2", 0); - textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0); - text.attr("dy", ".32em").style("text-anchor", "start"); - pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize); - break; - } - } - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1); - } - tickEnter.call(tickTransform, scale0); - tickUpdate.call(tickTransform, scale1); - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = arguments; - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; - }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; - }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function() { - return arguments.length && axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x) { - selection.attr("transform", function(d) { - return "translate(" + x(d) + ",0)"; - }); - } - function d3_svg_axisY(selection, y) { - selection.attr("transform", function(d) { - return "translate(0," + y(d) + ")"; - }); - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } - } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; - } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; - } else { - max = position; - } - } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; - } - } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } - } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; - }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; - }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; - }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; - }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; - }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; - } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; - } - } : interval)); - }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); - } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(+start, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); - }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; - }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; - }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) { - define(d3); - } else if (typeof module === "object" && module.exports) { - module.exports = d3; - } else { - this.d3 = d3; - } -}(); \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.min.js b/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.min.js deleted file mode 100644 index 8cfc9ef3f4..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/libs/d3.v3.min.js +++ /dev/null @@ -1,5 +0,0 @@ -!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(Mt(u[0]),Mt(u[1]),Mt(u[2]))}return(i=Va.get(n))?t(i.r,i.g,i.b):(null!=n&&"#"===n.charAt(0)&&(4===n.length?(o=n.charAt(1),o+=o,a=n.charAt(2),a+=a,c=n.charAt(3),c+=c):7===n.length&&(o=n.substring(1,3),a=n.substring(3,5),c=n.substring(5,7)),o=parseInt(o,16),a=parseInt(a,16),c=parseInt(c,16)),t(o,a,c))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function zt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){if(m&&n%1)return"";var e=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var u=Xo.formatPrefix(n,h);n=u.scale(n),d=u.symbol}else n*=p;n=g(n,h);var c=n.lastIndexOf("."),x=0>c?n:n.substring(0,c),M=0>c?"":t+n.substring(c+1);!s&&f&&(x=i(x));var _=v.length+x.length+M.length+(y?0:e.length),b=l>_?new Array(_=l-_+1).join(r):"";return y&&(x=i(b+x)),e+=v,n=x+M,("<"===o?e+n+b:">"===o?b+e+n:"^"===o?b.substring(0,_>>=1)+e+n+b.substring(_):e+(y?n:b+n))+d}}}function qt(n){return n+""}function Tt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=Tt;var r=new Tt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=Tt;var r=new Tt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=Tt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=Tt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++ea;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=oa(_)>Sa,w=p*x;if(hc.add(Math.atan2(w*Math.sin(_),v*M+w*Math.cos(_))),i+=b?_+(_>=0?ka:-ka):_,b^h>=e^m>=e){var S=fe(se(f),se(n));pe(S);var k=fe(u,S);pe(k);var E=(b^_>=0?-1:1)*X(k[2]);(r>E||r===E&&(S[0]||S[1]))&&(o+=b^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function ze(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Te(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)0?0:3:oa(r[0]-e)0?2:1:oa(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),zc>t&&(zc=t),t>Tc&&(Tc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)i||oa((y*L+x*z)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b -},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function zr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];zr(n);for(var c=i;c.circle&&oa(e-c.circle.x)l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function Tr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)Aa?{x:f,y:oa(t-f)Aa?{x:oa(e-p)Aa?{x:h,y:oa(t-h)Aa?{x:oa(e-g)=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xr;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=zu(t,e),i=qu(Tu(e,t,-u))||0;t[0]*e[1]180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++ie;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++iu&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Ti(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():Ti(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=Ti(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Ti(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++0;h--)o.push(i(s)*h);for(s=0;o[s]c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++ae?[0/0,0/0]:[e>0?u[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++ue?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Ti(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.1"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ur&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ur&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ue&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ue&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=e);)e=u=void 0;for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=e);)e=void 0;for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)r;){var i=r+u>>>1;er?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++rr;++r)p[r]=z(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++oi;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=T.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,za=Math.SQRT2,qa=2,Ta=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(za*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(za*t+v)]}return[r+n*s,u+n*l,i*Math.exp(za*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+Ta*f)/(2*i*qa*h),p=(c*c-i*i-Ta*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/za;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=z.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=z.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=z.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=z.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",z=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=z.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,z,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv(" ","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;Tt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:zt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nhc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h -}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,ze,Te,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,zc,qc,Tc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=Tc=-(Lc=zc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,zc],[qc,Tc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.xm&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++fg;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++ie.dx)&&(l=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[]) -},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(zo(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=To,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),z.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),z=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?z.on("touchmove.brush",v).on("touchend.brush",y):z.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),T=+/^n/.test(k);M=[l[1-q]-L[0],f[1-T]-L[1]],L[0]=l[q],L[1]=f[T]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(+n,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}(); \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/pca.html b/ThirdParty/Ert/devel/share/gui/plots/pca.html deleted file mode 100644 index 22fbdf4ffb..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/pca.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/rft.html b/ThirdParty/Ert/devel/share/gui/plots/rft.html deleted file mode 100644 index c84775d54e..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/rft.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/rft_overview.html b/ThirdParty/Ert/devel/share/gui/plots/rft_overview.html deleted file mode 100644 index f73115fab0..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/rft_overview.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot.js deleted file mode 100644 index ed70241950..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot.js +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'base_plot.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function BasePlot(element, x_dimension, y_dimension) { - this.stored_data = null; - this.margin = {left: 90, right: 20, top: 20, bottom: 30}; - this.root_elemenet = element; - - this.render_observations = true; - this.render_refcase = true; - - this.custom_y_min = null; - this.custom_y_max = null; - this.custom_x_min = null; - this.custom_x_max = null; - - this.render_finished = false; - this.render_callback_finished = false; - this.rendering_finished_callback = null; - - this.pre_render_callback = null; - this.render_callback = null; - - this.dimension_x = x_dimension; - this.dimension_y = y_dimension; - - this.vertical_error_bar = true; - this.error_bar_only = false; - - var group = this.root_elemenet.append("div") - .attr("class", "plot"); - - this.title = group.append("div") - .attr("class", "plot-title") - .text(this.getTitle()); - - this.axis_label_group = group.append("div") - .attr("id", "axis-label-group") - - this.x_label = this.axis_label_group.append("div") - .attr("class", "x axis-label") - .text("") - - this.y_label = this.axis_label_group.append("div") - .attr("class", "y axis-label") - .text(""); - - var plot_area = group.append("div").attr("class", "plot-area"); - - this.width = 1024 - this.margin.left - this.margin.right; - this.height = 512 - this.margin.top - this.margin.bottom; - - this.canvas = plot_area.append("canvas") - .attr("id", "plot-canvas") - .attr("width", this.width) - .attr("height", this.height) - .style("position", "absolute") - .style("top", (this.margin.top) + "px") - .style("left", (this.margin.left) + "px") - .style("z-index", 5); - - this.overlay_canvas = plot_area.append("canvas") - .attr("id", "plot-overlay-canvas") - .attr("width", this.width) - .attr("height", this.height) - .style("position", "absolute") - .style("top", (this.margin.top) + "px") - .style("left", (this.margin.left) + "px") - .style("z-index", 5); - - this.plot_group = plot_area.append("svg") - .attr("class", "plot-svg") - .style("z-index", 10); - - this.legend_group = group.append("div") - .attr("class", "plot-legend-group"); - - this.y_axis = d3.svg.axis() - .scale(this.dimension_y.scale()) - .orient("left"); - - this.dimension_y.format(this.y_axis, this.width); - - this.x_axis = d3.svg.axis() - .scale(this.dimension_x.scale()) - .orient("bottom"); - - this.dimension_x.format(this.x_axis, this.height); - - this.plot_group.append("g") - .attr("class", "y axis pale") - .attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")") - .call(this.y_axis); - - this.plot_group.append("g") - .attr("class", "x axis pale") - .attr("transform", "translate(" + this.margin.left + ", " + (this.height + this.margin.top) + ")") - .call(this.x_axis); - - - this.x = this.dimension_x; - this.y = this.dimension_y; - - this.legend = CanvasPlotLegend(); - this.legend_list = []; - - this.line_renderer = CanvasPlotLine().x(this.x).y(this.y); - this.area_renderer = CanvasPlotArea().x(this.x).y(this.y); - this.error_bar_renderer = CanvasErrorBar().x(this.x).y(this.y); - this.stippled_line_renderer = CanvasPlotStippledLine().x(this.x).y(this.y); -} - -BasePlot.prototype.resize = function(width, height) { - //Some magic margins... - width = width - 80; - height = height - 70; - - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - - this.dimension_x.format(this.x_axis, this.height); - this.dimension_y.format(this.y_axis, this.width); - - this.dimension_x.setRange(0, this.width); - this.dimension_y.setRange(this.height, 0); - - this.plot_group.style("width", width + "px").style("height", height + "px"); - - this.canvas.attr("width", this.width).attr("height", this.height); - this.overlay_canvas.attr("width", this.width).attr("height", this.height); - - this.plot_group.select(".x.axis").attr("transform", "translate(" + this.margin.left + ", " + (this.height + this.margin.top) + ")"); -}; - -BasePlot.prototype.setScales = function(x_min, x_max, y_min, y_max) { - - if(this.custom_y_min != y_min || this.custom_y_max != y_max || - this.custom_x_min != x_min || this.custom_x_max != x_max) { - this.custom_y_min = y_min; - this.custom_y_max = y_max; - this.custom_x_min = x_min; - this.custom_x_max = x_max; - } -}; - -BasePlot.prototype.setYDomain = function(min_y, max_y, ordinals) { - if (arguments.length == 3 && this.dimension_y.isOrdinal()) { - this.dimension_y.setDomain(ordinals); - } else { - var min = min_y; - var max = max_y; - - if (this.custom_y_min != null) { - min = this.custom_y_min; - } - - if (this.custom_y_max != null) { - max = this.custom_y_max; - } - - this.dimension_y.setDomain(min, max); - } -}; - -BasePlot.prototype.setXDomain = function(min_x, max_x, ordinals) { - if (arguments.length == 3 && this.dimension_x.isOrdinal()) { - this.dimension_x.setDomain(ordinals); - } else { - var min = min_x; - var max = max_x; - if (this.custom_x_min != null) { - min = this.custom_x_min; - } - - if (this.custom_x_max != null) { - max = this.custom_x_max; - } - - this.dimension_x.setDomain(min, max); - } -}; - -BasePlot.prototype.setData = function(data) { - this.stored_data = data; -}; - -BasePlot.prototype.getTitle = function(){ - if(this.stored_data != null && "name" in this.stored_data){ - return this.stored_data.name(); - } else { - return "No data"; - } -}; - -BasePlot.prototype.render = function() { - if(this.stored_data == null) { - return; - } - - var data = this.stored_data; - this.render_finished = false; - this.render_callback_finished = false; - - this.title.text(this.getTitle()); - - if (this.dimension_x.getUnit() == "") { - this.x_label.text(""); - } else { - this.x_label.text("X: " + this.dimension_x.getUnit()); - } - - if (this.dimension_y.getUnit() == "") { - this.y_label.text(""); - } else { - this.y_label.text("Y: " + this.dimension_y.getUnit()); - } - - if(data.hasBoundaries()) { - this.setYDomain(data.minY(), data.maxY()); - this.setXDomain(data.minX(), data.maxX()); - } - - if(this.pre_render_callback != null) { - this.pre_render_callback(data); - } - - this.resetLegends(); - - var axis = this.plot_group.select(".y.axis").call(this.y_axis); - this.dimension_y.relabel(axis); - - axis = this.plot_group.select(".x.axis").call(this.x_axis); - this.dimension_x.relabel(axis); - - this.canvas.attr("width", this.width).attr("height", this.height); - this.overlay_canvas.attr("width", this.width).attr("height", this.height); - - var context = this.canvas.node().getContext("2d"); - context.save(); - context.clearRect(0, 0, this.width, this.height); - - var overlay_context = this.overlay_canvas.node().getContext("2d"); - overlay_context.save(); - overlay_context.clearRect(0, 0, this.width, this.height); - - this.render_callback(context, data); - - if(this.render_observations) { - this.renderObservations(overlay_context, data); - } - - if(this.render_refcase) { - this.renderRefcase(overlay_context, data); - } - - overlay_context.restore(); - context.restore(); - this.finishedRendering(); - -}; - -BasePlot.prototype.setRenderCallback = function(callback) { - this.render_callback = callback; -}; - -BasePlot.prototype.setPreRenderCallback = function(callback) { - this.pre_render_callback = callback; -}; - - -BasePlot.prototype.resetLegends = function() { - this.legend_list = []; -}; - -BasePlot.prototype.addLegend = function(style, name, render_function) { - this.legend_list.push({"style": style, "name": name,"render_function": render_function}); -}; - - -BasePlot.prototype.renderObservations = function(context, data) { - if(data.hasObservationData()) { - var obs_data = data.observationData(); - if(obs_data.isContinuous() && !this.error_bar_only) { - var x_values = obs_data.xValues(); - var y_values = obs_data.yValues(); - var std_values = obs_data.stdValues(); - - var obs_x_area_samples = []; - var obs_y_area_samples = []; - - for (var index = 0; index < x_values.length; index++) { - obs_x_area_samples.push(x_values[index]); - obs_y_area_samples.push(y_values[index] + std_values[index]); - } - - for (var index = x_values.length - 1; index >= 0; index--) { - obs_x_area_samples.push(x_values[index]); - obs_y_area_samples.push(y_values[index] - std_values[index]); - } - - this.area_renderer.style(STYLES["observation_area"]); - this.area_renderer(context, obs_x_area_samples, obs_y_area_samples); - - this.stippled_line_renderer.style(STYLES["observation"]); - this.stippled_line_renderer(context, x_values, y_values); - - this.addLegend(STYLES["observation"], "Observation", CanvasPlotLegend.stippledLine); - this.addLegend(STYLES["observation_area"], "Observation error", CanvasPlotLegend.filledCircle); - - } else { - - var obs_x_samples = obs_data.xValues(); - var obs_y_samples = obs_data.yValues(); - var obs_std_samples = obs_data.stdValues(); - - for (var index = 0; index < obs_x_samples.length; index++) { - var x = obs_x_samples[index]; - var y = obs_y_samples[index]; - var error = obs_std_samples[index]; - - this.error_bar_renderer.style(STYLES["observation_error_bar"]); - this.error_bar_renderer(context, x, y, error, this.vertical_error_bar); - } - this.addLegend(STYLES["observation_error_bar"], "Observation error bar", CanvasPlotLegend.errorBar); - } - } -}; - - -BasePlot.prototype.renderRefcase = function(context, data) { - if(data.hasRefcaseData()) { - var refcase_data = data.refcaseData(); - var style = STYLES["refcase"]; - - this.line_renderer.style(style); - this.line_renderer(context, refcase_data.xValues(), refcase_data.yValues()); - - this.addLegend(style, "Refcase", CanvasPlotLegend.simpleLine); - } -}; - -BasePlot.prototype.createLineRenderer = function() { - return CanvasPlotLine().x(this.x).y(this.y); -}; - -BasePlot.prototype.createCircleRenderer = function() { - return CanvasCircle().x(this.x).y(this.y); -}; - -BasePlot.prototype.createCrossRenderer = function() { - return CanvasCross().x(this.x).y(this.y); -}; - -BasePlot.prototype.createStippledLineRenderer = function() { - return CanvasPlotStippledLine().x(this.x).y(this.y); -}; - -BasePlot.prototype.createAreaRenderer = function() { - return CanvasPlotArea().x(this.x).y(this.y); -}; - - -BasePlot.prototype.setVerticalErrorBar = function(vertical){ - this.vertical_error_bar = vertical; - -}; - -BasePlot.prototype.setCustomSettings = function (settings) { - if ("error_bar_only" in settings) { - this.error_bar_only = settings["error_bar_only"]; - } - - if ("show_observations" in settings) { - this.setRenderObservations(settings["show_observations"]); - } - - if ("show_refcase" in settings) { - this.setRenderRefcase(settings["show_refcase"]); - } -}; - -BasePlot.prototype.renderCallbackFinishedRendering = function(){ - this.render_callback_finished = true; - this.emitFinishedRendering() -}; - -BasePlot.prototype.finishedRendering = function(){ - this.render_finished = true; - this.emitFinishedRendering(); -}; - -BasePlot.prototype.emitFinishedRendering = function(){ - if(this.rendering_finished_callback != null){ - if(this.render_finished && this.render_callback_finished) { - this.legend_group.selectAll(".plot-legend").data(this.legend_list).call(this.legend); - this.rendering_finished_callback(); - } - } -}; - -BasePlot.prototype.setRenderingFinishedCallback = function(callback) { - this.rendering_finished_callback = callback; -}; - -BasePlot.prototype.setLogScaleOnDimensionX = function(use_log_scale) { - this.dimension_x.setIsLogScale(use_log_scale); - this.x_axis.scale(this.dimension_x.scale()); - this.dimension_x.format(this.x_axis, this.height); -}; - -BasePlot.prototype.setLogScaleOnDimensionY = function(use_log_scale) { - this.dimension_y.setIsLogScale(use_log_scale); - this.y_axis.scale(this.dimension_y.scale()); - this.dimension_y.format(this.y_axis, this.width); -}; - -BasePlot.prototype.setRenderObservations = function(enabled) { - this.render_observations = enabled; -}; - -BasePlot.prototype.setRenderRefcase = function(enabled) { - this.render_refcase = enabled; -}; - -function isNumber(n) { - return !isNaN(parseFloat(n)) && isFinite(n); -} diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_integer_dimension.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_integer_dimension.js deleted file mode 100644 index d0f62f3bba..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_integer_dimension.js +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'base_plot_time_dimension.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function BasePlotIntegerDimension(){ - var scale = d3.time.scale().range([0, 1]).domain([1, 0]); - var unit = ""; - - var scaler = function(d) { - return scale(d); - }; - - var count_format = d3.format("d"); - - function dimension(value) { - return scaler(value); - } - - dimension.setDomain = function(min, max) { - if(min == max) { - min = Math.floor(min - 0.1 * min); - max = Math.ceil(max + 0.1 * max); - } - - scale.domain([min, max]); - - }; - - dimension.setRange = function(min, max) { - scale.range([min, max]); - }; - - dimension.scale = function() { - return scale; - }; - - dimension.isOrdinal = function() { - return false; - }; - - dimension.format = function(axis, max_length){ - axis.ticks(5) - .tickSize(-max_length, -max_length) - .tickFormat(count_format); - - return dimension; - }; - - dimension.relabel = function (axis) { - - }; - - dimension.setUnit = function(unit_in) { - unit = unit_in; - }; - - dimension.getUnit = function() { - return unit; - }; - - return dimension; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_ordinal_dimension.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_ordinal_dimension.js deleted file mode 100644 index d46197f0f2..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_ordinal_dimension.js +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'base_plot_ordinal_dimension.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function BasePlotOrdinalDimension(point_style){ - var scale = null; - var unit = ""; - - if(point_style) { - scale = d3.scale.ordinal().rangePoints([0, 1], 1).domain(["unknown"]); - } else { - scale = d3.scale.ordinal().rangeRoundBands([0, 1], .5).domain(["unknown"]); - } - - var scaler = function(d) { - return scale(d); - }; - - function dimension(value) { - return scaler(value); - } - - dimension.setDomain = function(values) { - scale.domain(values); - }; - - dimension.setRange = function(min, max) { - if(point_style) { - scale.rangePoints([min, max], 1); - } else { - scale.rangeRoundBands([min, max], .5); - } - }; - - dimension.scale = function() { - return scale; - }; - - dimension.format = function(axis, max_length){ - axis.tickSize(-max_length, -max_length); - - return dimension; - }; - - dimension.isOrdinal = function() { - return true; - }; - - dimension.relabel = function (axis) { - - }; - - dimension.setUnit = function(unit_in) { - unit = unit_in; - }; - - dimension.getUnit = function() { - return unit; - }; - - return dimension; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_time_dimension.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_time_dimension.js deleted file mode 100644 index d69c7b6663..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_time_dimension.js +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'base_plot_time_dimension.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function BasePlotTimeDimension(){ -// var scale = d3.scale.linear().range([1, 0]).domain([0, 1]).nice(); - var scale = d3.time.scale().range([0, 1]).domain([1, 0]); - var time_scale = d3.time.scale().range([0, 1]).domain([1, 0]); - - var unit = "Date"; - - var scaler = function(d) { - return scale(d); - }; - - var customTimeFormat = d3.time.format.multi([ - [".%L", function(d) { return d.getMilliseconds(); }], - [":%S", function(d) { return d.getSeconds(); }], - ["%I:%M", function(d) { return d.getMinutes(); }], - ["%I %p", function(d) { return d.getHours(); }], - ["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }], - ["%b %d", function(d) { return d.getDate() != 1; }], - ["%b", function(d) { return d.getMonth(); }], - ["%Y", function() { return true; }] - ]); - - function dimension(value) { - return scaler(value); - } - - dimension.setDomain = function(min, max) { - time_scale.domain([new Date(min * 1000), new Date(max * 1000)]).nice(); - var domain = time_scale.domain(); - scale.domain([domain[0].getTime() / 1000, domain[1].getTime() / 1000]); - }; - - dimension.setRange = function(min, max) { - scale.range([min, max]); - time_scale.range([min, max]); - }; - - dimension.scale = function() { - return time_scale; - }; - - dimension.isOrdinal = function() { - return false; - }; - - dimension.format = function(axis, max_length){ - axis.tickFormat(customTimeFormat); - - return dimension; - }; - - dimension.relabel = function (axis) { - - }; - - dimension.setUnit = function(unit_in) { - unit = unit_in; - }; - - dimension.getUnit = function() { - return unit; - }; - - return dimension; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_value_dimension.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_value_dimension.js deleted file mode 100644 index 2ff866d8b7..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/base_plot_value_dimension.js +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'base_plot_value_dimension.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function BasePlotValueDimension(flip_range) { - if (!arguments.length) { - var flip_range = false; - } - - var is_log_scale = false; - var tick_count = 10; - var ticks = null; - var unit = ""; - - var scale = d3.scale.linear().range([1, 0]).domain([0, 1]).nice(); - var log_scale = d3.scale.log().range([1, 0]).domain([0, 1]).nice(); - - var value_format = d3.format(".4g"); -// var value_log_format = d3.format("e"); -// -// var value_log_format_function = function (d) { -// var x = Math.log(d) / Math.log(10) + 1e-6; -// return Math.abs(x - Math.floor(x)) < 0.3 ? value_log_format(d) : ""; -// }; - - var scaler = function (d) { - if (is_log_scale) { - return log_scale(d); - } else { - return scale(d); - } - }; - - function dimension(value) { - return scaler(value); - } - - function powerOfTen(d) { - return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1; - } - - dimension.setDomain = function (min, max) { - if (min == max) { - min = min - 0.1 * min; - max = max + 0.1 * max; - } - - if (flip_range) { - var tmp = min; - min = max; - max = tmp; - } - scale.domain([min, max]).nice(); - - - if(min <= 0.0) { - min = 0.000000001; - } - - if(max <= 0.0) { - max = 0.000000016; - } - - var from_log = Math.floor(Math.log(min) / Math.log(10)); - var to_log = Math.ceil(Math.log(max) / Math.log(10)); - var from = Math.pow(10, from_log); - var to = Math.pow(10, to_log); - log_scale.domain([from, to]); - }; - - dimension.setRange = function (min, max) { - scale.range([min, max]).nice(); - log_scale.range([min, max]).nice(); - }; - - dimension.scale = function () { - if (is_log_scale) { - return log_scale; - } else { - return scale; - } - }; - - dimension.isOrdinal = function () { - return false; - }; - - dimension.format = function (axis, max_length) { - - if (is_log_scale) { - axis.tickValues(null) - .tickPadding(10) - .ticks(1) - .tickSize(-max_length, -max_length); -// .tickFormat(value_log_format_function); - } else { - axis.tickPadding(10) - .tickSize(-max_length, -max_length) - .tickFormat(value_format) - .ticks(tick_count) - .tickValues(ticks); - } - - return dimension; - }; - - dimension.setIsLogScale = function (use_log_scale) { - is_log_scale = use_log_scale; - }; - - dimension.isLogScale = function () { - return is_log_scale; - }; - - dimension.relabel = function (axis) { - if (is_log_scale) { - axis.selectAll(".tick text") - .text(null) - .filter(powerOfTen) - .text(function (d) { - return "1.0×10"; - }) - .append("tspan") - .style("font-size", "70%") - .attr("dy", "-.7em") - .text(function (d) { - return Math.round(Math.log(d) / Math.LN10); - }); - } - }; - - dimension.setTicks = function(tick_list) { - ticks = tick_list; - }; - - dimension.setUnit = function(unit_in) { - unit = unit_in; - }; - - dimension.getUnit = function() { - return unit; - }; - - return dimension; -} diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_error_bar.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_error_bar.js deleted file mode 100644 index 2081f2c155..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_error_bar.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_error_bar.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - - -function CanvasErrorBar() { - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - var radius = 2.5; - - function render(context, x, y, error, vertical) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - - x = X(x); - y = Y(y); - - context.beginPath(); - context.arc(x, y, radius, 0, 2 * Math.PI); - context.stroke(); - - - context.beginPath(); - if(vertical){ - error = Y(y + error) - Y(y); - - context.moveTo(x, y - radius); - context.lineTo(x, y - radius + error); - - context.moveTo(x - radius, y - radius + error); - context.lineTo(x + radius, y - radius + error); - - context.moveTo(x, y + radius); - context.lineTo(x, y + radius - error); - - context.moveTo(x - radius, y + radius - error); - context.lineTo(x + radius, y + radius - error); - - } else { - error = X(x + error) - X(x); - - context.moveTo(x - radius, y); - context.lineTo(x - radius + error, y); - - context.moveTo(x - radius + error, y - radius); - context.lineTo(x - radius + error, y + radius); - - context.moveTo(x + radius, y); - context.lineTo(x + radius - error, y); - - context.moveTo(x + radius - error, y - radius); - context.lineTo(x + radius - error, y + radius); - } - - context.stroke(); - - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot.js deleted file mode 100644 index ac70f58b21..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot.js +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function Plot(element, x_dimension, y_dimension) { - this.plot = new BasePlot(element, x_dimension, y_dimension); - - this.horizontal_draw_direction = true; - this.waiting_for_render_restart = false; - - - this.line_renderers = []; - for (var index = 1; index <= 5; index++) { - var renderer = this.plot.createLineRenderer(); - renderer.style(STYLES["ensemble_" + (index)]); - this.line_renderers.push(renderer) - } - - this.circle_renderers = []; - for (var index = 1; index <= 5; index++) { - var renderer = this.plot.createCircleRenderer(); - renderer.style(STYLES["ensemble_" + (index)]); - this.circle_renderers.push(renderer) - } - - this.tracker = new IncrementalRenderTracker(); - - var self = this; - - var progressivePreRenderer = function (context, data) { - var case_list = data.caseList(); - - for (var case_index = 0; case_index < case_list.length; case_index++) { - var style = STYLES["ensemble_" + (case_index + 1)]; - var case_name = case_list[case_index]; - - self.plot.addLegend(style, case_name, CanvasPlotLegend.simpleLine); - } - - self.progressiveRenderer(context, data, self, 0, 0); - }; - - var renderEnsembleProgressively = function (context, data) { - if (data.hasEnsembleData()) { - self.tracker.start(function () { - progressivePreRenderer(context, data); - }); - } - }; - - this.progressiveRenderer = function (context, data, self, case_index, realization) { - if (self.tracker.shouldStop()) { - self.tracker.stoppedRendering(); - return; - } - - var case_list = data.caseList(); - var case_name = case_list[case_index]; - var line_renderer = self.line_renderers[case_index]; - var circle_renderer = self.circle_renderers[case_index]; - - var ensemble_data = data.ensembleData(case_name); - var x_values = ensemble_data.xValues(); - var y_values = ensemble_data.yValues(); - - var realization_count = y_values.length; - if (!self.horizontal_draw_direction) { - realization_count = x_values.length; - } - - self.tracker.loopStart(); - for (var i = realization; i < realization_count; i++) { - if (self.horizontal_draw_direction) { - if(x_values.length == 1) { - circle_renderer(context, x_values[0], y_values[i][0]) - } else { - line_renderer(context, x_values, y_values[i]); - } - - } else { - if(y_values.length == 1) { - circle_renderer(context, x_values[i][0], y_values[0]) - } else { - line_renderer(context, x_values[i], y_values); - } - } - - realization++; - - if (self.tracker.shouldLoopStop()) { - break; - } - } - - if (realization == realization_count) { - case_index++; - realization = 0; - } - - if (case_index < case_list.length) { - window.setTimeout(function () { - self.progressiveRenderer(context, data, self, case_index, realization); - }, 15); - } else { - self.tracker.stoppedRendering(); - self.plot.renderCallbackFinishedRendering(); - } - }; - - - var renderEnsembleDirect = function(context, data) { - if(data.hasEnsembleData()) { - var case_list = data.caseList(); - - for(var case_index = 0; case_index < case_list.length; case_index++) { - var style = STYLES["ensemble_" + (case_index + 1)]; - var case_name = case_list[case_index]; - var line_renderer = self.line_renderers[case_index]; - var circle_renderer = self.circle_renderers[case_index]; - - var ensemble_data = data.ensembleData(case_name); - var x_values = ensemble_data.xValues(); - var y_values = ensemble_data.yValues(); - - var realization_count = y_values.length; - if (!self.horizontal_draw_direction) { - realization_count = x_values.length; - } - - - for (var i = 0; i < realization_count; i++) { - if (self.horizontal_draw_direction) { - if(x_values.length == 1) { - circle_renderer(context, x_values[0], y_values[i][0]) - } else { - line_renderer(context, x_values, y_values[i]); - } - - } else { - if(y_values.length == 1) { - circle_renderer(context, x_values[i][0], y_values[0]) - } else { - line_renderer(context, x_values[i], y_values); - } - } - - } - - self.plot.addLegend(style, case_name, CanvasPlotLegend.simpleLine); - } - self.plot.renderCallbackFinishedRendering(); - } - }; - - this.plot.setRenderCallback(renderEnsembleProgressively); - //this.plot.setRenderCallback(renderEnsembleDirect); -} - -Plot.prototype.resize = function (width, height) { - this.plot.resize(width, height); -}; - -Plot.prototype.setScales = function (x_min, x_max, y_min, y_max) { - this.plot.setScales(x_min, x_max, y_min, y_max); -}; - -Plot.prototype.setData = function (data) { - this.plot.setData(data); -}; - -Plot.prototype.setVerticalErrorBar = function (vertical) { - this.plot.setVerticalErrorBar(vertical); -}; - -Plot.prototype.setHorizontalDrawDirection = function (horizontal) { - this.horizontal_draw_direction = horizontal; -}; - -Plot.prototype.setCustomSettings = function (settings) { - this.plot.setCustomSettings(settings); -}; - -Plot.prototype.setRenderingFinishedCallback = function(callback) { - this.plot.setRenderingFinishedCallback(callback); -}; - -Plot.prototype.renderNow = function(){ - if(!this.tracker.isRunning()) { - this.waiting_for_render_restart = false; - this.plot.render(); - } else { - if(!this.waiting_for_render_restart) { - this.tracker.forceStop(); - this.waiting_for_render_restart = true; - - window.setTimeout(function () { - self.renderNow(); - }, 15); - } - } -}; - -Plot.prototype.getTitle = function(){ - return this.plot.getTitle(); -}; diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_area.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_area.js deleted file mode 100644 index 55ca1b417c..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_area.js +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_area.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function CanvasPlotArea() { - var x = function(d) { return d;}; - var y = function(d) { return d;}; - var style = STYLES["default"]; - - function render(context, x_samples, y_samples) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.fillStyle = style["fill"]; - - context.beginPath(); - for(var index in x_samples) { - var x_sample = x_samples[index]; - var y_sample = y_samples[index]; - if(index == 0) { - context.moveTo(x(x_sample), y(y_sample)); - } else { - context.lineTo(x(x_sample), y(y_sample)); - } - } - context.closePath(); - context.stroke(); - context.fill(); - } - - render.x = function(value) { - if (!arguments.length) return x; - x = value; - return render; - }; - - render.y = function(value) { - if (!arguments.length) return y; - y = value; - return render; - }; - - render.style = function(value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - return render; -} - -//append list_2 reversed to list_1 as a new list -CanvasPlotArea.mergePoints = function(list_1, list_2) { - var result = []; - - for (var j = 0; j < list_1.length; j++) { - result.push(list_1[j]); - } - - for (var k = list_2.length - 1; k >= 0; k--) { - result.push(list_2[k]); - } - - return result; -}; \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_circle.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_circle.js deleted file mode 100644 index 48e1ef1081..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_circle.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_circle.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - - -function CanvasCircle() { - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - var radius = 2.5; - var fill = false; - - function render(context, x, y) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.fillStyle = style["fill"]; - - context.beginPath(); - context.arc(X(x), Y(y), radius, 0, 2 * Math.PI); - - if(fill) { - context.fill(); - } - - context.stroke(); - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - render.fillCircle = function(fill_circle) { - if (!arguments.length) return fill; - fill = fill_circle; - return render; - }; - - render.radius = function(value) { - if (!arguments.length) return radius; - radius = value; - return render; - }; - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_cross.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_cross.js deleted file mode 100644 index 1f66513ea5..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_cross.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_circle.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - - -function CanvasCross() { - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - var radius = 2.5; - var fill = false; - - function render(context, x, y) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.fillStyle = style["fill"]; - - var cx = X(x); - var cy = Y(y); - context.beginPath(); - context.moveTo(cx - radius, cy - radius); - context.lineTo(cx + radius, cy + radius); - - context.moveTo(cx + radius, cy - radius); - context.lineTo(cx - radius, cy + radius); - - context.stroke(); - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - render.radius = function(value) { - if (!arguments.length) return radius; - radius = value; - return render; - }; - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_distribution.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_distribution.js deleted file mode 100644 index 8ea0167fcc..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_distribution.js +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'canvas_plot_distribution.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function DistributionPlot(element, x_dimension, y_dimension) { - this.plot = new BasePlot(element, x_dimension, y_dimension); - this.horizontal_draw_direction = true; - - var self = this; - - var preRenderCallback = function(data) { - if (data.hasEnsembleData()) { - if (!self.horizontal_draw_direction) { - self.plot.setLogScaleOnDimensionX(data.shouldUseLogScale()); - } else { - self.plot.setLogScaleOnDimensionY(data.shouldUseLogScale()); - } - - self.plot.setXDomain(data.minX(), data.maxX(), data.caseList()); - self.plot.setYDomain(data.minY(), data.maxY(), data.caseList()); - } - }; - - var renderCallback = function (context, data) { - if (data.hasEnsembleData()) { - var case_list = data.caseList(); - - for (var i = 0; i < case_list.length; i++) { - var style = STYLES[("ensemble_" + (i + 1))]; - var case_name = case_list[i]; - var ensemble_data = data.ensembleData(case_name); - - - var values; - if (!self.horizontal_draw_direction) { - values = ensemble_data.xValues(); - } else { - values = ensemble_data.yValues(); - } - - var circle_renderer = self.plot.createCircleRenderer(); - circle_renderer.style(style); - circle_renderer.fillCircle(true); - circle_renderer.radius(5); - - for(var j = 0; j < values.length; j++) { - var value = values[j]; - if(isNumber(value)) { - if (self.horizontal_draw_direction) { - circle_renderer(context, case_name, value); - } else { - circle_renderer(context, value, case_name); - } - } - } - - self.plot.addLegend(style, case_name, CanvasPlotLegend.filledCircle); - } - self.plot.renderCallbackFinishedRendering(); - } - }; - - this.plot.setPreRenderCallback(preRenderCallback); - this.plot.setRenderCallback(renderCallback); -} - -DistributionPlot.prototype.resize = function (width, height) { - this.plot.resize(width, height); -}; - -DistributionPlot.prototype.setScales = function (x_min, x_max, y_min, y_max) { - this.plot.setScales(x_min, x_max, y_min, y_max); -}; - -DistributionPlot.prototype.setData = function (data) { - this.plot.setData(data); -}; - -DistributionPlot.prototype.setHorizontalDrawDirection = function (horizontal) { - this.horizontal_draw_direction = horizontal; -}; - -DistributionPlot.prototype.setCustomSettings = function (settings) { - this.plot.setCustomSettings(settings); -}; - -DistributionPlot.prototype.renderNow = function(){ - this.plot.render(); -}; - -DistributionPlot.prototype.getTitle = function(){ - return this.plot.getTitle(); -}; diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_legend.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_legend.js deleted file mode 100644 index 458a68c5d5..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_legend.js +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_legend.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function CanvasPlotLegend() { - - var size = 12; - - function legend(selection) { - var groups = selection.enter() - .append("div") - .attr("class", "plot-legend"); - - groups.append("canvas") - .attr("width", size) - .attr("height", size) - .attr("class", "legend-marker") - .call(markerRenderer); - - selection.selectAll(".legend-marker") - .data(function(d) { return [d];}) - .transition() - .call(markerRenderer); - - groups.append("div") - .attr("class", "plot-legend-label") - .text(function(d) { - return d["name"]; - }); - - selection.selectAll(".plot-legend-label") - .data(function(d) { - return [d]; - }) - .transition() - .text(function(d) { - return d["name"]; - }); - - selection.exit() - .remove(); - } - - var markerRenderer = function(selection) { - selection.each(function(datum) { - var ctx = d3.select(this).node().getContext("2d"); - ctx.clearRect(0, 0, size, size); - var style = datum["style"]; - - ctx.save(); - if("render_function" in datum) { - ctx.transform(1, 0, 0, 1, 1, 1); - datum["render_function"](ctx, style, size - 2, size - 2); - } else { - ctx.fillStyle = style["fill"]; - ctx.fillRect(1, 1, size - 2, size - 2); - - ctx.strokeStyle = style["stroke"]; - ctx.lineWidth = style["stroke_width"]; - ctx.strokeRect(1, 1, size - 2, size - 2); - } - ctx.restore(); - }); - }; - - return legend; - -} - -CanvasPlotLegend.parseColor = function(input) { - var result = [255, 255, 255, 1]; - -// match = input.match(/^#([0-9a-f]{3})$/i); -// if(match) { -// match = match[1]; -// // in three-character format, each value is multiplied by 0x11 to give an -// // even scale from 0x00 to 0xff -// result[0] = parseInt(match.charAt(0), 16) * 0x11; -// result[1] = parseInt(match.charAt(1), 16) * 0x11; -// result[2] = parseInt(match.charAt(2), 16) * 0x11; -// return result; -// } -// -// console.log("2"); -// match = input.match(/^#([0-9a-f]{6})$/i); -// if(match) { -// match = match[1]; -// result[0] = parseInt(match.substr(0,2), 16); -// result[1] = parseInt(match.substr(2,4), 16); -// result[2] = parseInt(match.substr(4,6), 16); -// return result; -// } -// -// match = input.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i); -// if(match) { -// result[0] = match[1]; -// result[1] = match[2]; -// result[2] = match[3]; -// return result; -// } -// if(input === undefined) { -// console.log("UNDEFINED!"); -// return result; -// } - var match = input.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+\.?\d*)\s*\)$/i); - if(match) { - result[0] = match[1]; - result[1] = match[2]; - result[2] = match[3]; - result[3] = parseFloat(match[4]); - return result; - } - - return result; -}; - -CanvasPlotLegend.asRgb = function(r, g, b) { - return "rgb(" + r + "," + g + "," + b + ")"; -}; - -CanvasPlotLegend.asRgba = function(r, g, b, a) { - return "rgba(" + r + "," + g + "," + b + "," + a + ")"; -}; - - -CanvasPlotLegend.componentToHex = function(c) { - var hex = c.toString(16); - return hex.length == 1 ? "0" + hex : hex; -}; - -CanvasPlotLegend.rgbToHex = function(r, g, b) { - return "#" + CanvasPlotLegend.componentToHex(r) + CanvasPlotLegend.componentToHex(g) + CanvasPlotLegend.componentToHex(b); -}; - -CanvasPlotLegend.circledLine = function(context, style, width, height) { - context.strokeStyle = style["stroke"]; - context.lineWidth = style["stroke_width"]; - context.fillStyle = style["fill"]; - context.beginPath(); - context.moveTo(0, height / 2); - context.lineTo(width, height / 2); - context.stroke(); - - context.beginPath(); - context.arc(width / 2, height / 2, 2.5, 0, 2 * Math.PI); - context.fill(); - context.stroke(); -}; - -CanvasPlotLegend.filledCircle = function(context, style, width, height) { - context.strokeStyle = style["stroke"]; - context.lineWidth = style["stroke_width"]; - context.fillStyle = style["fill"]; - - context.beginPath(); - context.arc(width / 2, height / 2, width / 2, 0, 2 * Math.PI); - context.fill(); - context.stroke(); -}; - -CanvasPlotLegend.cross = function(context, style, width, height) { - context.strokeStyle = style["stroke"]; - context.lineWidth = style["stroke_width"]; - context.fillStyle = style["fill"]; - - var cx = width / 2; - var cy = height / 2; - var radius = width / 2; - - context.beginPath(); - context.moveTo(cx - radius, cy - radius); - context.lineTo(cx + radius, cy + radius); - - context.moveTo(cx + radius, cy - radius); - context.lineTo(cx - radius, cy + radius); - context.stroke(); -}; - -CanvasPlotLegend.errorBar = function(context, style, width, height) { - context.strokeStyle = style["stroke"]; - context.lineWidth = 1; - context.fillStyle = style["fill"]; - var cx = width / 2; - var cy = height / 2; - var radius = 2; - context.beginPath(); - context.moveTo(cx, cy - radius); - context.lineTo(cx, 0); - context.moveTo(cx - radius, 0); - context.lineTo(cx + radius, 0); - - context.moveTo(cx, cy + radius); - context.lineTo(cx, height); - context.moveTo(cx - radius, height); - context.lineTo(cx + radius, height); - context.stroke(); - - context.beginPath(); - context.arc(cx, cy, radius, 0, 2 * Math.PI); - context.fill(); - context.stroke(); -}; - -CanvasPlotLegend.simpleLine = function(context, style, width, height) { - var color = style["stroke"]; - var rgba = CanvasPlotLegend.parseColor(color); - context.strokeStyle = CanvasPlotLegend.asRgba(rgba[0], rgba[1], rgba[2], 1.0); - context.lineWidth = style["stroke_width"] * 2; - - context.beginPath(); - context.moveTo(0, height / 2); - context.lineTo(width, height / 2); - context.stroke(); -}; - -CanvasPlotLegend.stippledLine = function(context, style, width, height) { - var line_renderer = CanvasPlotStippledLine(); - line_renderer.style(style); - line_renderer(context, [0, width], [height / 2, height / 2]); -}; - -CanvasPlotLegend.filledCircleWithLine = function(context, style, width, height) { - context.strokeStyle = style[0]["stroke"]; - context.lineWidth = style[0]["stroke_width"]; - context.fillStyle = style[0]["fill"]; - - context.beginPath(); - context.arc(width / 2, height / 2, (width - 1) / 2, 0, 2 * Math.PI); - context.fill(); - context.stroke(); - - - context.strokeStyle = style[1]["stroke"]; - context.lineWidth = style[1]["stroke_width"]; - context.fillStyle = style[1]["fill"]; - - context.beginPath(); - context.moveTo(0, height / 2); - context.lineTo(width, height / 2); - context.stroke(); -}; \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_line.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_line.js deleted file mode 100644 index 6fca068fcd..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_line.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_line.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function CanvasPlotLine() { - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - - function render(context, x_samples, y_samples) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.lineCap = style["line_cap"]; - - var length = Math.min(x_samples.length, y_samples.length); - - context.beginPath(); - for (var index = 0; index < length; index++) { - var x_sample = x_samples[index]; - var y_sample = y_samples[index]; - var x = X(x_sample); - var y = Y(y_sample); - - if (index == 0) { - context.moveTo(x, y); - } else { - context.lineTo(x, y); - } - } - - context.stroke(); - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_overview.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_overview.js deleted file mode 100644 index dda9c48f3f..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_overview.js +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_overview.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function OverviewPlot(element, x_dimension, y_dimension) { - this.plot = new BasePlot(element, x_dimension, y_dimension); - - this.horizontal_draw_direction = true; - - var self = this; - - var renderEnsemble = function (context, data) { - if (data.hasEnsembleData()) { - var case_list = data.caseList(); - - for (var i = 0; i < case_list.length; i++) { - var style = STYLES[("ensemble_" + (i + 1))]; - var case_name = case_list[i]; - var ensemble_data = data.ensembleData(case_name); - - var values = ensemble_data.xValues(); - if (!self.horizontal_draw_direction) { - values = ensemble_data.yValues(); - } - - var y_min_values = ensemble_data.yMinValues(); - var y_max_values = ensemble_data.yMaxValues(); - - var x_area_values = CanvasPlotArea.mergePoints(values, values); - var y_area_values = CanvasPlotArea.mergePoints(y_min_values, y_max_values); - - - self.plot.area_renderer.style(style); - if (self.horizontal_draw_direction) { - self.plot.area_renderer(context, x_area_values, y_area_values); - } else { - self.plot.area_renderer(context, y_area_values, x_area_values); - } - - self.plot.addLegend(style, case_name, CanvasPlotLegend.filledCircle); - } - self.plot.renderCallbackFinishedRendering(); - } - }; - - - this.plot.setRenderCallback(renderEnsemble); -} - -OverviewPlot.prototype.resize = function (width, height) { - this.plot.resize(width, height); -}; - -OverviewPlot.prototype.setScales = function (x_min, x_max, y_min, y_max) { - this.plot.setScales(x_min, x_max, y_min, y_max); -}; - -OverviewPlot.prototype.setData = function (data) { - this.plot.setData(data); -}; - - -OverviewPlot.prototype.setVerticalErrorBar = function (vertical) { - this.plot.setVerticalErrorBar(vertical); -}; - -OverviewPlot.prototype.setHorizontalDrawDirection = function (horizontal) { - this.horizontal_draw_direction = horizontal; -}; - -OverviewPlot.prototype.setCustomSettings = function (settings) { - this.plot.setCustomSettings(settings); -}; - -OverviewPlot.prototype.setRenderingFinishedCallback = function(callback) { - this.plot.setRenderingFinishedCallback(callback); -}; - -OverviewPlot.prototype.renderNow = function(){ - this.plot.render(); -}; - -OverviewPlot.prototype.getTitle = function(){ - return this.plot.getTitle(); -}; - diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_pca.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_pca.js deleted file mode 100644 index 3f8bae63a6..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_pca.js +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'canvas_plot_distribution.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function PcaPlot(element, x_dimension, y_dimension) { - this.plot = new BasePlot(element, x_dimension, y_dimension); - this.plot.setRenderObservations(false); - this.plot.setRenderRefcase(false); - - this.horizontal_draw_direction = true; - this.group_scale = d3.scale.ordinal(); - - var self = this; - - var preRenderCallback = function(data) { - if (data.hasEnsembleData()) { - if (!self.horizontal_draw_direction) { - self.plot.setLogScaleOnDimensionX(data.shouldUseLogScale()); - } else { - self.plot.setLogScaleOnDimensionY(data.shouldUseLogScale()); - } - - self.plot.setXDomain(data.minX(), data.maxX(), data.observationData().xValues()); - self.plot.setYDomain(data.minY(), data.maxY(), data.observationData().yValues()); - } - }; - - var renderCallback = function (context, data) { - if (data.hasEnsembleData()) { - var obs_data = data.observationData(); - var obs_x_values = obs_data.xValues(); - var obs_y_values = obs_data.yValues(); - - var case_list = data.caseList(); - - for (var i = 0; i < case_list.length; i++) { - var style = STYLES[("ensemble_" + (i + 1))]; - var case_name = case_list[i]; - - var ensemble_data = data.ensembleData(case_name); - - var x_values = ensemble_data.xValues(); - var y_values = ensemble_data.yValues(); - - var realization_count = y_values.length; - var pc_count = x_values.length; - if (!self.horizontal_draw_direction) { - realization_count = x_values.length; - pc_count = y_values.length; - } - - var circle_renderer = self.plot.createCircleRenderer(); - - var circle_scale = circle_renderer.x().scale(); - self.group_scale.domain(case_list).rangePoints([0, circle_scale.rangeBand()], 1); - - var scaler = function(value) { - var pc = value[0]; - var case_name = value[1]; - return circle_scale(pc) + self.group_scale(case_name); - }; - - circle_renderer.x(scaler); - - circle_renderer.style(style); - circle_renderer.fillCircle(true); - circle_renderer.radius(5); - - for (var j = 0; j < realization_count; j++) { - for(var pc = 0; pc < pc_count; pc++) { - if (self.horizontal_draw_direction) { - circle_renderer(context, [x_values[pc], case_name], y_values[j][pc]) - - } else { - circle_renderer(context, x_values[j][pc], [y_values[pc], case_name]) - } - } - } - - - var cross_renderer = self.plot.createCrossRenderer(); - - cross_renderer.x(scaler); - - cross_renderer.style(STYLES["observation"]); - cross_renderer.radius(5); - - - for(var pc = 0; pc < pc_count; pc++) { - if (self.horizontal_draw_direction) { - cross_renderer(context, [obs_x_values[pc], case_name], obs_y_values[pc]) - - } else { - cross_renderer(context, obs_x_values[pc], [obs_y_values[pc], case_name]) - } - } - - self.plot.addLegend(style, case_name, CanvasPlotLegend.filledCircle); - } - - self.plot.addLegend(STYLES["observation"], "Observation", CanvasPlotLegend.cross); - - self.plot.renderCallbackFinishedRendering(); - } - }; - - this.plot.setPreRenderCallback(preRenderCallback); - this.plot.setRenderCallback(renderCallback); -} - -PcaPlot.prototype.resize = function (width, height) { - this.plot.resize(width, height); -}; - -PcaPlot.prototype.setScales = function (x_min, x_max, y_min, y_max) { - this.plot.setScales(x_min, x_max, y_min, y_max); -}; - -PcaPlot.prototype.setData = function (data) { - this.plot.setData(data); -}; - -PcaPlot.prototype.setHorizontalDrawDirection = function (horizontal) { - this.horizontal_draw_direction = horizontal; -}; - -PcaPlot.prototype.setCustomSettings = function (settings) { - this.plot.setCustomSettings(settings); -}; - -PcaPlot.prototype.renderNow = function(){ - this.plot.render(); -}; - -PcaPlot.prototype.getTitle = function(){ - return this.plot.getTitle(); -}; - -PcaPlot.prototype.setRenderingFinishedCallback = function(callback) { - this.plot.setRenderingFinishedCallback(callback); -}; diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_rect.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_rect.js deleted file mode 100644 index 9bbb9fef42..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_rect.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_rect.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - - -function CanvasRect() { - var margin = {top: 0, right: 0, bottom: 0, left: 0}; - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - - function render(context, x1, y1, x2, y2) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.fillStyle = style["fill"]; - - var x = X(x1); - var y = Y(y1); - var w = X(x2) - x; - var h = Y(y2) - y; - context.fillRect(x + margin.left, y + margin.top, w - margin.left - margin.right, h - margin.top - margin.bottom); - context.strokeRect(x + margin.left, y + margin.top, w - margin.left - margin.right, h - margin.top - margin.bottom); - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - render.margin = function (top, right, bottom, left) { - if (!arguments.length) return margin; - margin = {top: top, right: right, bottom: bottom, left: left}; - return render; - }; - - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_statistics.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_statistics.js deleted file mode 100644 index 9511ccfc1b..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_statistics.js +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'canvas_plot_overview.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function StatisticsPlot(element, x_dimension, y_dimension) { - this.plot = new BasePlot(element, x_dimension, y_dimension); - - var horizontal_draw_direction = true; - - var line_renderer = this.plot.createLineRenderer(); - var stippled_line_renderer = this.plot.createStippledLineRenderer(); - var area_renderer = this.plot.createAreaRenderer(); - var dark_area_renderer = this.plot.createAreaRenderer(); - - - var self = this; - - var renderEnsemble = function (context, data) { - if (data.hasEnsembleData()) { - var case_list = data.caseList(); - - for (var i = 0; i < case_list.length; i++) { - var style = STYLES[("ensemble_" + (i + 1))]; - var case_name = case_list[i]; - var ensemble_data = data.ensembleData(case_name); - - var values = ensemble_data.xValues(); - if (!horizontal_draw_direction) { - values = ensemble_data.yValues(); - } - - var y_min_values = ensemble_data.yMinValues(); - var y_max_values = ensemble_data.yMaxValues(); - var median = ensemble_data.xPercentile(0.5); - var p10 = ensemble_data.xPercentile(0.1); - var p33 = ensemble_data.xPercentile(0.33); - var p67 = ensemble_data.xPercentile(0.67); - var p90 = ensemble_data.xPercentile(0.9); - - var area_values = CanvasPlotArea.mergePoints(values, values); - - var area_style = { - stroke: "rgba(255,255, 255, 0.0)", - fill: style["fill"], - stroke_width: 1 - }; - - var dark_area_style = { - stroke: "rgba(255,255, 255, 0.0)", - fill: STYLES.darker(style["fill"]), - stroke_width: 1 - }; - - var stipple_style = { - stroke: style["stroke"], - fill: "rgba(255, 255, 255, 0.0)", - stroke_width: style["stroke_width"], - line_cap: "butt" - }; - - line_renderer.style(style); - stippled_line_renderer.style(stipple_style); - stippled_line_renderer.stippleLength(5); - area_renderer.style(area_style); - dark_area_renderer.style(dark_area_style); - - if (horizontal_draw_direction) { - stippled_line_renderer(context, values, y_max_values); - stippled_line_renderer(context, values, y_min_values); - - area_renderer(context, area_values, CanvasPlotArea.mergePoints(p10, p90)); - dark_area_renderer(context, area_values, CanvasPlotArea.mergePoints(p33, p67)); - - stippled_line_renderer(context, values, median); - - } else { - stippled_line_renderer(context, y_max_values, values); - stippled_line_renderer(context, y_min_values, values); - - area_renderer(context, CanvasPlotArea.mergePoints(p10, p90), area_values); - dark_area_renderer(context, CanvasPlotArea.mergePoints(p33, p67), area_values); - - stippled_line_renderer(context, median, values); - } - - self.plot.addLegend(area_style, "P10 - P90", CanvasPlotLegend.filledCircle); - self.plot.addLegend(dark_area_style, "P33 - P67", CanvasPlotLegend.filledCircle); - self.plot.addLegend(stipple_style, "Min - Median - Max", CanvasPlotLegend.stippledLine); - self.plot.addLegend(style, case_name, CanvasPlotLegend.filledCircle); - } - self.plot.renderCallbackFinishedRendering(); - } - }; - - - this.plot.setRenderCallback(renderEnsemble); -} - -StatisticsPlot.prototype.resize = function (width, height) { - this.plot.resize(width, height); -}; - -StatisticsPlot.prototype.setScales = function (x_min, x_max, y_min, y_max) { - this.plot.setScales(x_min, x_max, y_min, y_max); -}; - -StatisticsPlot.prototype.setData = function (data) { - this.plot.setData(data); -}; - - -StatisticsPlot.prototype.setVerticalErrorBar = function (vertical) { - this.plot.setVerticalErrorBar(vertical); -}; - -StatisticsPlot.prototype.setHorizontalDrawDirection = function (horizontal) { - this.horizontal_draw_direction = horizontal; -}; - -StatisticsPlot.prototype.setCustomSettings = function (settings) { - this.plot.setCustomSettings(settings); -}; - -StatisticsPlot.prototype.setRenderingFinishedCallback = function(callback) { - this.plot.setRenderingFinishedCallback(callback); -}; - -StatisticsPlot.prototype.renderNow = function(){ - this.plot.render(); -}; - -StatisticsPlot.prototype.getTitle = function(){ - return this.plot.getTitle(); -}; - diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_stippled_line.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_stippled_line.js deleted file mode 100644 index c8e6d6ef39..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/canvas_plot_stippled_line.js +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (C) 2014 Statoil ASA, Norway. -// -// The file 'canvas_plot_stippled_line.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function CanvasPlotStippledLine() { - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - var stipple_length = 2; - - var dashing = true; - var unfinished_pixels_from_previous = 0; - - - function render(context, x_samples, y_samples) { - context.lineWidth = style["stroke_width"]; - context.strokeStyle = style["stroke"]; - context.lineCap = style["line_cap"]; - dashing = true; - unfinished_pixels_from_previous = 0; - - var length = Math.min(x_samples.length, y_samples.length); - - context.beginPath(); - var previous_x = 0; - var previous_y = 0; - for (var index = 0; index < length; index++) { - var x_sample = x_samples[index]; - var y_sample = y_samples[index]; - var x = X(x_sample); - var y = Y(y_sample); - - if (index > 0) { - render.dashedLineFromTo(context, previous_x, previous_y, x, y); - } - previous_x = x; - previous_y = y; - } - - context.stroke(); - } - - render.dashedLineFromTo = function(context, x1, y1, x2, y2) { - var x = x1; - var y = y1; - var dash_length = stipple_length; - var dx = (x2 - x) + 0.00000001; - var dy = (y2 - y); - var slope = dy / dx; - var distance_remaining = Math.sqrt(dx * dx + dy * dy); - var unfinished_pixels = false; - var current_dash_length; - var x_step; - - context.moveTo(x, y); - - while(distance_remaining >= 0.1) { - if(unfinished_pixels_from_previous === 0) { - current_dash_length = dash_length; - } else { - current_dash_length = unfinished_pixels_from_previous; - unfinished_pixels_from_previous = 0; - dashing = !dashing; - } - - if(dash_length > distance_remaining) { - dash_length = distance_remaining; - unfinished_pixels = true; - } - - x_step = Math.sqrt(current_dash_length * current_dash_length / (1 + slope * slope)); - x += x_step; - y += slope * x_step; - - if(dashing) { - context.lineTo(x, y); - } else { - context.moveTo(x, y); - } - distance_remaining -= current_dash_length; - dashing = !dashing; - } - - if(unfinished_pixels) { - unfinished_pixels_from_previous = current_dash_length; - } - - - }; - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - render.stippleLength = function (value) { - if (!arguments.length) return stipple_length; - stipple_length = value; - return render; - }; - - - return render; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram.js deleted file mode 100644 index 6db4fbe9f5..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram.js +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'histogram.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function Histogram(element, x_dimension, y_dimension) { - var stored_data = null; - var stored_case_name = ""; - - var margin = {left: 40, right: 30, top: 20, bottom: 30}; - var width = 384 - margin.left - margin.right; - var height = 256 - margin.top - margin.bottom; - - var style = STYLES["default"]; - - var custom_value_min = null; - var custom_value_max = null; - - var x_dimension = x_dimension; - var y_dimension = y_dimension; - - - var histogram_renderer = HistogramRenderer().x(x_dimension).y(y_dimension).margin(0, 1, 0, 1); - var line_renderer = CanvasPlotLine().x(x_dimension).y(y_dimension); - var stipple_renderer = CanvasPlotStippledLine().x(x_dimension).y(y_dimension); - var area_renderer = CanvasPlotArea().x(x_dimension).y(y_dimension); - var circle_renderer = CanvasCircle().x(x_dimension).y(y_dimension); - - var legend = CanvasPlotLegend(); - var legend_list = []; - - - - var group = element.append("div") - .attr("class", "histogram"); - - - var title = group.append("div") - .attr("class", "plot-title") - .text("Histogram"); - - var axis_label_group = group.append("div") - .attr("id", "axis-label-group") - - var x_label = axis_label_group.append("div") - .attr("class", "x axis-label") - .text(""); - - var y_label = axis_label_group.append("div") - .attr("class", "y axis-label") - .text(""); - - var histogram_area = group.append("div").attr("class", "plot-area"); - - var legend_group = group.append("div") - .attr("class", "plot-legend-group"); - - var histogram_group = histogram_area.append("svg") - .attr("class", "plot-svg"); - - - var svg = histogram_group.append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") - .style("width", width + "px") - .style("height", height + "px"); - - var canvas = histogram_area.append("canvas") - .attr("id", "histogram-canvas") - .attr("width", width) - .attr("height", height) - .style("position", "absolute") - .style("top", (margin.top) + "px") - .style("left", (margin.left) + "px") - .style("z-index", 5); - - - - - var y_axis = d3.svg.axis() - .scale(y_dimension.scale()) - .orient("left"); - - var x_axis = d3.svg.axis() - .scale(x_dimension.scale()) - .orient("bottom"); - - histogram_group.append("g") - .attr("class", "y axis pale") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") - .call(y_axis); - - histogram_group.append("g") - .attr("class", "x axis") - .attr("transform", "translate(" + margin.left + ", " + (height + margin.top) + ")") - .call(x_axis); - - var resetLegends = function() { - legend_list = []; - }; - - var addLegend = function(style, name, render_function) { - legend_list.push({"style": style, "name": name,"render_function": render_function}); - }; - - function formatDate(ctime) { - var date = new Date(ctime * 1000); - var year = date.getFullYear(); - var month = date.getMonth() + 1; - var day = date.getDate(); - - if (month < 10) { - month = "0" + month; - } - - if (day < 10) { - day = "0" + day; - } - - return year + "-" + month + "-" + day; - } - - - function createLogBinFunction (bin_count) { - function binner(range, values) { - var thresholds = []; - - var range_diff = range[1] - range[0]; - - var from_log = Math.round(Math.log(range[0]) / Math.log(10)); - var to_log = Math.round(Math.log(range[1]) / Math.log(10)); - - var from_to_diff = to_log - from_log; - var log_bin_count = from_to_diff; - var log_bin_count_next = from_to_diff * 2; - - while(log_bin_count_next < bin_count) { - log_bin_count = log_bin_count_next; - log_bin_count_next += from_to_diff; - } - - - - if(log_bin_count_next - bin_count < bin_count - log_bin_count) { - bin_count = log_bin_count_next; - } else { - bin_count = log_bin_count; - } - - var step = from_to_diff / bin_count ; - - var sum = 0; - for(var i = 0; i <= bin_count; i++) { - sum += Math.pow(10, i * step); - } - - var bin_size = range_diff / sum; - - thresholds.push(range[0]); - - for(var i = 1; i < bin_count; i++) { - var value = thresholds[i - 1] + (bin_size * Math.pow(10, i * step)); - thresholds.push(value); - } - - - thresholds.push(range[1]); - - return thresholds; - - } - return binner; - } - - - - - function histogram(data, case_name) { - if (!arguments.length) { - if(stored_data == null) { - return; - } - data = stored_data; - case_name = stored_case_name; - } else { - stored_data = data; - stored_case_name = case_name; - } - - x_axis.scale(x_dimension.scale()); - x_dimension.format(x_axis, height); - x_axis.tickSize(0, 0); - - y_axis.scale(y_dimension.scale()); - y_dimension.format(y_axis, width); - - - resetLegends(); - - title.text(histogram.getTitle()); - - if (x_dimension.getUnit() == "") { - x_label.text(""); - } else { - x_label.text("X: " + x_dimension.getUnit()); - } - - if (y_dimension.getUnit() == "") { - y_label.text(""); - } else { - y_label.text("Y: " + y_dimension.getUnit()); - } - - var context = canvas.node().getContext("2d"); - context.save(); - context.clearRect(0, 0, width, height); - - - if(data.hasObservation()) { - line_renderer.style(STYLES["observation"]); - var obs = data.observation(); - var top = data.maxCount() + 1; - stipple_renderer(context, [obs, obs], [0, top]); - addLegend(STYLES["observation"], "Observation", CanvasPlotLegend.stippledLine); - - var error = data.observationError(); - area_renderer.style(STYLES["observation_area"]); - area_renderer(context, [obs - error, obs + error, obs + error, obs - error], [top, top, 0, 0]); - - addLegend(STYLES["observation_area"], "Observation error", CanvasPlotLegend.filledCircle); - } - - if(data.hasRefcase()) { - line_renderer.style(STYLES["refcase"]); - line_renderer(context, [data.refcase(), data.refcase()], [0, data.maxCount() + 1]); - addLegend(STYLES["refcase"], "Refcase", CanvasPlotLegend.simpleLine); - } - - if(data.hasCaseHistogram(case_name)) { - - var case_histogram = data.caseHistogram(case_name); - var bin_count = data.numberOfBins(); - - var bins = histogram.histogramLayout(bin_count)(case_histogram.samples()); - -// var ticks = []; -// for(var i = 0; i < bins.length; i++) { -// ticks.push(bins[i].x); -// -// if(i == bins.length - 1) { -// ticks.push(bins[i].x + bins[i].dx); -// } -// } -// -// x_dimension.setTicks(ticks); - - histogram_renderer.style(style); - histogram_renderer(context, bins); - - addLegend(style, case_name, CanvasPlotLegend.filledCircle); - } - - legend_group.selectAll(".plot-legend").data(legend_list).call(legend); - histogram_group.select(".y.axis").call(y_axis); - var axis = histogram_group.select(".x.axis").call(x_axis); - x_dimension.relabel(axis); - - context.restore(); - } - - - histogram.histogramLayout = function(bin_count) { - var layout = null; - var use_log_scale = false; - - if("isLogScale" in x_dimension) { - use_log_scale = x_dimension.isLogScale(); - } - - if(use_log_scale) { - layout = d3.layout.histogram() - .range(x_dimension.scale().domain()) - .bins(createLogBinFunction(bin_count)); - } else { - layout = d3.layout.histogram() - .range(x_dimension.scale().domain()) - .bins(bin_count); - } - - return layout; - }; - - histogram.setSize = function(w, h) { - w = w - 80; - h = h - 70; - - width = w - margin.left - margin.right; - height = h - margin.top - margin.bottom; - - x_dimension.setRange(0, width); - y_dimension.setRange(height, 0); - - histogram_group.style("width", w + "px"); - histogram_group.style("height", h + "px"); - - canvas.attr("width", width).attr("height", height); - - svg.style("width", width + "px"); - svg.style("height", height + "px"); - - histogram_group.select(".x.axis") - .attr("transform", "translate(" + margin.left + ", " + (height + margin.top) + ")"); - - }; - - - histogram.style = function (value) { - if (!arguments.length) return style; - style = value; - return histogram; - }; - - histogram.setValueScales = function(min, max) { - custom_value_min = min; - custom_value_max = max; - }; - - histogram.setVisible = function(visible) { - if(!visible) { - group.style("display", "none"); - } else { - group.style("display", "inline-block"); - } - }; - - histogram.getTitle = function(){ - var data = stored_data; - var report_date = data.reportStepTime(); - if(report_date == 0){ - return data.name(); - } else { - return data.name() + " @ " + formatDate(data.reportStepTime()); - } - }; - - return histogram; -} \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram_renderer.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram_renderer.js deleted file mode 100644 index 1675c774f2..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/histogram_renderer.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'histogram_renderer.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - - -function HistogramRenderer() { - var margin = {top: 0, right: 0, bottom: 0, left: 0}; - var X = function (d) { return d; }; - var Y = function (d) { return d; }; - var style = STYLES["default"]; - - - function render(context, histogram_values) { - context.lineWidth = "1"; - context.strokeStyle = "rgba(0, 0, 0, 0.5)"; - - var fill = style["fill"]; - - context.fillStyle = STYLES.blendWithWhite(fill, 1.0); - - for(var j = 0; j < histogram_values.length; j++) { - var value = histogram_values[j]; - if(value.y > 0) { - var x = X(value.x); - var y = Y(value.y); - var w = X(value.x + value.dx) - x; - var h = Y(0) - y; - - context.fillRect(x + margin.left, y + margin.top, w - margin.left - margin.right, h - margin.top - margin.bottom); - context.strokeRect(x + margin.left, y + margin.top, w - margin.left - margin.right, h - margin.top - margin.bottom); - } - } - } - - render.x = function (value) { - if (!arguments.length) return X; - X = value; - return render; - }; - - render.y = function (value) { - if (!arguments.length) return Y; - Y = value; - return render; - }; - - render.style = function (value) { - if (!arguments.length) return style; - style = value; - return render; - }; - - render.margin = function (top, right, bottom, left) { - if (!arguments.length) return margin; - margin = {top: top, right: right, bottom: bottom, left: left}; - return render; - }; - - return render; -} diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/render_tracker.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/render_tracker.js deleted file mode 100644 index c7d02e68f5..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/render_tracker.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2013 Statoil ASA, Norway. -// -// The file 'render_tracker.js' is part of ERT - Ensemble based Reservoir Tool. -// -// ERT 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 3 of the License, or -// (at your option) any later version. -// -// ERT 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 at -// for more details. - -function IncrementalRenderTracker() { - this.rendering_start = null; - this.max_loop_time = 500; - this.is_running = false; - this.should_stop = false; - - this.loop_start = null; - -} - -IncrementalRenderTracker.prototype.start = function(render_function) { - if(this.is_running) { -// console.log("Rendering -> activating kill!"); - this.should_stop = true; - } - - this.run(this, render_function); -}; - - -IncrementalRenderTracker.prototype.run = function(self, render_function) { - if(!this.is_running) { - this.rendering_start = Date.now(); - this.is_running = true; - this.should_stop = false; - - render_function(); - - } else { -// console.log("Waiting!"); - window.setTimeout(function() { self.run(self, render_function); }, 15); - } -}; - - -IncrementalRenderTracker.prototype.shouldStop = function() { - return this.should_stop; -}; - - -IncrementalRenderTracker.prototype.loopStart = function() { - this.loop_start = Date.now(); -}; - -IncrementalRenderTracker.prototype.shouldLoopStop = function() { - return (Date.now() - this.loop_start) > this.max_loop_time; -}; - -IncrementalRenderTracker.prototype.stoppedRendering = function() { - this.is_running = false; - this.should_stop = false; -// console.log("Rendering time: " + this.runningTime() + " ms"); -}; - -IncrementalRenderTracker.prototype.isRunning = function() { - return this.is_running; -}; - -IncrementalRenderTracker.prototype.runningTime = function() { - return (Date.now() - this.rendering_start); -}; - -IncrementalRenderTracker.prototype.forceStop = function() { - this.should_stop = true; -}; - - - - - - - - - - - diff --git a/ThirdParty/Ert/devel/share/gui/plots/scripts/styles.js b/ThirdParty/Ert/devel/share/gui/plots/scripts/styles.js deleted file mode 100644 index 394a075ff6..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/scripts/styles.js +++ /dev/null @@ -1,201 +0,0 @@ -var STYLES = { - default: { - stroke: "rgba(0, 0, 0, 1.0)", - fill: "rgba(200, 200, 200, 1.0)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - observation: { - stroke: "rgba(0, 0, 0, 1.0)", - fill: "rgba(0, 0, 0, 0.0)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - observation_error_bar: { - stroke: "rgba(0, 0, 0, 1.0)", - fill: "rgba(0, 0, 0, 0.0)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - observation_area: { - stroke: "rgba(0, 0, 0, 0.15)", - fill: "rgba(0, 0, 0, 0.2)", - stroke_width: 2, - dash_array: [], - line_cap: "butt" - }, - refcase: { - stroke: "rgba(0, 0, 0, 0.7)", - fill: "rgba(0, 0, 0, 0.0)", - stroke_width: 1.5, - dash_array: [], - line_cap: "butt" - }, - ensemble_1: { - stroke: "rgba(56, 108, 176, 0.8)", - fill: "rgba(56, 108, 176, 0.5)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - ensemble_2: { - stroke: "rgba(127, 201, 127, 0.8)", - fill: "rgba(127, 201, 127, 0.5)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - ensemble_3: { - stroke: "rgba(253, 192, 134, 0.8)", - fill: "rgba(253, 192, 134, 0.5)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - ensemble_4: { - stroke: "rgba(240, 2, 127, 0.8)", - fill: "rgba(240, 2, 127, 0.5)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - ensemble_5: { - stroke: "rgba(191, 91, 23, 0.8)", - fill: "rgba(191, 91, 23, 0.5)", - stroke_width: 1, - dash_array: [], - line_cap: "butt" - }, - - ensemble_colors: ["ensemble_1", "ensemble_2", "ensemble_3", "ensemble_4", "ensemble_5"] - -}; - - -STYLES.parseColor = function(input) { - var result = [255, 255, 255, 1]; - - var match = input.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+\.?\d*)\s*\)$/i); - if(match) { - result[0] = match[1]; - result[1] = match[2]; - result[2] = match[3]; - result[3] = parseFloat(match[4]); - return result; - } - - return result; -}; - - -STYLES.asRgb = function(r, g, b) { - return "rgb(" + r + "," + g + "," + b + ")"; -}; - -STYLES.asRgba = function(r, g, b, a) { - return "rgba(" + r + "," + g + "," + b + "," + a + ")"; -}; - - -STYLES.componentToHex = function(c) { - var hex = c.toString(16); - return hex.length == 1 ? "0" + hex : hex; -}; - -STYLES.rgbToHex = function(r, g, b) { - return "#" + CanvasPlotLegend.componentToHex(r) + CanvasPlotLegend.componentToHex(g) + CanvasPlotLegend.componentToHex(b); -}; - -STYLES.darker = function(color) { - var rgba = STYLES.parseColor(color); - - var f = 0.80; - var a = rgba[3]; - var r = parseInt(rgba[0] * f); - var g = parseInt(rgba[1] * f); - var b = parseInt(rgba[2] * f); - - return STYLES.asRgba(r, g, b, a); -}; - -STYLES.blendWithWhite = function(color, result_alpha) { - var rgba = STYLES.parseColor(color); - - var a = rgba[3]; - var ab = (1 - rgba[3]) * 255; - var r = parseInt(rgba[0] * a + ab); - var g = parseInt(rgba[1] * a + ab); - var b = parseInt(rgba[2] * a + ab); - - return STYLES.asRgba(r, g, b, result_alpha); -}; - -STYLES.createFillColor = function(color, fill_alpha, blend_with_white_alpha) { - var rgba = STYLES.parseColor(color); - rgba[3] = fill_alpha; - return STYLES.blendWithWhite(STYLES.asRgba(rgba[0], rgba[1], rgba[2], rgba[3]), blend_with_white_alpha); -}; - - -STYLES.updateColors = function(settings) { - var alpha = 0.7; - var fill_alpha = 0.5; - if("observation" in settings) { - STYLES["observation"]["stroke"] = settings["observation"]; - } - - if("observation_error_bar" in settings) { - STYLES["observation_error_bar"]["stroke"] = settings["observation_error_bar"]; - } - - if("observation_area" in settings) { - STYLES["observation_area"]["stroke"] = settings["observation_area"]; - STYLES["observation_area"]["fill"] = settings["observation_area"]; - } - - if("refcase" in settings) { - STYLES["refcase"]["stroke"] = settings["refcase"]; - } - - if("ensemble_1" in settings) { - STYLES["ensemble_1"]["stroke"] = settings["ensemble_1"]; -// STYLES["ensemble_1"]["fill"] = settings["ensemble_1"]; - STYLES["ensemble_1"]["fill"] = STYLES.createFillColor(settings["ensemble_1"], fill_alpha, alpha); - } - - if("ensemble_2" in settings) { - STYLES["ensemble_2"]["stroke"] = settings["ensemble_2"]; - STYLES["ensemble_2"]["fill"] = STYLES.createFillColor(settings["ensemble_2"], fill_alpha, alpha); -// STYLES["ensemble_2"]["fill"] = settings["ensemble_2"]; - } - - if("ensemble_3" in settings) { - STYLES["ensemble_3"]["stroke"] = settings["ensemble_3"]; - STYLES["ensemble_3"]["fill"] = STYLES.createFillColor(settings["ensemble_3"], fill_alpha, alpha); -// STYLES["ensemble_3"]["fill"] = settings["ensemble_3"]; - } - - if("ensemble_4" in settings) { - STYLES["ensemble_4"]["stroke"] = settings["ensemble_4"]; - STYLES["ensemble_4"]["fill"] = STYLES.createFillColor(settings["ensemble_4"], fill_alpha, alpha); -// STYLES["ensemble_4"]["fill"] = settings["ensemble_4"]; - } - - if("ensemble_5" in settings) { - STYLES["ensemble_5"]["stroke"] = settings["ensemble_5"]; - STYLES["ensemble_5"]["fill"] = STYLES.createFillColor(settings["ensemble_5"], fill_alpha, alpha); -// STYLES["ensemble_5"]["fill"] = settings["ensemble_5"]; - } - -}; - - -var alpha = 0.7; -STYLES["ensemble_1"]["fill"] = STYLES.blendWithWhite(STYLES["ensemble_1"]["fill"], alpha); -STYLES["ensemble_2"]["fill"] = STYLES.blendWithWhite(STYLES["ensemble_2"]["fill"], alpha); -STYLES["ensemble_3"]["fill"] = STYLES.blendWithWhite(STYLES["ensemble_3"]["fill"], alpha); -STYLES["ensemble_4"]["fill"] = STYLES.blendWithWhite(STYLES["ensemble_4"]["fill"], alpha); -STYLES["ensemble_5"]["fill"] = STYLES.blendWithWhite(STYLES["ensemble_5"]["fill"], alpha); \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/simple_overview_plot.html b/ThirdParty/Ert/devel/share/gui/plots/simple_overview_plot.html deleted file mode 100644 index 506cbe30cd..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/simple_overview_plot.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/simple_plot.html b/ThirdParty/Ert/devel/share/gui/plots/simple_plot.html deleted file mode 100644 index a7f549f5e1..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/simple_plot.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/gui/plots/style/plot.css b/ThirdParty/Ert/devel/share/gui/plots/style/plot.css deleted file mode 100644 index 6ce4738592..0000000000 --- a/ThirdParty/Ert/devel/share/gui/plots/style/plot.css +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2013 Statoil ASA, Norway. */ -/* */ -/* The file 'plot.css' is part of ERT - Ensemble based Reservoir Tool. */ -/* */ -/* ERT 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 3 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* ERT 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 at */ -/* for more details. */ - -html { - height: 100%; -} - -body { - height: 90%; - background-color: #eee; -} - -.plot { - margin: 5px; - padding: 10px; - border: 1px solid black; - background-color: white; - display: inline-block; -} - -.histogram { - margin: 5px; - padding: 10px; - border: 1px solid black; - background-color: white; - display: inline-block; -} - -.plot-svg { - display: block; - margin: 0; - padding: 0; -} - -.plot-title { - font-size: large; - width: auto; - text-align: center; - margin: 0px; - /*color: goldenrod;*/ - -} - - -.plot-area { - position: relative; -} - -.plot-legend-group { - /*background-color: #7FC97F;*/ - margin-left: auto; - margin-right: auto; - display: inline-block; - float: right; - -} - -.plot-legend { - display: inline; - margin-right: 15px; -} - - -.plot-legend-label { - font-family: Helvetica,serif; - font-size: medium; - font-variant: small-caps; - display: inline-block; - padding-left: 5px; -} - -.plot-legend-box { - border: solid 1px #000; - width: 10px; - height: 10px; - display: inline-block; - background-color: darkorchid; -} - -.plot-legend-line { - border: 2px none #000; - border-top-style: dotted; - - width: 10px; - height: 1px; - display: inline-block; - vertical-align: middle; -} - -/*.histograms {*/ - -/*}*/ - -/*.histogram-div {*/ - -/*}*/ - - -.histogram-svg { - display: block; - margin: 20px; - padding: 0; - width: 384px; - height: 256px; -} - -.histogram-title { - font-size: large; - width: auto; - text-align: center; - margin: 10px; - /*color: goldenrod;*/ - -} - - -.axis path, .axis line { - fill: none; - stroke: #000000; - shape-rendering: crispEdges; -} - -.axis line.minor { - fill: none; - stroke-dasharray: 1, 4; -} - -.pale line { - fill: none; - stroke: #999; - stroke-dasharray: 2, 2; -} - -#axis-label-group { - width: auto; - text-align: center; -} - -.axis-label { - font-size: small; - display: inline; - margin-right: 10px; -} diff --git a/ThirdParty/Ert/devel/share/lib/synthesizer/__init__.py b/ThirdParty/Ert/devel/share/lib/synthesizer/__init__.py new file mode 100644 index 0000000000..0bc890b220 --- /dev/null +++ b/ThirdParty/Ert/devel/share/lib/synthesizer/__init__.py @@ -0,0 +1,4 @@ +from .prime_generator import PrimeGenerator +from .perlin import PerlinNoise +from .shaped_perlin import ShapedNoise, ShapeFunction, ShapeCreator +from .oil_simulator import OilSimulator \ No newline at end of file diff --git a/ThirdParty/Ert/devel/share/lib/synthesizer/oil_simulator.py b/ThirdParty/Ert/devel/share/lib/synthesizer/oil_simulator.py new file mode 100644 index 0000000000..8ebf162e42 --- /dev/null +++ b/ThirdParty/Ert/devel/share/lib/synthesizer/oil_simulator.py @@ -0,0 +1,136 @@ +from . import ShapeFunction, ShapeCreator + +class OilSimulator(object): + OPR_SHAPE = ShapeFunction([0.0, 0.2, 0.5, 0.7, 1.0], [0.0, 0.7, 0.2, 0.1, 0.01]) + GPR_SHAPE = ShapeFunction([0.0, 0.2, 0.5, 0.7, 1.0], [0.0, 0.5, 0.7, 0.7, 0.3]) + WPR_SHAPE = ShapeFunction([0.0, 0.2, 0.5, 0.7, 1.0], [0.0, 0.01, 0.3, 0.7, 1]) + BPR_SHAPE= ShapeFunction([0.0, 0.2, 0.5, 0.7, 1.0], [1.0, 0.7, 0.5, 0.3, 0.1]) + + O_DIVERGENCE = ShapeFunction([0.0, 0.5, 0.7, 0.9, 1.0], [0.0, 0.5, 0.3, 0.1, 0.01]) + G_DIVERGENCE = ShapeFunction([0.0, 0.5, 0.7, 0.9, 1.0], [0.0, 0.1, 0.3, 0.2, 0.1]) + W_DIVERGENCE = ShapeFunction([0.0, 0.5, 0.7, 0.9, 1.0], [0.0, 0.1, 0.3, 0.2, 0.01]) + B_DIVERGENCE = ShapeFunction([0.0, 0.5, 0.7, 0.9, 1.0], [0.0, 0.1, 0.2, 0.3, 0.5]) + + def __init__(self): + self.__oprFunc = {} + self.__gprFunc = {} + self.__wprFunc = {} + self.__bprFunc = {} + self.__current_step = 0 + + self.__fopt = 0.0 + self.__fopr = 0.0 + self.__fgpt = 0.0 + self.__fgpr = 0.0 + self.__fwpt = 0.0 + self.__fwpr = 0.0 + + self.__fgor = 0.0 + self.__fwct = 0.0 + + self.__wells = {} + self.__bpr = {} + + def addWell(self, name, seed, persistence=0.2, octaves=8, divergence_scale=1.0): + oil_div = OilSimulator.O_DIVERGENCE.scaledCopy(divergence_scale) + gas_div = OilSimulator.G_DIVERGENCE.scaledCopy(divergence_scale) + water_div = OilSimulator.W_DIVERGENCE.scaledCopy(divergence_scale) + self.__oprFunc[name] = ShapeCreator.createNoiseFunction(OilSimulator.OPR_SHAPE, oil_div, seed, persistence=persistence, octaves=octaves, cutoff=0.0) + self.__gprFunc[name] = ShapeCreator.createNoiseFunction(OilSimulator.GPR_SHAPE, gas_div, seed * 7, persistence=persistence * 3.5, octaves=octaves / 2, cutoff=0.0) + self.__wprFunc[name] = ShapeCreator.createNoiseFunction(OilSimulator.WPR_SHAPE, water_div, seed * 11, persistence=persistence, octaves=octaves, cutoff=0.0) + + self.__wells[name] = {"opr": 0.0, "opt": 0.0, "gpr": 0.0, "gpt": 0.0, "wpr": 0.0, "wpt": 0.0} + + def addBlock(self, name, seed, persistence=0.2): + self.__bprFunc[name] = ShapeCreator.createNoiseFunction(OilSimulator.BPR_SHAPE, OilSimulator.B_DIVERGENCE, seed, persistence=persistence, cutoff=0.0) + self.__bpr[name] = 0.0 + + def step(self, scale=1.0): + self.__fopr = 0.0 + self.__fgpr = 0.0 + self.__fwpr = 0.0 + self.__fgor = 0.0 + self.__fwct = 0.0 + for key in self.__wells: + oprFunction = self.__oprFunc[key] + gprFunction = self.__gprFunc[key] + wprFunction = self.__wprFunc[key] + opr_value = oprFunction(self.__current_step, scale) + gpr_value = gprFunction(self.__current_step, scale) + wpr_value = wprFunction(self.__current_step, scale) + + well = self.__wells[key] + well["opr"] = opr_value + well["opt"] += opr_value + well["gpr"] = gpr_value + well["gpt"] += gpr_value + well["wpr"] = wpr_value + well["wpt"] += wpr_value + self.__fopr += opr_value + self.__fgpr += gpr_value + self.__fwpr += wpr_value + + self.__fgor += self.gor(key) + self.__fwct += self.wct(key) + + self.__fopt += self.__fopr + self.__fgpt += self.__fgpr + self.__fwpt += self.__fwpr + + self.__fgor /= len(self.__wells) + self.__fwct /= len(self.__wells) + + for key in self.__bpr: + bprFunction = self.__bprFunc[key] + self.__bpr[key] = bprFunction(self.__current_step, scale) + + self.__current_step += 1 + + def fopt(self): + return self.__fopt + + def fopr(self): + return self.__fopr + + def fgpt(self): + return self.__fgpt + + def fgpr(self): + return self.__fgpr + + def fwpt(self): + return self.__fwpt + + def fwpr(self): + return self.__fwpr + + def fgor(self): + return self.__fgor + + def fwct(self): + return self.__fwct + + def opr(self, well_name): + return self.__wells[well_name]["opr"] + + def gpr(self, well_name): + return self.__wells[well_name]["gpr"] + + def wpr(self, well_name): + return self.__wells[well_name]["wpr"] + + def wct(self, well_name): + opr = self.opr(well_name) + wpr = self.wpr(well_name) + opr = max(opr, 0.1) + return wpr / (wpr + opr) if (wpr + opr) > 0.0 else 0.0 + + def gor(self, well_name): + opr = self.opr(well_name) + gpr = self.gpr(well_name) + opr = max(opr, 0.1) + gpr = max(gpr, 0.1) + return gpr / opr + + def bpr(self, block_name): + return self.__bpr[block_name] diff --git a/ThirdParty/Ert/devel/share/lib/synthesizer/perlin.py b/ThirdParty/Ert/devel/share/lib/synthesizer/perlin.py new file mode 100644 index 0000000000..b3da8ae7e1 --- /dev/null +++ b/ThirdParty/Ert/devel/share/lib/synthesizer/perlin.py @@ -0,0 +1,57 @@ +import math + +from .prime_generator import PrimeGenerator + + +class PerlinNoise(object): + def __init__(self, persistence=0.5, number_of_octaves=4, prime_generator=None): + self.persistence = persistence + self.number_of_octaves = number_of_octaves + + self.octave_primes = prime_generator if prime_generator is not None else PrimeGenerator() + + def cosineInterpolation(self, a, b, x): + ft = x * 3.1415927 + f = (1.0 - math.cos(ft)) * 0.5 + return a * (1 - f) + b * f + + MAX_INT = (1 << 31) - 1 + + def noise(self, x, perturbation): + x += perturbation + x = ((x << 13) & PerlinNoise.MAX_INT) ^ x + x = (x * (x * x * 15731 + 789221) + 1376312589) & PerlinNoise.MAX_INT + return 1.0 - x / 1073741824.0 + + def smoothedNoise(self, x, perturbation): + return self.noise(x, perturbation) / 2.0 + self.noise(x - 1, perturbation) / 4.0 + self.noise(x + 1, perturbation) / 4.0 + + def interpolatedNoise(self, x, octave_number): + int_x = int(x) + frac_x = x - int_x + + perturbation = self.octave_primes[octave_number] + + v1 = self.smoothedNoise(int_x, perturbation) + v2 = self.smoothedNoise(int_x + 1, perturbation) + + return self.cosineInterpolation(v1, v2, frac_x) + + def perlinNoise1D(self, x): + total = 0.0 + + for octave in range(self.number_of_octaves - 1): + frequency = math.pow(2, octave) + amplitude = math.pow(self.persistence, octave) + + total += self.interpolatedNoise(x * frequency, octave_number=octave) * amplitude + + return total + + def __getitem__(self, x): + """ :rtype: float """ + return self.perlinNoise1D(x * 10.0) + + def __call__(self, x): + """ :rtype: float """ + return self[x] diff --git a/ThirdParty/Ert/devel/share/lib/synthesizer/prime_generator.py b/ThirdParty/Ert/devel/share/lib/synthesizer/prime_generator.py new file mode 100644 index 0000000000..d7c35107b4 --- /dev/null +++ b/ThirdParty/Ert/devel/share/lib/synthesizer/prime_generator.py @@ -0,0 +1,40 @@ +import random + +def rwh_primes2(n): + # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188 + """ Input n>=6, Returns a list of primes, 2 <= p < n """ + correction = (n % 6 > 1) + n = {0: n, 1: n - 1, 2: n + 4, 3: n + 3, 4: n + 2, 5: n + 1}[n % 6] + sieve = [True] * (n / 3) + sieve[0] = False + for i in xrange(int(n ** 0.5) / 3 + 1): + if sieve[i]: + k = 3 * i + 1 | 1 + sieve[((k * k) / 3)::2 * k] = [False] * ((n / 6 - (k * k) / 6 - 1) / k + 1) + sieve[(k * k + 4 * k - 2 * k * (i & 1)) / 3::2 * k] = [False] * ( + (n / 6 - (k * k + 4 * k - 2 * k * (i & 1)) / 6 - 1) / k + 1) + return [2, 3] + [3 * i + 1 | 1 for i in xrange(1, n / 3 - correction) if sieve[i]] + + + +class PrimeGenerator(object): + LIST_OF_PRIMES = rwh_primes2(10000) + + def __init__(self, seed=None): + self.__primes = {} + self.__random = random.Random(seed) + random.seed(seed) + + def __getitem__(self, index): + if not isinstance(index, (int, long)) or index < 0: + raise IndexError("Index must be a positive integer: %d" % index) + + if not index in self.__primes: + p1 = self.randomPrime() + self.__primes[index] = p1 + + return self.__primes[index] + + def randomPrime(self): + random_index = self.__random.randint(0, len(PrimeGenerator.LIST_OF_PRIMES) - 1) + return PrimeGenerator.LIST_OF_PRIMES[random_index] diff --git a/ThirdParty/Ert/devel/share/lib/synthesizer/shaped_perlin.py b/ThirdParty/Ert/devel/share/lib/synthesizer/shaped_perlin.py new file mode 100644 index 0000000000..65b63a1f02 --- /dev/null +++ b/ThirdParty/Ert/devel/share/lib/synthesizer/shaped_perlin.py @@ -0,0 +1,106 @@ +import math +from . import PrimeGenerator, PerlinNoise + + +class Interpolator(object): + def __init__(self, x, y): + self.x = x + self.y = y + + assert len(x) == len(y) + + def __call__(self, x): + if x <= self.x[0]: + y = self.y[0] + elif x >= self.x[len(self.x) - 1]: + y = self.y[len(self.x) - 1] + else: + y = None + for i in range(len(self.x) - 1): + if self.x[i] <= x < self.x[i + 1]: + x_diff = self.x[i + 1] - self.x[i] + frac_x = (x - self.x[i]) / x_diff + y = self.cosineInterpolation(self.y[i], self.y[i + 1], frac_x) + break + + return y + + def cosineInterpolation(self, a, b, x): + ft = x * 3.1415927 + f = (1.0 - math.cos(ft)) * 0.5 + return a * (1 - f) + b * f + + +class ShapeFunction(object): + def __init__(self, x, y, scale=1.0): + self.scale = scale + self.interpolator = Interpolator(x, y) + + def __call__(self, x): + return self.interpolator(x) * self.scale + + def scaledCopy(self, scale=1.0): + return ShapeFunction(self.interpolator.x, self.interpolator.y, scale) + + +class ConstantShapeFunction(ShapeFunction): + def __init__(self, value): + super(ConstantShapeFunction, self).__init__([0.0], [value]) + + + +class ShapedNoise(object): + + def __init__(self, noiseFunction, shapeFunction, divergenceFunction, offset=0.0, cutoff=None): + self.shapeFunction = shapeFunction + self.divergenceFunction = divergenceFunction + self.noiseFunction = noiseFunction + self.offset = offset + self.cutoff = cutoff + + def __call__(self, x, scale=1.0): + scaled_x = x * scale + result = self.shapeFunction(scaled_x) + self.noiseFunction(scaled_x) * self.divergenceFunction(scaled_x) + result += self.offset + if self.cutoff is not None: + result = max(result, self.cutoff) + return result + + +class ShapeCreator(object): + + @staticmethod + def createShapeFunction(count=1000, persistence=0.2, octaves=8, seed=1): + """ @rtype: ShapeFunction """ + prime_generator = PrimeGenerator(seed=seed) + perlininator = PerlinNoise(persistence=persistence, number_of_octaves=octaves, prime_generator=prime_generator) + + x_values = [x / float(count) for x in range(count)] + y_values = [perlininator(x) for x in x_values] + + return ShapeFunction(x_values, y_values) + + @staticmethod + def createShapedPerlinFunction(divergence_x, divergence_y, shape_seed=None, perlin_seed=None, count=1000, persistence=0.2, octaves=8, offset=0.0, cutoff=None): + """ @rtype: ShapedNoise """ + shapeFunction = ShapeCreator.createShapeFunction(count, persistence, octaves, shape_seed) + divergenceFunction = ShapeFunction(divergence_x, divergence_y) + prime_generator = PrimeGenerator(perlin_seed) + perlin_noise = PerlinNoise(persistence, octaves, prime_generator) + + return ShapedNoise(perlin_noise, shapeFunction, divergenceFunction, offset=offset, cutoff=cutoff) + + @staticmethod + def createNoiseFunction(shapeFunction=None, divergenceFunction=None, seed=None, persistence=0.2, octaves=8, offset=0.0, cutoff=None): + """ @rtype: ShapedNoise """ + if shapeFunction is None: + shapeFunction = ConstantShapeFunction(0.0) + + if divergenceFunction is None: + divergenceFunction = ConstantShapeFunction(1.0) + + prime_generator = PrimeGenerator(seed) + perlin_noise = PerlinNoise(persistence, octaves, prime_generator) + + noise = ShapedNoise(perlin_noise, shapeFunction, divergenceFunction, offset=offset, cutoff=cutoff) + return noise diff --git a/ThirdParty/Ert/devel/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py b/ThirdParty/Ert/devel/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py index 52f2bebec5..76c705cf73 100644 --- a/ThirdParty/Ert/devel/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py +++ b/ThirdParty/Ert/devel/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py @@ -80,7 +80,7 @@ class GenDataRFTCSVExportJob(ErtPlugin): conventions: 1. All the GEN_DATA RFT observations have key RFT_$WELL - 2. The trajectory files are in $trajectory_path/$WELL.txt + 2. The trajectory files are in $trajectory_path/$WELL.txt or $trajectory_path/$WELL_R.txt """ @@ -145,9 +145,8 @@ class GenDataRFTCSVExportJob(ErtPlugin): std = obs_node.getStandardDeviation( obs_index ) obs[data_index,0] = value obs[data_index,1] = std - - real_data = pandas.DataFrame( index = ["Realization","Well"]) + for iens in realizations: realization_frame = pandas.DataFrame( data = {"TVD" : tvd_arg , "Pressure" : rft_data[iens], @@ -160,9 +159,9 @@ class GenDataRFTCSVExportJob(ErtPlugin): realization_frame["Case"] = case realization_frame["Iteration"] = iteration_number - case_frame = pandas.concat( [case_frame , realization_frame] ) - - data_frame = pandas.concat([data_frame, case_frame]) + case_frame = case_frame.append(realization_frame) + + data_frame = data_frame.append(case_frame) data_frame.set_index(["Realization" , "Well" , "Case" , "Iteration"] , inplace = True) data_frame.to_csv(output_file) diff --git a/ThirdParty/Ert/devel/test-data/local/custom_kw/Refcase/CASE.EGRID b/ThirdParty/Ert/devel/test-data/local/custom_kw/Refcase/CASE.EGRID new file mode 100644 index 0000000000..33da9f7a70 Binary files /dev/null and b/ThirdParty/Ert/devel/test-data/local/custom_kw/Refcase/CASE.EGRID differ diff --git a/ThirdParty/Ert/devel/test-data/local/custom_kw/mini_config b/ThirdParty/Ert/devel/test-data/local/custom_kw/mini_config index 68cee8ce40..21a409d739 100644 --- a/ThirdParty/Ert/devel/test-data/local/custom_kw/mini_config +++ b/ThirdParty/Ert/devel/test-data/local/custom_kw/mini_config @@ -37,3 +37,5 @@ DATA_KW CSV_OUTPUT_PATH custom_output.csv OBS_CONFIG Observations/observations CUSTOM_KW AGGREGATED aggregated.txt aggregated_out.txt + +GRID Refcase/CASE.EGRID \ No newline at end of file