├── Unplugged.Segy ├── icon.ico ├── icon.png ├── packages.config ├── IReadingProgress.cs ├── ITrace.cs ├── IFileHeader.cs ├── ISegyFile.cs ├── Trace.cs ├── SegyFile.cs ├── FileHeader.cs ├── TraceHeader.cs ├── FormatCode.cs ├── ITraceHeader.cs ├── Unplugged.Segy.nuspec ├── ISegyOptions.cs ├── SegyOptions.cs ├── Properties │ └── AssemblyInfo.cs ├── Unplugged.Segy.csproj ├── ImageWriter.cs └── SegyReader.cs ├── packages ├── Moq.4.0.10827 │ ├── Moq.chm │ ├── lib │ │ ├── NET35 │ │ │ ├── Moq.dll │ │ │ └── Moq.pdb │ │ ├── NET40 │ │ │ ├── Moq.dll │ │ │ └── Moq.pdb │ │ └── Silverlight4 │ │ │ ├── Castle.Core.dll │ │ │ ├── Moq.Silverlight.dll │ │ │ └── Moq.Silverlight.pdb │ ├── Moq.4.0.10827.nupkg │ └── License.txt ├── NUnit.2.6.0.12054 │ ├── license.txt │ └── lib │ │ └── nunit.framework.dll ├── TestDrivenDesign.0.0.3 │ ├── TestDrivenDesign.0.0.3.nupkg │ └── lib │ │ └── net40 │ │ ├── TestDrivenDesign.dll │ │ └── TestDrivenDesign.dll.CodeAnalysisLog.xml ├── Unplugged.IbmBits.0.0.0.3 │ └── lib │ │ ├── net40 │ │ └── Unplugged.IbmBits.dll │ │ └── monotouch │ │ └── Unplugged.IbmBits.MonoTouch.dll └── repositories.config ├── Unplugged.Segy.Tests ├── Examples │ ├── lineE.sgy │ └── bigEndianIEEEFloat.sgy ├── packages.config ├── SegyOptionsTest.cs ├── Properties │ └── AssemblyInfo.cs ├── Unplugged.Segy.Tests.csproj ├── ImageWriterTest.cs └── SegyReaderTest.cs ├── Unplugged.Segy.MonoTouch.Tests ├── Images │ ├── icon57.png │ ├── icon72.png │ ├── icon114.png │ └── icon144.png ├── Main.cs ├── Info.plist ├── AppDelegate.cs └── Unplugged.Segy.MonoTouch.Tests.csproj ├── Unplugged.Segy.NUnitTests ├── packages.config ├── Unplugged.Segy.NUnitTests.csproj └── SegyReading.cs ├── .gitignore ├── CodeAnalysisDictionary.xml ├── UnpluggedSegy.vsmdi ├── Local.testsettings ├── license.txt ├── readme.md ├── TraceAndTestImpact.testsettings ├── Unplugged.Segy.MonoTouch └── Unplugged.Segy.MonoTouch.csproj └── UnpluggedSegy.sln /Unplugged.Segy/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy/icon.ico -------------------------------------------------------------------------------- /Unplugged.Segy/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy/icon.png -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/Moq.chm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/Moq.chm -------------------------------------------------------------------------------- /packages/NUnit.2.6.0.12054/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/NUnit.2.6.0.12054/license.txt -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/Examples/lineE.sgy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.Tests/Examples/lineE.sgy -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/NET35/Moq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/NET35/Moq.dll -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/NET35/Moq.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/NET35/Moq.pdb -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/NET40/Moq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/NET40/Moq.dll -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/NET40/Moq.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/NET40/Moq.pdb -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/Moq.4.0.10827.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/Moq.4.0.10827.nupkg -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Images/icon57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.MonoTouch.Tests/Images/icon57.png -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Images/icon72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.MonoTouch.Tests/Images/icon72.png -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Images/icon114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.MonoTouch.Tests/Images/icon114.png -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Images/icon144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.MonoTouch.Tests/Images/icon144.png -------------------------------------------------------------------------------- /Unplugged.Segy/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/NUnit.2.6.0.12054/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/NUnit.2.6.0.12054/lib/nunit.framework.dll -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/Examples/bigEndianIEEEFloat.sgy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/Unplugged.Segy.Tests/Examples/bigEndianIEEEFloat.sgy -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/Silverlight4/Castle.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/Silverlight4/Castle.Core.dll -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/Silverlight4/Moq.Silverlight.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/Silverlight4/Moq.Silverlight.dll -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/lib/Silverlight4/Moq.Silverlight.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Moq.4.0.10827/lib/Silverlight4/Moq.Silverlight.pdb -------------------------------------------------------------------------------- /packages/TestDrivenDesign.0.0.3/TestDrivenDesign.0.0.3.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/TestDrivenDesign.0.0.3/TestDrivenDesign.0.0.3.nupkg -------------------------------------------------------------------------------- /packages/TestDrivenDesign.0.0.3/lib/net40/TestDrivenDesign.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/TestDrivenDesign.0.0.3/lib/net40/TestDrivenDesign.dll -------------------------------------------------------------------------------- /Unplugged.Segy.NUnitTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/Unplugged.IbmBits.0.0.0.3/lib/net40/Unplugged.IbmBits.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Unplugged.IbmBits.0.0.0.3/lib/net40/Unplugged.IbmBits.dll -------------------------------------------------------------------------------- /packages/Unplugged.IbmBits.0.0.0.3/lib/monotouch/Unplugged.IbmBits.MonoTouch.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfoshee/UnpluggedSegy/HEAD/packages/Unplugged.IbmBits.0.0.0.3/lib/monotouch/Unplugged.IbmBits.MonoTouch.dll -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj 2 | [Bb]in 3 | TestResults 4 | *.user 5 | *.suo 6 | *.[Cc]ache 7 | *.bak 8 | *.ncb 9 | *.log 10 | *.DS_Store 11 | [Tt]humbs.db 12 | _ReSharper.* 13 | *.resharper 14 | Ankh.NoLoad 15 | *.docstates 16 | *.nupkg 17 | -------------------------------------------------------------------------------- /Unplugged.Segy/IReadingProgress.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public interface IReadingProgress 5 | { 6 | void ReportProgress(int progressPercentage); 7 | bool CancellationPending { get; } 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Unplugged.Segy/ITrace.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Unplugged.Segy 4 | { 5 | public interface ITrace 6 | { 7 | ITraceHeader Header { get; } 8 | IList Values { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Unplugged.Segy/IFileHeader.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public interface IFileHeader 5 | { 6 | string Text { get; } 7 | FormatCode SampleFormat { get; } 8 | bool IsLittleEndian { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Unplugged.Segy/ISegyFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Unplugged.Segy 4 | { 5 | public interface ISegyFile 6 | { 7 | IFileHeader Header { get; } 8 | IList Traces { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Unplugged.Segy/Trace.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Unplugged.Segy 4 | { 5 | class Trace : ITrace 6 | { 7 | public ITraceHeader Header { get; set; } 8 | public IList Values { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Unplugged.Segy/SegyFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Unplugged.Segy 4 | { 5 | class SegyFile : ISegyFile 6 | { 7 | public IFileHeader Header { get; set; } 8 | public IList Traces { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CodeAnalysisDictionary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bpp 6 | Rgba 7 | crossline 8 | segy 9 | 10 | 11 | -------------------------------------------------------------------------------- /Unplugged.Segy/FileHeader.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | class FileHeader : IFileHeader 5 | { 6 | public string Text { get; set; } 7 | public FormatCode SampleFormat { get; set; } 8 | public bool IsLittleEndian { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Unplugged.Segy/TraceHeader.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | class TraceHeader : ITraceHeader 5 | { 6 | public int SampleCount { get; set; } 7 | public int TraceNumber { get; set; } 8 | public int InlineNumber { get; set; } 9 | public int CrosslineNumber { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Unplugged.Segy/FormatCode.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public enum FormatCode 5 | { 6 | None, 7 | IbmFloatingPoint4, 8 | TwosComplementInteger4, 9 | TwosComplementInteger2, 10 | FixedPointWithGain4, 11 | IeeeFloatingPoint4, 12 | Unused1, 13 | Unused2, 14 | TwosComplementInteger1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Unplugged.Segy/ITraceHeader.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public interface ITraceHeader 5 | { 6 | int SampleCount { get; } 7 | int TraceNumber { get; } 8 | int InlineNumber { get; } 9 | int CrosslineNumber { get; } 10 | //int SampleIntervalInMicroseconds { get; } 11 | //int X { get; } 12 | //int Y { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UnpluggedSegy.vsmdi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using MonoTouch.Foundation; 6 | using MonoTouch.UIKit; 7 | 8 | namespace Unplugged.Segy.MonoTouch.Tests 9 | { 10 | public class Application 11 | { 12 | // This is the main entry point of the application. 13 | static void Main (string[] args) 14 | { 15 | // if you want to use a different Application Delegate class from "AppDelegate" 16 | // you can specify it here. 17 | UIApplication.Main (args, null, "AppDelegate"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Unplugged.Segy/Unplugged.Segy.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | http://segy.net 10 | https://github.com/jfoshee/UnpluggedSegy/raw/ce8bb8c0182852423afdd1fa254f5de13efbe5c3/Unplugged.Segy/icon.png 11 | false 12 | $description$ 13 | Copyright Unplugged Development 2012 14 | SEG-Y, SEGY, SGY, Seismic, IBM 15 | 16 | -------------------------------------------------------------------------------- /Unplugged.Segy/ISegyOptions.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public interface ISegyOptions 5 | { 6 | bool? IsEbcdic { get; } 7 | //bool? IsLittleEndian { get; } 8 | 9 | int TextHeaderColumnCount { get; } 10 | int TextHeaderRowCount { get; } 11 | bool TextHeaderInsertNewLines { get; } 12 | 13 | //int BinaryHeaderLength { get; } 14 | //int BinaryHeaderLocationForSampleFormat { get; } 15 | 16 | //int TraceHeaderLength { get; } 17 | //int TraceHeaderLocationForInlineNumber { get; } 18 | //int TraceHeaderLocationForCrosslineNumber { get; } 19 | //int TraceHeaderLocationForSampleCount { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Local.testsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | These are default test settings for a local test run. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | SEGY Tests 7 | CFBundleIconFiles 8 | 9 | Images/icon57.png 10 | Images/icon114.png 11 | Images/icon72.png 12 | Images/icon144.png 13 | 14 | UIDeviceFamily 15 | 16 | 1 17 | 2 18 | 19 | UISupportedInterfaceOrientations 20 | 21 | UIInterfaceOrientationPortrait 22 | UIInterfaceOrientationPortraitUpsideDown 23 | UIInterfaceOrientationLandscapeLeft 24 | UIInterfaceOrientationLandscapeRight 25 | 26 | UISupportedInterfaceOrientations~ipad 27 | 28 | UIInterfaceOrientationPortrait 29 | UIInterfaceOrientationPortraitUpsideDown 30 | UIInterfaceOrientationLandscapeLeft 31 | UIInterfaceOrientationLandscapeRight 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Unplugged.Segy is free software distributed under the terms of the 2 | MIT License reproduced below. 3 | 4 | Unplugged.Segy 5 | http://segy.net 6 | Copyright (c) 2011 - 2015 Unplugged Development, Jacob Foshee 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /Unplugged.Segy/SegyOptions.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Unplugged.Segy 3 | { 4 | public class SegyOptions : ISegyOptions 5 | { 6 | public bool? IsEbcdic { get; set; } 7 | //public bool? IsLittleEndian { get; set; } 8 | 9 | public int TextHeaderColumnCount { get; set; } 10 | public int TextHeaderRowCount { get; set; } 11 | public bool TextHeaderInsertNewLines { get; set; } 12 | 13 | //public int BinaryHeaderLength { get; set; } 14 | //public int BinaryHeaderLocationForSampleFormat { get; set; } 15 | 16 | //public int TraceHeaderLength { get; set; } 17 | //public int TraceHeaderLocationForInlineNumber { get; set; } 18 | //public int TraceHeaderLocationForCrosslineNumber { get; set; } 19 | //public int TraceHeaderLocationForSampleCount { get; set; } 20 | 21 | public SegyOptions() 22 | { 23 | IsEbcdic = true; 24 | //IsLittleEndian = false; 25 | TextHeaderColumnCount = 80; 26 | TextHeaderRowCount = 40; 27 | TextHeaderInsertNewLines = true; 28 | //BinaryHeaderLength = 400; 29 | //BinaryHeaderLocationForSampleFormat = 25; 30 | //TraceHeaderLength = 240; 31 | //TraceHeaderLocationForSampleCount = 115; 32 | //TraceHeaderLocationForInlineNumber = 189; 33 | //TraceHeaderLocationForCrosslineNumber = 193; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/SegyOptionsTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using TestDrivenDesign; 3 | 4 | namespace Unplugged.Segy.Tests 5 | { 6 | [TestClass] 7 | public class SegyOptionsTest : TestBase 8 | { 9 | [TestMethod] 10 | public void ImplementsInterface() 11 | { 12 | Assert.IsInstanceOfType(Subject, typeof(ISegyOptions)); 13 | } 14 | 15 | [TestMethod] 16 | public void DefaultValues() 17 | { 18 | Assert.AreEqual(true, Subject.IsEbcdic); 19 | //Assert.AreEqual(false, Subject.IsLittleEndian); 20 | 21 | Assert.AreEqual(80, Subject.TextHeaderColumnCount); 22 | Assert.AreEqual(40, Subject.TextHeaderRowCount); 23 | Assert.AreEqual(true, Subject.TextHeaderInsertNewLines); 24 | 25 | //Assert.AreEqual(400, Subject.BinaryHeaderLength); 26 | //Assert.AreEqual(25, Subject.BinaryHeaderLocationForSampleFormat); 27 | 28 | //Assert.AreEqual(240, Subject.TraceHeaderLength); 29 | //Assert.AreEqual(115, Subject.TraceHeaderLocationForSampleCount); 30 | //Assert.AreEqual(189, Subject.TraceHeaderLocationForInlineNumber, "According to SEGY Rev 1, byte 189 - 192 in the trace header should be used for the in-line number"); 31 | //Assert.AreEqual(193, Subject.TraceHeaderLocationForCrosslineNumber, "According to SEGY Rev 1, byte 193 - 196 in the trace header should be used for the cross-line number"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Unplugged.Segy.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Unplugged Development")] 12 | [assembly: AssemblyProduct("Unplugged.Segy.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © Unplugged Development 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5aeeaf75-62ca-4ecf-9b2c-d71aa0d87c3d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using MonoTouch.Foundation; 6 | using MonoTouch.UIKit; 7 | using MonoTouch.NUnit.UI; 8 | 9 | namespace Unplugged.Segy.MonoTouch.Tests 10 | { 11 | // The UIApplicationDelegate for the application. This class is responsible for launching the 12 | // User Interface of the application, as well as listening (and optionally responding) to 13 | // application events from iOS. 14 | [Register ("AppDelegate")] 15 | public partial class AppDelegate : UIApplicationDelegate 16 | { 17 | // class-level declarations 18 | UIWindow window; 19 | TouchRunner runner; 20 | 21 | // 22 | // This method is invoked when the application has loaded and is ready to run. In this 23 | // method you should instantiate the window, load the UI into it and then make the window 24 | // visible. 25 | // 26 | // You have 17 seconds to return from this method, or iOS will terminate your application. 27 | // 28 | public override bool FinishedLaunching (UIApplication app, NSDictionary options) 29 | { 30 | // create a new window instance based on the screen size 31 | window = new UIWindow (UIScreen.MainScreen.Bounds); 32 | runner = new TouchRunner (window); 33 | 34 | // register every tests included in the main application/assembly 35 | runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); 36 | 37 | window.RootViewController = new UINavigationController (runner.GetViewController ()); 38 | 39 | // make the window visible 40 | window.MakeKeyAndVisible (); 41 | 42 | return true; 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Unplugged.Segy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Unplugged.Segy")] 9 | [assembly: AssemblyDescription("Supports reading of seismic images stored in SEG-Y format")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Unplugged Development")] 12 | [assembly: AssemblyProduct("Unplugged.Segy")] 13 | [assembly: AssemblyCopyright("Copyright © Unplugged Development 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6cec6899-288e-4a02-9d1b-3df1d87fa359")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.6.1")] 36 | [assembly: AssemblyFileVersion("0.6.1")] 37 | [assembly: CLSCompliant(true)] -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # SEG-Y Reading Library in C# # 2 | 3 | SEG-Y is a file format for seismic image data. It is also known as SEGY or SGY. 4 | 5 | Issues and sample data welcome. 6 | 7 | ### Example 8 | 9 | ```C# 10 | using System; 11 | using Unplugged.Segy; 12 | ``` 13 | 14 | ```C# 15 | var reader = new SegyReader(); 16 | ISegyFile line = reader.Read(@"RMOTC Seismic data set\2D_Seismic\NormalizedMigrated_segy\lineA.sgy"); 17 | ITrace trace = line.Traces[0]; 18 | double mean = 0; 19 | double max = double.MinValue; 20 | double min = double.MaxValue; 21 | foreach (var sampleValue in trace.Values) 22 | { 23 | mean += sampleValue / trace.Values.Count; 24 | if (sampleValue < min) min = sampleValue; 25 | if (sampleValue > max) max = sampleValue; 26 | } 27 | Console.WriteLine(min); 28 | Console.WriteLine(max); 29 | Console.WriteLine(mean); 30 | ``` 31 | 32 | ### Supported Sample Formats 33 | - IBM Floating Point 4 (Big Endian) 34 | - IEEE Floating Point 4 (Little Endian) 35 | - Two's Complement Integer 4 (Big and Little Endian) 36 | - Two's Complement Integer 2 (Big and Little Endian) 37 | - Two's Complement Integer 1 38 | 39 | ### Current Known Limitations 40 | - Assumed to be built on Little Endian architecture 41 | - Sample Format not supported: Fixed Point With Gain 4 42 | - Extended Text Headers are not supported 43 | - Writing SEGY files is not supported 44 | 45 | If you have example files of unsupported formats or feature requests, they would be appreciated! Please, send to 46 | 47 | ### Acknowledgements 48 | 49 | Example data is courtesy of the [Rocky Mountian Oilfield Testing Center](http://www.rmotc.doe.gov/) and the U.S. Department of Energy 50 | 51 | Resources on the SEG-Y format: 52 | 53 | - http://walter.kessinger.com/work/segy.html 54 | - http://en.wikipedia.org/wiki/SEG_Y 55 | - http://www.seg.org/documents/10161/77915/seg_y_rev1.pdf 56 | -------------------------------------------------------------------------------- /packages/Moq.4.0.10827/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007. Clarius Consulting, Manas Technology Solutions, InSTEDD 2 | http://code.google.com/p/moq/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, 6 | with or without modification, are permitted provided 7 | that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the 10 | above copyright notice, this list of conditions and 11 | the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce 14 | the above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of Clarius Consulting, Manas Technology Solutions or InSTEDD nor the 19 | names of its contributors may be used to endorse 20 | or promote products derived from this software 21 | without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 24 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 28 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 | SUCH DAMAGE. 37 | 38 | [This is the BSD license, see 39 | http://www.opensource.org/licenses/bsd-license.php] -------------------------------------------------------------------------------- /TraceAndTestImpact.testsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | These are test settings for Trace and Test Impact. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Unplugged.Segy.NUnitTests/Unplugged.Segy.NUnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.0 7 | 2.0 8 | {5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4} 9 | Library 10 | Unplugged.Segy.NUnitTests 11 | Unplugged.Segy.NUnitTests 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug 18 | DEBUG; 19 | prompt 20 | 4 21 | false 22 | 23 | 24 | none 25 | false 26 | bin\Release 27 | prompt 28 | 4 29 | false 30 | 31 | 32 | 33 | ..\packages\NUnit.2.6.0.12054\lib\nunit.framework.dll 34 | 35 | 36 | 37 | 38 | 39 | 40 | {096016A3-C38E-41C0-9853-4C4AF2DF8782} 41 | Unplugged.Segy 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Examples\lineE.sgy 51 | PreserveNewest 52 | 53 | 54 | 55 | Examples\bigEndianIEEEFloat.sgy 56 | PreserveNewest 57 | 58 | 59 | -------------------------------------------------------------------------------- /Unplugged.Segy.NUnitTests/SegyReading.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using NUnit.Framework; 4 | 5 | namespace Unplugged.Segy.MonoTouch.Tests 6 | { 7 | [TestFixture] 8 | public class SegyReading 9 | { 10 | [Test] 11 | public void ShouldReadSegyFile() 12 | { 13 | var subject = new SegyReader(); 14 | var segy = subject.Read(@"./Examples/lineE.sgy"); 15 | Console.WriteLine(segy.Header.Text); 16 | Assert.That(segy.Traces.Count, Is.EqualTo(111)); 17 | } 18 | 19 | [Test] 20 | public void ShouldReadBigEndianIEEEFloatingPoint() 21 | { 22 | var subject = new SegyReader(); 23 | var segy = subject.Read(@"./Examples/bigEndianIEEEFloat.sgy"); 24 | Console.WriteLine(segy.Header.Text); 25 | Assert.That(segy.Traces.Count, Is.EqualTo(120)); 26 | Assert.That(segy.Traces[0].Values[0], Is.EqualTo(0)); 27 | Assert.That(segy.Traces[60].Values[159], Is.EqualTo(0.896f).Within(0.001f)); 28 | Assert.That(segy.Traces[60].Values[160], Is.EqualTo(1.000f).Within(0.001f)); 29 | Assert.That(segy.Traces[60].Values[161], Is.EqualTo(0.896f).Within(0.001f)); 30 | } 31 | 32 | [Test] 33 | public void ShouldGetImageBytes() 34 | { 35 | var reader = new SegyReader(); 36 | var segy = reader.Read(@"./Examples/lineE.sgy"); 37 | var imageWriter = new ImageWriter(); 38 | var bytes = imageWriter.GetRaw32BppRgba(segy.Traces); 39 | var expected = 4 * segy.Traces.Count * segy.Traces[0].Values.Count; 40 | Assert.That(bytes.Length, Is.EqualTo(expected)); 41 | } 42 | 43 | [Test] 44 | public void ShouldReturnEmptyArrayForNoTraces() 45 | { 46 | var bytes = new ImageWriter().GetRaw32BppRgba(new ITrace[]{}); 47 | Assert.That(bytes.Length, Is.EqualTo(0)); 48 | } 49 | 50 | class TestProgressReporter : IReadingProgress 51 | { 52 | public void ReportProgress (int progressPercentage) 53 | { 54 | ProgressReported.Add(progressPercentage); 55 | } 56 | 57 | public bool CancellationPending { get; set; } 58 | public List ProgressReported { get; private set; } 59 | 60 | public TestProgressReporter () 61 | { 62 | ProgressReported = new List(); 63 | } 64 | } 65 | 66 | [Test] 67 | public void ShouldReportProgress() 68 | { 69 | var subject = new SegyReader(); 70 | var testProgressReporter = new TestProgressReporter(); 71 | 72 | subject.Read(@"./Examples/lineE.sgy", testProgressReporter); 73 | 74 | // Assert that message received for each percentage 0 to 100 75 | // (The example has more than 100 traces, so this is reasonable) 76 | var p = testProgressReporter.ProgressReported; 77 | for (int i = 0; i < 101; i++) 78 | Assert.That(p.Contains(i), i.ToString()); 79 | } 80 | 81 | class CancelsAtThirty : IReadingProgress 82 | { 83 | public void ReportProgress (int progressPercentage) 84 | { 85 | if (progressPercentage == 30) 86 | CancellationPending = true; 87 | if (progressPercentage > 30) 88 | Assert.Fail("Should not proceed past 30%"); 89 | } 90 | public bool CancellationPending { get; set; } 91 | } 92 | 93 | [Test] 94 | public void ShouldStopReadingWhenCancellationPending() 95 | { 96 | var subject = new SegyReader(); 97 | var segy = subject.Read(@"./Examples/lineE.sgy", new CancelsAtThirty()); 98 | var expected = (int)(.3 * 111); 99 | Assert.That(segy.Traces.Count, Is.EqualTo(expected)); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Unplugged.Segy/Unplugged.Segy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {096016A3-C38E-41C0-9853-4C4AF2DF8782} 9 | Library 10 | Properties 11 | Unplugged.Segy 12 | Unplugged.Segy 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | ExtendedDesignGuidelineRules.ruleset 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | ExtendedDesignGuidelineRules.ruleset 33 | 34 | 35 | icon.ico 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ..\packages\Unplugged.IbmBits.0.0.0.3\lib\net40\Unplugged.IbmBits.dll 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Designer 71 | 72 | 73 | 74 | 75 | Properties\CodeAnalysisDictionary.xml 76 | 77 | 78 | 79 | 80 | 81 | 82 | 89 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/Unplugged.Segy.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {7BE2D039-A482-4792-BBB8-90F68C5B0F57} 10 | Library 11 | Properties 12 | Unplugged.Segy.Tests 13 | Unplugged.Segy.Tests 14 | v4.0 15 | 512 16 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll 39 | 40 | 41 | 42 | 3.5 43 | 44 | 45 | 46 | ..\packages\TestDrivenDesign.0.0.3\lib\net40\TestDrivenDesign.dll 47 | 48 | 49 | False 50 | ..\packages\Unplugged.IbmBits.0.0.0.3\lib\net40\Unplugged.IbmBits.dll 51 | 52 | 53 | 54 | 55 | False 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {096016A3-C38E-41C0-9853-4C4AF2DF8782} 71 | Unplugged.Segy 72 | 73 | 74 | 75 | 82 | -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch/Unplugged.Segy.MonoTouch.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.0 7 | 2.0 8 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF} 9 | {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Library 11 | Unplugged.Segy.MonoTouch 12 | Unplugged.Segy.MonoTouch 13 | 14 | 15 | true 16 | full 17 | false 18 | bin\Debug 19 | DEBUG;MONO_TOUCH 20 | prompt 21 | 4 22 | false 23 | 24 | 25 | none 26 | false 27 | bin\Release 28 | prompt 29 | 4 30 | false 31 | MONO_TOUCH 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | ..\packages\Unplugged.IbmBits.0.0.0.3\lib\monotouch\Unplugged.IbmBits.MonoTouch.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Unplugged.Segy\FileHeader.cs 49 | 50 | 51 | Unplugged.Segy\FormatCode.cs 52 | 53 | 54 | Unplugged.Segy\IFileHeader.cs 55 | 56 | 57 | Unplugged.Segy\ISegyFile.cs 58 | 59 | 60 | Unplugged.Segy\ISegyOptions.cs 61 | 62 | 63 | Unplugged.Segy\ITrace.cs 64 | 65 | 66 | Unplugged.Segy\ITraceHeader.cs 67 | 68 | 69 | Unplugged.Segy\SegyFile.cs 70 | 71 | 72 | Unplugged.Segy\SegyOptions.cs 73 | 74 | 75 | Unplugged.Segy\SegyReader.cs 76 | 77 | 78 | Unplugged.Segy\Trace.cs 79 | 80 | 81 | Unplugged.Segy\TraceHeader.cs 82 | 83 | 84 | Unplugged.Segy\ImageWriter.cs 85 | 86 | 87 | Unplugged.Segy\IReadingProgress.cs 88 | 89 | 90 | -------------------------------------------------------------------------------- /Unplugged.Segy.MonoTouch.Tests/Unplugged.Segy.MonoTouch.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | iPhoneSimulator 6 | 10.0.0 7 | 2.0 8 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5} 9 | {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Exe 11 | Unplugged.Segy.MonoTouch.Tests 12 | UnpluggedSegyMonoTouchTests 13 | 14 | 15 | true 16 | full 17 | false 18 | bin\iPhoneSimulator\Debug 19 | DEBUG; 20 | prompt 21 | 4 22 | false 23 | true 24 | true 25 | None 26 | rare 27 | 28 | 29 | none 30 | false 31 | bin\iPhoneSimulator\Release 32 | prompt 33 | 4 34 | false 35 | None 36 | rare 37 | 38 | 39 | true 40 | full 41 | false 42 | bin\iPhone\Debug 43 | DEBUG; 44 | prompt 45 | 4 46 | false 47 | iPhone Developer 48 | true 49 | true 50 | 51 | rare 52 | 53 | 54 | none 55 | false 56 | bin\iPhone\Release 57 | prompt 58 | 4 59 | false 60 | iPhone Developer 61 | rare 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | SegyReading.cs 78 | 79 | 80 | 81 | 82 | 83 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF} 84 | Unplugged.Segy.MonoTouch 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | Examples\lineE.sgy 94 | 95 | 96 | 97 | 98 | 99 | 100 | Examples\bigEndianIEEEFloat.sgy 101 | 102 | 103 | -------------------------------------------------------------------------------- /UnpluggedSegy.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unplugged.Segy.Tests", "Unplugged.Segy.Tests\Unplugged.Segy.Tests.csproj", "{7BE2D039-A482-4792-BBB8-90F68C5B0F57}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{11DD3C5B-FC93-42FB-8065-3ACE2DDFCADB}" 7 | ProjectSection(SolutionItems) = preProject 8 | CodeAnalysisDictionary.xml = CodeAnalysisDictionary.xml 9 | Local.testsettings = Local.testsettings 10 | readme.md = readme.md 11 | TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings 12 | UnpluggedSegy.vsmdi = UnpluggedSegy.vsmdi 13 | EndProjectSection 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unplugged.Segy", "Unplugged.Segy\Unplugged.Segy.csproj", "{096016A3-C38E-41C0-9853-4C4AF2DF8782}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unplugged.Segy.MonoTouch", "Unplugged.Segy.MonoTouch\Unplugged.Segy.MonoTouch.csproj", "{4FE7CCB7-A96F-41E7-849E-C6236043BEEF}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unplugged.Segy.NUnitTests", "Unplugged.Segy.NUnitTests\Unplugged.Segy.NUnitTests.csproj", "{5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unplugged.Segy.MonoTouch.Tests", "Unplugged.Segy.MonoTouch.Tests\Unplugged.Segy.MonoTouch.Tests.csproj", "{884678D1-863C-45C1-BAB1-85BF75E2B3A5}" 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Release|Any CPU = Release|Any CPU 27 | Debug|iPhoneSimulator = Debug|iPhoneSimulator 28 | Release|iPhoneSimulator = Release|iPhoneSimulator 29 | Debug|iPhone = Debug|iPhone 30 | Release|iPhone = Release|iPhone 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {096016A3-C38E-41C0-9853-4C4AF2DF8782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {096016A3-C38E-41C0-9853-4C4AF2DF8782}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {096016A3-C38E-41C0-9853-4C4AF2DF8782}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {096016A3-C38E-41C0-9853-4C4AF2DF8782}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {4FE7CCB7-A96F-41E7-849E-C6236043BEEF}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {5FB4FF59-8350-4596-B3D0-0EF11FA6BCD4}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {7BE2D039-A482-4792-BBB8-90F68C5B0F57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 46 | {7BE2D039-A482-4792-BBB8-90F68C5B0F57}.Debug|Any CPU.Build.0 = Debug|Any CPU 47 | {7BE2D039-A482-4792-BBB8-90F68C5B0F57}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {7BE2D039-A482-4792-BBB8-90F68C5B0F57}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator 50 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator 51 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|iPhone.ActiveCfg = Debug|iPhone 52 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|iPhone.Build.0 = Debug|iPhone 53 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator 54 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator 55 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator 56 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|Any CPU.Build.0 = Release|iPhoneSimulator 57 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|iPhone.ActiveCfg = Release|iPhone 58 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|iPhone.Build.0 = Release|iPhone 59 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator 60 | {884678D1-863C-45C1-BAB1-85BF75E2B3A5}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator 61 | EndGlobalSection 62 | GlobalSection(NestedProjects) = preSolution 63 | EndGlobalSection 64 | GlobalSection(MonoDevelopProperties) = preSolution 65 | StartupItem = Unplugged.Segy.MonoTouch.Tests\Unplugged.Segy.MonoTouch.Tests.csproj 66 | EndGlobalSection 67 | GlobalSection(TestCaseManagementSettings) = postSolution 68 | CategoryFile = UnpluggedSegy.vsmdi 69 | EndGlobalSection 70 | GlobalSection(SolutionProperties) = preSolution 71 | HideSolutionNode = FALSE 72 | EndGlobalSection 73 | EndGlobal 74 | -------------------------------------------------------------------------------- /Unplugged.Segy/ImageWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | #if !MONO_TOUCH 8 | using System.Drawing.Imaging; 9 | #endif 10 | 11 | namespace Unplugged.Segy 12 | { 13 | /// 14 | /// Responsible for converting SEGY data to a bitmap image 15 | /// 16 | public class ImageWriter 17 | { 18 | /// 19 | /// When true, sample values that are exactly 0.0f will have their alpha component set to 0. 20 | /// Defaults to true. 21 | /// 22 | public bool SetNullValuesToTransparent { get; set; } 23 | 24 | public ImageWriter() 25 | { 26 | SetNullValuesToTransparent = false; 27 | } 28 | 29 | #if !MONO_TOUCH 30 | 31 | /// 32 | /// Writes one or more bitmap for the given SEGY file. 33 | /// If the SEGY has multiple inline numbers, it is assumed to be 3D, and one bitmap is written for each inline. 34 | /// 35 | /// 36 | /// The destination path for the image. 37 | /// If multiple images are written, each inline number is added parenthetically to the file name. 38 | /// 39 | public virtual void Write(ISegyFile segyFile, string path) 40 | { 41 | if (segyFile.Traces == null) 42 | { 43 | using (var bitmap = new Bitmap(1, 1)) 44 | bitmap.Save(path); 45 | return; 46 | } 47 | var inlineNumbers = GetInlineNumbers(segyFile); 48 | if (inlineNumbers.Count() == 1) 49 | Write(segyFile.Traces, path); 50 | else 51 | { 52 | dynamic range = FindRange(segyFile.Traces); 53 | WriteBitmapPerInline(segyFile, path, inlineNumbers, range); 54 | } 55 | } 56 | 57 | /// 58 | /// Writes a bitmap image with the given traces to the given destination path. 59 | /// 60 | public virtual void Write(IEnumerable traces, string path) 61 | { 62 | using (var bitmap = GetBitmap(traces)) 63 | bitmap.Save(path); 64 | } 65 | 66 | /// 67 | /// Returns a single bitmap image composed from all the trace in the SEGY file. 68 | /// The caller is responsible for disposing of the bitmap. This is highy recommended 69 | /// so that GDI resources will be cleaned up. 70 | /// 71 | /// A disposable bitmap 72 | public virtual Bitmap GetBitmap(ISegyFile segyFile) 73 | { 74 | return GetBitmap(segyFile.Traces); 75 | } 76 | 77 | /// 78 | /// Returns a single bitmap image composed from the given traces. 79 | /// The caller is responsible for disposing of the bitmap. This is highy recommended 80 | /// so that GDI resources will be cleaned up. 81 | /// 82 | /// A disposable bitmap 83 | public virtual Bitmap GetBitmap(IEnumerable traces) 84 | { 85 | dynamic range = FindRange(traces); 86 | return GetBitmap(traces, range); 87 | } 88 | #endif 89 | 90 | /// 91 | /// Returns a bitmap as a one-dimensional byte array. Pixels are layed out as R, G, B, A with one byte per channel. 92 | /// 93 | public virtual byte[] GetRaw32BppRgba(IEnumerable traces) 94 | { 95 | return GetRaw(traces, 4); 96 | } 97 | 98 | /// 99 | /// Returns a bitmap as a one-dimensional byte array. The pixel format is 1 unsigned byte per pixel. 100 | /// Thus, the seismic data is quantized to the range 0...255. 101 | /// 102 | public virtual byte[] GetRaw8Bpp(IEnumerable traces) 103 | { 104 | return GetRaw(traces, 1); 105 | } 106 | 107 | #region Behind the Scenes 108 | 109 | private class ValueRange 110 | { 111 | public float Min { get; set; } 112 | public float Max { get; set; } 113 | public float Delta { get; set; } 114 | } 115 | 116 | private class RawBitmap 117 | { 118 | public int Width { get; set; } 119 | public int Height { get; set; } 120 | public byte[] Bytes { get; set; } 121 | } 122 | 123 | // O(N) 124 | private static ValueRange FindRange(IEnumerable traces) 125 | { 126 | var min = float.MaxValue; 127 | var max = float.MinValue; 128 | foreach (var trace in traces) 129 | foreach (var value in trace.Values) 130 | { 131 | if (value < min) min = value; 132 | if (value > max) max = value; 133 | } 134 | return new ValueRange { Min = min, Max = max, Delta = max - min }; 135 | } 136 | 137 | private byte[] GetRaw(IEnumerable traces, int components) 138 | { 139 | var range = FindRange(traces); 140 | return GetRawBytesAndSize(traces, range, components).Bytes; 141 | } 142 | 143 | // O(N) 144 | private RawBitmap GetRawBytesAndSize(IEnumerable traces, ValueRange range, int components) 145 | { 146 | var traceList = traces.ToList(); 147 | int width = traceList.Count; 148 | if (width == 0) 149 | return new RawBitmap { Bytes = new byte[] { }, Width = 0, Height = 0 }; 150 | int height = traceList.First().Values.Count; 151 | var length = components * width * height; 152 | var bytes = new byte[length]; 153 | for (int i = 0; i < width; i++) 154 | for (int j = 0; j < height; j++) 155 | { 156 | var index = components * (j * width + i); 157 | SetColor(bytes, index, range.Min, range.Delta, traceList[i].Values[j], components); 158 | } 159 | return new RawBitmap { Bytes = bytes, Width = width, Height = height }; 160 | } 161 | 162 | #if !MONO_TOUCH 163 | 164 | private void WriteBitmapPerInline(ISegyFile segyFile, string path, IEnumerable inlineNumbers, ValueRange range) 165 | { 166 | foreach (var inline in inlineNumbers) 167 | { 168 | var traces = segyFile.Traces.Where(t => t.Header.InlineNumber == inline); 169 | var filename = Path.GetFileNameWithoutExtension(path); 170 | var extenstion = Path.GetExtension(path); 171 | var newPath = filename + " (" + inline + ")" + extenstion; 172 | WriteBitmapForTraces(traces, newPath, range); 173 | } 174 | } 175 | 176 | private void WriteBitmapForTraces(IEnumerable traces, string path, ValueRange range) 177 | { 178 | using (var bitmap = GetBitmap(traces, range)) 179 | bitmap.Save(path); 180 | } 181 | 182 | private Bitmap GetBitmap(IEnumerable traces, dynamic range) 183 | { 184 | dynamic raw = GetRawBytesAndSize(traces, range, 4); 185 | return GetBitmap(raw.Bytes, raw.Width, raw.Height); 186 | } 187 | 188 | private static Bitmap GetBitmap(byte[] bytes, int width, int height) 189 | { 190 | var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 191 | var bitmapData = bitmap.LockBits(Rectangle.FromLTRB(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat); 192 | Marshal.Copy(bytes, 0, bitmapData.Scan0, bytes.Length); 193 | bitmap.UnlockBits(bitmapData); 194 | return bitmap; 195 | } 196 | 197 | #endif 198 | 199 | private void SetColor(byte[] bytes, int offset, float valueMin, float valueRange, float value, int components) 200 | { 201 | var alpha = byte.MaxValue; 202 | if (SetNullValuesToTransparent && value == 0.0f) // Exactly zero is assumed to be a null sample 203 | alpha = byte.MinValue; 204 | var byteValue = (byte)(byte.MaxValue * (value - valueMin) / valueRange); 205 | if (components == 1) 206 | bytes[offset + 0] = byteValue; 207 | else if (components == 4) 208 | { 209 | bytes[offset + 0] = byteValue; 210 | bytes[offset + 1] = byteValue; 211 | bytes[offset + 2] = byteValue; 212 | bytes[offset + 3] = alpha; 213 | } 214 | else 215 | throw new ArgumentException("Unsupported option", "components"); 216 | } 217 | 218 | private static IEnumerable GetInlineNumbers(ISegyFile segyFile) 219 | { 220 | return segyFile.Traces.Select(t => 221 | { 222 | if (t.Header == null) 223 | return 0; 224 | return t.Header.InlineNumber; 225 | } 226 | ).Distinct(); 227 | } 228 | 229 | #endregion 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /Unplugged.Segy/SegyReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using Unplugged.IbmBits; 7 | 8 | namespace Unplugged.Segy 9 | { 10 | /// 11 | /// Responsible for reading SEGY files given a path or a Stream. 12 | /// 13 | public class SegyReader 14 | { 15 | public ISegyOptions Options { get; set; } 16 | public int InlineNumberLocation { get; set; } 17 | public int CrosslineNumberLocation { get; set; } 18 | 19 | public SegyReader() 20 | { 21 | Options = new SegyOptions(); 22 | InlineNumberLocation = 189; 23 | CrosslineNumberLocation = 193; 24 | } 25 | 26 | #region From the Top: Methods that start reading from the beginning of the file 27 | 28 | /// 29 | /// Given a file path, reads entire SEGY file into memory 30 | /// 31 | public virtual ISegyFile Read(string path, IReadingProgress progress = null) 32 | { 33 | using (var stream = File.OpenRead(path)) 34 | return Read(stream, progress); 35 | } 36 | 37 | /// 38 | /// Given stream, reads entire SEGY file into memory. 39 | /// Assumes the stream is at the start of the file. 40 | /// 41 | public virtual ISegyFile Read(Stream stream, IReadingProgress progress = null) 42 | { 43 | return Read(stream, int.MaxValue, progress); 44 | } 45 | 46 | /// 47 | /// Given stream and traceCount, reads the requested number 48 | /// of traces into memory. The given traceCount may exceed 49 | /// the number of traces in the file; 50 | /// in that case all the traces in the file are read. 51 | /// Assumes the stream is at the start of the file. 52 | /// 53 | public virtual ISegyFile Read(Stream stream, int traceCount, IReadingProgress progress = null) 54 | { 55 | using (var reader = new BinaryReader(stream)) 56 | { 57 | var fileHeader = ReadFileHeader(reader); 58 | var traces = new List(); 59 | for (int i = 0; i < traceCount; i++) 60 | { 61 | if (progress != null) 62 | { 63 | // TODO: Check if stream.Length breaks when streaming from web 64 | int percentage = (int)(100 * stream.Position / stream.Length); 65 | progress.ReportProgress(percentage); 66 | if (progress.CancellationPending) 67 | break; 68 | } 69 | var trace = ReadTrace(reader, fileHeader.SampleFormat, fileHeader.IsLittleEndian); 70 | if (trace == null) 71 | break; 72 | traces.Add(trace); 73 | } 74 | return new SegyFile { Header = fileHeader, Traces = traces }; 75 | } 76 | } 77 | 78 | /// 79 | /// Given a BinaryReader, reads the SEGY File Header into memory. 80 | /// Asummes the BinaryReader is at the start of the file. 81 | /// 82 | public virtual IFileHeader ReadFileHeader(BinaryReader reader) 83 | { 84 | var text = ReadTextHeader(reader); 85 | FileHeader header = ReadBinaryHeader(reader) as FileHeader; 86 | header.Text = text; 87 | return header; 88 | } 89 | 90 | /// 91 | /// Given a file path reads the text header from the beginning 92 | /// of the SEGY file. 93 | /// 94 | public virtual string ReadTextHeader(string path) 95 | { 96 | using (var stream = File.OpenRead(path)) 97 | return ReadTextHeader(stream); 98 | } 99 | 100 | /// 101 | /// Given a stream reads the text header. 102 | /// Assumes the stream is at the start of the file. 103 | /// 104 | public virtual string ReadTextHeader(Stream stream) 105 | { 106 | using (var reader = new BinaryReader(stream)) 107 | return ReadTextHeader(reader); 108 | } 109 | 110 | /// 111 | /// Given a BinaryReader reads the text header. 112 | /// Assumes the BinaryReader is at the start of the file. 113 | /// 114 | public virtual string ReadTextHeader(BinaryReader reader) 115 | { 116 | var textHeaderLength = Options.TextHeaderColumnCount * Options.TextHeaderRowCount; 117 | var bytes = reader.ReadBytes(textHeaderLength); 118 | string text = (bytes[0] == 'C') || Options.IsEbcdic == false ? 119 | ASCIIEncoding.Default.GetString(bytes) : 120 | IbmConverter.ToString(bytes); 121 | return Options.TextHeaderInsertNewLines ? InsertNewLines(text) : text; 122 | } 123 | 124 | #endregion 125 | 126 | #region Already in progress: Methods that start reading from the current location in the stream 127 | 128 | /// 129 | /// Given a BinaryReader, reads the binary header. 130 | /// Assumes that the binary header is the next item to be read. 131 | /// 132 | public virtual IFileHeader ReadBinaryHeader(BinaryReader reader) 133 | { 134 | var binaryHeader = reader.ReadBytes(_binaryHeaderSize); 135 | var byte0 = binaryHeader[_sampleFormatIndex]; 136 | var byte1 = binaryHeader[_sampleFormatIndex + 1]; 137 | bool isLittleEndian = (byte1 == 0); 138 | var sampleFormat = isLittleEndian ? 139 | (FormatCode)byte0 : 140 | (FormatCode)byte1; 141 | return new FileHeader { SampleFormat = sampleFormat, IsLittleEndian = isLittleEndian }; 142 | } 143 | 144 | /// 145 | /// Given a BinaryReader, reads the trace header. 146 | /// Assumes that the trace header is the next item to be read. 147 | /// Assumes that the byte order is Big Endian. 148 | /// 149 | public virtual ITraceHeader ReadTraceHeader(BinaryReader reader) 150 | { 151 | return ReadTraceHeader(reader, false); 152 | } 153 | 154 | /// 155 | /// Given a BinaryReader, reads the trace header. 156 | /// Assumes that the trace header is the next item to be read. 157 | /// 158 | public virtual ITraceHeader ReadTraceHeader(BinaryReader reader, bool isLittleEndian) 159 | { 160 | var traceHeader = new TraceHeader(); 161 | var headerBytes = reader.ReadBytes(_traceHeaderSize); 162 | if (headerBytes.Length < _traceHeaderSize) 163 | return null; 164 | if (headerBytes.Length >= CrosslineNumberLocation + 3) 165 | traceHeader.CrosslineNumber = traceHeader.TraceNumber = 166 | ToInt32(headerBytes, CrosslineNumberLocation - 1, isLittleEndian); 167 | if (headerBytes.Length >= InlineNumberLocation + 3) 168 | traceHeader.InlineNumber = ToInt32(headerBytes, InlineNumberLocation - 1, isLittleEndian); 169 | if (headerBytes.Length >= _sampleCountIndex + 2) 170 | traceHeader.SampleCount = ToInt16(headerBytes, _sampleCountIndex, isLittleEndian); 171 | return traceHeader; 172 | } 173 | 174 | /// 175 | /// Reads the trace (header and sample values). 176 | /// Assumes that the trace header is the next item to be read. 177 | /// 178 | public virtual ITrace ReadTrace(BinaryReader reader, FormatCode sampleFormat, bool isLittleEndian) 179 | { 180 | var header = ReadTraceHeader(reader, isLittleEndian); 181 | if (header == null) 182 | return null; 183 | var values = ReadTrace(reader, sampleFormat, header.SampleCount, isLittleEndian); 184 | return new Trace { Header = header, Values = values }; 185 | } 186 | 187 | /// 188 | /// Assuming the trace header has been read, reads the array of sample values 189 | /// 190 | public virtual IList ReadTrace(BinaryReader reader, FormatCode sampleFormat, int sampleCount, bool isLittleEndian) 191 | { 192 | var trace = new float[sampleCount]; 193 | try 194 | { 195 | for (int i = 0; i < sampleCount; i++) 196 | { 197 | switch (sampleFormat) 198 | { 199 | case FormatCode.IbmFloatingPoint4: 200 | trace[i] = reader.ReadSingleIbm(); 201 | break; 202 | case FormatCode.IeeeFloatingPoint4: 203 | trace[i] = isLittleEndian ? 204 | reader.ReadSingle() : 205 | ReadReversedSingle(reader); 206 | break; 207 | case FormatCode.TwosComplementInteger1: 208 | trace[i] = ReadSignedByte(reader); 209 | break; 210 | case FormatCode.TwosComplementInteger2: 211 | trace[i] = isLittleEndian ? 212 | reader.ReadInt16() : 213 | reader.ReadInt16BigEndian(); 214 | break; 215 | case FormatCode.TwosComplementInteger4: 216 | trace[i] = isLittleEndian ? 217 | reader.ReadInt32() : 218 | reader.ReadInt32BigEndian(); 219 | break; 220 | default: 221 | throw new NotSupportedException( 222 | String.Format("Unsupported sample format: {0}. Send an email to dev@segy.net to request support for this format.", sampleFormat)); 223 | } 224 | } 225 | } 226 | catch (EndOfStreamException) { /* Encountered end of stream before end of trace. Leave remaining trace samples as zero */ } 227 | return trace; 228 | } 229 | 230 | #endregion 231 | 232 | #region Behind the Scenes 233 | 234 | private const int _binaryHeaderSize = 400; 235 | private const int _traceHeaderSize = 240; 236 | private const int _sampleFormatIndex = 24; 237 | private const int _sampleCountIndex = 114; 238 | 239 | private string InsertNewLines(string text) 240 | { 241 | var rows = Options.TextHeaderRowCount; 242 | var cols = Options.TextHeaderColumnCount; 243 | var result = new StringBuilder(text.Length + rows); 244 | for (int i = 0; i < 1 + text.Length / cols; i++) 245 | { 246 | var line = new string(text.Skip(cols * i).Take(cols).ToArray()); 247 | result.AppendLine(line); 248 | } 249 | return result.ToString(); 250 | } 251 | 252 | private static int ToInt16(byte[] bytes, int index, bool isLittleEndian) 253 | { 254 | return isLittleEndian ? 255 | BitConverter.ToInt16(bytes, index) : 256 | IbmConverter.ToInt16(bytes, index); 257 | } 258 | 259 | private static int ToInt32(byte[] bytes, int index, bool isLittleEndian) 260 | { 261 | return isLittleEndian ? 262 | BitConverter.ToInt32(bytes, index) : 263 | IbmConverter.ToInt32(bytes, index); 264 | } 265 | 266 | private static float ReadSignedByte(BinaryReader reader) 267 | { 268 | byte b = reader.ReadByte(); 269 | return b < 128 ? b : b - 256; 270 | } 271 | 272 | private static float ReadReversedSingle(BinaryReader reader) 273 | { 274 | var b = reader.ReadBytes(4).Reverse().ToArray(); 275 | return BitConverter.ToSingle(b, 0); 276 | } 277 | 278 | #endregion 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/ImageWriterTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Drawing.Imaging; 4 | using System.Runtime.InteropServices; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Moq; 7 | using TestDrivenDesign; 8 | 9 | namespace Unplugged.Segy.Tests 10 | { 11 | [TestClass] 12 | public class ImageWriterTest : TestBase 13 | { 14 | [TestMethod] 15 | public void ImageWriterOptions() 16 | { 17 | // Arrange 18 | bool setNullValuesToTransparent = Subject.SetNullValuesToTransparent; 19 | 20 | // Assert 21 | Assert.AreEqual(false, setNullValuesToTransparent); 22 | } 23 | 24 | [TestMethod] 25 | public void ShouldCreateImageFile() 26 | { 27 | // Arrange 28 | var path = TestPath() + ".png"; 29 | ISegyFile segyFile = new Mock().Object; 30 | 31 | // Act 32 | Subject.Write(segyFile, path); 33 | 34 | // Assert 35 | BinaryFileAssert.Exists(path); 36 | var image = Bitmap.FromFile(path); 37 | Assert.AreEqual(1, image.Width); 38 | Assert.AreEqual(1, image.Height); 39 | } 40 | 41 | [TestMethod] 42 | public void ShouldGetBitmapWithoutWritingIt() 43 | { 44 | // Arrange 45 | var expectedWidth = 5; 46 | var expectedHeight = 21; 47 | var segy = new MockSegyFile(expectedWidth, expectedHeight); 48 | 49 | // Act 50 | Bitmap image = Subject.GetBitmap((ISegyFile)segy); 51 | 52 | // Assert 53 | Assert.AreEqual(expectedWidth, image.Width); 54 | Assert.AreEqual(expectedHeight, image.Height); 55 | image.Dispose(); 56 | } 57 | 58 | [TestMethod] 59 | public void ShouldHaveCorrectResolution() 60 | { 61 | // Arrange 62 | var expectedWidth = 7; 63 | var expectedHeight = 11; 64 | var segy = new MockSegyFile(expectedWidth, expectedHeight); 65 | var path = TestPath() + ".png"; 66 | 67 | // Act 68 | Subject.Write(segy, path); 69 | 70 | // Assert 71 | using (var image = Bitmap.FromFile(path)) 72 | { 73 | Assert.AreEqual(expectedWidth, image.Width); 74 | Assert.AreEqual(expectedHeight, image.Height); 75 | } 76 | } 77 | 78 | [TestMethod] 79 | public void PixelValuesShouldBeBlackToWhite() 80 | { 81 | // Arrange 82 | var traceValues = new float[] { 150, 175, 125, 200, 111, 100, 123 }; // Min: 100, Max: 200 83 | var trace = new MockTrace { Values = traceValues }; 84 | var segy = new MockSegyFile { Traces = new ITrace[] { trace } }; 85 | var path = TestPath() + ".png"; 86 | 87 | // Act 88 | Subject.Write(segy, path); 89 | 90 | // Assert 91 | Bitmap image = new Bitmap(path); 92 | Assert.AreEqual(Color.FromArgb(0, 0, 0), image.GetPixel(0, 5)); 93 | Assert.AreEqual(Color.FromArgb(127, 127, 127), image.GetPixel(0, 0)); 94 | Assert.AreEqual(Color.FromArgb(255, 255, 255), image.GetPixel(0, 3)); 95 | } 96 | 97 | [TestMethod] 98 | public void NullSamplesShouldBeTransparent() 99 | { 100 | // Arrange: A sample value of exactly 0 101 | var traceValues = new float[] { 0.00001f, 0, -0.00001f }; 102 | var trace = new MockTrace { Values = traceValues }; 103 | var segy = new MockSegyFile { Traces = new ITrace[] { trace } }; 104 | var path = TestPath() + ".png"; 105 | Subject.SetNullValuesToTransparent = true; 106 | 107 | // Act 108 | Subject.Write(segy, path); 109 | 110 | // Assert 111 | Bitmap image = new Bitmap(path); 112 | Assert.AreEqual(255, image.GetPixel(0, 0).A); 113 | Assert.AreEqual(0, image.GetPixel(0, 1).A); 114 | Assert.AreEqual(255, image.GetPixel(0, 2).A); 115 | } 116 | 117 | [TestMethod] 118 | public void WhenDisabledNullSamplesShouldNotBeTransparent() 119 | { 120 | // Arrange 121 | var trace = new MockTrace { Values = new float[] { 0, 1, -1 } }; 122 | var segy = new MockSegyFile { Traces = new ITrace[] { trace } }; 123 | var path = TestPath() + ".png"; 124 | 125 | // Act 126 | Subject.SetNullValuesToTransparent = false; 127 | Subject.Write(segy, path); 128 | 129 | // Assert 130 | Bitmap image = new Bitmap(path); 131 | Assert.AreEqual(255, image.GetPixel(0, 0).A); 132 | } 133 | 134 | [TestMethod] 135 | public void ShouldCreateImageForEachInline() 136 | { 137 | // Arrange 138 | var values = new float[] { 1, 2, 3 }; 139 | var trace12a = new MockTrace { Header = new MockTraceHeader { InlineNumber = 12, CrosslineNumber = 1 }, Values = values }; 140 | var trace12b = new MockTrace { Header = new MockTraceHeader { InlineNumber = 12, CrosslineNumber = 2 }, Values = values }; 141 | var trace14 = new MockTrace { Header = new MockTraceHeader { InlineNumber = 14 }, Values = values }; 142 | var segy = new MockSegyFile { Traces = new ITrace[] { trace12a, trace12b, trace14 } }; 143 | var path = TestPath() + ".png"; 144 | 145 | // Act 146 | Subject.Write(segy, path); 147 | 148 | // Assert 149 | var image12 = new Bitmap(TestPath() + " (12).png"); 150 | Assert.AreEqual(3, image12.Height); 151 | Assert.AreEqual(2, image12.Width); 152 | var image14 = new Bitmap(TestPath() + " (14).png"); 153 | Assert.AreEqual(3, image14.Height); 154 | Assert.AreEqual(1, image14.Width); 155 | } 156 | 157 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 158 | public void ImageFromExample() 159 | { 160 | // Arrange 161 | var segy = new SegyReader().Read("lineE.sgy"); 162 | var path = TestPath() + ".png"; 163 | 164 | // Act 165 | Subject.Write(segy, path); 166 | 167 | // Assert 168 | BinaryFileAssert.Exists(path); 169 | TestContext.AddResultFile(path); 170 | } 171 | 172 | [TestMethod] 173 | public void ShouldCreateBlackImageWhenRangeIsZero() 174 | { 175 | // Arrange 176 | var path = TestPath() + ".png"; 177 | Subject.SetNullValuesToTransparent = false; 178 | 179 | // Act 180 | Subject.Write(new MockSegyFile(10, 10), path); 181 | 182 | // Assert 183 | TestContext.AddResultFile(path); 184 | Bitmap image = new Bitmap(path); 185 | Assert.AreEqual(0, image.GetPixel(0, 0).R); 186 | Assert.AreEqual(255, image.GetPixel(0, 0).A); 187 | } 188 | 189 | [TestMethod] 190 | public void ShouldCreateImageWithGivenTraces() 191 | { 192 | // Arrange 193 | IEnumerable traces = MockTraces2x3(); 194 | var path = TestPath() + ".jpg"; 195 | 196 | // Act 197 | Subject.Write(traces, path); 198 | 199 | // Assert 200 | BinaryFileAssert.Exists(path); 201 | TestContext.AddResultFile(path); 202 | var image = new Bitmap(path); 203 | VerifyBitmapFromMockTraces2x3(image); 204 | } 205 | 206 | [TestMethod] 207 | public void ShouldGetBitmapWithGivenTraces() 208 | { 209 | // Arrange 210 | IEnumerable traces = MockTraces2x3(); 211 | 212 | // Act 213 | Bitmap image = Subject.GetBitmap(traces); 214 | 215 | // Assert 216 | VerifyBitmapFromMockTraces2x3(image); 217 | } 218 | 219 | [TestMethod] 220 | public void ShouldGetFourComponentByteArray() 221 | { 222 | // Arrange 223 | IEnumerable traces = MockTraces2x3(); 224 | 225 | // Act 226 | byte[] bytes = Subject.GetRaw32BppRgba(traces); 227 | 228 | // Assert 229 | Assert.AreEqual(2 * 3 * 4, bytes.Length); 230 | Assert.AreEqual(127, bytes[0], "r"); 231 | Assert.AreEqual(255, bytes[3], "a"); 232 | using (var bmp = Subject.GetBitmap(traces)) 233 | { 234 | var bmpData = bmp.LockBits(Rectangle.FromLTRB(0, 0, 2, 3), ImageLockMode.ReadOnly, bmp.PixelFormat); 235 | int length = bmpData.Stride * bmp.Height; 236 | byte[] expected = new byte[length]; 237 | Marshal.Copy(bmpData.Scan0, expected, 0, length); 238 | CollectionAssert.AreEqual(expected, bytes); 239 | } 240 | } 241 | 242 | [TestMethod] 243 | public void ShouldGetSingleComponentByteArray() 244 | { 245 | // Arrange 246 | IEnumerable traces = MockTraces2x3(); 247 | 248 | // Act 249 | byte[] bytes = Subject.GetRaw8Bpp(traces); 250 | 251 | // Assert 252 | var expected = new byte[] 253 | { 254 | 127, 63, // 20, 15 255 | 0, 255, // 10, 30 256 | 191, 191 // 25, 25 257 | }; 258 | CollectionAssert.AreEqual(expected, bytes); 259 | } 260 | 261 | private static IEnumerable MockTraces2x3() 262 | { 263 | var trace1 = new MockTrace { Values = new float[] { 20, 10, 25 } }; 264 | var trace2 = new MockTrace { Values = new float[] { 15, 30, 25 } }; 265 | return new ITrace[] { trace1, trace2 }; 266 | } 267 | 268 | private static void VerifyBitmapFromMockTraces2x3(Bitmap image) 269 | { 270 | Assert.AreEqual(2, image.Width); 271 | Assert.AreEqual(3, image.Height); 272 | Assert.AreEqual(Color.FromArgb(127, 127, 127), image.GetPixel(0, 0)); 273 | image.Dispose(); 274 | } 275 | 276 | [TestMethod] 277 | public void GivenTracesForCrosslineShouldCreateOneImage() 278 | { 279 | // Arrange 280 | var trace1 = new MockTrace { Values = new float[] { 99 }, Header = new MockTraceHeader { CrosslineNumber = 1, InlineNumber = 10 } }; 281 | var trace2 = new MockTrace { Values = new float[] { 77 }, Header = new MockTraceHeader { CrosslineNumber = 1, InlineNumber = 20 } }; 282 | IEnumerable traces = new ITrace[] { trace1, trace2 }; 283 | var path = TestPath() + ".jpg"; 284 | 285 | // Act 286 | Subject.Write(traces, path); 287 | 288 | // Assert 289 | BinaryFileAssert.Exists(path); 290 | TestContext.AddResultFile(path); 291 | var image = new Bitmap(path); 292 | Assert.AreEqual(2, image.Width); 293 | Assert.AreEqual(1, image.Height); 294 | } 295 | 296 | //[TestMethod] 297 | //public void ImageFromExample3D() 298 | //{ 299 | // // Arrange 300 | // var reader = new SegyReader { InlineNumberLocation = 17 }; 301 | // var userprofile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); 302 | // var segy = reader.Read(userprofile + @"\Desktop\RMOTC Data\RMOTC Seismic data set\3D_Seismic\filt_mig.sgy"); 303 | // var path = TestPath() + ".png"; 304 | 305 | // // Act 306 | // Subject.Write(segy, path); 307 | 308 | // // Assert 309 | // TestContext.AddResultFile(path); 310 | //} 311 | 312 | // TODO: Should verify trace range normalized over whole volume 313 | // TODO: Handle variable length traces 314 | } 315 | 316 | class MockTraceHeader : ITraceHeader 317 | { 318 | public int SampleCount { get; set; } 319 | public int TraceNumber { get; set; } 320 | public int InlineNumber { get; set; } 321 | public int CrosslineNumber { get; set; } 322 | } 323 | 324 | class MockTrace : ITrace 325 | { 326 | public ITraceHeader Header { get; set; } 327 | public IList Values { get; set; } 328 | } 329 | 330 | class MockSegyFile : ISegyFile 331 | { 332 | public IFileHeader Header { get; set; } 333 | public IList Traces { get; set; } 334 | 335 | public MockSegyFile() 336 | { 337 | } 338 | 339 | public MockSegyFile(int traces, int samplesPerTrace) 340 | { 341 | var trace = new MockTrace { Values = new float[samplesPerTrace] }; 342 | Traces = new ITrace[traces]; 343 | for (int i = 0; i < traces; i++) 344 | Traces[i] = trace; 345 | } 346 | } 347 | 348 | } 349 | -------------------------------------------------------------------------------- /packages/TestDrivenDesign.0.0.3/lib/net40/TestDrivenDesign.dll.CodeAnalysisLog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Consider replacing the language-specific data type identifier 'Bool' in member name 'TestBase.DataValueAsBool(string)' with either a language-independent equivalent or a more generic term, such as 'value'. 17 | 18 | 19 | Because the behavior of 'Convert.ToBoolean(object)' could vary based on the current user's locale settings, replace this call in 'TestBase.DataValueAsBool(string)' with a call to 'Convert.ToBoolean(object, IFormatProvider)'. If the result of 'Convert.ToBoolean(object, IFormatProvider)' will be based on input from the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will based on input stored and accessed by software, such as when it is loaded from disk or from a database, specify 'CultureInfo.InvariantCulture'. 20 | 21 | 22 | 23 | 24 | 25 | 26 | Consider replacing the language-specific data type identifier 'Float' in member name 'TestBase.DataValueAsFloat(string)' with either a language-independent equivalent or a more generic term, such as 'value'. 27 | 28 | 29 | Because the behavior of 'Convert.ToSingle(object)' could vary based on the current user's locale settings, replace this call in 'TestBase.DataValueAsFloat(string)' with a call to 'Convert.ToSingle(object, IFormatProvider)'. If the result of 'Convert.ToSingle(object, IFormatProvider)' will be based on input from the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will based on input stored and accessed by software, such as when it is loaded from disk or from a database, specify 'CultureInfo.InvariantCulture'. 30 | 31 | 32 | 33 | 34 | 35 | 36 | Consider replacing the language-specific data type identifier 'Int' in member name 'TestBase.DataValueAsInt(string)' with either a language-independent equivalent or a more generic term, such as 'value'. 37 | 38 | 39 | Because the behavior of 'Convert.ToInt32(object)' could vary based on the current user's locale settings, replace this call in 'TestBase.DataValueAsInt(string)' with a call to 'Convert.ToInt32(object, IFormatProvider)'. If the result of 'Convert.ToInt32(object, IFormatProvider)' will be based on input from the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will based on input stored and accessed by software, such as when it is loaded from disk or from a database, specify 'CultureInfo.InvariantCulture'. 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Consider a design where 'TestBase<T>.Verify(Expression<Action<T>>)' doesn't nest generic type 'Expression<Action<T>>'. 51 | 52 | 53 | In externally visible method 'TestBase<T>.Verify(Expression<Action<T>>)', validate parameter 'expression' before using it. 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Do not nest generic types in member signatures 69 | Avoid API that require users to instantiate a generic type with another generic type as type argument. The syntax gets too complex. 70 | Consider a design where {0} doesn't nest generic type {1}. 71 | 72 | http://msdn.microsoft.com/library/ms182144(VS.100).aspx 73 | [none] 74 | CriticalError 75 | 76 | 77 | 78 | Identifiers should not contain type names 79 | Avoid using language-specific types name in parameters and members and data type identifiers in parameters. Types names might not be intuitive for all developers. It is recommended that you select a generic name, such as 'value', instead. If this is not sufficient, be sure to use the type name as it is defined in the .NET Framework Library and avoid language-specific type names completely. Some examples of C#-specific type names are 'float' (use 'Single' if a generic name is not sufficient), and 'ulong' (use 'UInt64' if a generic name is not sufficient). 80 | In member {0}, consider replacing the data type identifier '{1}' in parameter name {2} with a more generic term, such as 'value'. 81 | Consider replacing the language-specific data type identifier '{0}' in member name {1} with either a language-independent equivalent or a more generic term, such as 'value'. 82 | 83 | http://msdn.microsoft.com/library/bb531486(VS.100).aspx 84 | [none] 85 | Error 86 | 87 | 88 | 89 | Specify IFormatProvider 90 | If an overload exists that takes an IFormatProvider argument, it should always be called in favor of an overload that does not. Some methods in the runtime convert a value to or from a string representation and take a string parameter that contains one or more characters, called format specifiers, which indicate how the value is to be converted. If the meaning of the format specifier varies by culture, a formatting object supplies the actual characters used in the string representation. In scenarios where sorting and comparison behavior should never change between cultures, specify CultureInfo.InvariantCulture, otherwise, specify CultureInfo.CurrentCulture. 91 | Because the behavior of {0} could vary based on the current user's locale settings, replace this call in {1} with a call to {2}. If the result of {2} will be based on input from the user, specify {3} as the 'IFormatProvider' parameter. Otherwise, if the result will based on input stored and accessed by software, such as when it is loaded from disk or from a database, specify {4}. 92 | 93 | http://msdn.microsoft.com/library/ms182190(VS.100).aspx 94 | [none] 95 | Error 96 | 97 | 98 | 99 | Validate arguments of public methods 100 | All reference arguments passed to externally visible methods should be checked against null (Nothing in VB). If appropriate, throw a System.ArgumentNullException when the argument is null. 101 | In externally visible method {0}, validate parameter '{1}' before using it. 102 | RuleOwner 103 | http://msdn.microsoft.com/library/ms182182(VS.100).aspx 104 | 105 | Warning 106 | 107 | 108 | 109 | 110 | Category 111 | Certainty 112 | Collapse All 113 | Check Id 114 | Error 115 | error(s) 116 | Expand All 117 | Help 118 | Line 119 | message(s) 120 | [Location not stored in Pdb] 121 | Project 122 | Resolution 123 | Rule 124 | Rule File 125 | Rule Description 126 | Source 127 | Status 128 | Target 129 | Warning 130 | warning(s) 131 | Code Analysis Report 132 | 133 | 134 | -------------------------------------------------------------------------------- /Unplugged.Segy.Tests/SegyReaderTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | using TestDrivenDesign; 9 | using Unplugged.IbmBits; 10 | 11 | namespace Unplugged.Segy.Tests 12 | { 13 | [TestClass] 14 | public class SegyReaderTest : TestBase 15 | { 16 | #region Loading Options 17 | 18 | [TestMethod] 19 | public void ShouldHaveDefaultOptions() 20 | { 21 | // Arrange 22 | ISegyOptions options = Subject.Options; 23 | 24 | // Assert 25 | Assert.IsInstanceOfType(options, typeof(SegyOptions)); 26 | } 27 | 28 | [TestMethod] 29 | public void InlineNumberLocation() 30 | { 31 | // Arrange 32 | int inlineNumberLocation = Subject.InlineNumberLocation; 33 | int crosslineNumberLocation = Subject.CrosslineNumberLocation; 34 | 35 | // Assert 36 | Assert.AreEqual(189, inlineNumberLocation, "According to SEGY Rev 1, byte 189 - 192 in the trace header should be used for the in-line number"); 37 | Assert.AreEqual(193, crosslineNumberLocation, "According to SEGY Rev 1, byte 193 - 196 in the trace header should be used for the cross-line number"); 38 | } 39 | 40 | #endregion 41 | 42 | /// The text header is typically 3200 EBCDIC encoded character bytes. That is, 80 columns by 40 lines (formerly punch cards). 43 | #region Textual Header 44 | 45 | [TestMethod] 46 | public void ShouldReadHeaderFromEbcdicEncoding() 47 | { 48 | // Arrange some Ebcdic characters at the beginning of the file 49 | var expected = "Once upon a time..."; 50 | var ebcdicBytes = ConvertToEbcdic(expected); 51 | var path = TestPath(); 52 | File.WriteAllBytes(path, ebcdicBytes); 53 | 54 | // Act 55 | string header = Subject.ReadTextHeader(path); 56 | 57 | // Assert 58 | StringAssert.StartsWith(header, expected); 59 | } 60 | 61 | [TestMethod] 62 | public void ShouldRead3200BytesForTextHeader() 63 | { 64 | // Arrange some Ebcdic characters at the beginning of the file 65 | var expected = "TheEnd"; 66 | var ebcdicBytes = ConvertToEbcdic(new string('c', 3200 - 6) + expected + "notExpected"); 67 | File.WriteAllBytes(TestPath(), ebcdicBytes); 68 | 69 | // Act 70 | var header = Subject.ReadTextHeader(TestPath()); 71 | 72 | // Assert 73 | StringAssert.EndsWith(header.TrimEnd(), expected); 74 | } 75 | 76 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 77 | public void ShouldReadExampleTextHeader() 78 | { 79 | // Act 80 | var header = Subject.ReadTextHeader(_example); 81 | 82 | // Assert 83 | Console.WriteLine(header); 84 | StringAssert.StartsWith(header, "C 1"); 85 | StringAssert.Contains(header, "CLIENT"); 86 | StringAssert.EndsWith(header.TrimEnd(), "END EBCDIC"); 87 | } 88 | 89 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 90 | public void ShouldReadTextHeaderGivenStream() 91 | { 92 | // Arrange 93 | using (Stream stream = File.OpenRead(_example)) 94 | { 95 | // Act 96 | string header = Subject.ReadTextHeader(stream); 97 | 98 | // Arrange 99 | StringAssert.EndsWith(header.TrimEnd(), "END EBCDIC"); 100 | } 101 | } 102 | 103 | [TestMethod] 104 | public void ShouldInsertNewlinesEvery80Characters() 105 | { 106 | // Arrange 107 | var line1 = new string('a', 80); 108 | var line2 = new string('b', 80); 109 | var line3 = new string('c', 80); 110 | var bytes = ConvertToEbcdic(line1 + line2 + line3); 111 | File.WriteAllBytes(TestPath(), bytes); 112 | 113 | // Act 114 | var header = Subject.ReadTextHeader(TestPath()); 115 | 116 | // Assert 117 | var lines = SplitLines(header); 118 | Assert.AreEqual(line1, lines[0]); 119 | Assert.AreEqual(line2, lines[1]); 120 | Assert.AreEqual(line3, lines[2]); 121 | } 122 | 123 | [TestMethod] 124 | public void ShouldDetectAsciiHeaderByFirstCharacter() 125 | { 126 | // Arrange 127 | var expected = "C 1 This is expected"; 128 | var extra = new string('z', 80); 129 | File.WriteAllText(TestPath(), expected + extra, Encoding.ASCII); 130 | 131 | // Act 132 | var header = Subject.ReadTextHeader(TestPath()); 133 | 134 | // Assert 135 | StringAssert.StartsWith(header, expected); 136 | Assert.AreEqual(2, SplitLines(header).Count(), "Should split lines for ascii header"); 137 | } 138 | 139 | [TestMethod] 140 | public void ShouldObserveOptionsForTextHeader() 141 | { 142 | // Arrange 143 | Subject.Options = new SegyOptions { TextHeaderColumnCount = 3, TextHeaderRowCount = 7, IsEbcdic = false }; 144 | var text = new string('e', 21) + "n"; 145 | File.WriteAllText(TestPath(), text); 146 | 147 | // Act 148 | var result = Subject.ReadTextHeader(TestPath()); 149 | 150 | // Assert 151 | StringAssert.StartsWith(result, "eee" + Environment.NewLine); 152 | CollectionAssert.DoesNotContain(result.ToCharArray(), 'n'); 153 | } 154 | 155 | [TestMethod] 156 | public void ShouldObserveNewLinesOption() 157 | { 158 | // Arrange 159 | Subject.Options = new SegyOptions { TextHeaderInsertNewLines = false }; 160 | var expected = new string('x', 3200); 161 | File.WriteAllBytes(TestPath(), ConvertToEbcdic(expected)); 162 | 163 | // Act 164 | var actual = Subject.ReadTextHeader(TestPath()); 165 | 166 | // Assert 167 | Assert.AreEqual(expected, actual); 168 | } 169 | 170 | #endregion 171 | 172 | /// 400-byte Binary File Header follows 3200 byte textual header 173 | /// Bytes 3225-3226: Data sample format code 174 | #region Binary File Header 175 | 176 | [TestMethod] 177 | public void ShouldReadSampleFormatFromByte25() 178 | { 179 | // Arrange 180 | var expected = FormatCode.IeeeFloatingPoint4; 181 | bool isLittleEndian = false; 182 | 183 | // Act 184 | IFileHeader result = Set16BitValueInBinaryStreamAndRead((sr, br) => sr.ReadBinaryHeader(br), 25, (Int16)expected, isLittleEndian); 185 | 186 | // Assert 187 | Assert.AreEqual(expected, result.SampleFormat); 188 | Assert.AreEqual(isLittleEndian, result.IsLittleEndian); 189 | } 190 | 191 | [TestMethod] 192 | public void ShouldDetectLittleEndiannessFromSampleFormat() 193 | { 194 | // Arrange 195 | var expected = FormatCode.TwosComplementInteger1; 196 | bool isLittleEndian = true; 197 | 198 | // Act 199 | IFileHeader result = Set16BitValueInBinaryStreamAndRead((sr, br) => sr.ReadBinaryHeader(br), 25, (Int16)expected, isLittleEndian); 200 | 201 | // Assert 202 | Assert.AreEqual(expected, result.SampleFormat); 203 | Assert.AreEqual(isLittleEndian, result.IsLittleEndian); 204 | } 205 | 206 | [TestMethod] 207 | public void ShouldConsume400Bytes() 208 | { 209 | AssertBytesConsumed((r) => Subject.ReadBinaryHeader(r), 400); 210 | } 211 | 212 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 213 | public void ShouldReadTextAndBinaryHeaderGivenBinaryReader() 214 | { 215 | // Arrange 216 | using (var stream = File.OpenRead(_example)) 217 | using (var reader = new BinaryReader(stream)) 218 | { 219 | // Act 220 | IFileHeader fileHeader = Subject.ReadFileHeader(reader); 221 | 222 | // Assert 223 | Assert.AreEqual(Subject.ReadTextHeader(_example), fileHeader.Text); 224 | Assert.AreEqual(FormatCode.IbmFloatingPoint4, fileHeader.SampleFormat); 225 | } 226 | } 227 | 228 | #endregion 229 | 230 | /// The Trace Header is typically 240 bytes with Big Endian values 231 | /// Info from the standard: 232 | /// 115-116 Number of samples in this trace 233 | /// 117-118 Sample Interval in Micro-Seconds 234 | /// 181-194 X CDP 235 | /// 185-188 Y CDP 236 | /// 189-192 Inline number (for 3D) 237 | /// 193-196 Cross-line number (for 3D) 238 | /// 239 | /// Header Information from Teapot load sheet 240 | /// Inline (line) bytes: 17- 20 and 181-184 241 | /// Crossline (trace) bytes: 13- 16 and 185-188 242 | /// CDP X_COORD bytes: 81- 84 and 189-193 243 | /// CDP Y_COORD bytes: 85- 88 and 193-196 244 | #region Trace Header 245 | 246 | [TestMethod] 247 | public void SystemShouldBeLittleEndian() 248 | { 249 | Assert.IsTrue(BitConverter.IsLittleEndian, "These tests assume the system is little endian"); 250 | } 251 | 252 | [TestMethod] 253 | public void ShouldReadTraceNumberFromSpecifiedByteLocation() 254 | { 255 | // Arrange 256 | Int32 expectedValue = Int16.MaxValue + 100; 257 | Subject.CrosslineNumberLocation = 113; 258 | 259 | // Act 260 | ITraceHeader result = Set32BitValueInBinaryStreamAndRead((sr, br) => sr.ReadTraceHeader(br), Subject.CrosslineNumberLocation, expectedValue); 261 | 262 | // Assert 263 | Assert.AreEqual(expectedValue, result.TraceNumber); 264 | Assert.AreEqual(expectedValue, result.CrosslineNumber); 265 | } 266 | 267 | [TestMethod] 268 | public void ShouldReadInlineNumberFromSpecifiedByteLocation() 269 | { 270 | // Arrange 271 | Int32 expectedValue = Int16.MaxValue + 100; 272 | Subject.InlineNumberLocation = 123; 273 | 274 | // Act 275 | ITraceHeader result = Set32BitValueInBinaryStreamAndRead((sr, br) => sr.ReadTraceHeader(br), Subject.InlineNumberLocation, expectedValue); 276 | 277 | // Assert 278 | Assert.AreEqual(expectedValue, result.InlineNumber); 279 | } 280 | 281 | [TestMethod] 282 | public void ShouldReadNumberOfSamplesFromByte115() 283 | { 284 | // Arrange 285 | Int16 expectedValue = 2345; 286 | 287 | // Act 288 | ITraceHeader result = Set16BitValueInBinaryStreamAndRead((sr, br) => sr.ReadTraceHeader(br), 115, expectedValue, false); 289 | 290 | // Assert 291 | Assert.AreEqual(expectedValue, result.SampleCount); 292 | } 293 | 294 | [TestMethod] 295 | public void ShouldConsume240Bytes() 296 | { 297 | AssertBytesConsumed(r => Subject.ReadTraceHeader(r), 240); 298 | } 299 | 300 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 301 | public void ShouldReadTraceHeaderFromExample() 302 | { 303 | // Arrange 304 | using (var stream = File.OpenRead(_example)) 305 | using (var reader = new BinaryReader(stream)) 306 | { 307 | var header = Subject.ReadFileHeader(reader); 308 | 309 | // Act 310 | var traceHeader = Subject.ReadTraceHeader(reader); 311 | 312 | // Assert 313 | Assert.AreEqual(1001, traceHeader.SampleCount); 314 | for (int i = 0; i < traceHeader.SampleCount; i++) 315 | { 316 | var value = reader.ReadSingleIbm(); 317 | Console.WriteLine(value); 318 | Assert.IsTrue(value < 10 && value > -10); 319 | } 320 | Assert.AreEqual(1001, Subject.ReadTraceHeader(reader).SampleCount); 321 | } 322 | } 323 | 324 | #endregion 325 | 326 | #region Trace Data 327 | 328 | [TestMethod] 329 | public void ShouldConsumeAllBytesInTrace() 330 | { 331 | // Arrange 332 | FormatCode sampleFormat = FormatCode.IeeeFloatingPoint4; 333 | int sampleCount = 200; 334 | var expected = 800; 335 | IList result = null; 336 | 337 | // Act 338 | AssertBytesConsumed(r => result = Subject.ReadTrace(r, sampleFormat, sampleCount, false), expected); 339 | 340 | // Assert 341 | Assert.AreEqual(sampleCount, result.Count); 342 | } 343 | 344 | [TestMethod] 345 | public void ShouldReadSinglesForIeeeFormat() 346 | { 347 | var expected = new float[] { 10, 20, 30 }; 348 | var bytes = BitConverter.GetBytes(10f).Concat(BitConverter.GetBytes(20f)).Concat(BitConverter.GetBytes(30f)).ToArray(); 349 | VerifyReadsSamplesOfGivenFormat(FormatCode.IeeeFloatingPoint4, expected, bytes, true); 350 | } 351 | 352 | [TestMethod] 353 | public void ShouldReadSingleIbmForIbmFormat() 354 | { 355 | // TODO: This test would be clearer if I had code to convert TO IBM Float 356 | var bytes = BitConverter.GetBytes(96795456).Concat(BitConverter.GetBytes(2136281153)).Concat(BitConverter.GetBytes(1025579328)).ToArray(); 357 | var expected = new float[] { 0.9834598f, 1.020873f, 0.09816343f }; 358 | VerifyReadsSamplesOfGivenFormat(FormatCode.IbmFloatingPoint4, expected, bytes, false); 359 | } 360 | 361 | [TestMethod] 362 | public void ShouldReadTwosComplementInteger2BigEndian() 363 | { 364 | var expected = new float[] { -777, 888 }; 365 | var bytes = BitConverter.GetBytes((Int16)(-777)).Reverse().Concat(BitConverter.GetBytes((Int16)888).Reverse()).ToArray(); 366 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger2, expected, bytes, false); 367 | } 368 | 369 | [TestMethod] 370 | public void ShouldReadTwosComplementInteger2LittleEndian() 371 | { 372 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger2, new float[] { 513 }, new byte[] { 1, 2 }, true); 373 | } 374 | 375 | [TestMethod] 376 | public void ShouldReadTwosComplementInteger4BigEndian() 377 | { 378 | var expected = new float[] { -777, 888 }; 379 | var bytes = BitConverter.GetBytes((Int32)(-777)).Reverse().Concat(BitConverter.GetBytes((Int32)888).Reverse()).ToArray(); 380 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger4, expected, bytes, false); 381 | } 382 | 383 | [TestMethod] 384 | public void ShouldReadTwosComplementInteger4LittleEndian() 385 | { 386 | var expected = new float[] { -777, 888 }; 387 | var bytes = BitConverter.GetBytes((Int32)(-777)).Concat(BitConverter.GetBytes((Int32)888)).ToArray(); 388 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger4, expected, bytes, true); 389 | } 390 | 391 | [TestMethod] 392 | public void ShouldReadTwosComplementInteger1() 393 | { 394 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger1, new float[] { -126, -128, 88 }, new byte[] { 130, 128, 88}, true); 395 | } 396 | 397 | [TestMethod] 398 | public void ShouldHandleEndOfStreamBeforeEndOfTrace() 399 | { 400 | // Arrange 401 | var bytes = new byte[] { 1, 0, 2, 0 }; 402 | var expected = new float[] { 1, 2, 0 }; 403 | 404 | // Act 405 | VerifyReadsSamplesOfGivenFormat(FormatCode.TwosComplementInteger2, expected, bytes, true); 406 | } 407 | 408 | private void VerifyReadsSamplesOfGivenFormat(FormatCode sampleFormat, float[] expected, byte[] bytes, bool isLittleEndian) 409 | { 410 | // Arrange 411 | var sampleCount = expected.Length; 412 | IList result = null; 413 | 414 | // Act 415 | using (var stream = new MemoryStream(bytes)) 416 | using (var reader = new BinaryReader(stream)) 417 | result = Subject.ReadTrace(reader, sampleFormat, sampleCount, isLittleEndian); 418 | 419 | // Assert 420 | for (int i = 0; i < sampleCount; i++) 421 | Assert.AreEqual(expected[i], result[i], 0.00001); 422 | } 423 | 424 | [TestMethod] 425 | public void ShouldReadTraceHeaderAndValuesGivenSampleFormat() 426 | { 427 | // Arrange 428 | var sampleFormat = FormatCode.IeeeFloatingPoint4; 429 | var expected = new float[] { 11, 111 }; 430 | var bytes = new byte[240]; // trace header 431 | SetBigIndianValue((Int16)expected.Length, bytes, 115); 432 | bytes = bytes.Concat(BitConverter.GetBytes(expected[0]).Reverse()).Concat(BitConverter.GetBytes(expected[1]).Reverse()).ToArray(); 433 | ITrace trace = null; 434 | 435 | // Act 436 | using (var stream = new MemoryStream(bytes)) 437 | using (var reader = new BinaryReader(stream)) 438 | trace = Subject.ReadTrace(reader, sampleFormat, false); 439 | 440 | // Assert 441 | Assert.AreEqual(expected.Length, trace.Header.SampleCount); 442 | CollectionAssert.AreEqual(expected, trace.Values.ToList()); 443 | } 444 | 445 | #endregion 446 | 447 | #region Reading Entire File 448 | 449 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 450 | public void ShouldReadFileHeadersAndAllTraces() 451 | { 452 | // Arrange 453 | var path = _example; 454 | 455 | // Act 456 | ISegyFile segy = Subject.Read(path); 457 | 458 | // Assert 459 | VerifyExampleValuesAndTraceCount(segy); 460 | } 461 | 462 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 463 | public void ShouldReadStreamHeadersAndAllTraces() 464 | { 465 | // Arrange 466 | var path = _example; 467 | ISegyFile segy = null; 468 | 469 | // Act 470 | using (Stream stream = File.OpenRead(path)) 471 | segy = Subject.Read(stream); 472 | 473 | // Assert 474 | VerifyExampleValuesAndTraceCount(segy); 475 | } 476 | 477 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 478 | public void ShouldBeAbleToReadSegyFromNetworkStream() 479 | { 480 | // Arrange 481 | var webclient = new WebClient(); 482 | using (var stream = webclient.OpenRead("https://github.com/jfoshee/UnpluggedSegy/raw/c44f0f65c4c80671964531cf5d45170fcb585d15/Unplugged.Segy.Tests/Examples/lineE.sgy")) 483 | { 484 | // Act 485 | var segy = Subject.Read(stream); 486 | 487 | // Assert 488 | VerifyExampleValuesAndTraceCount(segy); 489 | } 490 | } 491 | 492 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 493 | public void ShouldReadNoMoreThanRequestedNumberOfTraces() 494 | { 495 | // Arrange 496 | int traceCount = 5; 497 | using (Stream stream = File.OpenRead(_example)) 498 | { 499 | // Act 500 | ISegyFile segy = Subject.Read(stream, traceCount); 501 | 502 | // Assert 503 | VerifyExampleValues(segy); 504 | Assert.AreEqual(traceCount, segy.Traces.Count); 505 | } 506 | } 507 | 508 | [TestMethod, DeploymentItem(@"Unplugged.Segy.Tests\Examples\lineE.sgy")] 509 | public void ShouldReadAllTracesIfRequestedTraceCountIsGreater() 510 | { 511 | // Arrange 512 | using (Stream stream = File.OpenRead(_example)) 513 | { 514 | // Act 515 | ISegyFile segy = Subject.Read(stream, 9999); 516 | 517 | // Assert 518 | VerifyExampleValuesAndTraceCount(segy); 519 | } 520 | } 521 | 522 | private const string _example = "lineE.sgy"; 523 | 524 | private static void VerifyExampleValues(ISegyFile result) 525 | { 526 | StringAssert.StartsWith(result.Header.Text, "C 1"); 527 | StringAssert.Contains(result.Header.Text, "C16 GEOPHONES"); 528 | Assert.AreEqual(FormatCode.IbmFloatingPoint4, result.Header.SampleFormat); 529 | Assert.AreEqual(1001, result.Traces.First().Header.SampleCount); 530 | var traceValues = result.Traces.First().Values.ToList(); 531 | Assert.AreEqual(1001, traceValues.Count); 532 | CollectionAssert.Contains(traceValues, 0f); 533 | CollectionAssert.Contains(traceValues, 0.9834598f); 534 | CollectionAssert.DoesNotContain(traceValues, float.PositiveInfinity); 535 | } 536 | 537 | private static void VerifyExampleValuesAndTraceCount(ISegyFile result) 538 | { 539 | VerifyExampleValues(result); 540 | var fileLength = new FileInfo(_example).Length; 541 | Assert.AreEqual((fileLength - 3200 - 400) / (240 + 1001 * 4), result.Traces.Count); 542 | } 543 | 544 | [TestMethod] 545 | public void AllReadMethodsShouldBeMockable() 546 | { 547 | // Act 548 | var readMethods = typeof(SegyReader).GetMethods().Where(m => m.Name == "Read"); 549 | 550 | // Assert 551 | foreach (var method in readMethods) 552 | Assert.IsTrue(method.IsVirtual); 553 | } 554 | 555 | #endregion 556 | 557 | #region Reading Little Endian 558 | 559 | [TestMethod] 560 | public void ShouldReadLittleEndianTraceHeader() 561 | { 562 | // Arrange 563 | var bytes = new byte[240]; 564 | bytes[114] = 1; // 1 565 | bytes[115] = 2; // 512 566 | Subject.InlineNumberLocation = 101; 567 | bytes[100] = 1; // 1 568 | bytes[103] = 2; // 33,554,432 569 | Subject.CrosslineNumberLocation = 201; 570 | bytes[200] = 2; // 2 571 | bytes[203] = 2; // 33,554,432 572 | ITraceHeader traceHeader = null; 573 | 574 | // Act 575 | using (var stream = new MemoryStream(bytes)) 576 | using (var reader = new BinaryReader(stream)) 577 | traceHeader = Subject.ReadTraceHeader(reader, true); 578 | 579 | // Assert 580 | Assert.AreEqual(513, traceHeader.SampleCount); 581 | Assert.AreEqual(33554433, traceHeader.InlineNumber); 582 | Assert.AreEqual(33554434, traceHeader.CrosslineNumber); 583 | Assert.AreEqual(33554434, traceHeader.TraceNumber); 584 | } 585 | 586 | // TODO: LittleEndianIntegrationTest 587 | 588 | #endregion 589 | 590 | #region Behind the scenes 591 | 592 | private static byte[] ConvertToEbcdic(string expected) 593 | { 594 | var unicode = Encoding.Unicode; 595 | var ebcdic = Encoding.GetEncoding("IBM037"); 596 | var unicodeBytes = unicode.GetBytes(expected); 597 | var ebcdicBytes = Encoding.Convert(unicode, ebcdic, unicodeBytes); 598 | return ebcdicBytes; 599 | } 600 | 601 | private static string[] SplitLines(string header) 602 | { 603 | return header.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 604 | } 605 | 606 | private TResult Set16BitValueInBinaryStreamAndRead(Func act, int byteNumber, Int16 value, bool isLittleEndian) 607 | { 608 | // Arrange 609 | var bytes = new byte[400]; 610 | if (isLittleEndian) 611 | BitConverter.GetBytes(value).CopyTo(bytes, byteNumber - 1); 612 | else 613 | SetBigIndianValue(value, bytes, byteNumber); 614 | 615 | // Act 616 | using (var stream = new MemoryStream(bytes)) 617 | using (var reader = new BinaryReader(stream)) 618 | return act(Subject, reader); 619 | } 620 | 621 | private TResult Set32BitValueInBinaryStreamAndRead(Func act, int byteNumber, Int32 value) 622 | { 623 | // Arrange 624 | var bytes = new byte[400]; 625 | SetBigIndianValue(value, bytes, byteNumber); 626 | 627 | // Act 628 | using (var stream = new MemoryStream(bytes)) 629 | using (var reader = new BinaryReader(stream)) 630 | return act(Subject, reader); 631 | } 632 | 633 | private static void SetBigIndianValue(Int16 value, byte[] bytes, int byteNumber) 634 | { 635 | var samplesBytes = BitConverter.GetBytes(value); 636 | bytes[byteNumber - 1] = samplesBytes[1]; 637 | bytes[byteNumber] = samplesBytes[0]; 638 | } 639 | 640 | private static void SetBigIndianValue(Int32 value, byte[] bytes, int byteNumber) 641 | { 642 | var samplesBytes = BitConverter.GetBytes(value); 643 | bytes[byteNumber - 1] = samplesBytes[3]; 644 | bytes[byteNumber + 0] = samplesBytes[2]; 645 | bytes[byteNumber + 1] = samplesBytes[1]; 646 | bytes[byteNumber + 2] = samplesBytes[0]; 647 | } 648 | 649 | // TODO: Move AssertBytesConsumed to TDD lib 650 | public static void AssertBytesConsumed(Action act, int expectedNumberOfBytes) 651 | { 652 | var bytes = new byte[2 * expectedNumberOfBytes]; 653 | using (var stream = new MemoryStream(bytes)) 654 | using (var reader = new BinaryReader(stream)) 655 | { 656 | // Act 657 | act(reader); 658 | 659 | // Assert 660 | Assert.AreEqual(expectedNumberOfBytes, stream.Position, "Wrong number of bytes were consumed."); 661 | } 662 | } 663 | #endregion 664 | } 665 | } 666 | --------------------------------------------------------------------------------