2015-09-15 15:23:25 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// ResInsight 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.
//
// ResInsight 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimWellLogFileCurve.h"
2017-02-24 14:14:29 +01:00
#include "RigWellLogCurveData.h"
2017-10-12 17:05:52 +02:00
#include "RigWellPath.h"
2017-02-24 14:14:29 +01:00
#include "RimProject.h"
2018-06-26 10:12:49 +02:00
#include "RimTools.h"
2015-09-16 16:06:06 +02:00
#include "RimWellLogFile.h"
2017-02-24 14:14:29 +01:00
#include "RimWellLogFileChannel.h"
2015-09-16 15:31:04 +02:00
#include "RimWellLogPlot.h"
2017-02-24 14:14:29 +01:00
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
2017-11-08 10:30:55 +01:00
#include "RimWellPlotTools.h"
2018-06-26 10:12:49 +02:00
#include "RimWellRftPlot.h"
2015-09-16 15:31:04 +02:00
2018-09-04 09:08:29 +02:00
#include "RiuQwtPlotCurve.h"
2017-10-12 17:05:52 +02:00
#include "RiuWellLogTrack.h"
2015-09-16 15:31:04 +02:00
#include "RiaApplication.h"
2015-10-30 11:42:11 +01:00
#include "RiaPreferences.h"
2015-09-16 15:31:04 +02:00
#include "cafPdmUiTreeOrdering.h"
2015-10-30 11:42:11 +01:00
#include <QMessageBox>
2017-10-19 16:12:22 +02:00
#include <QFileInfo>
2015-10-30 11:42:11 +01:00
2015-09-15 15:23:25 +02:00
CAF_PDM_SOURCE_INIT ( RimWellLogFileCurve , "WellLogFileCurve" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogFileCurve :: RimWellLogFileCurve ()
{
CAF_PDM_InitObject ( "Well Log File Curve" , "" , "" , "" );
2015-09-16 15:31:04 +02:00
CAF_PDM_InitFieldNoDefault ( & m_wellPath , "CurveWellPath" , "Well Path" , "" , "" , "" );
2016-10-10 15:38:31 +02:00
m_wellPath . uiCapability () -> setUiTreeChildrenHidden ( true );
2015-09-16 15:31:04 +02:00
CAF_PDM_InitFieldNoDefault ( & m_wellLogChannnelName , "CurveWellLogChannel" , "Well Log Channel" , "" , "" , "" );
2017-10-19 16:12:22 +02:00
CAF_PDM_InitFieldNoDefault ( & m_wellLogFile , "WellLogFile" , "Well Log File" , "" , "" , "" );
2017-10-12 17:05:52 +02:00
m_wellPath = nullptr ;
2015-09-15 15:23:25 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogFileCurve ::~ RimWellLogFileCurve ()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-09-23 08:47:04 +02:00
void RimWellLogFileCurve :: onLoadDataAndUpdate ( bool updateParentPlot )
2015-09-15 15:23:25 +02:00
{
2017-11-11 23:15:13 +01:00
this -> RimPlotCurve :: updateCurvePresentation ( updateParentPlot );
2015-09-16 15:31:04 +02:00
2015-10-27 14:44:53 +01:00
if ( isCurveVisible ())
2015-09-16 15:31:04 +02:00
{
2015-10-15 11:27:12 +02:00
m_curveData = new RigWellLogCurveData ;
2015-10-30 11:42:11 +01:00
RimWellLogPlot * wellLogPlot ;
2016-09-21 13:59:41 +02:00
firstAncestorOrThisOfType ( wellLogPlot );
2015-10-30 11:42:11 +01:00
CVF_ASSERT ( wellLogPlot );
2017-10-19 16:12:22 +02:00
if ( m_wellPath && m_wellLogFile )
2015-09-16 15:31:04 +02:00
{
2017-11-15 16:17:55 +01:00
RigWellLogFile * wellLogFile = m_wellLogFile -> wellLogFileData ();
2017-10-19 16:12:22 +02:00
if ( wellLogFile )
2015-09-16 15:31:04 +02:00
{
2017-10-19 16:12:22 +02:00
std :: vector < double > values = wellLogFile -> values ( m_wellLogChannnelName );
std :: vector < double > measuredDepthValues = wellLogFile -> depthValues ();
2017-10-12 17:05:52 +02:00
2017-10-19 16:12:22 +02:00
if ( wellLogPlot && wellLogPlot -> depthType () == RimWellLogPlot :: TRUE_VERTICAL_DEPTH )
{
bool canUseTvd = false ;
if ( wellLogFile -> hasTvdChannel ())
2017-10-12 17:05:52 +02:00
{
2017-10-19 16:12:22 +02:00
std :: vector < double > tvdMslValues = wellLogFile -> tvdMslValues ();
2017-10-12 17:05:52 +02:00
2017-10-19 16:12:22 +02:00
if ( values . size () == measuredDepthValues . size () && values . size () == tvdMslValues . size ())
{
m_curveData -> setValuesWithTVD ( values , measuredDepthValues , tvdMslValues , wellLogFile -> depthUnit (), false );
canUseTvd = true ;
2017-10-16 08:38:38 +02:00
}
2017-10-19 16:12:22 +02:00
}
2017-10-16 08:38:38 +02:00
2017-10-19 16:12:22 +02:00
if ( ! canUseTvd )
{
RigWellPath * rigWellPath = m_wellPath -> wellPathGeometry ();
if ( rigWellPath )
2017-10-16 08:38:38 +02:00
{
2017-10-19 16:12:22 +02:00
std :: vector < double > trueVerticeldepthValues ;
for ( double measuredDepthValue : measuredDepthValues )
2017-10-12 17:05:52 +02:00
{
2017-10-19 16:12:22 +02:00
trueVerticeldepthValues . push_back ( - rigWellPath -> interpolatedPointAlongWellPath ( measuredDepthValue ). z ());
2017-10-12 17:05:52 +02:00
}
2017-10-19 16:12:22 +02:00
if ( values . size () == trueVerticeldepthValues . size () && values . size () == measuredDepthValues . size ())
2017-10-12 17:05:52 +02:00
{
2017-10-19 16:12:22 +02:00
m_curveData -> setValuesWithTVD ( values , measuredDepthValues , trueVerticeldepthValues , wellLogFile -> depthUnit (), false );
canUseTvd = true ;
2017-10-12 17:05:52 +02:00
}
}
}
2017-10-19 16:12:22 +02:00
if ( ! canUseTvd )
2015-10-12 12:40:10 +02:00
{
2017-10-19 16:12:22 +02:00
if ( RiaApplication :: instance () -> preferences () -> showLasCurveWithoutTvdWarning ())
2017-10-12 17:05:52 +02:00
{
2017-10-19 16:12:22 +02:00
QString tmp = QString ( "Display of True Vertical Depth (TVD) for LAS curves is not possible without a well log path, and the LAS curve will be hidden in this mode. \n\n " );
tmp += "Control display of this warning from \" Preferences->Show LAS curve without TVD warning \" " ;
QMessageBox :: warning ( nullptr , "LAS curve without TVD" , tmp );
2017-10-12 17:05:52 +02:00
}
2015-10-12 12:40:10 +02:00
}
2015-09-18 09:05:15 +02:00
}
2017-10-19 16:12:22 +02:00
else
2015-09-22 15:45:58 +02:00
{
2017-10-19 16:12:22 +02:00
if ( values . size () == measuredDepthValues . size ())
{
m_curveData -> setValuesAndMD ( values , measuredDepthValues , wellLogFile -> depthUnit (), false );
}
2015-09-22 15:45:58 +02:00
}
2015-09-16 15:31:04 +02:00
}
2015-10-15 11:27:12 +02:00
2017-10-19 16:12:22 +02:00
if ( m_isUsingAutoName )
{
m_qwtPlotCurve -> setTitle ( createCurveAutoName ());
}
}
2017-10-12 17:05:52 +02:00
2017-06-13 15:41:52 +02:00
RiaDefines :: DepthUnitType displayUnit = RiaDefines :: UNIT_METER ;
2015-12-02 13:39:16 +01:00
if ( wellLogPlot )
{
displayUnit = wellLogPlot -> depthUnit ();
}
2017-10-12 17:05:52 +02:00
if ( wellLogPlot && wellLogPlot -> depthType () == RimWellLogPlot :: TRUE_VERTICAL_DEPTH )
{
m_qwtPlotCurve -> setSamples ( m_curveData -> xPlotValues (). data (), m_curveData -> trueDepthPlotValues ( displayUnit ). data (), static_cast < int > ( m_curveData -> xPlotValues (). size ()));
}
else
{
m_qwtPlotCurve -> setSamples ( m_curveData -> xPlotValues (). data (), m_curveData -> measuredDepthPlotValues ( displayUnit ). data (), static_cast < int > ( m_curveData -> xPlotValues (). size ()));
}
2015-11-06 10:08:35 +01:00
m_qwtPlotCurve -> setLineSegmentStartStopIndices ( m_curveData -> polylineStartStopIndices ());
2015-09-22 11:17:24 +02:00
2018-05-23 11:28:57 +02:00
if ( updateParentPlot )
{
updateZoomInParentPlot ();
}
2015-09-22 11:17:24 +02:00
2018-05-23 11:28:57 +02:00
if ( m_parentQwtPlot )
{
m_parentQwtPlot -> replot ();
}
2015-09-16 15:31:04 +02:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: setWellPath ( RimWellPath * wellPath )
{
m_wellPath = wellPath ;
2015-09-15 15:23:25 +02:00
}
2017-10-05 10:54:52 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath * RimWellLogFileCurve :: wellPath () const
{
return m_wellPath ;
}
2015-09-15 15:23:25 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-09-16 15:31:04 +02:00
void RimWellLogFileCurve :: setWellLogChannelName ( const QString & name )
2015-09-15 15:23:25 +02:00
{
2015-09-16 15:31:04 +02:00
m_wellLogChannnelName = name ;
2015-09-15 15:23:25 +02:00
}
2015-09-16 15:31:04 +02:00
2017-10-19 16:12:22 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: setWellLogFile ( RimWellLogFile * wellLogFile )
{
m_wellLogFile = wellLogFile ;
}
2015-09-16 15:31:04 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: fieldChangedByUi ( const caf :: PdmFieldHandle * changedField , const QVariant & oldValue , const QVariant & newValue )
{
2015-11-04 16:19:38 +01:00
RimWellLogCurve :: fieldChangedByUi ( changedField , oldValue , newValue );
2015-09-16 15:31:04 +02:00
if ( changedField == & m_wellPath )
{
2017-09-23 08:47:04 +02:00
this -> loadDataAndUpdate ( true );
2015-09-16 15:31:04 +02:00
}
else if ( changedField == & m_wellLogChannnelName )
{
2017-09-23 08:47:04 +02:00
this -> loadDataAndUpdate ( true );
2015-09-16 15:31:04 +02:00
}
2017-10-19 16:12:22 +02:00
else if ( changedField == & m_wellLogFile )
{
this -> loadDataAndUpdate ( true );
}
2016-05-23 17:13:03 +02:00
if ( m_parentQwtPlot ) m_parentQwtPlot -> replot ();
2015-09-16 15:31:04 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: defineUiOrdering ( QString uiConfigName , caf :: PdmUiOrdering & uiOrdering )
{
2017-03-17 15:51:32 +01:00
RimPlotCurve :: updateOptionSensitivity ();
2015-09-22 15:23:52 +02:00
caf :: PdmUiGroup * curveDataGroup = uiOrdering . addNewGroup ( "Curve Data" );
curveDataGroup -> add ( & m_wellPath );
2017-10-19 16:12:22 +02:00
curveDataGroup -> add ( & m_wellLogFile );
2017-10-23 19:09:08 +02:00
curveDataGroup -> add ( & m_wellLogChannnelName );
2015-09-22 15:23:52 +02:00
caf :: PdmUiGroup * appearanceGroup = uiOrdering . addNewGroup ( "Appearance" );
2017-04-07 14:43:26 +02:00
RimPlotCurve :: appearanceUiOrdering ( * appearanceGroup );
caf :: PdmUiGroup * nameGroup = uiOrdering . addNewGroup ( "Curve Name" );
2017-05-01 20:13:13 +02:00
nameGroup -> add ( & m_showLegend );
2017-04-07 14:43:26 +02:00
RimPlotCurve :: curveNameUiOrdering ( * nameGroup );
2015-09-16 15:31:04 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: defineUiTreeOrdering ( caf :: PdmUiTreeOrdering & uiTreeOrdering , QString uiConfigName /*= ""*/ )
{
2017-03-22 15:57:04 +01:00
uiTreeOrdering . skipRemainingChildren ( true );
2015-09-16 15:31:04 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList < caf :: PdmOptionItemInfo > RimWellLogFileCurve :: calculateValueOptions ( const caf :: PdmFieldHandle * fieldNeedingOptions , bool * useOptionsOnly )
{
2017-01-05 07:57:37 +01:00
QList < caf :: PdmOptionItemInfo > options ;
2015-09-16 15:31:04 +02:00
2017-01-05 07:57:37 +01:00
options = RimWellLogCurve :: calculateValueOptions ( fieldNeedingOptions , useOptionsOnly );
if ( options . size () > 0 ) return options ;
2015-12-01 16:22:18 +01:00
2015-09-16 15:31:04 +02:00
if ( fieldNeedingOptions == & m_wellPath )
{
2018-06-26 10:12:49 +02:00
auto wellPathColl = RimTools :: wellPathCollection ();
if ( wellPathColl )
2015-09-16 15:31:04 +02:00
{
2018-06-26 10:12:49 +02:00
caf :: PdmChildArrayField < RimWellPath *>& wellPaths = wellPathColl -> wellPaths ;
2015-09-16 15:31:04 +02:00
for ( size_t i = 0 ; i < wellPaths . size (); i ++ )
{
2017-01-05 07:53:14 +01:00
// Only include well paths coming from a well log file
2017-10-19 16:12:22 +02:00
if ( wellPaths [ i ] -> wellLogFiles (). size () > 0 )
2015-09-25 18:04:10 +02:00
{
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( wellPaths [ i ] -> name (), wellPaths [ i ]));
2015-09-25 18:04:10 +02:00
}
2015-09-16 15:31:04 +02:00
}
2017-01-05 07:57:37 +01:00
if ( options . size () > 0 )
2015-09-16 15:31:04 +02:00
{
2017-01-05 07:57:37 +01:00
options . push_front ( caf :: PdmOptionItemInfo ( "None" , nullptr ));
2015-09-16 15:31:04 +02:00
}
}
}
if ( fieldNeedingOptions == & m_wellLogChannnelName )
{
if ( m_wellPath ())
{
2017-10-19 16:12:22 +02:00
if ( m_wellLogFile )
2015-09-16 15:31:04 +02:00
{
2017-10-19 16:12:22 +02:00
std :: vector < RimWellLogFileChannel *> fileLogs = m_wellLogFile -> wellLogChannels ();
2015-09-16 15:31:04 +02:00
2017-10-06 13:34:45 +02:00
for ( size_t i = 0 ; i < fileLogs . size (); i ++ )
2015-09-16 15:31:04 +02:00
{
2017-10-06 13:34:45 +02:00
QString wellLogChannelName = fileLogs [ i ] -> name ();
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( wellLogChannelName , wellLogChannelName ));
2015-09-16 15:31:04 +02:00
}
}
}
2015-09-18 09:05:15 +02:00
2017-01-05 07:57:37 +01:00
if ( options . size () == 0 )
2015-09-18 09:05:15 +02:00
{
2017-01-05 07:57:37 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( "None" , "None" ));
2015-09-18 09:05:15 +02:00
}
2015-09-16 15:31:04 +02:00
}
2017-11-15 17:06:46 +01:00
if ( fieldNeedingOptions == & m_wellLogFile )
2017-10-19 16:12:22 +02:00
{
2017-11-15 17:06:46 +01:00
if ( m_wellPath () && m_wellPath -> wellLogFiles (). size () > 0 )
2017-10-19 16:12:22 +02:00
{
2017-11-15 17:06:46 +01:00
for ( RimWellLogFile * const wellLogFile : m_wellPath -> wellLogFiles () )
2017-10-19 16:12:22 +02:00
{
2017-11-15 17:06:46 +01:00
QFileInfo fileInfo ( wellLogFile -> fileName ());
options . push_back ( caf :: PdmOptionItemInfo ( fileInfo . baseName (), wellLogFile ));
2017-10-19 16:12:22 +02:00
}
}
}
2017-01-05 07:57:37 +01:00
return options ;
2015-09-16 15:31:04 +02:00
}
2017-10-20 10:17:30 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve :: initAfterRead ()
{
2018-03-14 13:38:59 +01:00
if ( ! m_wellPath ) return ;
2017-10-20 10:17:30 +02:00
if ( m_wellPath -> wellLogFiles (). size () == 1 )
{
m_wellLogFile = m_wellPath -> wellLogFiles (). front ();
}
}
2017-10-23 19:09:08 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-10-24 11:36:52 +02:00
bool RimWellLogFileCurve :: isRftPlotChild () const
2017-10-23 19:09:08 +02:00
{
RimWellRftPlot * rftPlot ;
firstAncestorOrThisOfType ( rftPlot );
return rftPlot != nullptr ;
}
2015-09-18 13:02:33 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-05-23 17:13:03 +02:00
QString RimWellLogFileCurve :: createCurveAutoName ()
2015-09-18 13:02:33 +02:00
{
2017-11-01 15:59:27 +01:00
QStringList name ;
QString unit ;
bool channelNameAvailable = false ;
2015-09-22 15:12:33 +02:00
if ( m_wellPath )
2015-09-18 13:43:09 +02:00
{
2017-11-01 15:59:27 +01:00
name . push_back ( wellName ());
2017-11-01 16:13:39 +01:00
name . push_back ( "LAS" );
2015-09-18 13:43:09 +02:00
2017-11-01 15:59:27 +01:00
if ( ! m_wellLogChannnelName (). isEmpty ())
{
name . push_back ( m_wellLogChannnelName );
channelNameAvailable = true ;
}
2015-09-18 13:43:09 +02:00
2017-11-15 16:17:55 +01:00
RigWellLogFile * wellLogFile = m_wellLogFile ? m_wellLogFile -> wellLogFileData () : nullptr ;
2017-11-01 15:59:27 +01:00
2015-09-22 15:12:33 +02:00
if ( wellLogFile )
2015-09-21 10:10:25 +02:00
{
2017-11-01 15:59:27 +01:00
if ( channelNameAvailable )
{
RimWellLogPlot * wellLogPlot ;
firstAncestorOrThisOfType ( wellLogPlot );
CVF_ASSERT ( wellLogPlot );
QString unitName = wellLogFile -> wellLogChannelUnitString ( m_wellLogChannnelName , wellLogPlot -> depthUnit ());
2015-12-02 14:21:22 +01:00
2017-11-01 15:59:27 +01:00
if ( ! unitName . isEmpty ())
{
name . back () += QString ( " [%1]" ). arg ( unitName );
}
}
QString date = wellLogFile -> date ();
if ( ! date . isEmpty ())
2015-09-22 15:12:33 +02:00
{
2017-11-01 15:59:27 +01:00
name . push_back ( wellLogFile -> date ());
2015-09-22 15:12:33 +02:00
}
2017-11-01 15:59:27 +01:00
2015-09-21 10:10:25 +02:00
}
2017-11-01 15:59:27 +01:00
return name . join ( ", " );
2015-09-18 13:43:09 +02:00
}
2017-10-12 17:05:52 +02:00
2015-09-18 13:43:09 +02:00
return "Empty curve" ;
2015-09-18 13:02:33 +02:00
}
2015-10-15 14:37:57 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogFileCurve :: wellLogChannelName () const
{
return m_wellLogChannnelName ;
}
2017-10-19 16:12:22 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogFile * RimWellLogFileCurve :: wellLogFile () const
{
return m_wellLogFile ();
}
2015-10-16 11:15:04 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogFileCurve :: wellName () const
{
2018-03-14 13:38:59 +01:00
if ( m_wellPath )
{
return m_wellPath -> name ();
}
return QString ( "" );
2015-10-16 11:15:04 +02:00
}