Skip to content

Commit

Permalink
Merge branch 'main' into fix-lithology-scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
MiraGeowerkstatt authored May 16, 2024
2 parents 1854162 + 39328e1 commit bf33bc4
Show file tree
Hide file tree
Showing 43 changed files with 7,147 additions and 704 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added `outcrop` to codelist `borehole_type`.
- Made boreholes table on the map page collapsible.
- Changed sidebar layout and design.
- Removed fields `Inclination` `InclinationDirection` and `QtInclinationDirectionId` from borehole.

### Fixed

Expand Down
31 changes: 0 additions & 31 deletions src/api-legacy/v1/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,37 +584,6 @@ def filterBorehole(self, filter={}):
qt_elevation_id_cli = %s
""" % self.getIdx())

if 'bore_inc_from' in keys and filter['bore_inc_from'] not in ['', None]:
params.append(float(filter['bore_inc_from']))
where.append("""
inclination_bho >= %s
""" % self.getIdx())

if 'bore_inc_to' in keys and filter['bore_inc_to'] not in ['', None]:
params.append(float(filter['bore_inc_to']))
where.append("""
inclination_bho <= %s
""" % self.getIdx())

if 'bore_inc_dir_from' in keys and filter['bore_inc_dir_from'] not in ['', None]:
params.append(float(filter['bore_inc_dir_from']))
where.append("""
inclination_direction_bho >= %s
""" % self.getIdx())

if 'bore_inc_dir_to' in keys and filter['bore_inc_dir_to'] not in ['', None]:
params.append(float(filter['bore_inc_dir_to']))
where.append("""
inclination_direction_bho <= %s
""" % self.getIdx())

if 'qt_inclination_direction' in keys and filter[
'qt_inclination_direction'] not in ['', None]:
params.append(int(filter['qt_inclination_direction']))
where.append("""
qt_inclination_direction_id_cli = %s
""" % self.getIdx())

if 'length_from' in keys and filter['length_from'] not in ['', None]:
params.append(float(filter['length_from']))
where.append("""
Expand Down
3 changes: 0 additions & 3 deletions src/api-legacy/v1/borehole/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ def get_sql(sql_lock='', file_permission=''):
qt_reference_elevation_id_cli as qt_reference_elevation,
reference_elevation_type_id_cli as reference_elevation_type,
inclination_bho as inclination,
inclination_direction_bho as inclination_direction,
total_depth_bho as total_depth,
total_depth_tvd_bho as total_depth_tvd,
qt_total_depth_tvd_id_cli as qt_total_depth_tvd,
Expand Down Expand Up @@ -99,7 +97,6 @@ def get_sql(sql_lock='', file_permission=''):
country_bho as country,
canton_bho as canton,
municipality_bho as municipality,
qt_inclination_direction_id_cli as qt_bore_inc_dir,
qt_depth_id_cli as qt_depth,
qt_top_bedrock,
qt_top_bedrock_tvd,
Expand Down
6 changes: 0 additions & 6 deletions src/api-legacy/v1/borehole/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ def get_sql_geolcode(cols=None, join=None, where=None):
cut.geolcode as cuttings,
prp.geolcode as purpose,
sts.geolcode as status,
inclination_bho as inclination,
inclination_direction_bho as inclination_direction,
qt_inc_dir.geolcode as qt_bore_inc_dir,
total_depth_bho as total_depth,
qt_len.geolcode as qt_depth,
Expand Down Expand Up @@ -147,9 +144,6 @@ def get_sql_geolcode(cols=None, join=None, where=None):
LEFT JOIN bdms.codelist as qt_len
ON qt_len.id_cli = qt_depth_id_cli
LEFT JOIN bdms.codelist as qt_inc_dir
ON qt_inc_dir.id_cli = qt_inclination_direction_id_cli
LEFT JOIN bdms.codelist as prp
ON prp.id_cli = purpose_id_cli
Expand Down
12 changes: 0 additions & 12 deletions src/api-legacy/v1/borehole/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ def get_column(field):
elif field == 'canton':
column = 'canton_num'

elif field == 'inclination':
column = 'inclination_bho'

elif field == 'inclination_direction':
column = 'inclination_direction_bho'

elif field == 'total_depth':
column = 'total_depth_bho'

Expand Down Expand Up @@ -153,9 +147,6 @@ def get_column(field):
elif field == 'extended.status':
column = 'status_id_cli'

elif field == 'custom.qt_bore_inc_dir':
column = 'qt_inclination_direction_id_cli'

elif field == 'custom.qt_depth':
column = 'qt_depth_id_cli'

