surfaceio.hpp
Go to the documentation of this file.
1// $Id: surfaceio.hpp 1232 2014-01-13 12:22:40Z gudmundh $
2
3// Copyright (c) 2011, Norwegian Computing Center
4// All rights reserved.
5// Redistribution and use in source and binary forms, with or without modification,
6// are permitted provided that the following conditions are met:
7// • Redistributions of source code must retain the above copyright notice, this
8// list of conditions and the following disclaimer.
9// • Redistributions in binary form must reproduce the above copyright notice, this list of
10// conditions and the following disclaimer in the documentation and/or other materials
11// provided with the distribution.
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
13// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
15// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
16// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
17// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
19// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
20// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
22#ifndef NRLIB_SURFACEIO_HPP
23#define NRLIB_SURFACEIO_HPP
24
25#include <string>
26#include <vector>
27#include <locale>
28
29namespace NRLib {
30 template <class A> class RegularSurface;
31 template <class A> class RegularSurfaceRotated;
32 template <class A> class Grid2D;
33
34 const double MULT_IRAP_MISSING = -999.25;
35 const double IRAP_MISSING = 9999900.0;
36 const double STORM_MISSING = -999.0;
37
45 // SURF_PLAIN_ASCII
46 // SURF_CPS3_ASCII
47 };
48
51
54
55 template <class A>
56 void ReadStormBinarySurf(const std::string & filename,
57 RegularSurface<A> & surface);
58
59 template <class A>
60 void ReadIrapClassicAsciiSurf(const std::string & filename,
61 RegularSurface<A> & surface,
62 double & angle);
63
64 template <class A>
65 void ReadSgriSurf(const std::string & filename,
66 RegularSurface<A> & surface,
67 double & angle);
68
69 // If labels is non-empty, the labels of the axes on the file are compared with these. Throws if mismatch.
70 std::vector<RegularSurfaceRotated<float> > ReadMultipleSgriSurf(const std::string& filename,
71 const std::vector<std::string> & labels);
72
73 template <class A>
75 RegularSurface<A> & surface,
76 double x_ref,
77 double y_ref,
78 double lx,
79 double ly,
80 int * ilxl_area,
81 double il0_ref,
82 double xl0_ref);
83
84 template <class A>
86 double angle,
87 const std::string & filename);
88
89 template <class A>
91 const std::string & filename);
92
93 bool FindMulticolumnAsciiLine(const std::string& filename, int & header_start_line);
94
95 // void WritePointAsciiSurf(const RegularSurface<double>& surf,
96 // const std::string& filename);
97
98 namespace NRLibPrivate {
100 bool Equal(double a, double b);
101 }
102
103} // namespace NRLib
104
105 // ----------- TEMPLATE IMPLEMENTATIONS ----------------------
106
107#include <fstream>
108#include <string>
109
110#include "regularsurface.hpp"
111#include "surface.hpp"
112#include "../exception/exception.hpp"
113#include "../math/constants.hpp"
114#include "../iotools/fileio.hpp"
115#include "../iotools/stringtools.hpp"
116
117
118template<class A>
120 RegularSurface<A> & surface)
121{
122 std::ifstream file;
123 OpenRead(file, filename.c_str(), std::ios::in | std::ios::binary);
124
125 int line = 0;
126
127 // Header
128 try {
129 std::string token = ReadNext<std::string>(file, line);
130 if (token != "STORMGRID_BINARY") {
131 throw FileFormatError("Error reading " + filename + ", file is not "
132 "in STORM binary format.");
133 }
134
135 int ni = ReadNext<int>(file, line);
136 int nj = ReadNext<int>(file, line);
137 double dx = ReadNext<double>(file, line);
138 double dy = ReadNext<double>(file, line);
139 double x_min = ReadNext<double>(file, line);
140 double x_max = ReadNext<double>(file, line);
141 double y_min = ReadNext<double>(file, line);
142 double y_max = ReadNext<double>(file, line);
143
144 double lx = x_max - x_min;
145 double ly = y_max - y_min;
146
147 if (!NRLibPrivate::Equal(lx/(ni-1), dx)) {
148 throw FileFormatError("Inconsistent data in file. dx != lx/(nx-1).");
149 }
150 if (!NRLibPrivate::Equal(ly/(nj-1), dy)) {
151 throw FileFormatError("Inconsistent data in file. dy != ly/(ny-1).");
152 }
153
154 surface.Resize(ni, nj);
155 surface.SetDimensions(x_min, y_min, lx, ly);
156
157 DiscardRestOfLine(file, line, true);
158 ReadBinaryDoubleArray(file, surface.begin(), surface.GetN());
159
160 surface.SetMissingValue(static_cast<A>(STORM_MISSING));
161
162 if (!CheckEndOfFile(file)) {
163 throw FileFormatError("File too long.");
164 }
165
166 surface.SetName(GetStem(filename));
167 }
168 catch (EndOfFile& ) {
169 throw FileFormatError("Unexcpected end of file found while parsing "
170 " \"" + filename + "\"");
171 }
172 catch (Exception& e) {
173 throw FileFormatError("Error parsing \"" + filename + "\" as a "
174 "STORM surface file at line " + ToString(line) + ":" + e.what() + "\n");
175 }
176}
177
178
179template <class A>
181 RegularSurface<A> & surface,
182 double & angle)
183{
184 std::ifstream file;
185 OpenRead(file, filename);
186
187 int line = 0;
188 // Header
189 try {
190 ReadNext<int>(file, line); // -996
191 int nj = ReadNext<int>(file, line);
192 double dx = ReadNext<double>(file, line);
193 double dy = ReadNext<double>(file, line);
194 // ----------- line shift --------------
195 double x_min = ReadNext<double>(file, line);
196 double x_max = ReadNext<double>(file, line);
197 double y_min = ReadNext<double>(file, line);
198 double y_max = ReadNext<double>(file, line);
199 // ----------- line shift --------------
200 int ni = ReadNext<int>(file, line);
201 angle = ReadNext<double>(file, line);
202 angle = NRLib::Degree*angle;
203 ReadNext<double>(file, line); // rotation origin - x
204 ReadNext<double>(file, line); // rotation origin - y
205 // ----------- line shift --------------
206 ReadNext<int>(file, line);
207 ReadNext<int>(file, line);
208 ReadNext<int>(file, line);
209 ReadNext<int>(file, line);
210 ReadNext<int>(file, line);
211 ReadNext<int>(file, line);
212 ReadNext<int>(file, line);
213 //double lx = (ni-1)*dx;
214 //double ly = (nj-1)*dy;
215 double lx = (x_max - x_min)*cos(angle);
216 double ly = (y_max - y_min)*cos(angle);
217
218
219 if (!NRLibPrivate::Equal(lx/(ni-1), dx)) {
220 std::string text = "Inconsistent data in file. dx != lx/(nx-1).\n";
221 text += "dx = "+NRLib::ToString(dx,2)+"\n";
222 text += "lx = "+NRLib::ToString(lx,2)+"\n";
223 text += "nx = "+NRLib::ToString(ni,0)+"\n";
224 text += "lx/(nx-1) = "+NRLib::ToString(lx/(ni - 1),2);
225 throw FileFormatError(text);
226 }
227 if (!NRLibPrivate::Equal(ly/(nj-1), dy)) {
228 std::string text = "Inconsistent data in file. dy != ly/(ny-1).\n";
229 text += "dy = "+NRLib::ToString(dy,2)+"\n";
230 text += "ly = "+NRLib::ToString(ly,2)+"\n";
231 text += "ny = "+NRLib::ToString(nj,0)+"\n";
232 text += "ly/(ny-1) = "+NRLib::ToString(ly/(nj - 1),2);
233 throw FileFormatError(text);
234 }
235
236
237 surface.Resize(ni, nj);
238 surface.SetDimensions(x_min, y_min, lx, ly);
239
240 ReadAsciiArrayFast(file, surface.begin(), surface.GetN());
241
242 surface.SetMissingValue(static_cast<A>(IRAP_MISSING));
243
244 surface.SetName(GetStem(filename));
245
246 if (!CheckEndOfFile(file)) {
247 throw FileFormatError("File too long.");
248 }
249 }
250 catch (EndOfFile& ) {
251 throw FileFormatError("Unexcpected end of file found while parsing "
252 " \"" + filename + "\"");
253 }
254 catch (Exception& e) {
255 throw FileFormatError("Error parsing \"" + filename + "\" as a "
256 "IRAP ASCII surface file at line " + ToString(line) + ":" + e.what() + "\n");
257 }
258}
259
260
261template<class A>
262void NRLib::ReadSgriSurf(const std::string & filename,
263 RegularSurface<A> & surface,
264 double & angle)
265{
266 std::ifstream header_file;
267 OpenRead(header_file, filename.c_str(), std::ios::in | std::ios::binary);
268 int i;
269 std::string tmp_str;
270 int dim;
271 try {
272 //Reading record 1: Version header
273 getline(header_file, tmp_str);
274 //Reading record 2: Grid dimension
275 header_file >> dim;
276 if(dim!=2)
277 throw Exception("Wrong dimension of Sgri file. We expect a surface, dimension should be 2.\n");
278
279 getline(header_file, tmp_str);
280 //Reading record 3 ... 3+dim: Axis labels + grid value label
281 std::vector<std::string> axis_labels(dim);
282 for (i=0; i<dim; i++)
283 getline(header_file, axis_labels[i]);
284 if (((axis_labels[0].find("X") == std::string::npos) && (axis_labels[0].find("x") == std::string::npos)) ||
285 ((axis_labels[1].find("Y") == std::string::npos) && (axis_labels[1].find("y") == std::string::npos)))
286 throw Exception("Wrong axis labels. First axis should be x-axis, second axis should be y-axis.\n");
287 // if((axis_labels[0]!="X" && axis_labels[0] !="x") || (axis_labels[1]!="Y" && axis_labels[1]!="y"))
288 // throw Exception("Wrong axis labels. First axis should be x-axis, second axis should be y-axis.\n");
289 getline(header_file, tmp_str);
290 //int config = IMISSING;
291
292 //Reading record 4+dim: Number of grids
293 int n_grid;
294 header_file >> n_grid;
295 if (n_grid < 1) {
296 throw Exception("Error: Number of grids read from sgri file must be >0");
297 }
298 getline(header_file, tmp_str);
299 //Reading record 5+dim ... 5+dim+ngrid-1: Grid labels
300
301 for (i=0; i<n_grid; i++)
302 getline(header_file, tmp_str);
303
304 std::vector<float> d_values1(dim);
305 std::vector<float> d_values2(dim);
306 std::vector<int> i_values(dim);
307 //Reading record 5+dim+ngrid: Scaling factor of grid values
308 for (i=0; i<dim; i++)
309 header_file >> d_values1[i];
310 getline(header_file,tmp_str);
311 //Reading record 6+dim+ngrid: Number of samples in each dir.
312 for (i=0; i<dim; i++)
313 header_file >> i_values[i];
314 getline(header_file,tmp_str);
315 //Reading record 7+dim+ngrid: Grid sampling in each dir.
316 for (i=0; i<dim; i++) {
317 header_file >> d_values2[i];
318 }
319 getline(header_file,tmp_str);
320 //Reading record 8+dim+ngrid: First point coord.
321 std::vector<float> min_values(dim);
322 for (i=0; i<dim; i++)
323 {
324 header_file >> min_values[i];
325 }
326 int nx = 1;
327 int ny = 1;
328
329 double dx, dy;
330 nx = i_values[0];
331 dx = d_values2[0];
332 ny = i_values[1];
333 dy = d_values2[1];
334
335 if (nx < 1) {
336 throw Exception("Error: Number of samples in X-dir must be >= 1.\n");
337 }
338 if (ny < 1) {
339 throw Exception("Error: Number of samples in Y-dir must be >= 1.\n");
340 }
341
342 if (dx <= 0.0) {
343 throw Exception("Error: Grid sampling in X-dir must be > 0.0.\n");
344
345 }
346 if (dy <= 0.0) {
347 throw Exception("Error: Grid sampling in Y-dir must be > 0.0.\n");
348 }
349
350 double lx = nx*dx;
351 double ly = ny*dy;
352
353 double x_min = min_values[0]-0.5*dx; //In regular grid, these are at value;
354 double y_min = min_values[1]-0.5*dy; //in sgri, at corner of cell, hence move.
355
356 header_file >> angle;
357
358 surface.Resize(nx, ny, 0.0);
359 surface.SetDimensions(x_min, y_min, lx, ly);
360
361 getline(header_file, tmp_str);
362 //Reading record 10+dim+ngrid: Undef value
363 float missing_code;
364 header_file >> missing_code;
365 surface.SetMissingValue(missing_code);
366 getline(header_file, tmp_str);
367 //Reading record 11+dim+ngrid: Filename of binary file
368 std::string bin_file_name;
369 getline(header_file, tmp_str);
370 if (!tmp_str.empty()) {
371 std::locale loc;
372 int i = 0;
373 char c = tmp_str[i];
374 while (!std::isspace(c,loc)) {
375 i++;
376 c = tmp_str[i];
377 }
378 tmp_str.erase(tmp_str.begin()+i, tmp_str.end());
379 }
380 if (tmp_str.empty())
381 bin_file_name = NRLib::ReplaceExtension(filename, "Sgri");
382 else {
383 std::string path = GetPath(filename);
384 bin_file_name = path + "/" + tmp_str;
385 }
386 //Reading record 12+dim+ngrid: Complex values
387 bool has_complex;
388 header_file >> has_complex;
389 if (has_complex != 0 ) {
390 throw Exception("Error: Can not read Sgri binary file. Complex values?");
391 }
392
393 surface.SetName(GetStem(bin_file_name));
394
395 std::ifstream bin_file;
396 OpenRead(bin_file, bin_file_name, std::ios::in | std::ios::binary);
397 ReadBinaryFloatArray(bin_file, surface.begin(), surface.GetN());
398 }
399 catch (Exception& e) {
400 throw FileFormatError("Error parsing \"" + filename + "\" as a "
401 "Sgri surface file " + e.what() + "\n");
402 }
403}
404
405template <class A>
407 RegularSurface<A> & surface,
408 double x_ref,
409 double y_ref,
410 double lx,
411 double ly,
412 int * ilxl_area,
413 double il0_ref,
414 double xl0_ref)
415{
416
417 try {
418 //Create surface with area corresponding to segy-grid (ilxl_area), but use sampling from surface file
419 //il0_ref and xl0_ref are il/xl values at rotation corner, this is used to match IL/XL values from surface with segy
420
421 int header_start_line;
422 bool is_multicolumn_ascii = false;
423 is_multicolumn_ascii = FindMulticolumnAsciiLine(filename, header_start_line);
424
425 if (is_multicolumn_ascii == false)
426 throw Exception("Error: Did not recognize file as a multicolumns ascii file.\n");
427
428 std::ifstream file;
429 NRLib::OpenRead(file, filename);
430 int line = 0;
431
432 for (int i = 0; i < header_start_line; i++) {
433 NRLib::DiscardRestOfLine(file, line, false);
434 }
435
436 //Header line, contains X, Y, Z, Inline, Crossline
437 std::vector<std::string> variable_names(5);
438 variable_names[0] = NRLib::ReadNext<std::string>(file, line);
439 variable_names[1] = NRLib::ReadNext<std::string>(file, line);
440 variable_names[2] = NRLib::ReadNext<std::string>(file, line);
441 variable_names[3] = NRLib::ReadNext<std::string>(file, line);
442 variable_names[4] = NRLib::ReadNext<std::string>(file, line);
443
444 std::vector<std::vector<double> > data(5);
445
446 while (NRLib::CheckEndOfFile(file)==false) {
447 for (int i = 0; i < 5; i++) {
448 data[i].push_back(NRLib::ReadNext<double>(file, line));
449 }
450 }
451
452 int il_index = -1;
453 int xl_index = -1;
454 int x_index = -1;
455 int y_index = -1;
456 int z_index = -1;
457 for (int i = 0; i < 5; i++) {
458 if (variable_names[i] == "Inline" || variable_names[i] == "IL")
459 il_index = i;
460 if (variable_names[i] == "Crossline" || variable_names[i] == "XL")
461 xl_index = i;
462 if (variable_names[i] == "X" || variable_names[i] == "UTMX")
463 x_index = i;
464 if (variable_names[i] == "Y" || variable_names[i] == "UTMY")
465 y_index = i;
466 if (variable_names[i] == "Attribute" || variable_names[i] == "Z" || variable_names[i] == "TWT")
467 z_index = i;
468 }
469
470 std::string err_txt = "";
471 if (il_index == -1)
472 err_txt += "Could not find variable name for Inline in file " + filename +". (Tried Inline, IL).\n";
473 if (xl_index == -1)
474 err_txt += "Could not find variable name for Crossline in file " + filename +". (Tried Crossline, XL).\n";
475 if (x_index == -1)
476 err_txt += "Could not find variable name for X in file " + filename +". (Tried X, UTMX).\n";
477 if (y_index == -1)
478 err_txt += "Could not find variable name for Y in file " + filename +". (Tried Y, UTMY).\n";
479 if (z_index == -1)
480 err_txt += "Could not find variable name for Attribute in file " + filename +". (Tried Attribute, Z, TWT).\n";
481
482 if (err_txt != "")
483 throw Exception("Error when finding header information in " + filename + " :" + err_txt + "\n");
484
485 std::vector<double> il_vec = data[il_index];
486 std::vector<double> xl_vec = data[xl_index];
487 std::vector<double> x_vec = data[x_index];
488 std::vector<double> y_vec = data[y_index];
489 std::vector<double> z_vec = data[z_index];
490
491 //Find min and max IL/XL
492 std::vector<double> il_vec_sorted = il_vec;
493 std::sort(il_vec_sorted.begin(), il_vec_sorted.end());
494 il_vec_sorted.erase(std::unique(il_vec_sorted.begin(), il_vec_sorted.end()), il_vec_sorted.end());
495
496 std::vector<double> xl_vec_sorted = xl_vec;
497 std::sort(xl_vec_sorted.begin(), xl_vec_sorted.end());
498 xl_vec_sorted.erase(std::unique(xl_vec_sorted.begin(), xl_vec_sorted.end()), xl_vec_sorted.end());
499
500 int ni_file = static_cast<int>(il_vec_sorted.size());
501 int nj_file = static_cast<int>(xl_vec_sorted.size());
502
503 int il_min_file = static_cast<int>(il_vec_sorted[0]);
504 int il_max_file = static_cast<int>(il_vec_sorted[ni_file-1]);
505
506 int xl_min_file = static_cast<int>(xl_vec_sorted[0]);
507 int xl_max_file = static_cast<int>(xl_vec_sorted[nj_file-1]);
508
509 int n = static_cast<int>(data[0].size());
510 A missing = static_cast<A>(NRLib::MULT_IRAP_MISSING);
511
512 NRLib::Grid2D<A> ilxl_grid_file(ni_file, nj_file, missing);
513
514 int d_il_file = static_cast<int>((il_max_file - il_min_file) / (ni_file - 1));
515 int d_xl_file = static_cast<int>((xl_max_file - xl_min_file) / (nj_file - 1));
516
517 for (int k = 0; k < n; k++) {
518 //Local IL/XL
519 int il_loc = (static_cast<int>(data[il_index][k]) - il_min_file)/d_il_file;
520 int xl_loc = (static_cast<int>(data[xl_index][k]) - xl_min_file)/d_xl_file;
521
522 ilxl_grid_file(il_loc, xl_loc) = static_cast<A>(data[z_index][k]);
523 }
524
525 //Check consistency between IL/XL sampling in surface and sampling of grid values
526 int t1 = 0;
527 int t2 = 0;
528 for (int i = 0; i < ni_file; i++) {
529 if (ilxl_grid_file(i,nj_file/2) != missing) {
530 t1 = i;
531 for (int k = t1+1; k < ni_file; k++) {
532 if (ilxl_grid_file(k,nj_file/2) != missing) {
533 t2 = k;
534 k = ni_file-1;
535 i = ni_file-1;
536 }
537 }
538 }
539 }
540 int diff_il = (t2 - t1)*d_il_file;
541 t1 = 0;
542 t2 = 0;
543 for (int j = 0; j < nj_file; j++) {
544 if (ilxl_grid_file(ni_file/2,j) != missing) {
545 t1 = j;
546 for (int k = t1+1; k < nj_file; k++) {
547 if (ilxl_grid_file(ni_file/2,k) != missing) {
548 t2 = k;
549 k = nj_file-1;
550 j = nj_file-1;
551 }
552 }
553 }
554 }
555 int diff_xl = (t2 - t1)*d_xl_file;
556
557 if (diff_il != d_il_file) {
558 err_txt += "Found sampling of IL-values to be " + NRLib::ToString(d_il_file) +
559 ", but grid values are given with a IL-sampling of " + NRLib::ToString(diff_il) + ".\n";
560 }
561 if (diff_xl != d_xl_file) {
562 err_txt += "Found sampling of XL-values to be " + NRLib::ToString(d_xl_file) +
563 ", but grid values are given with a XL-sampling of " + NRLib::ToString(diff_xl) + ".\n";
564 }
565
566 if (err_txt != "")
567 throw Exception(err_txt);
568
569 int il_min_segy = ilxl_area[0];
570 int il_max_segy = ilxl_area[1];
571 int xl_min_segy = ilxl_area[2];
572 int xl_max_segy = ilxl_area[3];
573 int il_step_segy = ilxl_area[4];
574 int xl_step_segy = ilxl_area[5];
575
576 //Create IL/XL surface as large as segy geometry, but with sampling from file
577 int n_il = (il_max_segy - il_min_segy)/d_il_file + 1;
578 int n_xl = (xl_max_segy - xl_min_segy)/d_xl_file + 1;
579
580 //Find IL/XL of rotation corner
581 int il0_segy = static_cast<int>(il0_ref+0.5);
582 int xl0_segy = static_cast<int>(xl0_ref+0.5);
583
584 // To ensure that the IL XL we find are existing traces
585 if (il0_segy < il_min_segy)
586 il0_segy -= (il0_segy - il_min_segy) % il_step_segy;
587 else if (il0_segy > il_max_segy)
588 il0_segy += (il_max_segy - il0_segy) % il_step_segy;
589
590 if (xl0_segy < xl_min_segy)
591 xl0_segy -= (xl0_segy - xl_min_segy) % xl_step_segy;
592 else if (xl0_segy > xl_max_segy)
593 xl0_segy += (xl_max_segy - xl0_segy) % xl_step_segy;
594
595 NRLib::Grid2D<A> surface_grid(n_il, n_xl, static_cast<A>(NRLib::MULT_IRAP_MISSING));
596 int grid_i, grid_j;
597 for (int i = 0; i < n_il; i++) {
598 for (int j = 0; j < n_xl; j++) {
599
600 //Global IL/XL of surface_grid
601 int il_glob = il_min_segy + i*d_il_file;
602 int xl_glob = xl_min_segy + j*d_xl_file;
603
604 //Get corresponding IL/XL from file_grid
605 int il_loc_file = (il_glob - il_min_file)/d_il_file;
606 int xl_loc_file = (xl_glob - xl_min_file)/d_xl_file;
607
608 //If surface is smaller than segy-grid, we set is as missing
609 A z;
610 if (il_loc_file < 0 || il_loc_file > ni_file-1 || xl_loc_file < 0 || xl_loc_file > nj_file-1)
611 z = missing;
612 else
613 z = ilxl_grid_file(il_loc_file, xl_loc_file);
614
615 //Fill in correct corner
616 if (il0_segy == il_min_segy && xl0_segy == xl_min_segy) {
617 grid_i = i;
618 grid_j = j;
619 }
620 else if (il0_segy == il_max_segy && xl0_segy == xl_max_segy) {
621 grid_i = n_il - i - 1;
622 grid_j = n_xl - j - 1;
623 }
624 else if (il0_segy == il_min_segy && xl0_segy == xl_max_segy) {
625 grid_i = i;
626 grid_j = n_xl - j - 1;
627 }
628 else { //il0_segy == il_max_segy && xl0_segy == xl_min_segy
629 grid_i = n_il - i - 1;
630 grid_j = j;
631 }
632
633 surface_grid(grid_i, grid_j) = z;
634 }
635 }
636
637 surface = RegularSurface<A>(x_ref, y_ref, lx, ly, surface_grid);
638 surface.SetMissingValue(static_cast<A>(MULT_IRAP_MISSING));
639 surface.SetName(GetStem(filename));
640 }
641 catch (Exception& e) {
642 throw FileFormatError("Error parsing \"" + filename + "\" as a "
643 "Multicolumn ASCII file: \n" + e.what() + "\n");
644 }
645
646}
647
648
649template <class A>
651 double angle,
652 const std::string & filename)
653{
654 std::ofstream file;
655 OpenWrite(file, filename);
656
657 file << std::fixed
658 << std::setprecision(6)
659 << -996 << " "
660 << surf.GetNJ() << " "
661 << surf.GetDX() << " "
662 << surf.GetDY() << "\n"
663 << std::setprecision(2)
664 << surf.GetXMin() << " "
665 << surf.GetXMax() << " "
666 << surf.GetYMin() << " "
667 << surf.GetYMax() << "\n"
668 << surf.GetNI() << " "
669 << std::setprecision(6)
670 << angle*180/NRLib::Pi << " "
671 << std::setprecision(2)
672 << surf.GetXMin() << " "
673 << surf.GetYMin() << "\n"
674 << " 0 0 0 0 0 0 0\n";
675
676 file.precision(6);
677
678 if (surf.GetMissingValue() == IRAP_MISSING) {
679 for (size_t i = 0; i < surf.GetN(); i++) {
680 file << surf(i) << " ";
681 if((i+1) % 6 == 0)
682 file << "\n";
683 }
684 }
685 else {
686 for (size_t i = 0; i < surf.GetN(); i++) {
687 if (surf.IsMissing(surf(i)))
688 file << IRAP_MISSING << " ";
689 else
690 file << surf(i) << " ";
691 if((i+1) % 6 == 0)
692 file << "\n";
693 }
694 }
695 file.close();
696}
697
698
699template <class A>
701 const std::string & filename)
702{
703 std::ofstream file;
704 OpenWrite(file, filename.c_str(), std::ios::out | std::ios::binary);
705
706 file.precision(14);
707
708 file << "STORMGRID_BINARY\n\n"
709 << surf.GetNI() << " " << surf.GetNJ() << " "
710 << surf.GetDX() << " " << surf.GetDY() << "\n"
711 << surf.GetXMin() << " " << surf.GetXMax() << " "
712 << surf.GetYMin() << " " << surf.GetYMax() << "\n";
713
714 if (surf.GetMissingValue() == STORM_MISSING) {
715 // Purify *sometimes* claims a UMR for the call below. No-one understands why...
716 WriteBinaryDoubleArray(file, surf.begin(), surf.end());
717 }
718 else {
719 std::vector<double> data(surf.GetN());
720 std::copy(surf.begin(), surf.end(), data.begin());
721 std::replace(data.begin(), data.end(), surf.GetMissingValue(), static_cast<A>(STORM_MISSING));
722 WriteBinaryDoubleArray(file, data.begin(), data.end());
723 }
724 file.close();
725}
726
727#endif // NRLIB_SURFACEIO_HPP
const cJSON *const b
Definition: cJSON.h:251
char const int const cJSON_bool format
Definition: cJSON.h:161
const char *const string
Definition: cJSON.h:170
Definition: exception.hpp:80
Definition: exception.hpp:34
Definition: exception.hpp:71
Definition: grid2d.hpp:32
size_t GetN() const
Definition: grid2d.hpp:63
iterator end()
Definition: grid2d.hpp:56
size_t GetNI() const
Definition: grid2d.hpp:61
iterator begin()
Definition: grid2d.hpp:55
size_t GetNJ() const
Definition: grid2d.hpp:62
Definition: regularsurface.hpp:39
bool IsMissing(A val) const
Check if grid value is missing.
Definition: regularsurface.hpp:203
double GetDX() const
Definition: regularsurface.hpp:191
void SetDimensions(double x_min, double y_min, double lx, double ly)
Definition: regularsurface.hpp:774
double GetXMin() const
Definition: regularsurface.hpp:187
double GetYMin() const
Definition: regularsurface.hpp:188
double GetDY() const
Definition: regularsurface.hpp:192
A GetMissingValue() const
Definition: regularsurface.hpp:222
void SetMissingValue(A missing_val)
Definition: regularsurface.hpp:223
double GetXMax() const
Definition: regularsurface.hpp:189
void Resize(size_t ni, size_t nj, const A &val=A())
Resize grid. Overrides Grid2D's resize.
Definition: regularsurface.hpp:789
double GetYMax() const
Definition: regularsurface.hpp:190
void SetName(const std::string &name)
Definition: regularsurface.hpp:226
bool Equal(double a, double b)
Definition: exception.hpp:31
std::string GetPath(const std::string &filename)
Get the path from a full file name.
I ReadBinaryFloatArray(std::istream &stream, I begin, size_t n, Endianess number_representation=END_BIG_ENDIAN)
Read an array of 4-byte floats on standard IEEE format.
Definition: fileio.hpp:688
void WriteIrapClassicAsciiSurf(const RegularSurface< A > &surf, double angle, const std::string &filename)
Definition: surfaceio.hpp:650
I ReadAsciiArrayFast(std::istream &stream, I begin, size_t n)
Gets sequence with elements of type T from input stream. Does no type checking, and does not count li...
Definition: fileio.hpp:481
const double STORM_MISSING
Definition: surfaceio.hpp:36
std::vector< RegularSurfaceRotated< float > > ReadMultipleSgriSurf(const std::string &filename, const std::vector< std::string > &labels)
void ReadIrapClassicAsciiSurf(const std::string &filename, RegularSurface< A > &surface, double &angle)
Definition: surfaceio.hpp:180
void ReadSgriSurf(const std::string &filename, RegularSurface< A > &surface, double &angle)
Definition: surfaceio.hpp:262
SurfaceFileFormat FindSurfaceFileType(const std::string &filename)
Find type of file.
std::string GetStem(const std::string &filename)
Get the stem of the filename (filename without path and extension)
void WriteStormBinarySurf(const RegularSurface< A > &surf, const std::string &filename)
Definition: surfaceio.hpp:700
I ReadBinaryDoubleArray(std::istream &stream, I begin, size_t n, Endianess number_representation=END_BIG_ENDIAN)
Read an array of 8-byte floats on standard IEEE format.
Definition: fileio.hpp:758
const double MULT_IRAP_MISSING
Definition: surfaceio.hpp:34
SurfaceFileFormat
Definition: surfaceio.hpp:38
@ SURF_STORM_BINARY
Definition: surfaceio.hpp:41
@ SURF_SGRI
Definition: surfaceio.hpp:42
@ SURF_RMS_POINTS_ASCII
Definition: surfaceio.hpp:43
@ SURF_UNKNOWN
Definition: surfaceio.hpp:39
@ SURF_IRAP_CLASSIC_ASCII
Definition: surfaceio.hpp:40
@ SURF_MULT_ASCII
Definition: surfaceio.hpp:44
void DiscardRestOfLine(std::istream &stream, int &line_num, bool throw_if_non_whitespace)
Reads and discard all characters until and including next newline.
bool FindMulticolumnAsciiLine(const std::string &filename, int &header_start_line)
void ReadMulticolumnAsciiSurf(std::string filename, RegularSurface< A > &surface, double x_ref, double y_ref, double lx, double ly, int *ilxl_area, double il0_ref, double xl0_ref)
Definition: surfaceio.hpp:406
std::string GetSurfFormatString(SurfaceFileFormat format)
String describing file format.
std::string ReplaceExtension(const std::string &filename, const std::string &extension)
Replace file extension.
bool CheckEndOfFile(std::istream &stream)
Check if end of file is reached. Discards all whitespace before end of file or next token.
void WriteBinaryDoubleArray(std::ostream &stream, I begin, I end, Endianess number_representation=END_BIG_ENDIAN)
Write an array of 8-byte floats on standard IEEE format.
Definition: fileio.hpp:726
void OpenWrite(std::ofstream &stream, const std::string &filename, std::ios_base::openmode mode=std::ios_base::out, bool create_dir=true)
Open file for writing.
const double IRAP_MISSING
Definition: surfaceio.hpp:35
void OpenRead(std::ifstream &stream, const std::string &filename, std::ios_base::openmode mode=std::ios_base::in)
Open file for reading.
std::string ToString(const T obj, int precision=-99999)
Definition: stringtools.hpp:177
void ReadStormBinarySurf(const std::string &filename, RegularSurface< A > &surface)
Definition: surfaceio.hpp:119
static const double e
Definition: exprtk.hpp:758
x y * z
Definition: exprtk.hpp:9663
static std::string data()
Definition: exprtk.hpp:40022