Expand Down Expand Up @@ -213,8 +204,6 @@ async def execute(self, id, field, value, user):
'depth_precision',
'drill_diameter',
'custom.drill_diameter',
'inclination',
'inclination_direction',
'total_depth',
'total_depth_tvd',
'extended.top_bedrock',
Expand Down Expand Up @@ -293,7 +282,6 @@ async def execute(self, id, field, value, user):
'custom.cuttings',
'extended.purpose',
'extended.status',
'custom.qt_bore_inc_dir',
'custom.qt_depth',
'custom.processing_status',
'custom.lithology_top_bedrock',
Expand Down
1 change: 0 additions & 1 deletion src/api/BdmsContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Borehole>().HasOne(l => l.Purpose).WithMany().HasForeignKey(l => l.PurposeId);
modelBuilder.Entity<Borehole>().HasOne(l => l.QtDepth).WithMany().HasForeignKey(l => l.QtDepthId);
modelBuilder.Entity<Borehole>().HasOne(l => l.ElevationPrecision).WithMany().HasForeignKey(l => l.ElevationPrecisionId);
modelBuilder.Entity<Borehole>().HasOne(l => l.QtInclinationDirection).WithMany().HasForeignKey(l => l.QtInclinationDirectionId);
modelBuilder.Entity<Borehole>().HasOne(l => l.LocationPrecision).WithMany().HasForeignKey(l => l.LocationPrecisionId);
modelBuilder.Entity<Borehole>().HasOne(l => l.QtTotalDepthTvd).WithMany().HasForeignKey(l => l.QtTotalDepthTvdId);
modelBuilder.Entity<Borehole>().HasOne(l => l.QtReferenceElevation).WithMany().HasForeignKey(l => l.QtReferenceElevationId);
Expand Down
5 changes: 0 additions & 5 deletions src/api/BdmsContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public static void SeedData(this BdmsContext context)
List<int> purposeIds = codelists.Where(c => c.Schema == "extended.purpose").Select(s => s.Id).ToList();
List<int> statusIds = codelists.Where(c => c.Schema == "extended.status").Select(s => s.Id).ToList();
List<int> lithologyTopBedrockIds = codelists.Where(c => c.Schema == "custom.lithology_top_bedrock").Select(s => s.Id).ToList();
List<int> qtInclinationDirectionIds = codelists.Where(c => c.Schema == "custom.qt_bore_inc_dir").Select(s => s.Id).ToList();
List<int> chronostratigraphyTopBedrockIds = codelists.Where(c => c.Schema == "custom.chronostratigraphy_top_bedrock").Select(s => s.Id).ToList();
List<int> lithostratigraphyTopBedrockIds = codelists.Where(c => c.Schema == "custom.lithostratigraphy_top_bedrock").Select(s => s.Id).ToList();
List<int> instrumentKindIds = codelists.Where(c => c.Schema == CompletionSchemas.InstrumentationTypeSchema).Select(s => s.Id).ToList();
Expand Down Expand Up @@ -158,8 +157,6 @@ public static void SeedData(this BdmsContext context)
.RuleFor(o => o.Purpose, _ => default!)
.RuleFor(o => o.StatusId, f => f.PickRandom(statusIds).OrNull(f, .05f))
.RuleFor(o => o.Status, _ => default!)
.RuleFor(o => o.Inclination, f => f.Random.Double(0, 5).OrNull(f, .05f))
.RuleFor(o => o.InclinationDirection, f => f.Random.Double(0, 360).OrNull(f, .05f))
.RuleFor(o => o.QtDepthId, f => f.PickRandom(qtDepthIds).OrNull(f, .05f))
.RuleFor(o => o.QtDepth, _ => default!)
.RuleFor(o => o.TopBedrock, f => f.Random.Double(0, 1000).OrNull(f, .05f))
Expand All @@ -177,8 +174,6 @@ public static void SeedData(this BdmsContext context)
.RuleFor(o => o.ReferenceElevation, f => f.Random.Double(0, 4500).OrNull(f, .05f))
.RuleFor(o => o.QtReferenceElevationId, f => f.PickRandom(elevationPrecisionIds).OrNull(f, .05f))
.RuleFor(o => o.QtReferenceElevation, _ => default!)
.RuleFor(o => o.QtInclinationDirectionId, f => f.PickRandom(qtInclinationDirectionIds).OrNull(f, .05f))
.RuleFor(o => o.QtInclinationDirection, _ => default!)
.RuleFor(o => o.ReferenceElevationTypeId, f => f.PickRandom(referenceElevationTypeIds).OrNull(f, .05f))
.RuleFor(o => o.ReferenceElevationType, _ => default!)
.RuleFor(o => o.TotalDepthTvd, f => f.Random.Double(0, 4500).OrNull(f, .05f))
Expand Down
87 changes: 87 additions & 0 deletions src/api/BoreholeGeometryFormat/AzIncFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using BDMS.Models;
using CsvHelper;
using CsvHelper.Configuration.Attributes;

namespace BDMS.BoreholeGeometryFormat;

/// <summary>
/// Accepts a CSV file where every data point has an Azimuth and Inclination.
/// </summary>
internal sealed class AzIncFormat : IBoreholeGeometryFormat
{
public string Key => "AzInc";
public string Name => "Azimuth Inclination";
private Lazy<string> expectedCsvHeader = new(Helper.GetCSVHeader<Geometry>);
public string CsvHeader => expectedCsvHeader.Value;

public IList<BoreholeGeometryElement> ReadCsv(IFormFile file, int boreholeId)
{
using var reader = new StreamReader(file.OpenReadStream());
using var csv = new CsvReader(reader, Helper.CsvConfig);

var data = csv.GetRecords<Geometry>().ToList();

// Convert degrees to radians
foreach (var entry in data)
{
entry.Azimuth = Helper.ToRadians(entry.Azimuth);
entry.Inclination = Helper.ToRadians(entry.Inclination);
}

return XYZFormat.ToBoreholeGeometry(ConvertToXYZ(data), boreholeId);
}

/// <summary>
/// Convert <see cref="Geometry"/> data to <see cref="XYZFormat.Geometry"/> data using the
/// <see href="https://www.drillingformulas.com/minimum-curvature-method/">Minimum Curvature</see> algorithm.
/// </summary>
/// <param name="data">The <see cref="Geometry"/> data.</param>
public static List<XYZFormat.Geometry> ConvertToXYZ(IList<Geometry> data)
{
List<XYZFormat.Geometry> result = new(data.Count);
result.Add(new XYZFormat.Geometry { X = 0, Y = 0, Z = 0 });

for (int i = 1; i < data.Count; i++)
{
var a = data[i - 1];
var b = data[i];

// Change in measured depth
double deltaMD = b.MeasuredDepth - a.MeasuredDepth;

// Dogleg Severity Angle
double beta = Math.Acos(Math.Cos(b.Inclination - a.Inclination) - (Math.Sin(a.Inclination) * Math.Sin(b.Inclination) * (1 - Math.Cos(b.Azimuth - a.Azimuth))));

// Ratio factor
double ratioFactor = beta == 0 ? 1 : (2 / beta) * Math.Tan(beta / 2);

// Half delta measured depth multiplied by ratio factor
double factor = (deltaMD / 2) * ratioFactor;

// Change in easting, northing and elevation
double deltaN = factor * ((Math.Sin(a.Inclination) * Math.Cos(a.Azimuth)) + (Math.Sin(b.Inclination) * Math.Cos(b.Azimuth)));
double deltaE = factor * ((Math.Sin(a.Inclination) * Math.Sin(a.Azimuth)) + (Math.Sin(b.Inclination) * Math.Sin(b.Azimuth)));
double deltaTVD = factor * (Math.Cos(a.Inclination) + Math.Cos(b.Inclination));

var previous = result[i - 1];
result.Add(new XYZFormat.Geometry
{
X = previous.X + deltaE,
Y = previous.Y + deltaN,
Z = previous.Z + deltaTVD,
});
}

return result;
}

internal sealed class Geometry
{
[Name("MD_m")]
public double MeasuredDepth { get; set; }
[Name("HAZI_deg")]
public double Azimuth { get; set; }
[Name("DEVI_deg")]
public double Inclination { get; set; }
}
}
35 changes: 35 additions & 0 deletions src/api/BoreholeGeometryFormat/Helper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using CsvHelper;
using CsvHelper.Configuration;
using Humanizer;
using System.Globalization;

namespace BDMS.BoreholeGeometryFormat;

public static class Helper
{
internal static readonly CsvConfiguration CsvConfig = new(new CultureInfo("de-CH"))
{
Delimiter = ";",
IgnoreReferences = true,
PrepareHeaderForMatch = args => args.Header.Humanize(LetterCasing.Title),
MissingFieldFound = null,
};

/// <summary>
/// Get the CSV header <see cref="CsvHelper"/> expects to read a class <typeparamref name="T"/>.
/// Uses the map generated by <see cref="CsvHelper.CsvContext.AutoMap{T}()"/>.
/// If a property has multiple possible column names only the first is considered.
/// </summary>
/// <typeparam name="T">The class to get the header for.</typeparam>
internal static string GetCSVHeader<T>()
{
var context = new CsvContext(CsvConfig);
var map = context.AutoMap<T>();
return string.Join("; ", map.MemberMaps.Select(m => m.Data.Names.FirstOrDefault(m.Data.Member.Name)));
}

internal static double ToRadians(double degrees)
{
return degrees * Math.PI / 180;
}
}
32 changes: 32 additions & 0 deletions src/api/BoreholeGeometryFormat/IBoreholeGeometryFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using BDMS.Models;

namespace BDMS.BoreholeGeometryFormat;

/// <summary>
/// Geometry format with method to read and convert the input CSV file to <see cref="BoreholeGeometryElement"/>s.
/// </summary>
public interface IBoreholeGeometryFormat
{
/// <summary>
/// Key to identify this <see cref="IBoreholeGeometryFormat"/>.
/// </summary>
string Key { get; }

/// <summary>
/// Human readable name of the <see cref="IBoreholeGeometryFormat"/>.
/// </summary>
string Name { get; }

/// <summary>
/// The expected header of the input CSV file.
/// </summary>
string CsvHeader { get; }

/// <summary>
/// Convert the provided CSV file into a List of <see cref="BoreholeGeometryElement"/>.
/// </summary>
/// <param name="file">The input CSV file.</param>
/// <param name="boreholeId">The id of the borehole this geometry belongs to.</param>
/// <returns></returns>
IList<BoreholeGeometryElement> ReadCsv(IFormFile file, int boreholeId);
}
71 changes: 71 additions & 0 deletions src/api/BoreholeGeometryFormat/PitchRollFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using BDMS.Models;
using CsvHelper;
using CsvHelper.Configuration.Attributes;

namespace BDMS.BoreholeGeometryFormat;

/// <summary>
/// Accepts a CSV file where every data point has a Pitch, Roll and Yaw angle.
/// </summary>
internal sealed class PitchRollFormat : IBoreholeGeometryFormat
{
public string Key => "PitchRoll";
public string Name => "Pitch Roll";
private Lazy<string> expectedCsvHeader = new(Helper.GetCSVHeader<Geometry>);
public string CsvHeader => expectedCsvHeader.Value;

public IList<BoreholeGeometryElement> ReadCsv(IFormFile file, int boreholeId)
{
using var reader = new StreamReader(file.OpenReadStream());
using var csv = new CsvReader(reader, Helper.CsvConfig);

var data = csv.GetRecords<Geometry>().ToList();

// Convert degrees to radians
foreach (var entry in data)
{
entry.Pitch = Helper.ToRadians(entry.Pitch);
entry.Roll = Helper.ToRadians(entry.Roll);
entry.MagneticRotation = Helper.ToRadians(entry.MagneticRotation);
}

return XYZFormat.ToBoreholeGeometry(AzIncFormat.ConvertToXYZ(ConvertToAzInc(data)), boreholeId);
}

/// <summary>
/// Convert the <see cref="Geometry"/> data to <see cref="AzIncFormat.Geometry"/> data by
/// calculating the Azimuth and Inclination of a the vector tangential to the borehole.
/// </summary>
/// <param name="data">The <see cref="Geometry"/> data.</param>
public static IList<AzIncFormat.Geometry> ConvertToAzInc(IEnumerable<Geometry> data)
{
return data.Select(d =>
{
var result = new AzIncFormat.Geometry() { MeasuredDepth = d.MeasuredDepth };

var alpha = d.MagneticRotation; // Rotation around z axis (down)
var beta = d.Pitch; // Rotation around y axis (north)
var gamma = d.Roll; // Rotation around x axis (east)

// Unit vector tangential to the borehole path
var x = (Math.Cos(alpha) * Math.Sin(beta) * Math.Cos(gamma)) + (Math.Sin(alpha) * Math.Sin(gamma));
var y = (Math.Sin(alpha) * Math.Sin(beta) * Math.Cos(gamma)) - (Math.Cos(alpha) * Math.Sin(gamma));
var z = Math.Cos(beta) * Math.Cos(gamma);

result.Azimuth = Math.Atan2(y, x);
result.Inclination = Math.Acos(z);

return result;
}).ToList();
}

internal sealed class Geometry
{
[Name("Kabellaenge")]
public double MeasuredDepth { get; set; }
public double Roll { get; set; }
public double Pitch { get; set; }
[Name("Magnetische Rotation")]
public double MagneticRotation { get; set; }
}
}
Loading

0 comments on commit bf33bc4

Please sign in to comment.