johnkris

model.pm

Oct 9th, 2025
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 143.57 KB | None | 0 0
  1.  
  2. ###################################
  3. # THIS PROGRAMM IS DOCUMENTED WITH INLINE PODs
  4. # There are different comments for users and programmers
  5. # Extract pod with
  6. # USERs:       sed '/=PROG/,/=cut/d' p.pl | sed 's/=USER/=/g' | pod2html
  7. # PROGRAMMERs: sed '/=USER/,/=cut/d' p.pl | sed 's/=PROG/=/g' | pod2html
  8. ###################################
  9.  
  10.  
  11. =PROGhead1 NAME model.pm
  12.  
  13. model - containing objects to represent a rayinvr model used by p.pl
  14.  
  15. =cut
  16.  
  17.  
  18. {
  19. ########################################################################
  20. package model;
  21. use strict;
  22. use warnings;
  23. use Carp;
  24. use lib '/opt/pray/lib';
  25. use Carp qw(cluck);
  26. use feature qw(switch say);
  27. use POSIX ('ceil', 'floor');
  28. use Data::Dumper;
  29. use Graphics-ColorUtils;
  30. use Math::Round;
  31. use File::Copy;
  32.  
  33. use layer;
  34. use floatingReflector.pm;
  35. use station;
  36. use codes;
  37.  
  38.  
  39. #use Tk::Animation;
  40. #use Tk::Splashscreen;
  41.  
  42.  
  43. =PROGhead1 C<model>
  44.  
  45. Draws rayinvr-model for seismic refraction data, keeps data storage, do
  46. administration
  47.  
  48. =PROGhead2 Tomo2D
  49.  
  50. =begin html
  51.  
  52. 'model' can also be used for viewing data from tomo2D. Reading tomo-data
  53. is started with button 'Tomo2D' from main PRay GUI which invokes
  54. <code>
  55. model->tomo [\&model::tomo, $model, "tomorays", \"1"]
  56. </code>
  57.  
  58.  
  59. =end html
  60.  
  61. =PROGhead2 Model keys
  62.  
  63.  contours
  64.  d2
  65.  km1
  66.  debug
  67.  profilelength
  68.  stationpositions
  69.  raycode
  70.  balloon
  71.  layers
  72.  d1
  73.  tmin
  74.  km2
  75.  tmax
  76.  stations
  77.  vredstate
  78.  layer
  79.  vgrid
  80.  zmax
  81.  tomotimes
  82.  ytscale
  83.  vred
  84.  foo
  85.  nodes
  86.  box
  87.  phasecodes r
  88.  ays
  89.  PicksCal
  90.  readStr
  91.  time
  92.  t1
  93.  t2
  94.  PicksMan
  95.  zmin
  96.  drawnStations
  97.  canvasheigth
  98.  xscale
  99.  canvaswidth
  100.  yscale
  101.  ShowRays
  102.  version
  103.  vnodes
  104.  xmin
  105.  space
  106.  drawnPhases
  107.  xmax
  108.  config
  109.  tomoGrid
  110.  tomorays
  111.  phasecolors
  112.  
  113. DEBUGING
  114.  
  115. All station objects are stored in the hash $model->{stations}
  116. x keys(%{$model->{stations}}) with position-km as hashkey.
  117. e.g.:
  118.  
  119.  DB<17> x keys(%{$model->{stations}})                                                                                  
  120.  0  250.000
  121.  1  89.300
  122.  2  175.000
  123.  3  25.000
  124.  4  225.000
  125.  5  50.000
  126.  6  275.000
  127.  7  200.000
  128.  8  100.000
  129.  9  125.000
  130.  10  150.000
  131.  
  132.  
  133.  DB<6> x $model->getStation(127) Gives you the stationreference
  134.  
  135. =cut
  136.  
  137. our ($tree, $debug, $dev, $verbose, $quiet);  # Debugging and verbosity variables
  138.  
  139.  
  140. sub new {
  141.  
  142. =PROGhead2 C<model::new(%args)>
  143.  
  144. A new model is born, blessed and issued with configuration values. Only argements,
  145. which are also defined in %defaults are allowed.
  146.  
  147.     my $model = new model('space'=> $cns, "time" => $lzd,
  148.             "balloon" => $balloon,
  149.             "zmin" => $config{zmin}, "zmax" => $config{zmax},
  150.             "yscale" => $yscale, "ytscale" => $ytscale, "xscale" => $xscale,
  151.             );
  152.  
  153. In Future it shall be:
  154.  
  155.     my $model = new model(
  156.             ["reverseStation" => (1/0)],    stationfile => statxz,
  157.             "working dir" => ... , tmin, tmax
  158.             "zmin" => $config{zmin}, "zmax" => $config{zmax},
  159.             );
  160.  
  161. =cut
  162.  
  163.     #print "model::new()\n";
  164.     my ($class, %args) = @_;
  165.     my $model = bless ({}, $class);
  166.     $model->{rays}=undef;
  167.     #$model->init(%args);
  168.    
  169.     # old $model->init function:
  170.     # Define default parameters for a model object
  171.     my %defaults = ( "space"        => undef,   # canvas for model
  172.                      "time"         => undef,   # canvas for ttdiagramm
  173.                      "statusline"    => undef,  # GUI status line
  174.                      "mainwindow"   => undef,   # MAIN WINDOW
  175.                      "splash"       => undef,
  176.                      "icons"        => undef,
  177.                      "balloon"      => undef,   # window, needed for balloons
  178.                      "init"         => -1,      # Is this model initialized? -1 no, 0 yes, 1 currently initializing
  179.                      "layer"        => 0,       # ??? obsolete??
  180.                      "layers"       => undef,   # array for storing layer objects
  181.                      "profilelength"=>  undef,
  182.                      "box"          => undef,
  183.                      "foo"          => "bar",
  184.                      "zmin"     => undef,
  185.                      "zmax"     => undef,
  186.                      "xscale"       => undef,
  187.                      "yscale"       => undef,
  188.                      "ytscale"      => undef,
  189.                      "vred"         => 3,
  190.                      "vredstate"    => 1,
  191.                      "canvaswidth"  => 1600,    # Width of cavas for time and model
  192.                      "canvasheigth" => 400,     # Heigth of cavas for time and model
  193.                      "tmin"         => 0,
  194.                      "tmax"         => 12,
  195.                      "stations"     => undef,   # refernce hash with links to stations
  196.                      "stationpositions" => undef, # hash with names and positions of stations
  197.                      "stationkm" => undef,        # hash with positions and names of stations
  198.                      "drawnStations" => [],
  199.                      "phasecolors"      => { "00" => "darkgrey",
  200.                                          "12" => "red",
  201.                                          "21" => "green",
  202.                                          "22" => "blue",
  203.                                          "31" => "orange",
  204.                                          "32" => "black",
  205.                                          "41" => "yellow",
  206.                                          "42" => "springgreen",
  207.                                          "51" => "green",
  208.                                          "52" => "blue",
  209.                                          "61" => "orange",
  210.                                          "62" => "black",
  211.                                          "71" => "yellow",
  212.                                          "72" => "springgreen",                                        
  213.                                      },
  214.                     # colors for phases and layer boundarys.
  215.                      "nodes"        => 1,       # Show and edit nodes
  216.                      "vnodes"       => 0,       # Show and edit vnodes
  217.                      "annotvnodes"  => 1,
  218.                      "drawnPhases"  => undef,   # which phases should be drawn
  219.                      "drawnRays"    => undef,   # which rays should be drawn
  220.                      "PicksMan"     => 1,       # Show manual picks?
  221.                      "PicksCal"     => 1,       # Show calculated picks?
  222.                      "vgrid"        => 0,
  223.                      "config"       => undef,   # Reference to configurationhash
  224.                      "rin"          => undef,   # Reference to rin
  225.                      "contours"     => 0,
  226.                      "contourcolor" => 0,
  227.                      "blocks"       => 0,
  228.                      "debug"        => undef,
  229.                      "ShowRays"     => 1,       # Show rays? Usefull when too many raypathes block view on model
  230.                      "phasecodes"   => { 21 => 2.1},    #conversion of phasecodes between ZP and RI
  231.                      "raycode"  => { 2.1 => 21},    #conversion of phasecodes between ZP and RI
  232.                      "tomorays" => 0,   # TEMPORARY
  233.                      "tomoGrid" => 0,   # Inital value for displaying tomogrid
  234.                      "tomotimes" => 0, # Flag for read tomo2D traveltime data
  235.                      "version" => '',  # Save model version
  236.                      "glueNodes" => 1, # Moving pinched nodes together?
  237.                      "xz" => 0,         # Show xz overlay files?
  238.                      "xt" => 0,         # Show xt overlay files?
  239.                      "igmasCoords" => {},   # Hash to store igmas coordinates  (see layer->getIgmasCoordintes()
  240.                      "densities" => 0,  # Annotate vnodes with densities after Barton
  241.                      "resolution" => 0,
  242.                      "codes" => undef, # Store codes object
  243.     );
  244.    
  245.     foreach (keys(%defaults)){
  246.         #print "Setting default for $_ -> $defaults{$_}\n";
  247.         $model->{$_}=$defaults{$_};
  248.     }
  249.    
  250.  
  251.     foreach (keys(%args)){
  252.         say "initModel:  $_  $args{$_}" if $debug;
  253.         croak "Unknown attribute <$_> for station initialization" unless exists $defaults{$_};
  254.         $model->{$_} = $args{$_};
  255.     }
  256.  
  257.     #foreach (keys(%{$model->{config}})) {
  258.         #say "initModel: apply config $_ $model->{config}->{$_}";
  259.         #$model->{$_} = $model->{config}->{$_} if exists $defaults{$_};
  260.     #}
  261.    
  262.     $model->{vred} = $model->{config}->{vred};
  263.    
  264.     $model->{box} = [0, 0, $model->{canvaswidth}, $model->{canvasheigth}];  # Size of model and runtimediagram in px
  265.  
  266.     # Setup scale parameters
  267.     $model->{km1} = $model->{config}->{xmin};
  268.     $model->{km2} = $model->{config}->{xmax} ;
  269.     $model->{d1} = $model->{config}->{zmin};
  270.     $model->{d2} = $model->{config}->{zmax};
  271.     $model->{t1} = $model->{config}->{tmin};
  272.     $model->{t2} = $model->{config}->{tmax};
  273.    
  274.     $model->{xmin} = $model->{config}->{xmin};
  275.     $model->{xmax} = $model->{config}->{xmax};
  276.     $model->{profilelength} = $model->{xmax} - $model->{xmin};
  277.    
  278.     my $cns = $model->{space};
  279.  
  280.     #say "Exit initalization of your model";
  281.     #print Dumper \$model->{color};
  282.    
  283.     # Setup debugging variables
  284.     $tree  = $model->{debug}->{tree};
  285.     $debug = $model->{debug}->{debug};
  286.     $dev   = $model->{debug}->{dev};
  287.     $verbose = $model->{debug}->{verbose};
  288.     $quiet = $model->{debug}->{quiet};
  289.  
  290.     return $model;
  291.  
  292. }
  293. sub init {
  294.  
  295. =PROGhead2 C<model::init(%args)>
  296.  
  297. Creates startup-splash (if configured) and reads model data. Currently
  298. started from C<p.pl>. Cannot be run by model->new because stations need
  299. to be defined in the model.
  300.  
  301. =cut
  302.  
  303.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  304.  
  305.     my ($model, %args) = @_;
  306.  
  307.     my $splash;
  308.     my $mw;
  309.    
  310.     # Display splash screen if switched on in configuration file
  311.     if ( $model->{config}->{splash} == 1) {
  312.         print "Display splash screen\n";
  313.         $model->_set("init", 1);  
  314.         $mw = $model->_get("mainwindow");
  315.        
  316.         # Make splash screen
  317.         $splash = $mw->Splashscreen;
  318.    
  319.         $mw->withdraw;
  320.         $splash->Splash;                     # show Splashscreen
  321.        
  322.         $splash->Label(-text => 'Building your Model ...', -bg => 'blue')->
  323.             pack(qw/-fill both -expand 1/);
  324.        
  325.            
  326.         my $animate;
  327.         if (@ARGV) {
  328.             $animate = $mw->Animation;
  329.             foreach (@ARGV) {
  330.                 $animate->add_frame($mw->Photo(-file => $_));
  331.             }
  332.         } else {
  333.             #my $gif89 = Tk->findINC('anim.gif');
  334.             my $icons = $model->_get("icons");
  335.             my $gif89 = "$icons/Praysplash.gif";
  336.             #my $gif89 = '/projects/nam2011/bin/pray/icons/Praysplash.gif';
  337.             print "Take gif $gif89\n";
  338.             $animate = $mw->Animation(-format => 'gif', -file => $gif89);
  339.         }
  340.         $animate->set_image(0);
  341.         $animate->start_animation;
  342.    
  343.        
  344.         $splash->Label(-text => "Button me",
  345.             #-image => $mw->Photo(-file => "$icons/reload.gif")
  346.             -image => $animate
  347.             )-> pack(qw/-fill both -expand 1/);
  348.        
  349.         $model->_set("splash" => $splash);
  350.         $mw->update;
  351.     }
  352.    
  353.     ## READ DATA
  354.     $model->read("vin", "rays", "times");
  355.     $model->_set("init", 0);
  356.     $model->drawAxes();
  357.    
  358.     # Draw stations
  359.     foreach (keys(%{$model->{stations}})){
  360.         if  (ref $model->{stations}{$_} eq "station") {
  361.             $model->{stations}{$_}->drawStation;
  362.         } else {
  363.             print "WARNING !! There's an unblessed station in your model!! Call the priest !!\n";
  364.         }
  365.     }
  366.    
  367.     # Draw user defined xz if configured
  368.     if ($model->{config}->{xz}) {
  369.         foreach my $file (@{$model->{config}->{xz}}) {
  370.             $model->_readxzfile("$file");
  371.         }
  372.     }
  373.    
  374.     # Draw user defined xz if configured
  375.     if ($model->{config}->{xt}) {
  376.         foreach my $file (@{$model->{config}->{xt}}) {
  377.             $model->_readxzfile("$file", 'xt');
  378.         }
  379.     }
  380.    
  381.     if ( $args{splash} == 1) {
  382.         $splash->Destroy;                    # tear down Splashscreen
  383.         $mw->deiconify;                      # show main window
  384.     }
  385. }
  386.  
  387.  
  388.  
  389. sub _get{
  390.  
  391. =PROGhead2 C<model::_get($key, ..)>
  392.  
  393. function returns any value stored in model.
  394. if a key is not found, undef is returned
  395. THIS FUNCTION IS INTENDED FOR INTERNAL USE
  396. external is C<model::get>
  397.  
  398. arguments are a list of keys to retrieve
  399.  
  400. =cut
  401.  
  402.     #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  403.  
  404.     my ($model, @args) = @_;
  405.     return undef unless @args;
  406.  
  407.     my ($key, $value);
  408.     my @return;
  409.    
  410.     foreach $key (@args){
  411.                
  412.         if (exists $model->{$key}){
  413.             $value = $model->{$key};
  414.             #print "Get ".$key." = ".$value."\n";
  415.         } else {
  416.             print "ERROR: no such key as $key in model!!\n";
  417.             $value = undef;
  418.         }
  419.  
  420.         push @return, $value;
  421.     }
  422.    
  423.     #D Return scalar, if only one argument
  424.     #D and referece to array if more
  425.     if ( @return == 1) {
  426.         return $value;
  427.     } else {
  428.         return \@return;
  429.     }
  430. } #D model->_get END
  431.  
  432. sub _set{
  433.  
  434. =PROGhead2 C<< model::_set( $key => $value, .. ) >>
  435.  
  436. model->_set can set a reference to data for any existing key in
  437. a model
  438. THIS FUNCTION IS INTENDED FOR INTERNAL USE
  439. external is set
  440.  
  441. =cut
  442.  
  443.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  444.  
  445.     my ($model, %args) = @_;
  446.     my ($key, $value);
  447.        
  448.     while (($key, $value) = each(%args)){
  449.        
  450.         if (exists $model->{$key}){
  451.             #print "Set ".$key.", ".$value."\n";   
  452.             $model->{$key} = $value;
  453.         } else {
  454.             print "ERROR: no such key as $key in model!!\n";
  455.             die;
  456.         }
  457.     }  
  458. }
  459.  
  460. sub status {
  461.  
  462. =PROGhead2 C<model::status()>
  463.  
  464. Prints number of layers, average, minimum and maximum depth and velocities, number of stations with phases.
  465.  
  466.     $model->status;
  467.  
  468. =cut
  469.  
  470.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  471.  
  472.  
  473.     say "--------------------------";
  474.     say "This is your status-report";
  475.    
  476.     my ($model, %args) = @_;
  477.    
  478.     my $s =" B  min  max  mean variance stddev\n"; # Return string
  479.    
  480.     my $n = keys(%{$model->{stations}});
  481.    
  482.    
  483.     say "Your model has <$n> stations\n";
  484.     #foreach (sort {$b <=> $a}(keys(%{$model->{stations}}))) {     
  485.         #$model->{stations}->{$_}->statusstation;
  486.     #}
  487.     my @layers = @{$model->{layers}};
  488.     say "Your model has <".@layers."> layers";
  489.     for (my $i=0; $i<=$#layers; $i++){
  490.         #say "Status layer $i";
  491.         $s .= $model->{layers}[$i]->status(%args);
  492.     }
  493.     say "--------------------------";
  494.     print "Modelparameter : ";
  495.     my @par = keys (%$model);
  496.     print "@par\n";
  497.     #print "ISA: \n";
  498.     #$model->DESTROY;\
  499.     return $s;
  500. }
  501.  
  502. sub printStatusMessage{
  503.  
  504. =PROGhead2 C<model::printStatusMessage("\nmsg")>
  505.  
  506. Prints msg to GUI. Same like main prog in p.pl
  507.  
  508. =cut
  509.  
  510.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  511.  
  512.     my ($model, $msg) = @_;
  513.    
  514.     my $stline = $model->{"statusline"};
  515.     $stline->insert ('end', "$msg");
  516.     $stline->see('end');
  517.     $model->_get("mainwindow")->update();
  518. }
  519.  
  520. sub getClosestStation{
  521.  
  522. =PROGhead2 C<model::getClosestStation($km)>
  523.  
  524. Returns position of closest station for given km. Currently only used when
  525. C<model::tomoReadRays>.
  526.  
  527. =cut
  528.  
  529.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  530.  
  531.     my ($model, @args) = @_;
  532.     # Used if you want to calculate moveout velocity.
  533.     # coding not complete
  534.     my $x = $args[0];
  535.     my @positions = sort{$a <=> $b}(keys(%{$model->{stations}}));
  536.    
  537.     my $dx;
  538.     my $min =  900;
  539.     my $st;
  540.     foreach (@positions) {
  541.         $dx = abs($_ - $x);
  542.         print "pos: $_, dx $dx, min $min\n" if ( $model->debug());
  543.         if ($dx > $min) {
  544.             print "Closest Position:dx $dx min $min pos $st\n" if ( $model->debug());
  545.             last;
  546.         } else {
  547.             #print "Closest Position: $_\n";
  548.             $min = $dx;
  549.             $st = $_;
  550.             print "Closest Position: $min, $dx, $st\n" if ( $model->debug());
  551.         }
  552.        
  553.     }
  554.     print "Returning $st\n" if ( $model->debug());
  555.     return $st;
  556. }
  557.  
  558.  
  559. sub addStation{
  560.  
  561. =PROGhead2 C<model::addStation()>
  562.  
  563. Initializes new station with C<< new station(%args, "model" => $model) >>
  564. and fills information in model-object:
  565.  
  566.  # Storage place for stations: $model->stations{position}
  567.  $model->{stations}{$st->{position}} = $st;
  568.  
  569.  # Information to find station
  570.  # name <-> position
  571.  $model->{stationpositions}->{$st->{name}} = $st->{position};
  572.  $model->{stationkm}->{$st->{position}} = $st->{name};
  573.  
  574. Stations are stored at hash key C<< $model->{stations}{$st->{position}} = $st >> !!
  575. Station position is an integer with three numbers behind comma.
  576.  
  577.  Check stations in model in perls debuging console:
  578.  x keys(%{$model->{stations}})
  579.  
  580. =cut
  581.  
  582.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  583.  
  584.     my ($model, %args) = @_;
  585.     my $st = new station(%args, "model" => $model);
  586.     #say "at ".$st->{position};
  587.    
  588.     # Storing station!!
  589.     $model->{stations}{$st->{position}} = $st;
  590.    
  591.     # Add information about station. Enables finding the station with
  592.     # stationname or stationposition
  593.     $model->{stationpositions}->{$st->{name}} = $st->{position};
  594.     $model->{stationkm}->{$st->{position}} = $st->{name};
  595. }
  596. sub edit{
  597.  
  598. =PROGhead2 C<model::edit()>
  599.  
  600. used for all kind of model editing like adding, deleting, moving nodes
  601. C<< $model->edit("op" => "edit", "tags" => \@tags, "value" => [$km, $v]); >>
  602.  
  603. =over
  604.  
  605. =item 'editPhase'
  606.  
  607.         # For SPrange selection:  tags = [phase, ["tagsofPick1"], ["tagsofPick2"]
  608.         # For changing all picks: tags = [phase, st]
  609.        
  610. =item 'allV'
  611.  
  612. =item other
  613.  
  614. calls
  615.  
  616.  layer->edit(%args);
  617.  
  618. =item return message
  619.  
  620. =back
  621.  
  622. =cut
  623.  
  624.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  625.  
  626.     my ($model, %args) = @_;
  627.    
  628.     my @tags = @{$args{"tags"}};
  629.     my $op = $args{"op"};
  630.     my $msg = ""; # Return message to model
  631.    
  632.     #print "model::edit tags: @tags\n";
  633.     #print Dumper(\%args);
  634.    
  635.     my $type = $tags[0];
  636.     print "My type is $type\n" if $debug;
  637.     if ($op eq "editPhase") {
  638.         $model->editPhase(%args);
  639.    
  640.     }
  641.    
  642.     if ($op =~ m/.*Shot/) {
  643.         #Find out, which station was clicked      
  644.         my $station = $model->getStation($tags[2]);
  645.         $station->set(%args);
  646.     }
  647.    
  648.     #####
  649.     # THIS HANDLES ALL OTHER OPERATIONS !!!
  650.     if ($type ne "allV" && $op ne "editPhase" && $op !~ m/.*Shot/){
  651.         #print "model::edit($type) args = \n";
  652.         #print Dumper \%args;
  653.    
  654.         my $layer = $tags[1];
  655.         my $node = $tags[2];
  656.         # TODO: Bug: Throws error for floating refl. Seems to work with
  657.         # just one refl, but probably causes error in the future
  658.         $model->getLayer($layer)->edit(%args);
  659.     }
  660.    
  661.     if ($type eq "allV"){
  662.        
  663.         for(my $i = 0; $i < $#{$model->{layers}}; $i++){
  664.             #print "Save v nodes into layer $i\n";
  665.             my $km = $args{value}->[0]->[$i];
  666.             my $vu = $args{value}->[1]->[$i];
  667.             my $vl = $args{value}->[2]->[$i];
  668.             my $vupar = $args{value}->[3]->[$i];
  669.             my $vlpar = $args{value}->[4]->[$i];           
  670.            
  671.             #print "Editging km @$vl\n";
  672.             # Tags are not necessary, but $layer->edit needs some values there
  673.             $model->{layers}->[$i]
  674.                 ->edit( "op" => "editAllV", "tags" => ["TYPE", "LAYER", "NODE"], "value" => [$km, $vu, $vl, $vupar, $vlpar]);
  675.         }
  676.     }
  677.    
  678.     $model->order;
  679. }
  680.  
  681. sub editAllParDerivs {
  682.  
  683.  
  684. =PROGhead2 C<model::editAllParDerivs()>
  685.  
  686. Set all partial derivatives to given value. This sub is used, when calculating
  687. the resolution for a model. So far no other use.
  688.  
  689. =cut
  690.  
  691.  
  692.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  693.  
  694.     my ($model, $switch) = @_;
  695.    
  696.     my $op;
  697.     $op = 'setPar' if ($switch == 1) ;
  698.     $op = 'unsetPar' if ($switch == 0);
  699.     print "model:: editAllParDerivs: $op\n" if $debug;
  700.    
  701.     my @coords = (0,0); # Fake, not needed
  702.     foreach my $layer (@{$model->{layers}}) {
  703.         my @tags = ('LAYER', "B$layer->{number}");
  704.         $layer->edit("tags", \@tags, "value", \@coords, "op" , $op);
  705.     }
  706.     $model->order();
  707. }
  708.  
  709. sub editPhase {
  710.  
  711. =PROGhead2 C<model::editPhase()>
  712.  
  713. Edit phasecodes in zp-Files. Called with right click on a phase in the
  714. traveltime canvas.
  715.  
  716. =cut
  717.  
  718.  
  719.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  720.  
  721.     my ($model, %args) = @_;
  722.     my @tags = @{$args{"tags"}};
  723.  
  724.     my $mode = $args{mode};
  725.     (my $oldphase = $args{value}[0]) =~ s/\.//;
  726.     (my $newphase = $args{value}[1]) =~ s/\.//;
  727.    
  728.     # For SPrange selection:  tags = [phase, ["tagsofPick1"], ["tagsofPick2"]
  729.     # For changing all picks: tags = [phase, st]
  730.     print Dumper(\@tags) if $debug;
  731.    
  732.     # Environment
  733.     my $config = $model->{config};
  734.     my $zpdir = $config->{zpdir};
  735.     my ($file, $st, $sp1, $sp2);
  736.    
  737.     # If only selected picks should change, SPs have to be found for them
  738.     if (@tags == 3){    # If there are not 3 elements in tags array, then there's no selection of SPrange
  739.         # Get variables for first pick
  740.         (my $st1 = $tags[1][1]) =~ s/RAYS//;
  741.         (my $ph1 = $tags[1][2]) =~ s/Ph//;
  742.         my ($pkm1, $t1, $unc) = split (/ /, $tags[1][3]);
  743.         $pkm1 =~ s/km//;
  744.         $t1  =~ s/t//;
  745.         $unc =~ s/unc//;
  746.         $ph1 =~ s/\.//; # Phases in Pickfile are without decimal ### TODO CHANGE THIS TO USE RIN MATCHES
  747.  
  748.         # Calculate offset of this pick
  749.         my $off1 = sprintf ("%.3f", $pkm1 - $model->{stationpositions}->{$st1});
  750.         print "Pickoffset is $off1\n" if $debug;
  751.        
  752.         # Get variables for second pick
  753.         (my $st2 = $tags[2][1]) =~ s/RAYS//;
  754.         (my $ph2 = $tags[2][2]) =~ s/Ph//;
  755.         my ($pkm2, $t2, $unc2) = split (/ /, $tags[2][3]);
  756.         $pkm2 =~ s/km//;
  757.         $t2  =~ s/t//;
  758.         $unc2 =~ s/unc//;
  759.         $ph2 =~ s/\.//; # Phases in Pickfile are without decimal ### TODO CHANGE THIS TO USE RIN MATCHES
  760.  
  761.         # Calculate offset of this pick
  762.         my $off2 = sprintf ("%.3f", $pkm2 - $model->{stationpositions}->{$st2});
  763.         print "Pickoffset is $off2\n" if $debug;
  764.  
  765.         $file = $model->getStation($st1)->{zpfile};
  766.         $file =~ s/head/unc/;
  767.        
  768.         # Find picks in unc file to get shotpoints
  769.         my $line;
  770.         open (FILE ,"<$zpdir/$file") or die "Can't open myfile: $_!\n";
  771.         while ($line = <FILE>) {
  772.  
  773.             if ($line =~ /$off1\s+$ph1/i) {
  774.                 my @line = split ( /\s+/ , $line);
  775.                 $sp1 = $line[1];
  776.                 print $line };
  777.  
  778.             if ($line =~ /$off2\s+$ph2/i) {
  779.                 my @line = split ( /\s+/ , $line);
  780.                 $sp2 = $line[1];
  781.                 print $line };
  782.         }
  783.         print "SP=$sp1, SP = $sp2\n" if $debug;
  784.        
  785.         if (!defined $sp1 || !defined $sp2) {
  786.             print "COULDN'T FIND BOTH SHOTPOINTS\n";
  787.             return undef;}
  788.    
  789.         # Sort shotpoints so sp2 is larger than sp1
  790.         if ($sp2 < $sp1 ) {
  791.             print "Swap sp1 $sp1 with sp2 $sp2\n" if $debug;
  792.             my $t = $sp2;
  793.             $sp2 = $sp1;
  794.             $sp1 = $t;
  795.             print "Now: sp1 $sp1, sp2 $sp2\n" if $debug;}
  796.        
  797.         #print "My stationnumber is $st1, ph $ph1 km $pkm1, t $t1, unc $unc\nOpen file $file\n";
  798.         $st = $st1;
  799.     } # Now SPs for picks are found
  800.     else {
  801.         $st = $tags[1];
  802.         print "CHange all picks for station $st\n" if $debug;
  803.     }
  804.    
  805.     $file = $model->getStation($st)->{zpfile};
  806.     $file =~ s/head/pick/;
  807.     #$file = "100st135.h.rloc.pickbak";
  808.     my ($sp, $t) = commons::readPicks("$zpdir/$file");
  809.     die "No file $file found\n" if (!defined $sp );
  810.  
  811.     if ($sp1) {
  812.         print "CALL editPhase($sp, $t,$sp, $t, 'sp1' => $sp1  'sp2' => $sp2,".
  813.               "'oldphase' => $oldphase, 'newphase' => $newphase, 'mode' => $mode \n";
  814.         ($sp, $t) = commons::editPhase($sp, $t, 'sp1' => $sp1, 'sp2' => $sp2,
  815.             "oldphase" => $oldphase, "newphase" => $newphase, "mode" => $mode);
  816.     } else {
  817.         print "CALL editPhase($sp, $t, 'oldphase' $oldphase 'newphase' $newphase 'mode' $mode)\n";         
  818.         ($sp, $t) = commons::editPhase($sp, $t,
  819.             'oldphase' => $oldphase, 'newphase' => $newphase, 'mode' => $mode);
  820.     }
  821.    
  822.     my $fileout = "$zpdir/$file";
  823.     #my $fileout = "$zpdir/100st135.h.rloc.pick" ;
  824.     commons::writePicks($sp, $t, $fileout) if ($sp);
  825.    
  826.     # Clean edited picks
  827.     print "model::edit() delete 'Ph$oldphase'\n";
  828.     $model->getStation($st)->emptyTimes( keys => ['txin'], phases => [$oldphase]);
  829.     $model->{time}->delete("Ph$oldphase");
  830.    
  831.         return;
  832.  
  833. }
  834.  
  835. sub getLayer {
  836.  
  837. =PROGhead2 C<model::getLayer($number)>
  838.  
  839. Returns the layer-object for $layernumber. Number is the same as in v.in
  840.  
  841. =cut
  842.  
  843.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  844.  
  845.     my ($model, $number) = @_;
  846.    
  847.     # Remove leading letters (B 1 -> 1)
  848.     $number =~ s/[a-zA-Z]//g;
  849.    
  850.     # Floats do not have any number left
  851.     #print "layer::getLayer -> number = $number\n" if $debug;
  852.    
  853.     #if ($number) {
  854.         # Get layer-object
  855.         my $l = $model->{layers}[$number-1];
  856.         return $l;
  857.     #} else {
  858.         #return 0;
  859.     #}
  860. }
  861.  
  862. sub getStation {
  863.  
  864. =PROGhead2 C<model::getStation($number)>
  865.  
  866. Returns station object which matches C<$number> either as stationname or
  867. stationposition. Currently it's a bit of luck, which one is used. Look at
  868. position first but if a stationnumber accidently is the same as the position
  869. of another, it gets confused. (This is a potential BUG, TODO)
  870.  
  871. =cut
  872.  
  873.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  874.  
  875.     # returns station-object
  876.     # give either stationname or stationpositions
  877.     my ($model, $number) = @_;
  878.     #print "model::getStation($number)\n" if $debug;
  879.    
  880.     # Return station reference
  881.     my $st;
  882.    
  883.     # Is number a station name? Then get profilekm for this station
  884.     if (exists $model->{stationpositions}->{$number}) {
  885.        #print "Input numer is a stationposition\n" if $debug;
  886.         $number = $model->{stationpositions}->{$number};
  887.     }  
  888.    
  889.     # Is number a stationkilometer? Then return the station object
  890.     if (exists $model->{stations}->{$number}) {
  891.        #print "Input number is a stationname\n" if $debug;
  892.          $st = $model->{stations}->{$number};
  893.     }  
  894.    
  895.    # Check if station is still undefined
  896.    unless ($st) {
  897.        print "WARNING !!! Couldn't find a station for >$number<.\n";
  898.    }
  899.    
  900.     # No check, if both might be right. It shouldn't anyway, because
  901.     # stationkms have three decimals and stationnames don't
  902.     #print "Return station $st->{name}\n";
  903.     return $st;
  904. }
  905.  
  906. sub getPhase {
  907.  
  908. =PROGhead2 C<model::getPhase(phase)>
  909.  
  910. Get alist of all station having a special phase picked
  911.  
  912. =cut
  913.  
  914.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  915.  
  916.    my ($model, @args) = @_;
  917.    my $ph = $args[0];
  918.    my @stations = sort { $a <=> $b } (keys(%{$model->{stations}}));
  919.    
  920.    my $s = ""; # Return string
  921.    
  922.    foreach my $st ( @stations ) {
  923.        my $n = 0;
  924.        
  925.        if ( exists $model->getStation($st)->{txin}->{'1.000'}->{$ph} ) {
  926.         $n += @{$model->getStation($st)->{txin}->{'1.000'}->{$ph}};
  927.        }
  928.        
  929.        if ( exists $model->getStation($st)->{txin}->{'-1.000'}->{$ph} ) {
  930.         $n += @{$model->getStation($st)->{txin}->{'-1.000'}->{$ph}};
  931.        }
  932.        
  933.        # Only return string for stations with this phase
  934.        if ( $n > 0 ) {
  935.            my $name = $model->getStation($st)->{name};
  936.            #print "Get station $name\n";
  937.            $s .= sprintf("%3d: Ph %3d %4d picks\n", $name, $ph, $n);
  938.        }
  939.    }
  940.    
  941.    return $s;
  942. }
  943.  
  944. sub getDensity {
  945. #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  946.  
  947. =PROGhead2 C<$model->getDensity (v)>
  948.  
  949. Returns density for given velocity C<v>. Conversion uses values from
  950. Barton(1986) "The relationship between seismic velocity and density in the continental crust - a useful constraint?"
  951.  
  952. =cut
  953.  
  954.    
  955.    my $model = shift;
  956.    my $v = shift;
  957.    
  958.    $v = sprintf("%.1f",nearest(.1,$v));
  959.    
  960.    #my $conv = "ludwig";
  961.    my $conv = "barton";
  962.    #my $conv = $model->getConfig('densityconversion');
  963.  
  964.    my $rho;
  965.    
  966.    if ( $conv eq "barton" ) {
  967.        # Densities after Barton(1986)
  968.        # "The relationship between seismic velocity and density in the continental crust - a useful constraint?"
  969.         my %densities = qw( 0.0 0.0 1.5 1.47 1.6    1.66 1.7    1.73 1.8    1.80 1.9    1.86
  970.             2.0 1.92 2.1    1.98 2.2    2.01 2.3    2.03 2.4    2.06
  971.             2.5 2.09 2.6    2.11 2.7    2.13 2.8    2.15 2.9    2.18
  972.             3.0 2.21 3.1    2.23 3.2    2.24 3.3    2.26 3.4    2.28
  973.             3.5 2.30 3.6    2.32 3.7    2.34 3.8    2.36 3.9    2.38
  974.             4.0 2.39 4.1    2.41 4.2    2.43 4.3    2.44 4.4    2.46
  975.             4.5 2.48 4.6    2.50 4.7    2.52 4.8    2.53 4.9    2.55
  976.             5.0 2.57 5.1    2.59 5.2    2.61 5.3    2.62 5.4    2.64
  977.             5.5 2.66 5.6    2.68 5.7    2.70 5.8    2.72 5.9    2.74
  978.             6.0 2.77 6.1    2.80 6.2    2.83 6.3    2.85 6.4    2.87
  979.             6.5 2.90 6.6    2.93 6.7    2.95 6.8    2.98 6.9    3.01
  980.             7.0 3.04 7.1    3.07 7.2    3.10 7.3    3.13 7.4    3.16
  981.             7.5 3.19 7.6    3.22 7.7    3.25 7.8    3.28 7.9    3.31
  982.             8.0 3.34 8.1    3.38 8.2    3.42 );
  983.  
  984.        $rho = $densities{$v};    
  985.    }
  986.    
  987.    if ( $conv eq "funck" ) {
  988.        # Densities after Ludwig(1970)
  989.        # "Seismic Refraction" in THE SEA
  990.        #a=-0.00283; b=0.0704; c=-0.598; d=2.23; e=-0.7;
  991.        #printf("v= %f, rho= %8.2f\n", $1,a*$1^4+b*$1^3+c*$1^2+d*$1+e)
  992.        
  993.        # Funck 2004 has approximated ludwig/barton
  994.        # But values are quite different!!
  995.        $rho = -0.00283*$v**4 + 0.0704*$v**3 - 0.598*$v**2 + 2.23*$v -0.7;    
  996.    }  
  997.    
  998.    unless ($rho) {
  999.        #print "WARNING!! Cannot find density for v=$v\n";
  1000.        if ($v > 8.2 ) {
  1001.            $rho = 3.5
  1002.        }
  1003.        if ($v < 1.5 ) {
  1004.            $rho = 1.47;
  1005.        }
  1006.        #print "Use density rho = $rho\n";
  1007.    }
  1008.    
  1009.    return $rho;
  1010. }
  1011.  
  1012.  
  1013. sub read {
  1014.  
  1015. =PROGhead2 C<model::read('data')>
  1016.  
  1017. Routine starts individual model-subroutines for reading data.
  1018. Keys can be C<'vin', 'rays', 'times', 'str', 'vgrid'>
  1019.  
  1020. =cut
  1021.  
  1022.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1023.  
  1024.     my ($model, @args) = @_;
  1025.     my $r = ""; # Return message
  1026.    
  1027.     if (grep $_ eq "vin", @args) {
  1028.        # Delete contours, grid
  1029.        $model->reset();
  1030.         $model->_readVin;
  1031.        $model->_readRes();
  1032.     }
  1033.    
  1034.     if (grep $_ eq "fin", @args) {
  1035.        $model->reset();
  1036.         $model->_readFin;
  1037.     }
  1038.    
  1039.     if (grep $_ eq "rays", @args) {
  1040.         $r = $model->_readRays;
  1041.        
  1042.     }
  1043.    
  1044.     if (grep $_ eq "times", @args) {
  1045.         $model->_readTimes;
  1046.     }
  1047.    
  1048.     if (grep $_ eq "str", @args) {
  1049.         # Read Streamerpicks and convert them to depth
  1050.         $model->_readStr;
  1051.     }
  1052.    
  1053.     if (grep $_ eq "vgrid", @args){
  1054.         $model->_readVgrid;
  1055.     }
  1056.     return $r;
  1057. }
  1058.  
  1059. sub _readVin {
  1060.  
  1061. =PROGhead2 C<model::_readVin()>
  1062.  
  1063. Called by C<< $model->read(vin) >> and reads model file C<'v.in'>.
  1064.  
  1065. =cut
  1066.  
  1067.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1068.  
  1069.    my ($model, %args) = @_;
  1070.    my $cns = $model->{space};
  1071.    my $xmax = $model->{rin}->{xmax}[0];
  1072.    my $xmin = $model->{rin}->{xmin}[0];
  1073.    my $file = "v.in";
  1074.    say "Reading file v.in" unless $quiet;
  1075.    
  1076.    open(FILE, $file) or croak "Can't open $file";
  1077.    my $l=0;
  1078.    my @line;
  1079.    my $currentlayer=0;
  1080.     my $pre;    # prefix of line. holds layernumber or shows that line is contiuned
  1081.     my $layer;  # current layer as layer-object
  1082.     my $v=0;    # Flag for depth or velocity in second line of block
  1083.                # 0 for depth
  1084.                # 1 for last depth reading
  1085.                # 2 for velocity upper border
  1086.                # 3 for velocity lower border
  1087.                
  1088.     my @km;     # stores profilekm for more than one line
  1089.     my @d;      # stores depth corresponding to @km
  1090.     my @par;    # stores partial derivatives
  1091.    
  1092.     #my (@uv, @lv); # stores velocity-Nodes
  1093.    
  1094.     my $n = 0;      # Number of nodes for a layer. Used as flag for end of layer
  1095.    my $type = "depth"; # Type of data for second line in block: depth, upper or lower
  1096.                        # velocities
  1097.    
  1098.    my $missXmin = 0;   # Flag that gets set, is any xmin value for v is missing
  1099.    
  1100.    # Clean up old data
  1101.    $model->{layers} = (); # Remove any old layers (because of DESTROY function of layer-object)
  1102.    $model->{space}->delete('VNODE');
  1103.    $model->{space}->delete('ANNOTVNODE');
  1104.    
  1105.     while(<FILE>) {
  1106.         chomp;
  1107.        next unless length;     # Don't cry if line is empty
  1108.         $l += 1;
  1109.         ($pre, my $tmp) = unpack "A2xA*";
  1110.         #print "(D) String $tmp contains of ".(length($tmp)/7)." packages \n" if $debug;
  1111.         if ( (length($tmp)/7) =~ m/^\d+.\d+$/ ) {
  1112.             print
  1113.                  "\n\n\nWARNING!!! Something is wrong with your v.in file in line $.\n"
  1114.                 ."I have problems to recognize the blocks. Please do not use\n"
  1115.                 ."tabs to deliminate the numbers. Use spaces.\n\n\n";
  1116.             die;
  1117.         }
  1118. #       @line = split (' ', $tmp);
  1119. #       @line = unpack "A7" , $tmp;
  1120.         @line = unpack "(A7)".(length($tmp)/7) , $tmp;
  1121.        
  1122.         #print "(D) v.in $. type $type: ". join (',', @line)."\n" if $debug;
  1123.        
  1124.         # Blocks of three lines belong together
  1125.         # First line holds layernumber, profilekm
  1126.         if ( $l%3 == 1 ) {
  1127.             # Line holds kilometer. If one layer has more nodes than fit
  1128.             # into one line, they still get pushed into the same array
  1129.             push @km, @line;
  1130.            
  1131.             # If layernumber has increased, create a new layer
  1132.             if ( $pre > $currentlayer ) {
  1133.                 $currentlayer += 1;
  1134.                 my $c = $model->{phasecolors}{sprintf('%d2',$pre-1)};
  1135.                 # Layer color is determined by the reflected phasecolor from upper layer
  1136.                 unless (defined $c) {
  1137.                     #print "(I) There is no specific color defined for the boundary of layer B$pre.\n I'm using black."
  1138.                     #."If you want the layer boundary in a different color \n";
  1139.                     $c = 'black';}
  1140.                 $layer = new layer("model" => $model, "number" => $pre, "color" => $c);
  1141.                 #print "Created a new Layer (B $pre).  My Profile is $xmax km long\n";
  1142.                 #print "(B $pre) Color: $c\n";
  1143.             }  
  1144.            
  1145.             # Check if end of profile is reached. km cannot be larger then
  1146.             # the whole profile
  1147.             if ( $line[-1] == $xmax ) {
  1148.                 $v += 1;
  1149.                 $n = @km;
  1150.                 #print "End of layerkm for $pre, $n elements in km\n";
  1151.             } elsif ($line[-1] > $xmax) {
  1152.                 print "Somethings wrong with your v.in-File. xmax = $xmax, but km = $line[-1]\n";
  1153.             }
  1154.         }
  1155.        
  1156.         # Second line of block holds depth/velocity for above km
  1157.         if ($l%3 == 2 ) {
  1158.             push @d, @line;
  1159.             #print "@line \n";
  1160.         }
  1161.    
  1162.         # Third line of block switches partial derivatives on/off
  1163.         if ($l%3 == 0 ) {
  1164.             push @par, @line;
  1165.            
  1166.             # Is depth array as large as km array?
  1167.             if ( $n == @d ) {
  1168.                 # Amount of nodes in @d is the same as @km. And end of layer is reached
  1169.                 # This is the last line, as km and d array have the same length
  1170.                 #print "End of second line in block is reached\n";
  1171.                
  1172.                 # is nodetype == depth?
  1173.                 if ( $type =~ "depth" ) {
  1174.                     #print "(D) This is last depth of layer @km, @d\n" if $debug;
  1175.                     #print "(D) addNodes vukm => \n@km, depth => \n@d, depthpar => \n@par\n" if $debug;
  1176.                     $layer->addNodes("km" => \@km, "depth" => \@d, "depthpar" => \@par);
  1177.                     @km = (); @d  = (); @par = (); $n = 0;  # Reset variables for next layer
  1178.                     $type = "upVelo";   # Flag velocities for next line
  1179.                     next;
  1180.                 }
  1181.                 ## This shouldn't really happen. rayinvr wouldn't work. But just in case...
  1182.                 ## Test if number of km- and depth-nodes fit
  1183.                 #if (@km != @d){
  1184.                     #print "Length km: ".@km.", Length d: ".@d."\n";
  1185.                     #die "Number of nodes for km and depth don't fit!!\n";
  1186.                 #}
  1187.                 #next;
  1188.            
  1189.                 if ($type =~ "upVelo") {
  1190.                     #print "velocity upper boundary\n";
  1191.                     #print "k @km \n";
  1192.                     #print "l @line \n";
  1193.                     #print "d @d\n";
  1194.                     #print "$currentlayer: readVin Partial derivatives upper layer >@par<\n";
  1195.                     #print "(D) addVNodes vukm => \n@km, vu => \n@d, vupar => \n@par\n" if $debug;
  1196.                     # Set missXmin-flag if no value for xmin found
  1197.                     #if ( $km[0] != $xmin){
  1198.                         #$missXmin = 1;
  1199.                         #unshift @km, $xmin;
  1200.                         #unshift @d,  $d[0];
  1201.                         #unshift @par, $par[0];
  1202.                         #print "(I) Added vl[km $xmin] nodes to $layer->{number}\n";
  1203.                     #}
  1204.                     $layer->addVNodes("vukm" => \@km, "vu" => \@d, "vupar" => \@par);
  1205.                     @km = (); @d = (); @par = (); $n = 0;
  1206.                     $type = "loVelo";
  1207.                     next;
  1208.                 }
  1209.                
  1210.                 if ($type =~ "loVelo") {
  1211.                     #print "velocity lower boundary \n";
  1212.                     #print "@km \n";
  1213.                     #print "@line \n";
  1214.                     #print "$currentlayer: readVin Partial derivatives lower layer >@par<\n";
  1215.                     #print "(D) addVNodes vlkm => \n@km, vl => \n@d, vlpar => \n@par\n" if $debug;
  1216.  
  1217.                     # Set missXmin-flag if no value for xmin found
  1218.                     #if ( $km[0] != $xmin){
  1219.                         #$missXmin = 1;
  1220.                         #unshift @km, $xmin;
  1221.                         #unshift @d,  $d[0];
  1222.                         #unshift @par, $par[0];
  1223.                         #print "(I) Added vl[km $xmin] nodes to $layer->{number}\n";
  1224.                     #}
  1225.                     $layer->addVNodes("vlkm" => \@km, "vl" => \@d, "vlpar" => \@par);
  1226.                     push @{$model->{layers}}, $layer;
  1227.                     $type = "depth";    # Next line is for depth again
  1228.                     @km = (); @d = (); @par = (); $n = 0;
  1229.                 }
  1230.             } else {
  1231.                 #print "Number of second line elements hasn't reached km n $n d @d\n";
  1232.             }
  1233.  
  1234.         }
  1235.        
  1236.     } #end of FILE-while
  1237.     close(FILE);
  1238.     # Adding last layer
  1239.     $layer->lastLayer("km" => \@km, "depth" => \@d);
  1240.     push @{$model->{layers}}, $layer;
  1241.    
  1242.     # Report missing xmin values!
  1243.     if ( $missXmin == 1 ) {
  1244.         my $t = "You are working with a v.in file that has no values for xmin. rayinvr works with this, but vin2xyz has problems. I'm adding nodes for xmin. Please write model to file before running dmplstsqr";
  1245.         my $m =   $model->{mainwindow}->Dialog(
  1246.                     -title => "Velocity nodes in v.in ",
  1247.                     -text => $t,
  1248.                     #-width => 75,
  1249.                     -wraplength => '6i',
  1250.                     -buttons => ['Ok']
  1251.                     );
  1252.      
  1253.         $m->Show;
  1254.     }
  1255.    
  1256.     #die;
  1257.     # Name layers:
  1258.     my %layernames = ( ' 1' => 'Water', ' 2' => 'Sediment', ' 3' => 'Sediment',
  1259.         ' 4' => 'Sediments ?', ' 5' => "Basement", ' 6' => "Upper crust",
  1260.         ' 7' => 'Middle crust', ' 8' => 'Lower crust', ' 9' => "Mantle");
  1261.     #print Dumper \%layernames;
  1262.    
  1263.     # Drawing layers
  1264.     foreach my $layer (@{$model->{layers}}){
  1265.         $layer->drawLayer;
  1266.        
  1267.         # TODO: change this naming behaviour
  1268.         if (exists $layernames{$layer->{number}}) {
  1269.             $layer->{name} = $layernames{$layer->{number}};
  1270.             #print "Name layer $layer->{number} $layer->{name}\n";
  1271.         } else {
  1272.             #print "Can't find a name for >$layer->{number}<\n";
  1273.         }
  1274.     }
  1275.    
  1276.     $model->writeV2xzyIn(); # Convert v.in to an vin2xyz-readable format
  1277.     $model->_readFin();
  1278. }
  1279.  
  1280. sub _readFin {
  1281.  
  1282. =PROGhead2 C<model::_readFin()>
  1283.  
  1284. Reads floating reflector file f.in
  1285.  
  1286. =cut
  1287.  
  1288.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1289.  
  1290.     my ($model, %args) = @_;
  1291.     my $cns = $model->{space};
  1292.     my $xmax = $model->{xmax};
  1293.     my $file = "f.in";
  1294.     say "Reading file $file";
  1295.  
  1296.     my $pre;    # prefix of line. holds layernumber or shows that line is contiuned
  1297.     my $layer;  # current layer as layer-object
  1298.     my $type='amount' ; # Flag linetype
  1299.                
  1300.     my @km;     # stores profilekm for more than one line
  1301.     my @d;      # stores depth corresponding to @km
  1302.     my @par;    # stores partial derivatives
  1303.    
  1304.    
  1305.     my $n = 0;      # Number of nodes for a layer. Used as flag for end of layer
  1306.  
  1307.     open(FILE, $file) or (print "Can't open $file", return);
  1308.     while (<FILE>) {
  1309.         chomp;
  1310.         #s/^\s+//;               # no leading white
  1311.         #s/\s+$//;               # no trailing white
  1312.        
  1313.         next unless length;     # Don't cry if line is empty
  1314.         #my @line = split;
  1315.        
  1316.         # First line defines the number of nodes in the floating reflector
  1317.         if ( $type eq 'amount' ) {
  1318.             my @line = split;
  1319.             $n = $line[0];
  1320.             $type = 'km';
  1321.             $layer = new floatingReflector("model" => $model,
  1322.                 "number" => 'Float', "color" => "black");
  1323.  
  1324.             next;
  1325.         }
  1326.  
  1327.        
  1328.         # Input file: f.in contains the "floating" reflecting boundaries;
  1329.         # these are interfaces with no associated velocity discontinuity
  1330.         # (hence the word "floating") at which rays can reflect in
  1331.         # addition to the layer boundaries; the file format is similar to
  1332.         # that for v.in:
  1333.         # (1) the number of nodes defining the floating reflector
  1334.         # (format: I2)
  1335.         # (2) the x-coordinates (km) of the nodes defining the floating
  1336.         # reflector (format: 3X, <number of nodes>F7.2)
  1337.         # (3) the z-coordinates (km) of the nodes defining the floating
  1338.         # reflector (format: 3X, <number of nodes>F7.2)
  1339.         # (4) a 0 or 1 for each node listed above depending on whether (1)
  1340.         # or not (0) partial derivatives are to be calculated for
  1341.         # this particular node (format: 3X, <number of nodes>I7)
  1342.         # Lines (1) through (4) are repeated for each floating reflector
  1343.        
  1344.         my $line = $_;
  1345.         my @line = unpack "A3".("A7" x $n);
  1346.         #print "line: @line\n" if $debug;
  1347.        
  1348.         # Remove line prefix
  1349.         shift @line;
  1350.         if ( $type eq 'km' ) {
  1351.  
  1352.             if (@line == $n) {
  1353.                 # Got all nodes I expect for this reflector
  1354.                 @km = @line;
  1355.                 $type = 'depth';
  1356.                 next;
  1357.             }
  1358.         }
  1359.        
  1360.         if ( $type eq 'depth' ) {
  1361.             @d = @line;
  1362.             $type = 'par';
  1363.             next;
  1364.         }
  1365.        
  1366.         if ( $type eq 'par' ) {
  1367.             @par = @line;
  1368.            
  1369.             #print "(D) addNodes \n"
  1370.                 #."vukm     => @km\n"
  1371.                 #."depth    => @d\n"
  1372.                 #."depthpar => @par\n" if $debug;
  1373.             $layer->addNodes("km" => \@km, "depth" => \@d, "depthpar" => \@par);
  1374.  
  1375.             @km = (); @d  = (); @par = (); $n = 0;  # Reset variables for next layer
  1376.             $type = 'amount';
  1377.             $layer->drawLayer;
  1378.             push @{$model->{layers}}, $layer;
  1379.             next;
  1380.         }
  1381.        
  1382.        
  1383.        
  1384.     }
  1385.     close(FILE);
  1386.    
  1387.    
  1388.  
  1389. }
  1390.  
  1391.  
  1392. sub _readRays{
  1393.  
  1394. =PROGhead2 C<model::_readRays()>
  1395.  
  1396. Large routine reading C<r1.out> and C<r2.out>. Before reading any data, old
  1397. ray-information is deleted from model-objects. Then phase information about rays
  1398. is read from C<r1.out> then data is read from C<r2.out> and connected with phases
  1399. from C<r1.out>.
  1400.  
  1401. Information from C<r1.out> is stored invariable C<@r1> for later use, when reading
  1402. C<r2.out>
  1403.  
  1404. =cut
  1405.  
  1406.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1407.  
  1408.     my ($model, %args) = @_;
  1409.     my $rayblock = 0;   # Flag. If 1 than first part of file is read and rayinfo begins
  1410.     my $r1ray = -1;     # raynumber in r1.out. should fit $raynumber from r2.out
  1411.     my @r1;             # Stores file r1.out, which keeps information about the number
  1412.                         # of points in a ray.
  1413.     my $phase;
  1414.     my $linenumber = 0;
  1415.    
  1416.     my $error = "";
  1417.     my $results = "";   # Store shot, phase and model information
  1418.    
  1419.     # TRY only deleting rays when the phase was recalculated. Otherwise keep informations
  1420.     ## Delete old rays
  1421.     # deleteRays
  1422.     #foreach (sort {$b <=> $a}(keys(%{$model->{stations}}))) {
  1423.         ## Safety maeasure for unblessed stations
  1424.         #if  (ref $model->{stations}{$_} eq "station") {
  1425.             #$model->{stations}->{$_}->emptyRays;
  1426.         #} else {
  1427.             #print "WARNING !! There's an unblessed station in your model!! Call the priest !!\n";
  1428.         #}
  1429.     #}
  1430.  
  1431.     ####################################################################
  1432.     #                            READ R1.OUT                           #
  1433.     ####################################################################
  1434.     open (RAYS, "r1.out") or do {print "Can't open r1.out\n"; return 0};
  1435.     #shot  ray i.angle  f.angle   dist     depth red.time  npts code
  1436.     #  -1   1    1.838   -4.103    0.000    1.31  10.327     4   1.2
  1437.     #  -1   2    2.865   -5.802    0.000    0.74  10.359     5   1.2
  1438.     #
  1439.     # If npts is 500, ray tracing wasn't successfull
  1440.     # "dist" fits with last lines value for "x" for one ray in r2
  1441.     # "i.angle" = 90 - r2(ang2); fist line for one ray
  1442.     # "f.angle" = 90 - r2(ang1); last line for one ray
  1443.    
  1444.     my $status = 0;  # Has rayinvr finished? This status is set to one when
  1445.         # rayinvrs output reached |----, which is followed by a tracing
  1446.         # summary. If you have a bad model and rayinvr can't run through
  1447.         # this status will stay at 0.
  1448.     my ($sh, $raynr, $i, $f, $dist, $d, $redtime, $npts, $ph);
  1449.     $model->printStatusMessage("Reading r1.out..");
  1450.     print "Reading r1.out\n" unless $quiet;
  1451.     while (<RAYS>){
  1452.         $linenumber += 1;
  1453.         chomp;
  1454.        
  1455.         my $line = $_;
  1456.         #my @line = unpack("A4A4A9A9A9A8A8A6A6",$_);
  1457.         #   0      1      2   3   4     5     6        7      8
  1458.         ($sh, $raynr, $i, $f, $dist, $d, $redtime, $npts, $ph) =  unpack("A4A4A9A9A9A8A8A6A6",$line);
  1459.         $ph =~ s/^\s+|\s+$//g; # remove trailing and leading spaces for phasecode
  1460.        
  1461.         # Read Phase numbers
  1462.         unless (defined $ph) {print "No phasecode defined >$ph<\n"; next;}
  1463.         if ($ph =~ /^\d\.?/){ # Only if there's a phasecode at the phasecodeposition
  1464.  
  1465.             # Special treatment for floating reflectors
  1466.             # TODO
  1467.             #if ($ph =~ /^\d\.4/ ) {
  1468.                 #$ph =~ s/4$/2/;
  1469.                 #print "A floating reflector has been traced. Change phase to $ph\n";
  1470.            
  1471.             #}
  1472.  
  1473.             #print "Push phase $ph\n";
  1474.             #           raynr   npts    code/phase
  1475.             push @r1, [$raynr, $npts, $ph, $linenumber];
  1476.             #print "r1.out: $sh, $raynr, $i, $f, $dist, $d, $redtime, $npts, $ph\n";
  1477.         } else {
  1478.             print "r1.out: $line\n" unless $quiet;
  1479.             $results.="$line\n";
  1480.            
  1481.             # Find shot kilometer
  1482.             $line =~ s/^\s+//;               # no leading white
  1483.             my @line = split /\s+/, $line;
  1484.            
  1485.             # Find station for this km, if first element fits the required
  1486.             # format
  1487.             if ($line[0] && $line[0] =~ /\d\.\d/) {
  1488.                 #print "Line array: $line[0] ";
  1489.                 my $st = $model->getStation($line[0]);
  1490.                 #print "Station = $st->{name}\n";
  1491.                 chomp $results;
  1492.                 $results .= "       st $st->{name}\n";
  1493.             }
  1494.            
  1495.         }
  1496.        
  1497.         if ($sh eq '|---') {
  1498.             #print "End of rays reached. Leaving loop .. \n";
  1499.             $status = 1;
  1500.             #last;
  1501.             #$model->printStatusMessage("\nThe model is talking to you!! ");
  1502.         }
  1503.  
  1504.         if ( grep(/Number of data points used/, $line ) ) {
  1505.             $model->printStatusMessage("\n$line");
  1506.         }        
  1507.        
  1508.         if ( grep(/RMS/, $line ) ) {
  1509.             $model->printStatusMessage(",  $line");
  1510.         }
  1511.        
  1512.         if (  grep(/Normalized/, $line )) {
  1513.             $model->printStatusMessage(",  $line");
  1514.         }
  1515.        
  1516.         # Update Splash screen during start up
  1517.         if ( $model->_get("init") == 1 && $linenumber % 200 == 0 ) {
  1518.             #print "Update Splash\n";
  1519.             $model->_get("mainwindow")->update();
  1520.         }
  1521.     }
  1522.     close(RAYS);
  1523.    
  1524.     unless ($linenumber > 0 ) {
  1525.         print "ERROR: File r1.out is empty!!!\n";
  1526.         $model->printStatusMessage("\nERROR: File r1.out is empty!!! Check command line output for rayinvr error message");
  1527.         return 1;}
  1528.     print "r1.out read and closed\n" unless $quiet;
  1529.    
  1530.     $model->{results} = $results;   # Store modeled results
  1531.    
  1532.     # Check if there have been any errors during the rayinvr run
  1533.     if ($status == 0) {
  1534.        
  1535.         # Find last successfully traced station
  1536.         my $k = $model->{rin}->{xshot}[abs($sh)-1];
  1537.         my $s = $model->{stations}->{$k}->{name};
  1538.         print "------------------------------------------------------------------------------------\n";
  1539.         print "| WARNING!! RAYINVR HASN'T FINISHED                                                \n";
  1540.         print "| RAYS WILL BE MISSING IN DISPLAY                                                  \n";
  1541.         print "| LAST SHOT TRACED: SHOT$sh, RAY$raynr, DISTANCE$dist, DEPTH$d, PHASE $ph \n";
  1542.         print "|$sh, $raynr, $i, $f, $dist, $d, $redtime, $npts, $ph      \n";
  1543.                 #4,   4, 79.256,-78.006,229.842,0.00,5.047, 46, 9.1
  1544.  
  1545.         print "| SHOT$sh = station $s at km $k                                 \n";
  1546.         print "------------------------------------------------------------------------------------\n";
  1547.        
  1548.         $model->printStatusMessage(
  1549.             "\nERROR: rayinvr could trace all stations. Traveltimes are not updated."
  1550.             ." See command line for more information");
  1551.         return;
  1552.     }
  1553.     ####################################################################
  1554.     #                            READ R2.OUT                           #
  1555.     ####################################################################
  1556.     open (RAYS, "r2.out") or return "Can't open r2.out. No rays can be displayed. Run rayinvr.";
  1557.     print "Reading r2.out \n" unless $quiet;
  1558.     $model->printStatusMessage("                  .. reading r2.out ..");
  1559.     # To be written if you want to display velocity as gradient
  1560.     # Block definition in r2.out
  1561.     # number of blocks (nblk) is equal number of nodes in c.in
  1562.     #layer# 7  nblk=   2 (ivg,x1,x2,z11,z12,z21,z22,s1,b1,s2,b2,vp1,vs1,vp2,vs2,         vp3,vs3,vp4,vs4,c1,c2,...,c11)
  1563.     #ivg         1         1
  1564.     #x1     0.0000   37.9700
  1565.     #x2    37.9700  750.0000
  1566.     #z11   10.0000   10.0000
  1567.     #z12   10.0000   10.0000
  1568.     #z21   20.0000   20.0000
  1569.     #z22   20.0000   20.0000
  1570.     #s1     0.0000    0.0000
  1571.     #b1    10.0000   10.0000
  1572.     #s2     0.0000    0.0000
  1573.     #b2    20.0000   20.0000
  1574.     #vp1    7.0000    7.0000
  1575.     #vs1    4.0415    4.0415
  1576.     #vp2    7.0000    7.0000
  1577.     #vs2    4.0415    4.0415
  1578.     #vp3    7.3000    7.3000
  1579.     #vs3    4.2147    4.2147
  1580.     #vp4    7.3000    7.3000
  1581.     #vs4    4.2147    4.2147
  1582.     #-0.477E-05 0.477E-05
  1583.      #0.000E+00 0.000E+00
  1584.      #0.114E+02 0.214E+03
  1585.      #0.477E-06-0.477E-06
  1586.      #0.254E+04 0.477E+05
  1587.      #0.000E+00 0.000E+00
  1588.      #0.380E+03 0.712E+04
  1589.      #0.000E+00 0.000E+00
  1590.      #0.000E+00 0.000E+00
  1591.      #0.181E-03-0.340E-02
  1592.     #-0.181E-02 0.340E-01
  1593.  
  1594.     $linenumber = 0;
  1595.     my $currentStation; my $currentray = 0; my $currentgroup = 1; my $currentphase = 0;
  1596.     my $r2ray; my $pointnumber; my $group;
  1597.     my $km;
  1598.     $i=0;
  1599.     my $numLays;    # number of layers, from line three in r2.out
  1600.     my $l = 0;      # flags blocks of layer x
  1601.     my $nblk;       # number of blocks within a layer
  1602.     my $skip = 0;   # flag to skip one line
  1603.     my $unpack = "";
  1604.     my $ll = 29;    # number of lines for layer blocks
  1605.                     # if layer has more than hundred nodes, block spread
  1606.                     # over two lines
  1607.     my @blocks;     # save data in matrix
  1608.     my $mod = -1;   # Needed for layer block lines spreading over two lines in
  1609.                     # file. It saves, if new line starts on even or odd linenumber
  1610.     while (<RAYS>){
  1611.         $linenumber += 1;
  1612.         chomp;
  1613.        
  1614.         # Update Splash screen
  1615.         if ( $model->_get("init") == 1 && $linenumber % 200 == 0 ) {
  1616.             #print "Update Splash\n";
  1617.             $model->_get("mainwindow")->update();
  1618.         }
  1619.        
  1620.         ##################################################################
  1621.         # Reading block information
  1622.         ##################################################################
  1623.         if ($rayblock == 0) {
  1624.             # Find the total number of layers in this model
  1625.             if ($linenumber == 3) {
  1626.                 my @line = split /=/;
  1627.                 $numLays = $line[-1];
  1628.                 #print "Number of layers: $numLays\n";
  1629.                 next;
  1630.             }
  1631.             # Find place with raypoints
  1632.             elsif ($_ =~ m/^gr*/) {
  1633.                 #print "Found start of rays at $linenumber: $_\n";
  1634.                 $rayblock = 1;
  1635.                 next;
  1636.             }
  1637.             # Find description of modelblocks and set up variables for block
  1638.             # reading
  1639.             elsif ($_ =~ m/^layer/ && $l >= 0 ) {
  1640.                 my @line = unpack("A6A2A7A4",$_);
  1641.                 #my @line = split;
  1642.                 $l = $line[1];
  1643.                 $i = -1; # gives linenumber within layer-block
  1644.                 $nblk   = $line[3];
  1645.                 #print "Layer $l, number of blocks $nblk\n";
  1646.    
  1647.                 #create unpack string from nblks
  1648.                 $unpack = "";
  1649.                 my $c = $nblk;
  1650.                 if ($nblk > 100) {  # POSSIBLE BUG IF MORE THAN 200 HUNDRED
  1651.                                     # NODES ARE USED
  1652.                     $c = 100;
  1653.                    
  1654.                     #$ll = 59;
  1655.                     $ll = 29;
  1656.                     $mod = $linenumber%2;
  1657.                     #print "For this layer $l, nblk $nblk mod: $mod is too much line: $linenumber\n";
  1658.                 } else {
  1659.                     $ll = 29;
  1660.                     $mod = -1;
  1661.                 };
  1662.                 for (my $i = 0; $i < $c; $i++){
  1663.                     $unpack .= "A10";
  1664.                 }
  1665.                 #print "Unpack format: $unpack\n";
  1666.                
  1667.                 next;
  1668.             }
  1669.             # Read Blockinformation for a layer
  1670.             elsif ($l > 0) {
  1671.                 my @line = unpack($unpack,$_);
  1672.                 #print "$linenumber: $i: @line\n";
  1673.                 $i += 1;
  1674.                 if ($mod == $linenumber%2) {
  1675.                     #print "Continue, paste line to previous\n >@line[-1]<\n";
  1676.                     $i-=1; # This line is sequel of previus one
  1677.                     # remove empty arrayplaces
  1678.                     @line = grep {$_ ne ''} @line;
  1679.                     #print "Sauber >@line[-1]<\n";
  1680.                 }
  1681.                
  1682.                 ######################################
  1683.                 #if ($l == 2 ) {
  1684.                    
  1685.                     #if (defined @{$blocks[$i]}) {print "L2 in array @{$blocks[$i]}\n";}
  1686.                     #print "L2 $i: @line\n";
  1687.                 #}
  1688.                 ######################################
  1689.                 push @{$blocks[$i]}, @line;
  1690.                
  1691.                 if ($i == $ll ) { # if more than hundred nodes, it needs two lines
  1692.                    
  1693.                     #print "End of layer $l, blocks $nblk, lines ".@blocks." \n";
  1694.                     $model->_addBlocks( "layer" => "$l", "blocks" => \@blocks );
  1695.                     @blocks = (); # Clear array for next line
  1696.                     $mod = -1; # Reset flag for long lines
  1697.                    
  1698.                     #print "End of layer $l\n";
  1699.                     if ($l == $numLays) { # All layers have been read once
  1700.                         # more layer information is not neccessary at this
  1701.                         # stage of software
  1702.                         #print "All layerblocks read\n";
  1703.                         $l = -1;   
  1704.                     }
  1705.                 }
  1706.                 next;
  1707.             }
  1708.         }
  1709.            
  1710.         next unless $rayblock == 1;
  1711.  
  1712.         ###################################################################################################
  1713.         # Reading raypathes
  1714.         #####################################
  1715.         # Ray is the same number as ray-column in r1. If ray equals zero, ray doesn't reach
  1716.         # the surface.
  1717.         # rays are numbered in column "ray". If that number increase, a new ray starts
  1718.         # if npt is 500, ray tracing wasn't successfull
  1719.         #   gr ray npt   x       z      ang1    ang2    v1     v2  lyr bk id iw
  1720.         #   1  0   1  20.285   2.000    0.00  -88.69   0.00   1.58  1  2 -1  1
  1721.         #   1  0   2  18.870   2.029  -88.93  -88.93   1.58   1.58  1  1 -1  1 
  1722.        
  1723.         # Problem occur if you use "split" because two columns can merge if numbers
  1724.         # become too large
  1725.         # "gr" is raygroup and means a group of rays with the same code, e.g. code 1.2 is group 1
  1726.         # code 2.2 is group 2
  1727.         my @line;
  1728.  
  1729.         # rayinvr and xrayinvr have different output formats in r2.out.
  1730.         # --> That seems to be a patch. Don't know where output-format is defined in rayinvr-source
  1731.         #if ( $model->{config}->{r2out} =~ m/[0-9]/ ) {
  1732.             # print "Config r2out <$model->{config}->{r2out}< matches a number!\n";
  1733.             my $pack;
  1734.             # Automatically check the r2out value!!
  1735.             if ( length $_ == 67 ) {
  1736.                 $pack = "A2A3A4A8A8A8A8A7A7A3A3A3A3";
  1737.             } elsif ( length $_ == 69 ) {
  1738.                 $pack = "A4A3A4A8A8A8A8A7A7A3A3A3A3";
  1739.             }else{
  1740.                 # If none is correct, just skip this line
  1741.                 print "Can't understand the format of r2.out. This is a programming error!";
  1742.                 next;
  1743.                 #die;
  1744.             }
  1745.             #@line = unpack("A".$model->{config}->{r2out}."A3A4A8A8A8A8A7A7A3A3A3A3",$_);
  1746.             @line = unpack($pack,$_);
  1747.         #} else {
  1748.             #print "Don't know your configfile-entry for r2.out! Got >$model->{config}->{r2out}<.\n".
  1749.             #"It should be the number of digits for first column of r2.out\n";
  1750.             #die;
  1751.         #}
  1752.  
  1753.         $r2ray       = $line[1]; # equals $r1[0]   
  1754.         $pointnumber = $line[2]; # corresponds to (can't be bigger than) $r1[1]
  1755.         $group       = $line[0]; # kind of correspondend to raycode in r1
  1756.        
  1757.         $km = sprintf "%.3f", $line[3];
  1758.         #$km =~ s/^\s+//;    # Remove leading whites
  1759.        
  1760.         # Check the format of group number. If too many rays are traced
  1761.         # it changes to '**'
  1762.         if ($group !~ m/\d+/){
  1763.             print
  1764.                 "\n\n\n________________________________________________________________\n"
  1765.                 ."\nERROR\n"
  1766.                 #."Gr >$group< is NO digit!\n"
  1767.                 ."Line $linenumber: @line\n"
  1768.                 ."Last station read: Station $model->{stations}->{$km}->{name} at "
  1769.                 ."km $model->{stations}->{$km}->{position}, phase $currentphase\n";
  1770.             print "Your traced rays are too big to fit into r2.out. This is"
  1771.                 ." a rayinvr problem and need to be solved there.\nYou need"
  1772.                 ." to find a way, to reduce the number of rays (also failed)"
  1773.                 ." tracings\n"
  1774.                 ."________________________________________________________________\n\n\n"
  1775.                 ;
  1776.             $model->printStatusMessage("\nYour r2.out is overflowed. Last station $model->{stations}->{$km}->{name} "
  1777.                 ."km $model->{stations}->{$km}->{position}, phase $currentphase");
  1778.             return;
  1779.         }
  1780.  
  1781.         # Second column in r2.out "ray" seems to be zero if raypath is not valid
  1782.         # Those rays are not listed in r1 and hence need to be ignored
  1783.         # You can have error messages in r2.out. They are sorted out with the $group-test
  1784.         # to be a digit.
  1785.         if ($rayblock == 1 && $group =~ m/\d+/ && $r2ray != 0) {
  1786.                        
  1787.            
  1788.             # A new ray starts
  1789.             if ($r2ray != $currentray || $group != $currentgroup){
  1790.                 #print "New ray starts\n";
  1791.                 #print "r2ray != currentray || group != currentgroup)";
  1792.                 #print "$r2ray != $currentray || $group != $currentgroup)\n";
  1793.                 #print "line:$. @line\n";
  1794.  
  1795.                 # If it's a new station, delete old rays in that station
  1796.                 if ( ! $currentStation || $currentStation != $model->{stations}->{$km} ){
  1797.                     #print "Delete rays for station $model->{stations}->{$km}->{name} at km $km\n" if $debug;
  1798.                     #$model->{stations}->{$km}->emptyRays;
  1799.                     $model->getStation($km)->emptyRays;
  1800.                 }
  1801.                 #print "station $model->{stations}->{$km}->{name} at km $km\n";
  1802.            
  1803.                 $currentray   = $r2ray;
  1804.                 $currentgroup = $group;
  1805.                 $currentStation = $model->{stations}->{$km};
  1806.                 $r1ray+=1;
  1807.                
  1808.                 $currentphase = $r1[$r1ray][2];
  1809.                 #print "Phase is $currentphase. Previous phase is $phase\n" if ($phase != $currentphase);
  1810.                 #$currentStation->emptyRays($currentphase) if ($phase != $currentphase);
  1811.                
  1812.                 $phase = $r1[$r1ray][2];
  1813.                 #print "r2.out:$linenumber: gr $group ray $r1ray, nbr: $r2ray, cur $currentray,".
  1814.                 #" ph: $phase , km <$km> <@line\n";
  1815.                 if (!defined $currentStation) {print "?? Which station? km $km in line $. of r2.out: @line\n"};
  1816.                
  1817.             }
  1818.  
  1819.             if (!defined $r1[$r1ray][0] && $status == 0){ # there's no information in r1 for this ray
  1820.                 # and rayinvr hasn't finished
  1821.                 print "WARNING !! RAYINVR DIDN'T RUN THROUGH THE WHOLE TRACING\n";
  1822.                 last;
  1823.             }
  1824.            
  1825.             # Check if r2rays fit:
  1826.             if ( $r1[$r1ray][0] != $r2ray){
  1827.                 print "________________________________________________________________\n".
  1828.                       "\nERROR\n".
  1829.                       "r2rays of r1 and r2 don't fit!! index $r1ray $r1[$r1ray][0] != $line[1]\n".
  1830.                       "Station $currentStation->{name}, ray $currentray\nr2 line $linenumber: @line\n".
  1831.                       "r1 raynr, npts, ph, linenumber\n".
  1832.                       "r1 @{$r1[$r1ray]}\n".           
  1833.                       "________________________________________________________________\n\n".
  1834.                       "  What to do?\n".
  1835.                       "  - Check if rayinvr has finished without problems\n".
  1836.                       "      - PRay cannot recognize segmentation faults of rayinvr\n".
  1837.                       "      - if rayinvr has'nt finished, check v.in for crossing layers, large gradients, ..\n".
  1838.                       "        (use vmodel) and/or go to last working version and delete r2.out\n".
  1839.                       "  - Check if format of r2.out matches your configuration:\n".
  1840.                       "      - get the number of digits of first column of raypart of r2.out\n".
  1841.                       "      - p.pl is expecting >$model->{config}->{r2out}< digits\n".
  1842.                       "      - Use 'r2out=NUMBER' in p.config to match r2.out with p.pl\n".
  1843.                       "_________________________________________________________________\n".
  1844.                       "\n\n";
  1845.                 $model->printStatusMessage("\nERROR: rayinvr has problems to trace all data. See command line output for more information");
  1846.                 close(RAYS);
  1847.                 return 1;
  1848.                 #die;
  1849.             }
  1850.             unless ($currentStation) {
  1851.                 print "WARNING no station for ray: @line\n";
  1852.                 $error = "\nERROR: Couldn't find station for some rays";
  1853.                 next;
  1854.             }
  1855.             # Use real raycodes as 'phase'. e.g 1.2 instead of 12. In older
  1856.             # versions, this has been different and only the tx-code was used
  1857.             # to sort in rays
  1858.             # $phase = '5.1'
  1859.             $currentStation->addRays("phase" => $phase, "raynumber" => $r1ray,
  1860.                                      "rays" =>  [$km, $line[4]] );
  1861.         } # if it is a ray
  1862.     } # end of while-loop for reading file
  1863.    
  1864.     close(RAYS);
  1865.     print "All rays read\n" unless $quiet;
  1866.     $model->printStatusMessage(".. Rays are read.");
  1867.     #die;
  1868.     $model->printStatusMessage($error);
  1869. }
  1870. sub _addBlocks {
  1871.  
  1872. =PROGhead2 C<model::_addBlocks()>
  1873.  
  1874. Add blocks read from C<v.in> to model
  1875.  
  1876. =cut
  1877.  
  1878.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1879.  
  1880.     # Finds corresponding layer object and adds blocks there
  1881.     my ($model, %args) = @_;
  1882.     #print "model::addBlocks\n";
  1883.     my $layer = $args{layer};
  1884.     my $blocks = $args{blocks};
  1885.     #print "Layer $layer, blocks $blocks\n";
  1886.     if (defined $model->{layers}[$layer-1]) {
  1887.         $model->{layers}[$layer-1]->addBlocks($blocks);
  1888.     } else {
  1889.         warn "Undefined value for layer $layer-1\n";
  1890.     }
  1891. }
  1892.  
  1893. sub _readVgrid {
  1894.  
  1895. =PROGhead2 C<model::_readVgrid()>
  1896.  
  1897. Creates grid file from v.in, reads grid file and creates little colored
  1898. squares to generate a smooth gradient.
  1899.  
  1900.  vin2xyz -R$xmin/$xmax/$zmin/$zmax -x$dx -z$dz < v2xyz.in > v.grid
  1901.  
  1902. =cut
  1903.  
  1904.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1905.  
  1906.     my ($model, %args) = @_;
  1907.     print "model::_readVgrid\n";
  1908.     $model->{space}->delete('VGRID');
  1909.     # Create gridfile with rayinvr-skript vin2xyz  
  1910.     my $xmin = $model->{xmin};
  1911.     my $xmax = $model->{xmax};
  1912.     my $zmin = $model->{zmin};
  1913.     my $zmax = $model->{zmax};
  1914.     my $dx = 1;
  1915.     my $dz = 0.5;
  1916.    
  1917.     my $command = "vin2xyz -R$xmin/$xmax/$zmin/$zmax -x$dx -z$dz < v2xyz.in > v.grid";
  1918.     print "$command\n";
  1919.     system ($command);
  1920.    
  1921.     # Read in vgrid
  1922.     print "Gridfile created\n";
  1923.    
  1924.     my $file = "v.grid";
  1925.     say "Reading file v.grid";
  1926.     my $cns = $model->{space};
  1927.    
  1928.     open(FILE, $file) or do {$model->{vgrid} = 0; die "Can't open $file"};
  1929.     while (<FILE>){
  1930.         chomp;
  1931.         my ($x, $z, $v) = split;
  1932.         my $color = _getColor($v);
  1933.         my @scaled = $model->model2screen([$x-$dx/2, $z-$dz/2, $x+$dx/2, $z+$dz/2], "space");
  1934.        
  1935.         $cns->createRectangle(@scaled, -fill => $color, -width=>0, -tags=>["VGRID", "km $x, d $z, v $v"]);
  1936.        
  1937.     }
  1938.     close (FILE);
  1939.    
  1940.     unless ($cns->find('withtag', 'VGRID')) {
  1941.         $model->{vgrid} = 0;
  1942.         $model->printStatusMessage("\nError in creating the velocity grid. Check the command manually:\n$command");
  1943.         }
  1944.  
  1945.     $model->order;
  1946.     print "model::_readVgrid() is done\n";
  1947. }
  1948. sub tomoReadGrid{
  1949.  
  1950. =PROGhead2 C<model::tomoReadGrid()>
  1951.  
  1952. Reads and displays grid file from Tomo2D
  1953.  
  1954. =cut
  1955.  
  1956.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  1957.  
  1958.     my ($model, %args) = @_;
  1959.     print "model::tomoReadGrid\n";
  1960.     $model->{space}->delete('VGRID');
  1961.     my $file = $model->{config}->{tomoGrid};
  1962.  
  1963.     my $cns = $model->{space};
  1964.     my $dx = 1;
  1965.     my $dz = 0.5;
  1966.  
  1967.     # CLEANUP
  1968.     $cns->delete('TOMOGRID');
  1969.     $cns->delete('TOMOREFL');
  1970.    
  1971.     print "This is tomogrid trying to open $file\n";
  1972.     open(FILE, $file) or (print("Can't open $file\n"), return 0);
  1973.     print "This is tomogrid reading $file\n";
  1974.     my $line = 0;
  1975.     while (<FILE>){
  1976.         chomp;
  1977.         my ($x, $z, $v) = split;
  1978.        
  1979.         #print "Reading line $line: $x $z $v\n";
  1980.         my $color = _getColor($v);
  1981.         my @scaled = $model->model2screen([$x-$dx/2, $z-$dz/2, $x+$dx/2, $z+$dz/2], "space");
  1982.         $v = sprintf "%5.2f", $v;
  1983.         $cns->createRectangle(@scaled, -fill => $color, -width=>0, -tags=>["TOMOGRID", "km $x, d $z, v $v"]);
  1984.         $line++;
  1985.     }
  1986.     close (FILE);
  1987.     $model->{tomoGrid}=1;
  1988.     # Read Reflector file
  1989.     $model->_readxzfile($model->{config}->{tomoRefl});
  1990.     $model->_readxzfile('bathyxz.dat');
  1991.     $model->_readxzfile('basement.dat');
  1992.    
  1993.     return 1;
  1994. }
  1995.  
  1996. sub _readxzfile {
  1997.  
  1998. =PROGhead2 C<model::readxzfile($file [, diagram])>
  1999.  
  2000. Reads given file and creates a line in model space with tags C<'XZ'>.
  2001. Calls C<< $model->order >>.
  2002.  
  2003. =cut
  2004.  
  2005.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2006.  
  2007.     # Read and plot given file
  2008.     my ($model, $file, $diagram) = @_;    
  2009.     $file =~ s/^\s+//;               # no leading white
  2010.     $file =~ s/\s+$//;               # no trailing white  
  2011.     #print "read xz file >$file<\n";
  2012.  
  2013.     my $color;
  2014.    
  2015.     ($file, $color) = split(/\s+/, $file,);
  2016.     $color = 'blue' unless ($color);
  2017.    
  2018.     $color = $model->_checkColor( $color );
  2019.     print "Draw file >$file<, color >$color<\n" if $verbose;
  2020.  
  2021.    
  2022.    
  2023.     my $cns = $model->{space};
  2024.     my $tag = "XZ";
  2025.     my $scalediagram = "space";
  2026.    
  2027.     if ($diagram && $diagram eq 'xt') {
  2028.         $cns = $model->{time};
  2029.         $tag = "XT";
  2030.         $scalediagram = "time";
  2031.     }
  2032.    
  2033.     my @refl;
  2034.    
  2035.     open(FILE, $file) or print("Can't open $file") , return 0;
  2036.         while (<FILE>){
  2037.             chomp;
  2038.             s/^\s*#.*//;            # whole line is commented
  2039.             s/^#.*//;               # whole line is commented
  2040.             next unless length;
  2041.  
  2042.             my ($x, $z) = split;
  2043.             push @refl, $x, $z;
  2044.         }
  2045.     close (FILE);
  2046.  
  2047.     my @scaled = $model->model2screen(\@refl, $scalediagram);
  2048.     # Line
  2049.     #$cns -> create('line',@scaled, -joinstyle=>"bevel", -fill=> $color, -width=>1,
  2050.             #tags => [$tag, "$file"]);
  2051.     my $s = .3; # size of circles
  2052.     for (my $i = 0; $i < $#scaled; $i += 2) {
  2053.         $cns -> create('oval',
  2054.             $scaled[$i]-$s, $scaled[$i+1]-$s ,$scaled[$i]+$s, $scaled[$i+1]+$s ,
  2055.             -fill=>$color, -outline=>$color, -width=>1,
  2056.             tags => [$tag, "$file"]);
  2057.     }
  2058.  
  2059.    
  2060.     if ($diagram && $diagram eq 'xt') {
  2061.         $model->{xt} = 1;
  2062.     } else {
  2063.         $model->{xz} = 1;
  2064.     }
  2065. }
  2066.  
  2067. sub tomoReadRays{
  2068.     # Reading in rays written by Korenaga's Tomo2D
  2069.     # Fileformat (ready for gmt plotting):
  2070.     # >
  2071.     # km d
  2072.     # .. ..
  2073.     # stkm std
  2074.     # >
  2075.     # .. next station
  2076.        
  2077.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2078.  
  2079.     my ($model, %args) = @_;
  2080.    
  2081.     my $file = $args{'file'};
  2082.     my $ph = $args{'ph'};
  2083.    
  2084.     print("tomoReadRays needs file >$file< and >$ph< \n"), return 0  unless (defined $file && defined $ph);
  2085.     print "model::readTomoRays ($file, $ph)\n";
  2086.  
  2087.     ### TODO TODO, only delete phases which shall get overwritten
  2088.     foreach (sort {$b <=> $a}(keys(%{$model->{stations}}))) {      
  2089.         $model->{stations}->{$_}->emptyRays($ph);
  2090.     }
  2091.    
  2092.  
  2093.     my @data;   # array to store input file
  2094.     my $cns = $model->{space};
  2095.     my $st;
  2096.     my $ray=0;
  2097.     my $new = 1;    # Flag new ray
  2098.     my $oldkm = -1; # Check if new ray is for same station as last one
  2099.     open(FILE, $file) or  print("Can't open $file\n"), return 0;
  2100.     while (<FILE>){
  2101.         chomp;
  2102.         my @line = split;
  2103.         if ($new == 1) {
  2104.             my $km = $line[0];
  2105.             my $stkm = $model->getClosestStation($km);
  2106.             $st = $model->getStation($stkm);
  2107.            
  2108.             print "Draw tomo ray for station $st->{name} at km $km\n" if $debug;   
  2109.             $new = 0;
  2110.             if ($oldkm != $km){
  2111.                 $ray = 0;
  2112.                 $oldkm = $km;
  2113.             }
  2114.         }
  2115.        
  2116.         if ($line[0] eq ">") {
  2117.             # This is when a new ray starts or ends        
  2118.             $new = 1;
  2119.             @data = ();
  2120.             $ray++;
  2121.         } else {           
  2122.             $st->addRays("phase" => $ph, "raynumber" => $ray,
  2123.                          "rays" =>  [$line[0], $line[1]] );            
  2124.         }
  2125.  
  2126.     }
  2127.     close (FILE);
  2128.     print "Finished reading $file for Tomo2D-rays\n";
  2129.    
  2130.  
  2131. }
  2132. sub _makeContours {
  2133.  
  2134. =PROGhead2 C<< model::_makeContours( "source" => tomo/rayinvr) >>
  2135.  
  2136. Program creates contour file for rayinvr or tomo2D. The file name used
  2137. for tomo2D it's still hardwired to tomo.grd!!
  2138. For rayinvr the v.grd is created by vin2xyz and xyz2grd.
  2139.  
  2140. It's called by model->tomo for tomo and model->ordner for rayinvr
  2141.  
  2142. =cut
  2143.  
  2144.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2145.  
  2146.     my ($model, %args) = @_;
  2147.     print "model::_makeContours\n";
  2148.  
  2149.     die "Give datasource for Contours. Either rayinvr or tomo2d" unless (exists $args{source});
  2150.    
  2151.     # Create gridfile with rayinvr-skript vin2xyz  
  2152.     my $xmin = $model->{xmin};
  2153.     my $xmax = $model->{xmax};
  2154.     my $zmin = $model->{zmin};
  2155.     my $zmax = $model->{zmax};
  2156.     my $dx = 1;
  2157.     my $dz = 0.1;
  2158.    
  2159.     my $grid = "v.grd";
  2160.     my $xyz = "v.xyz";
  2161.    
  2162.     if ($args{source} eq "rayinvr") {
  2163.         my $command =
  2164.         "vin2xyz -R$xmin/$xmax/$zmin/$zmax -x$dx -z$dz < v2xyz.in > $xyz";
  2165.         print "Make xyz: $command\n";
  2166.         system ($command);
  2167.         $command = $model->getConfig('gmt')." xyz2grd $xyz -R$xmin/$xmax/$zmin/$zmax -I1/0.1 -Gv.grd";
  2168.         print "Make grid:  $command\n";
  2169.         system ($command);
  2170.  
  2171.     }
  2172.  
  2173.     if ($args{source} eq "tomo") {
  2174.         $xyz = $model->getConfig("tomoGrid");
  2175.         $grid = "tomo.grd";
  2176.     }
  2177.  
  2178.     # -MC: means: M for use one file with multiple segments
  2179.     # C is a flag with marks a new segment
  2180.     #my $command = "grdcontour $grid -C0.2 -D -MC -JX1/1 > contours.ps";
  2181.     my $command =
  2182.        # Old gmt command (for gmt4)
  2183.        # "grdcontour v.grd -C0.2 -D -MC -JX25/-16 -B50/10:.'Version $model->{version}': ".
  2184.        # New configurable gmt-switch
  2185.        $model->getConfig('gmt')." grdcontour v.grd -C0.2 -D -MC -JX25/-16 -B50/10:.'Version $model->{version}': ".
  2186.        " -R$xmin/$xmax/$zmin/$zmax --HEADER_FONT_SIZE=9 > contours.ps";
  2187.     print "Make contours \n$command\n";
  2188.     system ($command);
  2189.    
  2190.     print "To create a postscript of your contours run:\n";
  2191.     print $model->getConfig('gmt')." grdimage v.grd -JX25/10 -R$xmin/$xmax/$zmin/$zmax -V -Ccolors_velocities.cpt > t.ps\n";
  2192.     print "model::_makeContours() is done\n";
  2193. }
  2194.  
  2195. sub _readContours {
  2196.  
  2197. =PROGhead2 C<model::_readContours>
  2198.  
  2199. Reads and draws contours with tag 'C<CLINE>'. No flag is set, no ordering
  2200. done. That's organized by C<order>.
  2201.  
  2202. =cut
  2203.  
  2204.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2205.  
  2206.     # Read file "contour" made by gmt programm grdcontour in sub _makeContours
  2207.     # and draws them.
  2208.     my ($model, %args) = @_;
  2209.     my $cns = $model->{space};
  2210.     #$model->_makeContours();
  2211.  
  2212.    print "_readContours\n";
  2213.    
  2214.     my $file = "contour";
  2215.     my @cline;  # Array for collecting point of a contour line
  2216.    my ($x, $z, $v);
  2217.     open(FILE, $file) or do {$model->printStatusMessage("\nCan't open file >$file<. Check the grdcontour command (see command lineoutput)"); return};
  2218.     while (<FILE>){
  2219.         chomp;
  2220.        
  2221.         # Skip first line
  2222.         if ($. == 1) {next};
  2223.        
  2224.         # If line matches "C.." then it's the start or end of a contourline
  2225.         unless ( m/C/) {
  2226.             ($x, $z, $v) = split;      
  2227.             #print "Reading line $.: $x $z $v\n";
  2228.             push @cline, $x, $z;
  2229.         } else {
  2230.             #print "Draw Contour line $_, previous $v\n";
  2231.             my @line = split;
  2232.             #my $v = $line[1];
  2233.             my $color = _getColor($v);
  2234.             my $rho = $model->getDensity($v);
  2235.            
  2236.            my $w = 4;      # Contourwidth
  2237.            
  2238.            if ( $model->{contourcolor} == 0 ) {
  2239.                #$color = 'gray20';
  2240.                my $g = 110 ;
  2241.                $color = sprintf('#%02x%02x%02x', $g,$g,$g); # RGB
  2242.                $w = 1;
  2243.            }
  2244.            #print "Contour color for $v km/s is  $color\n";
  2245.             my @scaled = $model->model2screen(\@cline, "space");
  2246.             $cns -> create('line',@scaled, -joinstyle=>"bevel", -fill=>$color, -width=>$w, tags => ['CLINE', "$v rho $rho"]);
  2247.             @cline = ();
  2248.         }
  2249. }
  2250.     close (FILE);
  2251.    print "model::_makeContours() is done\n";
  2252. }
  2253.  
  2254. sub tomo {
  2255.  
  2256. =PROGhead2 C<model::tomo($key, $value)>
  2257.  
  2258. C<model::tomo> handles buttons for drawing
  2259. C< $key =  tomorays, tomogrid>
  2260.  
  2261. Ends with calling C<< model->order() >>.
  2262.  
  2263. =cut
  2264.  
  2265.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2266.  
  2267.     my ($model, %args) = @_;
  2268.     print "model::tomo (%args)\n";
  2269.     print Dumper(\%args) ;
  2270.  
  2271.     my $cns = $model->{space};
  2272.     my $lzd = $model->{time};
  2273.  
  2274.    # ONLY TOMO2D FUNCTIONS LEFT
  2275.    # AT THE END: $model->order();
  2276.    if (exists $args{"tomorays"}) {
  2277.  
  2278.  
  2279. =PROGbegin html
  2280.  
  2281. <ol>
  2282. <li> Delete old rays <br>
  2283.    <code>$model->{stations}->{$_}->emptyRays;</code><br></li>
  2284.    
  2285. <li> Get version from file 'tomoversion' and update window title </li>
  2286.  
  2287. <li> Read rays and traveltimes <br>
  2288.    If 'tomoRaysPg' is defined, then Pg and PmP are read from different
  2289.    ray and tx-files <br>
  2290.    
  2291.    <code>
  2292.        $model->tomoReadRays('file' => $model->getConfig('tomoRaysPmP'),
  2293.        'ph' => $model->getConfig('tomoPhasePmP')); <br>  
  2294.    $model->_readTx('file' => $model->getConfig('tomoTimesPg'),  key => 'txTomo');
  2295.    </code></li>
  2296.  
  2297. <li> Read tomo grid<br>
  2298.    <code>
  2299.    $model->tomoReadGrid;
  2300.    </code>
  2301.    
  2302. </ol>
  2303.  
  2304. =end html
  2305.  
  2306. =cut
  2307.  
  2308.        ## Just set value. Drawing is done by model::order
  2309.  
  2310.        #$model->{nodes} = 0; # Flaggin nodes not to show
  2311.        
  2312.        ####################
  2313.        # 1. Delete old rays
  2314.        ### TODO TODO, only delete phases which shall get overwritten
  2315.        foreach (sort {$b <=> $a}(keys(%{$model->{stations}}))) {
  2316.            $model->{stations}->{$_}->emptyRays;
  2317.        }
  2318.  
  2319.        # Get tomoversion
  2320.        my $version = "Tomo2D";
  2321.        my $file = "tomoversion";
  2322.        open(FILE, $file) or die "Can't open $file";
  2323.        while (<FILE>){
  2324.            chomp;
  2325.            #my ($x, $z, $v) = split;
  2326.            $version = $_;
  2327.            print "Version: $version\n";
  2328.        }
  2329.        close(FILE);
  2330.        $model->_set("version", $version);
  2331.        
  2332.        # Update windowtitle
  2333.        $model->{"mainwindow"}->title("PRay: Model: $version");
  2334.        $model->{"mainwindow"}->update;
  2335.        
  2336.        # There are two possibilities for input files. Either one file with
  2337.        # all rays for phases, or two files with Pg and PmP seperated
  2338.        if ( $model->getConfig('tomoPhasePg') ) {
  2339.            print "model->getConfig(tomoRaysPg) $model->getConfig('tomoRaysPg')\n";
  2340.            $model->tomoReadRays('file' => $model->getConfig('tomoRaysPg'),
  2341.                'ph' => $model->{config}->{'tomoPhasePg'});
  2342.                
  2343.            $model->tomoReadRays('file' => $model->getConfig('tomoRaysPmP'),
  2344.                'ph' => $model->getConfig('tomoPhasePmP'));
  2345.            
  2346.            $model->_readTx('file' => $model->getConfig('tomoTimesPg'),  key => 'txTomo');
  2347.            #$model->_readTx('file' => $model->getConfig('tomoTimesPmP'), key => 'txTomo');
  2348.            $model->{tomotimes} = 1
  2349.        } else {
  2350.                        
  2351.            # One file with both phases. Cannot distinguish raypathes for
  2352.            # reflections and refractions. It doesn't matter for picked
  2353.             # times
  2354.             print "WARNING !! RAYS FOR PG AND PMP ARE UNDISTINGUISHABLE\n";
  2355.             if ($model->{config}->{'tomoRays'}) {
  2356.                 $model->tomoReadRays('file' => $model->getConfig('tomoRays'),
  2357.                     'ph' => $model->{config}->{'tomoPhase'});
  2358.             }
  2359.              
  2360.             if ($model->{config}->{'tomoTimes'}){
  2361.                     $model->_readTx('file' => $model->getConfig('tomoTimes'), key => 'txTomo');
  2362.             }
  2363.             $model->{tomotimes} = 1
  2364.         }
  2365.         print "Read files\n";
  2366.  
  2367. =PROGpod
  2368.  
  2369.  model->{tomotimes} = 1, if traveltimes for tomo2D have been read
  2370.  No distinction between Pg, PmP or both is made in this flag
  2371.  
  2372.  otherwise model->{tomotimes} = 0
  2373.  
  2374. =cut
  2375.  
  2376.         my $e = $model->tomoReadGrid;
  2377.         if ( $e == 1 ) {
  2378.             print "Grid read successfully. Deactivate nodes\n";
  2379.             $model->{nodes} = 0;
  2380.         }
  2381.         #$model->{tomorays} = ${$args{'tomorays'}};
  2382.     } # end tomorays
  2383.    
  2384.     if (exists $args{'tomoGrid'}){
  2385.         # Only draw grid, if none is already there
  2386.         my $e = 1;
  2387.         unless ($cns->find('withtag', 'TOMOGRID')) {
  2388.             $e = $model->tomoReadGrid;}
  2389.    
  2390.         print "Error code is $e\n";
  2391.         # $e is set to zero, if reading the grid fails.
  2392.         # Then nodes should still be drawn
  2393.         if ( $e == 1 ) {
  2394.             print "Grid read successfully. Deactivate nodes\n";
  2395.             $model->{tomoGrid} = ${$args{'tomoGrid'}};
  2396.             $model->{nodes} = 0;
  2397.         }
  2398.     }
  2399.    
  2400.     if (exists $args{tomoContours}) {
  2401.         $model->_makeContours( "source" => "tomo");
  2402.         $model->_readContours;
  2403.         $model->{tomoContours} = ${$args{'tomoContours'}};
  2404.     }
  2405.    
  2406.     print "Order yourself!\n" if $debug;
  2407.     $model->order;
  2408. }
  2409.  
  2410. sub order {
  2411.  
  2412. =PROGhead2 C<model::order()>
  2413.  
  2414. Change the sequence of object on canvases. Does not draw new objects
  2415. (apart from contours (should that be changed in future?)). Reads config
  2416. of objects from model and raises or lowers the object accordingly. E.g.
  2417. if nodes should not be displayed the are lowered, so they lie behind the
  2418. model layers and cannot be seen. If they should be shown later, they
  2419. don't need to be redrawn
  2420.  
  2421. =cut
  2422.  
  2423.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2424.  
  2425.     # Make order of objects according to settings
  2426.     # Like raise or lower bounds, nodes, ..
  2427.     my ($model) = shift;
  2428.     my $cns = $model->{space};
  2429.     my $lzd = $model->{time};
  2430.  
  2431.     print "model::order\n" if $tree;
  2432.    
  2433.  
  2434.     if ($model->{tomoGrid} == 1) {
  2435.         $cns->raise('TOMOGRID');
  2436.         $cns->raise('TOMOREFL');
  2437.     } else {
  2438.         $cns->lower('TOMOGRID');
  2439.         $cns->lower('TOMOREFL');       
  2440.     }
  2441.    
  2442.     if ($model->{vgrid} == 1) {
  2443.        #print "Raise VGRID\n";
  2444.        unless ($cns->find('withtag', 'VGRID')) {
  2445.            $model->_readVgrid;
  2446.        }
  2447.         $cns->raise('VGRID');
  2448.     } else {
  2449.        #print "Lower VGRID\n";
  2450.         $cns->lower('VGRID');
  2451.     }
  2452.  
  2453.     if ($model->{contours} == 1){
  2454.         unless ($cns->find('withtag', 'CLINE')) {
  2455.             print "There should be contours, but there aren't. So I make them\n";
  2456.             $model->_makeContours("source" => 'rayinvr');
  2457.             $model->_readContours();
  2458.         }
  2459.         $cns->raise('CLINE');  
  2460.     } else {
  2461.         $cns->lower('CLINE')
  2462.     }
  2463.    
  2464.    #print "model->{xz} = $model->{xz}\n";
  2465.    if ($model->{xz} == 1){
  2466.        $cns->raise('XZ');
  2467.    } else {
  2468.        $cns->lower('XZ')
  2469.    }
  2470.    
  2471.    #print "model->{xt} = $model->{xt}\n";
  2472.    if ($model->{xt} == 1){
  2473.        $lzd->raise('XT');
  2474.    } else {
  2475.        $lzd->lower('XT')
  2476.    }
  2477.    
  2478.    if ($model->{blocks} == 1 ){
  2479.        $cns->raise('BLOCK');
  2480.    } else {
  2481.        $cns->lower('BLOCK');
  2482.    }
  2483.  
  2484.     #if ($model->{tomorays} == 1){
  2485.         #unless ($cns->find('withtag', 'TOMORAYS')) {
  2486.             #print "There should be tomorays, but there aren't. So I make them\n";
  2487.             #$model->tomoReadRays();
  2488.         #}     
  2489.         ##$cns->raise('TOMORAYS'); 
  2490.     #} else {
  2491.         ##$cns->lower('TOMORAYS')
  2492.     #}
  2493.        
  2494.     $cns->raise('AXES');
  2495.     #$cns->raise('RAYS');
  2496.     if ($model->{ShowRays} == 1) {
  2497.         print "order::Raise RAYS\n" if $debug;
  2498.         $cns->raise('RAYS');
  2499.     } else {
  2500.         print "order::Lower RAYS\n" if $debug;
  2501.         $cns->lower('RAYS');
  2502.     }
  2503.  
  2504.  
  2505.    #if ($model->{nodes} == 1 ){
  2506.        #$cns->raise('BOUND'); $cns->raise('NODE');
  2507.    #} else {
  2508.        #$cns->lower('BOUND'); $cns->lower('NODE');
  2509.    #}
  2510.    $cns->raise('BOUND');
  2511.    if ($model->{nodes} == 1 ){
  2512.         $cns->raise('NODE');
  2513.     } else {
  2514.         $cns->lower('NODE');
  2515.     }
  2516.  
  2517.    if ($model->{vnodes} == 1 ){
  2518.        unless ($cns->find('withtag', 'VNODE')) {
  2519.            foreach my $layer (@{$model->{layers}}){
  2520.                $layer->drawVNodes;
  2521.            }
  2522.        }
  2523.        $cns->raise('VNODE');
  2524.    } else {
  2525.        $cns->lower('VNODE');
  2526.    }
  2527.    
  2528.    if ($model->{annotvnodes} == 1 && $model->{vnodes} == 1 ){
  2529.        $cns->raise('ANNOTVNODE');
  2530.    } else {
  2531.        $cns->lower('ANNOTVNODE');
  2532.    }
  2533.    
  2534.    if ($model->{densities} == 1 && $model->{vnodes} == 1 ){
  2535.        $cns->raise('ANNOTRHO');
  2536.        $cns->lower('ANNOTVNODE');
  2537.    } else {
  2538.        $cns->lower('ANNOTRHO');
  2539.    }
  2540.  
  2541.    if ($model->{resolution} == 1 && $model->{vnodes} == 1 ){
  2542.        $cns->raise('ANNOTRES');
  2543.        $cns->lower('ANNOTVNODE');
  2544.    } else {
  2545.        $cns->lower('ANNOTRES');
  2546.    }
  2547.  
  2548.    $cns->raise('STATION');
  2549.    $lzd->raise('PICK');
  2550.    
  2551.    if ($model->{PicksMan} == 0) {
  2552.        $lzd->lower('txin');
  2553.    }
  2554.    if ($model->{PicksCal} == 0) {
  2555.        $lzd->lower('txout');
  2556.    }
  2557. }
  2558.  
  2559. sub drawSingleStationData {
  2560.  
  2561. =PROGhead2 C<model::drawSingleStationData( $station, $value)>
  2562.  
  2563. Called by p::bc_drawstation and sets ONE station. It's either added or
  2564. removed from array C<< $model->{drawnStations} >>. Calls C<<station::drawSingleStationData(value)>
  2565. for drawing.
  2566.  
  2567.  - $station->draw(value);
  2568.  - Update $model->{drawnStations}
  2569.  - $model->order;
  2570.  
  2571. =cut
  2572.  
  2573.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2574.  
  2575.     my $model = shift;
  2576.     my $arg = shift;
  2577.     my $value = shift;
  2578.     #print "model::drawSingleStationData($arg) <$value> on/off\n" if ($model->tree());
  2579.    
  2580.     my $pos = $model->{stationpositions}->{$arg};
  2581.     $model->{stations}{$pos}->draw($value);     # <----- DRAWING
  2582.    
  2583.     # Update array $model->{drawnStations}
  2584.     if ($value == 1 ){
  2585.         push @{$model->{drawnStations}}, $pos;
  2586.     } else {
  2587.         # Delete station picks, if no rays are there
  2588.         my @stations = grep {$_ ne $pos} @{$model->{drawnStations}};
  2589.         $model->{drawnStations} = \@stations;
  2590.     }
  2591.     #print "drawn Stations: @{$model->{drawnStations}}\n";
  2592.  
  2593.     $model->order;
  2594. }
  2595.  
  2596. sub drawPhaseStationList{
  2597.  
  2598. =PROGhead2 C<< model::drawPhaseStationList("phases" => [@phaselist], "stations" => [@stationlist]) >>
  2599.  
  2600. This sub is ONLY called by drawOOP from p.pl. It delete all drawings and
  2601. draws the given lists of phases and rays.
  2602.  
  2603.  $model->{drawnStations}=$args{stations}
  2604.  $st->draw;
  2605.  $model->order;
  2606.  
  2607. Also takes the 'redraw' subroutine. If no arguments are given, drawn Phases and stations
  2608. are redrawn.
  2609.  
  2610. =cut
  2611.  
  2612.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2613.  
  2614.     #say "model::drawPhaseStationList";
  2615.     my ($model, %args) = @_;
  2616.    
  2617.     # Set new stations and phases
  2618.     $model->{drawnPhases}   = $args{phases}   if (exists $args{phases});
  2619.     $model->{drawnRays}     = $args{rays}     if (exists $args{rays});
  2620.     $model->{drawnStations} = $args{stations} if (exists $args{stations});
  2621.  
  2622.     my @positions = @{$model->{drawnStations}}; # Stationpositions to be drawn
  2623.     my @phases    = @{$model->{drawnPhases}};   # Phases to be drawn
  2624.  
  2625.     # Draw rays and times for given stationlist
  2626.     for (my $i = 0; $i <= $#positions; $i++){
  2627.         my $st = $model->getStation($positions[$i]);
  2628.         #say "Draw rays and times for Station at position >$positions[$i]<, $st->{name}";
  2629.         $model->{stations}{$positions[$i]}->draw(1);
  2630.     }
  2631.     $model->order;
  2632. }
  2633.  
  2634. sub drawPhase {
  2635.  
  2636. =PROGhead2 C<model::drawPhase($ph, $value)>
  2637.  
  2638. Called by p::bc_drawPhase when phase/raybutton has changed.
  2639.  
  2640.  
  2641.  - Update $model->{drawnRays}
  2642.  - Update $model->{drawnPhases}
  2643.  - Draws rays and times for all stations in $model->{drawnStations}
  2644.  - $model->order
  2645.  
  2646. =cut
  2647.  
  2648.      printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2649.  
  2650.    #print Dumper \@_;
  2651.     #print @_;
  2652.    
  2653.     my ($model, %args) = @_;
  2654.     my $cns = $model->{space};
  2655.     my $lzd = $model->{time};
  2656.  
  2657.     if (exists $args{ray}) {
  2658.         my $rc = $args{ray}[0];
  2659.         my $value = $args{ray}[1];
  2660.         print "model::drawPhase() set ray $rc to $value\n" if $debug;
  2661.  
  2662.         if ($value == 0) {
  2663.             print "model::drawPhase() Delete phase $rc from @{$model->{drawnRays}}\n" if $debug;
  2664.             $cns->delete("Ph$rc");
  2665.        
  2666.             my @raycodes = grep {$_ ne $rc} @{$model->{drawnRays}};
  2667.             $model->{drawnRays} = \@raycodes;
  2668.         } else {
  2669.             push @{$model->{drawnRays}}, $rc;
  2670.             say "model::drawPhase() Added $rc to >@{$model->{drawnRays}}<" if $debug;
  2671.         }
  2672.     } # if exists $args{ray}
  2673.    
  2674.     if (exists $args{phase}){
  2675.         my $ph = $args{phase}[0];
  2676.         my $value = $args{phase}[1];
  2677.         print "model::drawPhase() set phase $ph, to $value\n" if $debug;
  2678.         if ($value == 0) {
  2679.             print "model::drawPhase() Delete phase $ph from @{$model->{drawnPhases}}\n" if $debug;
  2680.             $lzd->delete("Ph$ph");
  2681.            
  2682.             my @phases = grep {$_ ne $ph} @{$model->{drawnPhases}};
  2683.             $model->{drawnPhases} = \@phases;
  2684.         } else {
  2685.             push @{$model->{drawnPhases}}, $ph;
  2686.             say "model::drawPhase() Added phase $ph to >@{$model->{drawnPhases}}<" if $debug;
  2687.         }
  2688.     } # if exists $args{phase}
  2689.  
  2690.     if (defined $model->{drawnStations}){
  2691.     # Is phase button pushed before stationbuttons?
  2692.         my @positions = @{$model->{drawnStations}};
  2693.         for (my $i = 0; $i <= $#positions; $i++){
  2694.             say "model::drawPhase() Draw for Station $positions[$i]" if $debug;
  2695.  
  2696.             $model->{stations}{$positions[$i]}->draw;
  2697.         }
  2698.     }
  2699.    
  2700.     $model->order;
  2701. }
  2702.  
  2703. sub drawAxes{
  2704.  
  2705. =PROGhead2 C<model::drawAxes()>
  2706.  
  2707. Deletes existing axes and draws new axes for model and traveltime diagram
  2708.  
  2709. =cut
  2710.  
  2711.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2712.  
  2713.     my $model = shift; 
  2714.     my $cns = $model->{space};
  2715.     my $lzd = $model->{time};
  2716.     my $box = $model->{box};
  2717.  
  2718.     #say "model::drawAxes()";
  2719.    
  2720.     ## Delete existing axes
  2721.     $cns->delete('AXES');
  2722.     $lzd->delete('AXES');
  2723.     $lzd->delete('GRID');
  2724.  
  2725.     my $km1 = $model->{km1};
  2726.     my $km2 = $model->{km2};
  2727.     my $xmin = $model->{xmin};
  2728.     my $xmax = $model->{xmax};
  2729.    
  2730.     my $d1 = $model->{d1};
  2731.     my $d2 = $model->{d2};
  2732.    
  2733.     ######
  2734.     # PROFILE LENGTH
  2735.     ## Draw x-axes
  2736.     #print "Draw xaxes\n";
  2737.     my @tick = $model->model2screen([$km1, $d2, $km2, $d2], "space");
  2738.     $cns -> create('line',
  2739.             $tick[0], $tick[1]-2, $tick[2], $tick[3]-2,
  2740.             -joinstyle=>"bevel", -fill=>"black", -width=>2, -tags => ["AXES"]);
  2741.    
  2742.     #print "Draw ticks\n";
  2743.     my $stepx = 50; # default
  2744.     my $xdist = $km2-$km1;
  2745.     if ($xdist < 10) {
  2746.         $stepx = 1;}   
  2747.     elsif ($xdist < 40) {
  2748.         $stepx = 5;}
  2749.     elsif ($xdist < 210) {
  2750.         $stepx = 10;}
  2751.     elsif ($xdist < 500) {
  2752.         $stepx = 25;}
  2753.    
  2754.     # Start at a nice number like 0,10, or so
  2755.     my $a = sprintf "%d",$xmin/$stepx;
  2756.     my $x0 = $a*$stepx;
  2757.    
  2758.     #print "step $stepx, xdist $xdist, km= $km2 - $km1 start from >$x0<\n";
  2759.    
  2760.     ###############################
  2761.     ## Labels and ticks for x-axes
  2762.    
  2763.     for (my $i=$x0; $i <= $xmax; $i+=$stepx) {
  2764.         #print "Mark tick $i, $d2 , from ".($xmin+$xmin%$stepx)."\n";
  2765.         @tick = $model->model2screen([$i, $d2], "space");
  2766.         $cns -> create('line',
  2767.             $tick[0], $tick[1]-5, $tick[0], $tick[1],
  2768.             -joinstyle=>"bevel", -fill=>"black", -width=>1, -tags => ["AXES"]);
  2769.            
  2770.         $cns -> createText(
  2771.             $tick[0], $tick[1]-10,
  2772.             -fill=>"black", -text => "$i", justify => "right", -tags => ["AXES"]);
  2773.  
  2774.         # Same for TT-diagramm
  2775.         $lzd -> create('line',
  2776.             $tick[0], $tick[1]-5, $tick[0], $tick[1],
  2777.             -joinstyle=>"bevel", -fill=>"black", -width=>1, -tags => ["AXES"]);
  2778.            
  2779.         $lzd -> createText(
  2780.             $tick[0], $tick[1]-10,
  2781.             -fill=>"black", -text => "$i", justify => "right", -tags => ["AXES"]);
  2782.  
  2783.     }
  2784.    
  2785.     #####################
  2786.     # DEPTH
  2787.     # Draw y-axes      
  2788.     my $dy = ($d2-$d1);
  2789.     my $stepy = 10; #default
  2790.     my $y1 = $d1;
  2791.     my $y2 = $d2;
  2792.    
  2793.     if ($dy < 10) {
  2794.         $stepy = 1;}   
  2795.     elsif ($dy < 26) {
  2796.         $stepy = 5;}
  2797.    
  2798.     # Draw Y-axes
  2799.     $cns -> create('line',
  2800.             $model->model2screen([$km1, $d1, $km1, $d2], "space"),
  2801.             -joinstyle=>"bevel", -fill=>"black", -width=>4, -tags => ["AXES"]);
  2802.  
  2803.     # Tick and Label Y-AXES
  2804.     # Start at a nice point
  2805.     $a = sprintf "%d",$model->{zmin}/$stepy;
  2806.     my $y0 = $a*$stepy;
  2807.    
  2808.     for (my $i=$y0; $i <= $model->{zmax}; $i+=$stepy) {
  2809.         @tick = $model->model2screen([$km1, $i, $km1, $i], "space");
  2810.         $cns ->
  2811.             create('line',
  2812.              $tick[0], $tick[1], $tick[2]+5, $tick[3],
  2813.             -joinstyle=>"bevel", -fill=>"black", -width=>1, -tags => ["AXES"]);
  2814.         $cns ->
  2815.             createText(
  2816.             $tick[0]+15, $tick[1],
  2817.             -text => $i,
  2818.             -fill=>"black", -tags => ["AXES"]);
  2819.     }
  2820.    
  2821.    
  2822.     #############
  2823.     # Working on TTDiagramm
  2824.     # Draw x-axes
  2825.    
  2826.     my $tmin = $model->{tmin};
  2827.     my $tmax = $model->{tmax};
  2828.     my $t1 = $model->{t1};
  2829.     my $t2 = $model->{t2};
  2830.     my $dt = $t2-$t1;
  2831.     $stepy = 1;
  2832.     if ($dt <= 2) {
  2833.         $stepy = 0.1;
  2834.     } elsif ($dt <= 4) {
  2835.         $stepy = 0.5;
  2836.     }
  2837.     #print "drawAxes:: tmin = $tmin, tmax = $tmax, t1 = $t1, t2 = $t2\n";
  2838.      
  2839.     # Draw axes
  2840.     @tick = $model->model2screen([$km1, $tmin, $km2, $tmax], "time", $km1);
  2841.     $lzd -> create('line',
  2842.             $tick[0], $tick[1], $tick[0], $tick[3],
  2843.             -joinstyle=>"bevel", -fill=>"black", -width=>2, -tags => ["AXES"]);
  2844.    
  2845.     # Draw ticks
  2846.     for (my $i=$tmin; $i <= $tmax; $i+=$stepy) {
  2847.         # $km2 is used for lenght of gridline
  2848.         # $i+stepy/2 is used for minor ticks and gridlines
  2849.         my $minortick = $i+$stepy/2;
  2850.         #print "Minortick = $minortick. major = $i\n";
  2851.         # need $km1 again for correct calculation of minortick
  2852.         #                       0         2                  4                  6         8
  2853.         @tick = $model->model2screen([$km1, $i, $km2, $minortick, $xmin, $minortick, $xmax, $i, $km1, $minortick], "time", $km1);
  2854.        
  2855.        
  2856.          #Draw gridlines (major)
  2857.         $lzd -> create('line',
  2858.                 $tick[4], $tick[1], $tick[6], $tick[1],
  2859.                 -joinstyle=>"bevel", -fill=>"grey", -width=>1, -tags => ["GRID"]);
  2860.        
  2861.         # Draw minor gridline
  2862.         $lzd -> create('line',
  2863.                 $tick[4], $tick[9], $tick[6], $tick[9],
  2864.                 -joinstyle=>"bevel", -fill=>"lightgrey", -width=>1, -tags => ["GRID"]);
  2865.         #print "Major grid: $tick[4], $tick[1], $tick[6], $tick[1]\n";
  2866.         #print "Minor grid: $tick[4], $tick[9], $tick[6], $tick[5]\n";
  2867.        
  2868.         # Major ticks
  2869.         $lzd -> create('line',
  2870.                 $tick[0], $tick[1], $tick[0]+5, $tick[1],
  2871.                 -joinstyle=>"bevel", -fill=>"black", -width=>1, -tags => ["AXES"]);
  2872.         # Minor ticks
  2873.         $lzd -> create('line',
  2874.                 $tick[0], $tick[5], $tick[0]+2, $tick[5],
  2875.                 -joinstyle=>"bevel", -fill=>"black", -width=>1, -tags => ["AXES"]);
  2876.    
  2877.        
  2878.         $lzd -> createText(
  2879.                 $tick[0]+15, $tick[1],
  2880.                 -fill=>"black", -text => "$i", -tags => ["AXES"]);
  2881.     }
  2882. }
  2883.  
  2884.  
  2885. sub _readTimes {
  2886.  
  2887. =PROGhead2 C<model::_readTimes()>
  2888.  
  2889. Function reads traveltimes from rayinvr. C<tx.in> und C<tx.out>.
  2890.  
  2891. =cut
  2892.  
  2893.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2894.  
  2895.     my $model = shift;
  2896.     #print "model::readTimes()\n" if ($model->tree());
  2897.     my $file = "tx.in";
  2898.  
  2899.     #say "Read picked times from $file";
  2900.     my $r = $model->_readTx( file => $file, key => 'txin');
  2901.  
  2902. =PROGfor html
  2903. stores txin-data using<br>
  2904. <code>$model->_readTx( file => $file, key => 'txin');</code>
  2905. <br>
  2906.  
  2907. =cut
  2908.  
  2909.     #print "Finished reading tx.in\n";
  2910.  
  2911.     #say "Reading calculated Traveltimes";
  2912.     $file = "tx.out";  
  2913.     $r = $model->_readTx( file => $file, key => 'txout');
  2914.  
  2915. =PROGfor html
  2916. stores txout-data using<br>
  2917. <code>$model->_readTx( file => $file, key => 'txout');</code>
  2918. <br>
  2919. Times for tomo2D are currently read in function <code>tomo</code> and stored in key
  2920. <code>tomoTimesPg</code>, <code>tomoTimesPmP</code> or <code>tomoTimes</code>
  2921.  
  2922. =cut
  2923.  
  2924.     #print "Finished reading tx.out\n";
  2925. }
  2926.  
  2927. sub _readTx {
  2928.  
  2929. =PROGhead2 C<< model::_readTx( file => 'txfile', key => 'key') >>
  2930.  
  2931. Reads given C<txfile> and stores it in C<< $model->{key} >>.
  2932.  
  2933. =cut
  2934.  
  2935.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  2936.  
  2937.     my ($model, %args) = @_;
  2938.    
  2939.     unless (exists $args{file} && exists $args{key}) {
  2940.         warn "File AND key are needed for _readTX!!\n".
  2941.              "Got %args\n";
  2942.         return 1;
  2943.     }
  2944.    
  2945.     my $file = $args{'file'};
  2946.     my $key = $args{'key'}; # Where to store data, model-hash key
  2947.    
  2948.     print "Reading tx-file >$file<\n" unless $quiet;
  2949.  
  2950.     open(T, $file) or print "Can't open $file\n", return 0;
  2951.     my $pos;
  2952.     my $station;
  2953.     my $richtung; # Welche Seite der Station ist der Pick? -1 fuer links, 1 fuer rechts
  2954.    
  2955.     my @readStations = (); # This arrray is a list of stations in your tx.in
  2956.     # If a station is twice in your tx.in it won't get cleared in the
  2957.     # second run
  2958.  
  2959.     #############################
  2960.     # Reading picks
  2961.     my %data;   # Hash of hashes with stations and phases as key and datapicks as values
  2962.     while(<T>){
  2963.         chomp;
  2964.         #print "$.: $_\n";
  2965.         s/^\s*#.*//;            # whole line is commented
  2966.         s/^#.*//;               # whole line is commented
  2967.  
  2968.         next unless length;
  2969.  
  2970.         my ($km, $t, $unc, $ph) = split;
  2971.         ## Lines like this mark new branches
  2972.         ##   188.959    -1.000     0.000     0
  2973.         ##  station-km  shot dir    mark    mark
  2974.        
  2975.         next unless ($t);
  2976.        
  2977.         $ph = 0 unless ($ph);
  2978.         #print "Read >$km, $t, $unc, $ph<\n";
  2979.         if (($t == -1 || $t == 1) && $ph == 0) {
  2980.         # if (($t == -1 || $t == 1) && $unc == 0 && $ph == 0) { # old conditions.
  2981.             # But $unc does not need to be zero. rayinvr works with non-zero values
  2982.             # New branch starts. First picks are usually left
  2983.             $richtung = $t;
  2984.             $pos = sprintf("%.3f",$km);
  2985.             #print "Reading arrivals for station at $pos, shot direction $t, $richtung\n";
  2986.             next;
  2987.         }
  2988.        
  2989.         unless ($pos ) {
  2990.             print "$.: $_\n";
  2991.             print "Station position undefined!!\n";
  2992.             next;
  2993.         }
  2994.        
  2995.         # tx-files all end with line
  2996.         #     0.000     0.000     0.000        -1
  2997.         if ($t == 0 && $unc == 0 && $ph == -1) {
  2998.             #print "Reached last line\n";
  2999.             next;
  3000.         }
  3001.        
  3002.         # This if-clause catches files with all picks in one branch, even
  3003.         # if they are on different sides of the station
  3004.         if ($km < $pos) {
  3005.             $richtung = '-1.000';
  3006.         } elsif ($km > $pos) {
  3007.             $richtung = '1.000';
  3008.         }
  3009.        
  3010.         if ($ph > 0) {
  3011.             # This is a pick. Save it to station
  3012.             # phase = 0     New station or branch
  3013.             # phase = -1    End of File
  3014.            
  3015.             # Store values
  3016.             # Pushing in unscaled values
  3017.             # print "Add pick to station at $pos, $richtung, $ph Data: $km, $t, $unc \n" if $dev;
  3018.             push @{$data{$pos}{$richtung}{$ph}}, [ $km, $t, $unc ];
  3019.  
  3020. =PROGfor html
  3021. <p> tx-times for tomo are stored in <code>$station->{$key}</code><br>
  3022. format: <code>push @{$data{$pos}{$richtung}{$ph}}, [ $km, $t, $unc ];
  3023. $station->{$key}->{$richtung}->{$ph} = @{$data{$pos}{$richtung}{$ph}}
  3024. </code><br>
  3025.  
  3026. =cut
  3027.  
  3028.         }
  3029.     } # END OF READING tx-formated file
  3030.     #print "Finished reading tx-file $file\n";
  3031.     close(T);
  3032.    
  3033.     #####
  3034.     # Storing data in station-object
  3035.     # Loop through stationpositions
  3036.     #print "Add pick data to stations\n";
  3037.     foreach my $pos (keys %data){
  3038.         my $station = $model->{stations}{$pos};
  3039.         #my $station = $model->{stations}{int($pos)};
  3040.         # Use int($pos) to remove unneeded numbers behind comma
  3041.        
  3042.         #print "Station >$station->{name}< at >$pos<\n";
  3043.         unless ( $station ) {
  3044.             print "\nError, no station defined for $pos!! This is likely a bug\n";
  3045.             $model->printStatusMessage("\nError, no station defined for $pos. This is likely a bug!!");
  3046.             next;
  3047.         }
  3048.         #print "Station $station->{name} at $pos is defined\n";
  3049.         $station->{$key} = undef; # Deleting ALL old traveltimes
  3050.         $model->{time}->delete('withtag',"RAYS$station->{name} "); # Clean up old data
  3051.  
  3052.         # Loop through directions
  3053.         foreach my $richtung (keys %{$data{$pos}}){
  3054.             # Loop through phases
  3055.             foreach my $ph (keys %{$data{$pos}{$richtung}}){
  3056.                 #print "Station $station->{name}: Use phase $ph";
  3057.                 my @picks = @{$data{$pos}{$richtung}{$ph}};
  3058.                 #print " with >".@picks."< picks\n";
  3059.                
  3060.                 $model->{time}->delete('withtag',"Ph$ph"); # Clean up old data
  3061.                 #print "model::_readTx: Add >".@picks."< picks to station $station->{name}, key = $key, richtung = $richtung, ph = $ph\n";
  3062.                 #$station->{$key}->{$richtung}->{$ph} = \@picks;    # This removes old existing data for that phase
  3063.                 $station->addPhase(key => $key, direction => $richtung, phase => $ph, data => \@picks );
  3064.             }
  3065.         }
  3066.     }
  3067.     return \%data;
  3068.  
  3069. }
  3070.  
  3071. #sub getCode {
  3072.  
  3073. #=PROGhead2 C<model::getCode(ph)> depricated!!
  3074.  
  3075.  
  3076. #Connects raycodes (ray) with phase numbering in tx-file (ivray) and returns the opposite
  3077. #code to the input code, e.g.: gets 1.2 (a ray-code) and returns 12
  3078. #( the tx code)
  3079.  
  3080. #NEW: new object CODES hold this information.
  3081.  
  3082. #=cut
  3083.  
  3084.     #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3085.  
  3086.     #my ($model, %args) = @_;
  3087.     #my $phase = "0";
  3088.  
  3089.     ## phasecodes has ZP phases as keys (e.g. 12)
  3090.     ## raycode has RI phases as keys (e.g. 1.2)        
  3091.  
  3092.     #return $model->{codes}->get(%args);
  3093.  
  3094.  
  3095.     ## Got tx-code, get ray-code
  3096.     #if (exists $args{phase} ) {
  3097.         #my $ph = $args{phase};
  3098.         #if (exists $model->{phasecodes}->{$ph}) {         
  3099.             #$phase = $model->{phasecodes}->{$ph};
  3100.         #} else {
  3101.             #print "Cannot find raycode for phase >$ph< in >".join(" ",sort(keys(%{$model->{phasecodes}})))."<\n";
  3102.         #}
  3103.     #}
  3104.  
  3105.     ## Got raycode, Get tx-phasecode
  3106.     #elsif (exists $args{ray} ) {
  3107.         #my $ray = $args{ray};
  3108.  
  3109.         ## Phase is reflected off floating reflector and has a an ambigous
  3110.         ## phase naming. (ray = X.2 in r.in, but X.4 in r1.out)
  3111.         #if ($ray =~ /.4$/ ) {
  3112.             #$ray =~ s/.4$/.2/;
  3113.         #}
  3114.         ##$model->{codes}->getCode(
  3115.         ##my @phases =  grep { $model->{raycode}[$_]}  0 .. $#{$model->{raycode}};
  3116.         ##if () {
  3117.             ##$phase = $model->{raycode}->{$ph};
  3118.         ##} else {
  3119.             ##print "Cannot find tx phasecode for phase >$ph< in >".join(" ",sort(keys(%{$model->{phasecodes}})))."<\n";
  3120.         ##}
  3121.     #}
  3122.    
  3123.     ## Didn't get specification for code
  3124.     #else {
  3125.         #print "I don't know, what you gave me\n";
  3126.         #print Dumper \%args;
  3127.     #}
  3128.  
  3129.     #return $phase;
  3130. #}
  3131.  
  3132. sub getConfig {
  3133.  
  3134. =PROGhead2 C<model::getConfig(key)>
  3135.  
  3136. Returns corresponding value for given key or undef if not defined
  3137.  
  3138. =cut
  3139.  
  3140.     #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3141.  
  3142.     my $model = shift;
  3143.     my $key = shift;
  3144.     my $value = undef;
  3145.    
  3146.     if ( exists $model->{config}->{$key} && defined  $model->{config}->{$key}) {
  3147.         $value = $model->{config}->{$key};
  3148.     } else {
  3149.         print "model->getConfig($key) - No entry for $key\n";
  3150.         return undef;
  3151.     }
  3152.    
  3153.     return $value;
  3154. }
  3155.  
  3156. sub screen2model {
  3157.  
  3158. =PROGhead2 C<model::screen2model([$x, $y], "space/time", $pos)>
  3159.  
  3160. Converts screen coordinates in km. C<$pos> is optional, if given,
  3161. times will be unreduced. Otherwise they are reduced.
  3162.  
  3163. =cut
  3164.    
  3165.     #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3166.  
  3167.     my $model = shift;
  3168.     my $coords = shift;
  3169.     my @coords = @$coords;
  3170.     my $diagramm = shift;   # Convert in timespace or modelspace?
  3171.     my $pos = shift if @_;
  3172.    
  3173.     # Error check for typos
  3174.     unless ( $diagramm =~ "time" || $diagramm =~ "space") {
  3175.         confess "model::model2screen: Don't know which diagram to use for >$diagramm<";
  3176.     }
  3177.    
  3178.     my @scaled = ();
  3179.    
  3180.     # Get current scaling values
  3181.     my $yscale  = $model->{yscale};
  3182.     my $ytscale  = $model->{ytscale};  
  3183.     my $xscale  = $model->{xscale};
  3184.    
  3185.     # Get model dimensions
  3186.     my $zmax = $model->{zmax};
  3187.     my $zmin = $model->{zmin};
  3188.     my $xmin = $model->{xmin};
  3189.     my $tmin = $model->{tmin};
  3190.     my $tmax = $model->{tmax};
  3191.    
  3192.     my $box = @{$model->{time}->configure(-scrollregion)}[-1];
  3193.    
  3194.     # Loop through given data and convert
  3195.     for (my $j=0; $j<= $#coords; $j++){
  3196.         # data comes in [x1,y1,x2,y2,..]
  3197.         #print "Convert $j: $coords[$j]\n";
  3198.         if ($j%2 != 0) {
  3199.  
  3200.             # y-value. Conversion depends on type of space: model or time
  3201.             if ($diagramm eq "space"){
  3202.                 # y: model depth (z) in km
  3203.                 push @scaled, $coords[$j]/$yscale+$zmin;
  3204.                 #print "Depth $scaled[-1]\n";
  3205.  
  3206.             } elsif ($diagramm eq "time"){
  3207.                 # y: traveltime value in s
  3208.                             # Reverse time?
  3209.            
  3210.                 if ( $model->{config}->{reverseTime} ) {
  3211.                     #print "(DEV) reverse coord $coords[$j] to time with $box->[3] to " if $dev;
  3212.                     $coords[$j] = $box->[3]-$coords[$j];
  3213.                     #print "(DEV) Reversed coord: $coords[$j] \n" if $dev;
  3214.                 }
  3215.            
  3216.                 my $t = $coords[$j]/$ytscale+$tmin;
  3217.                
  3218.                 if ($pos && $model->{vredstate} == 1) {
  3219.                     # A station position is defined. Scale coordinates
  3220.                     # without reduction
  3221.                     my $vred = $model->{vred};
  3222.                     $t = $t + abs($pos - abs($scaled[-1]))/$vred + $tmin;
  3223.                 }
  3224.                 push @scaled, $t;
  3225.             }
  3226.         } else {
  3227.             # x: Profilkm
  3228.             push @scaled, $coords[$j]/$xscale+$xmin;
  3229.            
  3230.         }
  3231.        
  3232.     }
  3233.    
  3234.     return @scaled;
  3235. }
  3236.  
  3237. sub model2screen{
  3238.  
  3239. =PROGhead2 C<model::model2screen([$x, $y], "space/time", $pos)>
  3240.  
  3241. Converts model coordinates in screen coordinates and reduces traveltimes
  3242. if needed (if C<$pos> is given and C<< $model->{vredstate} >> is set)
  3243.  
  3244. =cut
  3245.  
  3246.     #printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3247.  
  3248.     # call: model2screen( model, coords, diagramm, stationkm)
  3249.     #print "Scale Got @_\n";
  3250.     my $model = shift; # Model
  3251.      
  3252.     my $zmax = $model->{zmax};
  3253.     my $zmin = $model->{zmin};
  3254.     my $xmin = $model->{xmin};
  3255.     #my $box = $model->{box};
  3256.     my $box = @{$model->{time}->configure(-scrollregion)}[-1];
  3257.     my $profilelength = $model->{profilelength};
  3258.     my $tmin = $model->{tmin};
  3259.     my $tmax = $model->{tmax};
  3260.  
  3261.     # TRY OOP SCALE
  3262.     my $yscale  = $model->{yscale};     # for model
  3263.     my $ytscale = $model->{ytscale};    # for time
  3264.     my $xscale  = $model->{xscale};
  3265.  
  3266.     my $vredbutton = $model->{vredstate};
  3267.     my $vred = $model->{vred};
  3268.    
  3269.     my @scaled; # = (1,2,3);
  3270.     my @in=$_[0];
  3271.     my $diagramm=$_[1];
  3272.    
  3273.     # Error check for typos
  3274.     unless ( $diagramm =~ "time" || $diagramm =~ "space") {
  3275.         confess "model::model2screen: Don't know which diagram to use for >$diagramm<";
  3276.     }
  3277.    
  3278.     my $pos = $_[2];
  3279.    
  3280.     for (my $j=0; $j<= $#{$in[0]}; $j++){
  3281.    
  3282.         # Every second value is a time value
  3283.         # data: km1, t1, km2, t2, ..
  3284.         if( $j%2 != 0 && $diagramm eq "time"){
  3285.            
  3286.             my $t;  # time in screen coordinates
  3287.            
  3288.             # reduce time
  3289.             if ($vredbutton == 1 ){
  3290.                
  3291.                 # no offset for reduction known
  3292.                 if (!defined $pos) {
  3293.                     #print "No position for reducing given, push in ".(($in[0][$j])*$ytscale)."\n" ;
  3294.                     # set position to current km, which basically undo the reduction
  3295.                     #$pos = $in[0][$j-1] if (!defined $pos);
  3296.                     #print "Set position to $pos\n";
  3297.                     $t = ($in[0][$j] - $tmin)*$ytscale;
  3298.                     #push @scaled, ($in[0][$j] - $tmin)*$ytscale;
  3299.                    
  3300.                 } else {
  3301.                     # Reduce time
  3302.                     #say " My position for reducing traveltime is $pos. data: >$in[0][$j-1]<";
  3303.                     #               Zeit     - |     x0-x            / v   |
  3304.                     #push @scaled, ($in[0][$j]-(abs($pos-$in[0][$j-1])/$vred) - $tmin)*$ytscale;
  3305.                     $t = ($in[0][$j]-(abs($pos-$in[0][$j-1])/$vred) - $tmin)*$ytscale;
  3306.                    
  3307.                     #push @scaled, ($tmax - $in[0][$j]-(abs($pos-$in[0][$j-1])/$vred))*$ytscale;
  3308.                     #print "Scaled; @scaled\n";
  3309.                 }
  3310.             } else {
  3311.                 # Time value is not reduced
  3312.                
  3313.                 #print "Button $vredbutton \n";
  3314.                 $t = ($in[0][$j] - $tmin)*$ytscale;
  3315.                 #push @scaled, ($in[0][$j] - $tmin)*$ytscale;
  3316.                
  3317.                 #push @scaled, ($tmax - $in[0][$j])*$ytscale;
  3318.                 #print "Zeit skaliert mit $in[0][$j]*$ytscale=". ($in[0][$j])*$ytscale."\n";
  3319.             }
  3320.            
  3321.             # Reverse time?
  3322.             if ( $model->{config}->{reverseTime} ) {
  3323.                 #print "(DEV) reverse time $in[0][$j] to coordinate $t with $box->[3] to " if $dev;
  3324.                 $t = $box->[3]-$t;
  3325.                 #print "$t\n" if $dev;
  3326.             }
  3327.             push @scaled, $t;
  3328.            
  3329.         } elsif ($j%2 != 0 && $diagramm eq "space"){
  3330.             # DEPTH IN MODEL (y-value)
  3331.             push @scaled, ($in[0][$j]-$zmin)*$yscale;
  3332.             #print "Scaled tiefe  $xscale, $yscale or $ytscale is @scaled \n";
  3333.        
  3334.         } else {
  3335.             # Profilkilometer
  3336.             push @scaled,
  3337.             ($in[0][$j]-$xmin)*
  3338.             $xscale;
  3339.            
  3340.             #print "(DEV) m2s ( $in[0][$j] - $xmin) * $xscale\n" if $dev;
  3341.             #print "Scale with x>$xscale<, y>$yscale< or yt>$ytscale< is @scaled \n";
  3342.         }
  3343.     }
  3344.     #print "Returning array with ".@scaled." elements\n";
  3345.     return @scaled;
  3346.     }
  3347.  
  3348. sub reduce {
  3349.  
  3350. =PROGhead2 C<model::reduce(km,time,pos,v)>
  3351.  
  3352. Reduce given C<<time>> for C<<pos-km>> with current model reduction velocity.
  3353.  
  3354. =cut
  3355.  
  3356.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3357.  
  3358.     my ($model) = shift;
  3359.     my $km = shift;
  3360.     my $t = shift;
  3361.     my $pos = shift;
  3362.     my $v = $model->{vred};
  3363.    
  3364.     my $tred = $t - ( (abs($pos-$km) )/ $v) if ($v > 0);
  3365.    
  3366.     # Don't reduce if reduction is switched off.
  3367.     $tred = $t if ($model->{vredstate} == 0 );
  3368.     #print "Don't reduce time. It's switched off\n" if ($model->{vredstate} == 0   && $debug);
  3369.    
  3370.     #print "Got $t s, $pos - $km = ".abs($pos-$km)."km , $v , return reduced time t = $tred\n";
  3371.     return $tred;
  3372. }
  3373.  
  3374. sub unreduce {
  3375.  
  3376. =PROGhead2 C<model::unreduce(km,time,pos)>
  3377.  
  3378. Removes reduction for given C<<time>> for C<<pos-km>> with current model reduction velocity.
  3379.  
  3380. =cut
  3381.  
  3382.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3383.  
  3384.     my ($model) = shift;
  3385.     my $km = shift;
  3386.     my $tred = shift;
  3387.     my $pos = shift;
  3388.     my $v = $model->{vred};
  3389.    
  3390.     my $t = $tred + ( (abs($pos-$km) )/ $v);
  3391.     #print "Got reduced time t = $tred s, $pos - $km = ".abs($pos-$km)."km , $v , return $t\n";
  3392.     return $t;
  3393. }
  3394.  
  3395. sub updateScale {
  3396.  
  3397. =PROGhead2 C<model::updateScale()>
  3398.  
  3399. Get's new values for y-,yt- and xscale. Deletes and redraws velocity and
  3400. depth nodes to keep a circular shape
  3401.  
  3402. =cut
  3403.  
  3404.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3405.  
  3406.    # Call: $model->updateScale("yscale" => $yscale, "ytscale" => $ytscale, "xscale" => $xscale);
  3407.    my ($model, %args) = @_;
  3408.    my $cns = $model->{space};
  3409.    my $lzd = $model->{time};
  3410.    
  3411.    #print "Updating to: ".%args."\n";
  3412.    while (my ($key, $value) = each(%args)){
  3413.        #say "$key => $value ";
  3414.        $model->{$key}= $value;
  3415.  
  3416.    }
  3417.    $model->drawAxes;
  3418.    
  3419.    $model->{space}->delete('VNODE');
  3420.    $model->{space}->delete( "NODE");
  3421.    foreach (@{$model->{layers}}){
  3422.        $_->drawNodes;
  3423.        if ($model->{'vnodes'} == 1){
  3424.            $_->drawVNodes;}
  3425.    }
  3426.    
  3427.    # Delete traveltimes
  3428.    $lzd->delete('PICK');
  3429.    if (defined $model->{drawnStations}){
  3430.    # Is phase button pushed before stationbuttons?
  3431.        my @positions = @{$model->{drawnStations}};
  3432.        for (my $i = 0; $i <= $#positions; $i++){
  3433.            say "model::drawPhase() Draw for Station $positions[$i]" if $debug;
  3434.  
  3435.            $model->{stations}{$positions[$i]}->draw;
  3436.        }
  3437.    }
  3438.    $model->order;
  3439. }
  3440.  
  3441. sub set {
  3442.  
  3443. =PROGhead2 C<< model::set( $key => $value ) >>
  3444.  
  3445. Interface for external setting of model configuration. C<$key> is checked
  3446. before applied. Only C<vredstate vred PicksMan PicksCal ShowRays glueNodes
  3447. version xz nodes annotvnodes contours>
  3448. are allowed. C<< $model->order >> does the changing.
  3449.  
  3450. =cut
  3451.  
  3452.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3453.  
  3454.    my ($model, %args) = @_;
  3455.    #say "model::set(%args)"; print Dumper(\%args);
  3456.    
  3457.    # Only options in this array are allowed to be set.
  3458.    my @options = (qw/vredstate vred PicksMan PicksCal ShowRays glueNodes
  3459.        version xz xt nodes annotvnodes contours contourcolor blocks vgrid vnodes densities
  3460.        resolution/);
  3461.    
  3462.    # Safe all valid keys and values in model
  3463.    foreach my $key (keys(%args)) {
  3464.        #print "model::set $key = $args{$key}\n";
  3465.        if (grep {$_ eq $key} @options){
  3466.        # Is key allowed to be set?
  3467.        
  3468.            if (ref($args{$key})) {
  3469.            # is argument a reference?
  3470.            
  3471.                $model->{$key} = ${$args{$key}};
  3472.                print "model::set $key = ${$args{$key}}\n" if $debug;
  3473.            } else {
  3474.            # argument is no reference
  3475.            
  3476.                $model->{$key} = $args{$key};
  3477.                print "model::set $key = $args{$key}\n" if $debug;
  3478.            }
  3479.        } else {
  3480.        # key is not allowed to be set
  3481.            print "Unknown option >$key< in model::set\nOptions are @options";
  3482.        }
  3483.    }
  3484.    
  3485.    ###################################################################
  3486.    # Some keys require action like drawing objects
  3487.    # - blocks
  3488.    # - vred
  3489.    
  3490.    # If traveltime reduction has been changed, picks have to be redrawn
  3491.    if ( exists $args{"vredstate"} || exists $args{"vred"} || exists $args{"PicksMan"}
  3492.        || exists $args{"PicksCal"} ){
  3493.            #TODO: find a more elegant way to remove observed and calculated picks
  3494.            # from station. fix this with drawPhaseStationList
  3495.            $model->{time}->delete('withtag', 'PICK');
  3496.        $model->drawPhaseStationList();
  3497.    }
  3498.  
  3499. =PROGpod
  3500.  
  3501. if (exists $args{"blocks"} && == 1 )
  3502. delete BLOCK
  3503. foreach layer->_drawBlock
  3504.  
  3505. =cut
  3506.  
  3507.    if (exists $args{"blocks"} && ${$args{"blocks"}} == 1 ) {
  3508.        $model->{space}->delete('BLOCK');
  3509.        foreach my $layer (@{$model->{layers}}){
  3510.            $layer->_drawBlocks;
  3511.        }
  3512.    }
  3513.  
  3514.    $model->order;
  3515. }
  3516.  
  3517. sub reset {
  3518.  
  3519. =PROGhead2 C<model::reset()>
  3520.  
  3521. This routine resets the model and is run, when the model is changed.
  3522. So all things, that change as consequence are deleted.
  3523. That are contours and grid. It deletes them, so they have to be
  3524. regenerated by model:: order.
  3525. All rays are deleted from stations.
  3526. All calculated traveltimes.
  3527.  
  3528. =cut
  3529.  
  3530.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3531.  
  3532.    my ($model, %args) = @_;
  3533.    my $lzd = $model->{time};
  3534.    my $cns = $model->{space};
  3535.    
  3536.    $cns->delete('CLINE');
  3537.    $cns->delete('VGRID');
  3538.    
  3539.    ## Delete old data
  3540.    foreach (sort {$b <=> $a}(keys(%{$model->{stations}}))) {
  3541.        # Safety maeasure for unblessed stations
  3542.        if  (ref $model->{stations}{$_} eq "station") {
  3543.            $model->{stations}->{$_}->emptyRays;
  3544.            $model->{stations}->{$_}->emptyTimes(keys => ['txout']);
  3545.        } else {
  3546.            print "WARNING !! There's an unblessed station in your model!! Call the priest !!\n";
  3547.        }
  3548.    }
  3549. }
  3550.  
  3551. sub writeVin {
  3552.  
  3553. =PROGhead2 C<model::writeVin()>
  3554.  
  3555. Called by p and controls writing C<v.in> formatted file by each layer calling
  3556. C<< layer->writeVin >> and resets model.
  3557.  
  3558. =cut
  3559.  
  3560.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3561.     printf "(T) %s(@_)\n", commons::whoami();
  3562.  
  3563.    my ($model, %args) = @_;
  3564.    my @layers = @{$model->{layers}};
  3565.    
  3566.    my $file = "v.in";
  3567.    my $output = "v";   # Default output are velocities
  3568.    if (exists $args{file}) {
  3569.        if ( $args{file} eq "rho.in") {
  3570.        # Write densities?
  3571.            $output = 'rho';
  3572.            $file = "rho.in";
  3573.        } else {
  3574.        # Write resolutions
  3575.            $file = $args{file};
  3576.            $output = "res";
  3577.        }
  3578.        print "Write file $file\n";
  3579.    }
  3580.    
  3581.    #print "model:: Writing v.in\n";
  3582.    
  3583.    # Start writing for each layer
  3584.    # Desired output is
  3585.    # v     velocities
  3586.    # rho   densities
  3587.    # res   resolution values
  3588.    
  3589.    # Delete old v.in file
  3590.     #print "(DEV) remove v.in ($file)\n";
  3591.    #unlink $file;
  3592.    
  3593.    open(FILE, ">$file") or die "Can't open $file";
  3594.    foreach (@layers){
  3595.        printf FILE $_->writeVin( 'output' => $output );
  3596.    }
  3597.    print "(D) Wrote file >$file< with $output-data\n" if $debug;
  3598.    close(FILE);
  3599.  
  3600.    # If v.in gets written, write an additional file for conversion
  3601.    # with vin2xyz (that v.in file needs values at both boundaries
  3602.    if ( $file eq "v.in" ) {
  3603.        #$model->writeV2xyzIn();
  3604.        $model->writeV2xzyIn;
  3605.    }
  3606.    
  3607.    # Copy file to export path (do keep a copy in rayinvr folder for
  3608.    # running plots and stuff
  3609.    print "copy($file, $model->{config}->{exportpath}$file\n";
  3610.    copy("$file", "$model->{config}->{exportpath}$file");
  3611.    
  3612.    # Why resetting?
  3613.    $model->reset;
  3614. }
  3615.  
  3616. sub writeV2xzyIn {
  3617.    
  3618.    my ($model, %args) = @_;
  3619.    my @layers = @{$model->{layers}};
  3620.  
  3621.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3622.  
  3623.    my $file = "v2xyz.in";
  3624.    my $output = "v2xyz";
  3625.    open(FILE, ">$file") or die "Can't open $file";
  3626.    foreach (@layers){
  3627.        printf FILE $_->writeVin( 'output' => $output );
  3628.    }
  3629.    close(FILE);
  3630.    print "(D) Wrote file >$file< with $output-data\n" if $debug;
  3631.  
  3632. }
  3633.  
  3634. sub get {
  3635.  
  3636. =PROGhead2 C<model::get(key)>
  3637.  
  3638. model->get()
  3639. interface function to p.pl to get information about model
  3640.  
  3641. Extract information out of tags for vnodes
  3642.  
  3643. key can be: vnode, vnodes, 1d or any key from model hash
  3644.  
  3645. =cut
  3646.  
  3647.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3648.  
  3649.     my $model = shift;
  3650.     my $arg = shift;
  3651.     my $cns = $model->{space};
  3652.  
  3653.     if ($arg eq "vnode"){
  3654.         # Get information for a single node
  3655.    
  3656.         my $id  = $cns->find(qw/withtag current/);
  3657.         my @tags = $cns->gettags($id);
  3658.         my $layer = $tags[1];
  3659.         #my ($km, $v, $vu, $vl, $vupar, $vlpar);
  3660.         my ($km, $v, $pos) = split (/ /, $tags[4]);
  3661.         # $pos is either vu or vl
  3662.         print "I'm .$arg. >$tags[1]<, id @$id, @tags, $v = v, $km = km\n";
  3663.         # get(vu/vl, index)
  3664.         #($km, $v, $vu, $vl, $vupar, $vlpar) = $model->getLayer($layer)->get("vnode", $tags[5], $tags[2]);
  3665.         #return ($v, $km, $vu, $vl, $vupar, $vlpar);
  3666.         my @return  = $model->getLayer($layer)->get("vnode", $tags[5], $tags[2]);
  3667.         return @return;
  3668.     }
  3669.    
  3670.     if ($arg eq "vnodes"){
  3671.         # Get information for ALL vnodes
  3672.                    
  3673.         my (@km, @vu, @vl, @vupar, @vlpar);
  3674.         # Get velocity nodes for each layer
  3675.         foreach (@{$model->{layers}}) {
  3676.             print "(DEV) Get nodes for $_->{number}\n" if $dev;
  3677.             #last layer doesn't have any velocity nodes
  3678.             last if ($_->{last} == 1);
  3679.            
  3680.             # lkm: layerkm
  3681.             my ($lkm, $lvu, $lvl, $lvupar, $lvlpar) = $_->get("vnodes");
  3682.             #print "Got back @$lkm\n@$lvu\n@$lvl\n";
  3683.             push @km, $lkm;
  3684.             push @vu, $lvu;
  3685.             push @vl, $lvl;
  3686.             push @vupar, $lvupar;
  3687.             push @vlpar, $lvlpar;
  3688.            
  3689.         }
  3690.         # Return references to arrays containing references
  3691.         return \@km, \@vu, \@vl, \@vupar, \@vlpar;
  3692.     }
  3693.    
  3694.     if ($arg eq "1d") {
  3695.         # Print out 1D velocity profile
  3696.        
  3697.         my $kmstring = shift;      
  3698.         my @km = split(/,/, $kmstring);
  3699.        
  3700.         # Clean directory from old files
  3701.         #opendir(DIR, "") or die $!;
  3702.         #my @files = grep { /^vd_\./ && -f "$_"}  readdir(DIR);
  3703.         #closedir(DIR);
  3704.         my @files = glob("km*_v*.vz");
  3705.         print "Delete files @files\n";
  3706.        
  3707.         foreach (@files){
  3708.             unlink("$_");   # Potential Problem if you run it on Windows!!
  3709.         }
  3710.                
  3711.         foreach my $km (@km) {
  3712.             $km =~ s/\s//g;
  3713.             #$km =~ sprintf ("%03f", $km);
  3714.             print "Extract for km >$km<\n";
  3715.             #my $file = "km${km}_v$model->{version}.vz";
  3716.             my $file = sprintf ("km%03d_v%d.vz", $km, $model->{version});
  3717.             open(FILE, ">$file") or die "Cannot open $file";
  3718.             foreach my $layer (@{$model->{layers}}){
  3719.                 my $vd = $layer->get($arg, $km);
  3720.                 print $vd;
  3721.                 printf FILE $vd;
  3722.             }
  3723.         close(FILE);
  3724.         }
  3725.        
  3726.     }
  3727.    
  3728.     if (exists $model->{$arg}) {
  3729.         return $model->_get($arg);
  3730.     }
  3731.    
  3732. }
  3733. sub _getColor {
  3734.  
  3735. =PROGhead2 C<model::_getColor(v)>
  3736.  
  3737. Returns color code depending on given velocity.Used for
  3738. gradient grid, contour lines and layer colors.
  3739.  
  3740. =cut
  3741.  
  3742.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3743.  
  3744.     my $v = shift;
  3745.    
  3746.     ######
  3747.     # Create color-palette
  3748.     my $vmin = 1.2;     # Lowest velocity to color
  3749.     my $vmax = 8;       # Highest velocity
  3750.    
  3751.     # Make sure, you don't overstep your limits
  3752.     if ( $v > $vmax ) { $v = $vmax }
  3753.  
  3754.     # Change color in steps of 0.1 km/s
  3755.     my $hmin = 240;     # "blue" in HSV-colorsystem
  3756.     #my $hmin = 340;        # "blue" in HSV-colorsystem
  3757.     my $hmax = 0;       # "red"
  3758.  
  3759.     my $i = sprintf "%3i", ($vmax - $v)/(($vmax - $vmin))*$hmin;
  3760.                                #h   s    v
  3761.    
  3762.     my $color = hsv2rgb( $i, 0.50, 0.80 ); # s und v < 1 !!
  3763.     #print "Color $i, $color, \n";
  3764.    
  3765.     return $color;
  3766. }
  3767.  
  3768. sub _checkColor {
  3769.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3770.  
  3771.     my $model = shift;
  3772.     my $color = shift;
  3773.     my $cns = $model->{space};
  3774.    
  3775.     my @coords = ( qw/0 0 10 10/ );
  3776.     eval {$cns -> create('line', @coords, -joinstyle=>"bevel",
  3777.         -fill=> $color, -width=>1, tags => ['COLOR'])};
  3778.  
  3779.     if ( $@ ) {
  3780.         #print "ERROR $@\n";
  3781.         $color = "#$color";
  3782.     }
  3783.    
  3784.     $cns->delete('COLOR');
  3785.     return $color;
  3786. }
  3787.        
  3788. sub exportRays {
  3789.  
  3790. =PROGhead2 C<model::exportRays()>
  3791.  
  3792.  1.  Delete old exported data in output directory (this can be switched
  3793.      off in p.config)
  3794.  2a. Loop through all stations
  3795.  2b. Loop through all phases
  3796.      Export rays
  3797.      Export picked phases
  3798.      Export calculated phases
  3799.  
  3800. =cut
  3801.    
  3802.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  3803.  
  3804.     my ($model, %args) = @_;
  3805.     my $dir = $model->{config}->{exportpath};
  3806.    
  3807.     print "Export Rays and picks to $dir\n";
  3808.  
  3809.     ############################################
  3810.     # 1. Remove old rays and picks in export directory
  3811.     unless (exists $model->{config}->{deleteExported} && $model->{config}->{deleteExported} == 0) {
  3812.         print "Deleting old exported data\n";
  3813.         if (-d $dir) {
  3814.             opendir(DIR, $dir) or die $!;
  3815.             my @files = grep { -f "$dir/$_"}  readdir(DIR);
  3816.             closedir(DIR);
  3817.            
  3818.             # Delete only pick, rays and refl-files
  3819.             foreach (@files){
  3820.                 if ($_ =~ m/(pick_st*)/ || $_ =~ m/(ray_st*)/ || $_ =~ m/(refl_st*)/ ){
  3821.                     # $1 represents the digit selected by regex (\d+)
  3822.                     #print "Delete $dir$_\n";
  3823.                     unlink("$dir/$_");   # Potential Problem if you run it on Windows!!
  3824.                 }
  3825.             }
  3826.         }
  3827.     }
  3828.    
  3829.     # Export absolute AND relative output
  3830.     for ( my $absolute = 0 ; $absolute <=1; $absolute++) {
  3831.     ############################################  
  3832.     # 2a. Loop through all stations
  3833.     foreach (keys(%{$model->{stations}})){
  3834.         my $pos = $_;
  3835.         my $station = $model->{stations}{$pos};
  3836.         say "----- Get data for station $station->{name} at $pos";
  3837.        
  3838.         # Relative position used for output x-position
  3839.         my $relpos = $pos;  # x position is relavitve to obs
  3840.        
  3841.         my $fileRays = $dir."/ray_st$_.dat";
  3842.         my $fileReflected = "$dir/refl_st$_.dat";
  3843.         my $fileOutPicks = $dir."/pick_st$_"."out.dat";
  3844.         my $fileInPicks = "$dir/pick_st$_"."in.dat";
  3845.  
  3846.         #if ($model->getConfig("outpos") eq "absolute" ) {
  3847.         if ($absolute ) {
  3848.             $relpos = 0;    # x position is absolute model km
  3849.             $fileRays        = "$dir/ray_st${_}_a.dat";
  3850.             $fileReflected   = "$dir/refl_st${_}_a.dat";
  3851.             $fileOutPicks    = "$dir/pick_st${_}out_a.dat";
  3852.             $fileInPicks     = "$dir/pick_st${_}in_a.dat";
  3853.         } else {
  3854.             $fileRays        = "$dir/ray_st${_}_r.dat";
  3855.             $fileReflected   = "$dir/refl_st${_}_r.dat";
  3856.             $fileOutPicks    = "$dir/pick_st${_}out_r.dat";
  3857.             $fileInPicks     = "$dir/pick_st${_}in_r.dat";
  3858.         }
  3859.        
  3860.         # Get rays
  3861.         my $rays = $model->{stations}{$pos}->getRays;
  3862.         #my $picks = $model->{stations}{$pos}->getPicks("direction" => '-1.000');
  3863.         my $manpicks = $model->{stations}{$pos}->{txin};
  3864.         next unless (defined $rays);
  3865.  
  3866.         my @rcodes = sort(keys(%$rays));
  3867.         print "(D) Got rays: $rays, ph: @rcodes\n" if $debug;
  3868.        
  3869.         next unless ( @rcodes);
  3870.        
  3871.  
  3872.         open (FILERAYS,     ">$fileRays")     or die "Can't open $fileRays\n";
  3873.         open (FILEREFL,     ">$fileReflected")or die "Can't open $fileReflected\n";
  3874.         open (FILEOUTPICKS, ">$fileOutPicks") or die "Can't open $fileOutPicks\n";
  3875.         open (FILEINPICKS,  ">$fileInPicks")  or die "Can't open $fileInPicks\n";
  3876.         #print "Write files $fileRays, $fileReflected, $fileOutPicks, $fileInPicks\n";
  3877.        
  3878.         ############################################
  3879.         # 2b. Loop through all raycodes
  3880.         foreach my $rc (@rcodes) {
  3881.             print "Print raycode $rc\n" if $debug;
  3882.             my $newDir = -1; # Start with rays left of station
  3883.            
  3884.             ###########################
  3885.             # RAYS
  3886.             foreach (@{$rays->{$rc}}) {
  3887.                 next unless (defined $_ );
  3888.                 #print "Ray: $_\n" ;
  3889.  
  3890.                 # Export turning points of reflections
  3891.                 if ($rc =~ m/2$/) {
  3892.                     #$turningPoints = 1;
  3893.                     my $i = 2;
  3894.                     my @a = @{$_};
  3895.                     my %h = @a;
  3896.                     my %i = reverse %h;
  3897.                     my $max = (sort(values(%h)))[-1];
  3898.                     #$i{$max};
  3899.                     #print "Print raycode $rc to file\n";
  3900.                     if ($newDir == -1 &&  $pos < $i{$max}) {
  3901.                         #print "Change direction at $i{$max} $max\n";
  3902.                         print FILEREFL ">\n";
  3903.                         $newDir = 1;
  3904.                     }
  3905.                     print FILEREFL "$i{$max} $max\n";
  3906.                 }
  3907.                
  3908.                 # Export raypath
  3909.                 for (my $i = 0; $i < $#{$_}; $i += 2) {
  3910.                     # 0 is just printed for compatibility
  3911.                     # with make_picks_rays.csh. There's a -1 for left shots and 1 for
  3912.                     # right shots. But I don't make this distinction here
  3913.                     #print "$_->[$i] $_->[$i+1] 0 $rc\n";
  3914.                     print FILERAYS "$_->[$i] $_->[$i+1] 0 $rc\n";
  3915.                    
  3916.                 }
  3917.                 #print ">\n";
  3918.                 print FILERAYS ">\n";
  3919.                                
  3920.             } # end of rays loop
  3921.             print FILEREFL ">\n";
  3922.         } # end of rcodes loop
  3923.        
  3924.             ###########################
  3925.             # PICKS
  3926.             my $key = $model->{tomotimes} ? 'txTomo' : 'txout' ;
  3927.  
  3928.        
  3929.         foreach (qw/ -1.000 1.000/){
  3930.             ###########################
  3931.             # CALCULATED TRAVELTIMES
  3932.             #my $ph = $model->{codes}->get('ray'=>$rc);
  3933.             # Get all phases for a station
  3934.             foreach my $ph (@{$station->getPhases()}) {
  3935.                
  3936.                 print "(D) Try to find out if picks are defined for key $key : $_, phasecode $ph\n" if $debug;
  3937.                 my $picks = $station->getPicks( 'direction' => $_, 'phase' => $ph, 'key' => $key );
  3938.  
  3939.                 if (defined $picks) {
  3940.                     print "(D) Got picks $picks\n" if $debug;
  3941.                     #print "txout for station at $pos, ph $ph, dir $_ is defined \n";
  3942.                     #print "Got an array $_\n";
  3943.                     #my $picks = @{$picks->{$_}->{$ph}};
  3944.                     #print "There are <".@{$picks}."> calculated picks for phase $ph\n";
  3945.      
  3946.                     for (my $i = 0; $i <= $#{$picks}; $i += 1) {
  3947.                         # Copy values to variabls, otherwise data is changed
  3948.                         # in the object!!
  3949.                         my $x = $picks->[$i][0];
  3950.                         my $t = $picks->[$i][1];
  3951.                         #print "my x: $x ref($x), t=$t\n";
  3952.                         printf FILEOUTPICKS "%.3f %.3f 0 %d\n",
  3953.                             ($x-$relpos),
  3954.                             $model->reduce($x,$t, $pos),
  3955.                             $ph;
  3956.                     }
  3957.                     print FILEOUTPICKS ">\n";
  3958.                 }
  3959.                
  3960.                 ###########################
  3961.                 # PICKED TRAVELTIMES
  3962.                 $picks = $station->getPicks
  3963.                     ( 'direction' => $_, 'phase' => $ph, 'key' => 'txin' );
  3964.                 print "(D) Get picks for direction $_\n" if $debug;
  3965.                 next unless (defined $picks);
  3966.                
  3967.                 #print "There are >$#{$picks}< for Phase $ph and $station->{name} and direction $_\n";
  3968.                 for (my $i = 0; $i <= $#{$picks}; $i += 1) {
  3969.                     # Copy values to variabls, otherwise data is changed
  3970.                     # in the object!!
  3971.                     my $x = $picks->[$i][0];
  3972.                     my $t = $picks->[$i][1];
  3973.                     my $unc = $picks->[$i][2];
  3974.                    
  3975.                     printf FILEINPICKS "%.3f %.3f 0 %d\n",
  3976.                         ($x-$relpos),
  3977.                         $model->reduce($x,$t-$unc, $pos),
  3978.                         $ph;
  3979.                     printf FILEINPICKS "%.3f %.3f 0 %d\n",
  3980.                         ($x-$relpos),
  3981.                         $model->reduce($x,$t+$unc, $pos),
  3982.                         $ph;
  3983.                     print FILEINPICKS ">\n";  
  3984.                 }
  3985.                
  3986.             } # foreach direction
  3987.         } # foreach phase
  3988.             #} else {
  3989.                 ## EXPORT PICKS FROM TOMO2D
  3990.                 #my $picks = $model->{stations}{$pos}->{txTomo};
  3991.                 #next unless $picks;
  3992.                 #print "Got $picks \n";
  3993.                 #foreach (keys(%{$picks})) {
  3994.                     #my $ph = $_;
  3995.                    
  3996.                     #for (my $i = 0; $i < $#{$picks->{$ph}}; $i++) {
  3997.                         ## Copy values to variabls, otherwise data is changed
  3998.                         ## in the object!!
  3999.                         #next unless (defined $picks->{$ph}->[$i]);
  4000.                         #my $x = $picks->{$ph}->[$i][0];
  4001.                         #my $t = $picks->{$ph}->[$i][1];
  4002.                         ##print "my x: $x ref($x)\n";
  4003.                                                
  4004.                         #print FILECALPICKS ($x-$pos)." "
  4005.                             #.$model->reduce($x,$t, $pos)
  4006.                             #." 0 $ph\n";
  4007.                        
  4008.                         ## if this x and next x don't have same sign
  4009.                         ## insert ">\n" for gmt to start a new line
  4010.                         #unless ( $picks->{$ph}->[$i+1][0] && commons::eqsig ($x-$pos, $picks->{$ph}->[$i+1][0]-$pos) ) {
  4011.                             #print FILECALPICKS ">\n";
  4012.                         #}
  4013.                        
  4014.                     #} # end of for pick loop
  4015.                     #print FILECALPICKS ">\n";
  4016.                 #} # end of foreach keys(picks)
  4017.             #} # end if-else tomo2d picks
  4018.            
  4019.            
  4020.             # Get picks
  4021.             # OUTPUT, ready for plotting with gmt, SHOULD LOOK LIKE:
  4022.             #-18.077 3.731375 0 0.0
  4023.             #-18.077 3.831375 0 0.0
  4024.             #>
  4025.             #-17.254 3.66325 0 0.0
  4026.             #-17.254 3.76325 0 0.0
  4027.             #
  4028.             # Picks are seperated by ">" to mark new segment for gmts multiple
  4029.             # segments plotting
  4030.             # zeroes at the end are inserted for compartibility with make_rays
  4031.             # script by Tobi
  4032.    
  4033.  
  4034.         close(FILERAYS);
  4035.         close(FILEREFL);
  4036.         close(FILEOUTPICKS);
  4037.         close(FILEINPICKS);
  4038.        
  4039.     } # end of station loop
  4040. } # for absolute = 0/1
  4041.    
  4042. } # end sub export rays
  4043.  
  4044. sub resolution {
  4045.  
  4046. =PROGhead2 C<model::resolution>
  4047.  
  4048. Control subs for reading and writing resolution. Called from p.pl,
  4049. export resolution button
  4050.  
  4051. =cut
  4052.  
  4053.     printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4054.  
  4055.     my $model = shift;
  4056.  
  4057.     # Read resolution
  4058.     $model->_readRes();
  4059.     # Now print res.in to file
  4060.     $model->writeVin( 'file' => "res.in");
  4061.     $model->printStatusMessage(" .. wrote resolution to res.in ..");
  4062.     $model->writeXZV();
  4063.     $model->order;
  4064.    
  4065. } # sub resolution
  4066.  
  4067.  
  4068. sub _readRes {
  4069.  
  4070. =PROGhead2 C<model::_readRes>
  4071.  
  4072. Reads d.out and stores data in model->layers.
  4073. d.out contains a list with nodes which have been selected for adjustments
  4074. and an updated velocity model (same that is written to v.in).
  4075. The node list contains only the original value, adjustment and new value
  4076. but no position or index to identify which node it is.
  4077. You've got to look into the model to find the nodes position.
  4078.  
  4079. For resolution plots depth resolution makes no sense.
  4080.  
  4081. =cut
  4082.  
  4083.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4084.  
  4085.    my $model = shift;
  4086.  
  4087.    my @type;
  4088.    my @value;
  4089.    my @resolution;
  4090.    my @stddev;
  4091.    my @results;    # Save result-table (all information for nodes)
  4092.    my $paragraph = 'start'; # Flag
  4093.    
  4094.    # Keep current position infos
  4095.    my $currentLayer = 0;
  4096.    my $currentNode = 0;
  4097.    
  4098.    # Save data in an array of arrays and add them to each layer
  4099.    # when finished reading
  4100.    my @res;
  4101.    
  4102.    ####################################################################
  4103.    # Read resolution file
  4104.    my $file = "d.out";
  4105.    open(FILE, $file) or print "Can't open $file\n", return 0;
  4106.    while(<FILE>){
  4107.        chomp;
  4108.        s/^\s+//;               # no leading white
  4109.        s/\s+$//;               # no trailing white  
  4110.        next unless length;
  4111.        
  4112.        my $line = $_;
  4113.        my @line = split(/\s+/,$line);
  4114.        #                  t or un ad nw re std
  4115.        #print "My line is >@line<\n";
  4116.        #print "Line $. ".join(';',@line)."\n";
  4117.        
  4118.        if ($line =~ m/overall damping factor/) {
  4119.            print "Damping factor = $line[-1]\n";
  4120.            next;
  4121.        }
  4122.        
  4123.        # Set flag for reading adjustments, uncertainties, resolution, .. values
  4124.        if ($line[0] eq 'type'){
  4125.            #print "Reading resolution values\n";
  4126.            $paragraph = 'resolution';
  4127.            next;
  4128.        }
  4129.        
  4130.        # set flag for reading velocity model
  4131.        if ($line[0] eq 'velocity'){
  4132.            #print "Reading updated model\n";
  4133.            $paragraph = 'velocity';
  4134.            last;
  4135.        }
  4136.        
  4137.        # Reading resolution values
  4138.        if ($paragraph eq 'resolution') {
  4139.            # Overwrite line. Split does not work proberly when values
  4140.            # become too large
  4141.            @line = unpack("A1A11A11A11A11A11A11",$line);
  4142.            # Remove whitespaces
  4143.            @line = split('\s+',join(' ', @line));
  4144.            #print "Line $. ".join(';',@line)."\n" if $debug;
  4145.            
  4146.            push @type, "$line[0]";
  4147.            push @value, "$line[4]";
  4148.            push @resolution, "$line[5]";
  4149.            push @stddev, "$line[6]";
  4150.            
  4151.            print "$. resolution $resolution[-1] $line[5]\n" if $debug; # Print resolution value
  4152.  
  4153.            # save linenumber
  4154.            unshift @line, $.;
  4155.            push @results, \@line;
  4156.            #print "READ: ".join('-',@line)."\n";
  4157.        } # endif reading resolution
  4158.        
  4159.    } # end while FILE
  4160.    close(FILE);
  4161.  
  4162.    #print "Resolution values: @resolution\n";
  4163.    #print "Standard deviation: @stddev\n"
  4164.        #."Value: @value\n\n\n";
  4165.    ####################################################################
  4166.  
  4167.    my $n = @{$model->{layers}}; # Get number of layers
  4168.    
  4169.    # Find nodes in layer-objects
  4170.    my $i = 0;  # Index for nodes
  4171.    my $j = 0;  # Index for layers
  4172.    
  4173.    # nodetype are the old values that can be compared with the information
  4174.    # given in the nodes list to see if the node fits
  4175.    my @nodetype = qw(depth vu vl);   # Do NOT change sequence!!!
  4176.    my %nodepos = ( depth => 'km',
  4177.                    vu => 'vukm',
  4178.                    vl => 'vlkm');
  4179.    
  4180.    
  4181.    #print "Start looking for nodes\n"
  4182.        #."Node type value resolution stddev\n";
  4183.    while ( $i < $#type ) { # Loop through all nodes
  4184.        my $type = $type[$i];
  4185.  
  4186.        print "$i $type[$i] $value[$i] $resolution[$i] $stddev[$i]\n" if $debug;
  4187.        
  4188.        while ($j < $n ) { # loop through n-layers
  4189.            last if ($i > $#type);
  4190.            
  4191.            my $layer = $model->{layers}[$j];
  4192.            my @dres;
  4193.  
  4194.            print "(D) Look in layer $layer->{number} for $i "
  4195.                ."$type[$i] $value[$i] $resolution[$i] $stddev[$i]\n" if $debug;
  4196.            
  4197.            # Get partial derivative arrays of current layer for depth,
  4198.            # upper and lower velocity in this sequence.
  4199.            foreach my $nodetype (@nodetype){ # loop through depth, vu, vl
  4200.                my $derivatives = $nodetype.'par';
  4201.                #print "Look for derivativekey $derivatives and values $nodetype\n";
  4202.                
  4203.                # Find indizes of elements with activated partial derivs
  4204.                my @activated = grep { $layer->{$derivatives}[$_] == 1 } 0 .. $#{$layer->{$derivatives}};
  4205.                
  4206.                # Create with same length for resolution
  4207.                @dres = (-1)x@{$layer->{$derivatives}};
  4208.                
  4209.                #if (@activated) {
  4210.                    print "(D) Found n = ".@activated." nodes with partial derivatives = 1 in layer $layer->{number} $nodetype: >@activated< \n" if $debug;
  4211.                    #print "Created resolution array >@dres<  with ".@dres." elements \n";
  4212.                #}
  4213.                
  4214.                # Check if values fit and save resolution at same index
  4215.                foreach my $active (@activated) {
  4216.                    # Check if values are equal
  4217.                    # Due to differences in rounding procedures it's necessary
  4218.                    # to allow small differences between values
  4219.                    #print "Get node $active from layer $layer->{number} in array @{$layer->{$nodetype}}\n";
  4220.                    unless (defined $value[$i]) {
  4221.                        my $msg =
  4222.                        "\n\n WARNING !!!\n\n"
  4223.                        ."There's no new value in d.in for $nodetype-node $layer->{$nodetype}[$active] at "
  4224.                        ."km $layer->{$nodepos{$nodetype}}[$active]\n"
  4225.                        ."\n\nThis is a rayinvr-problem!\n\n"
  4226.                        ;
  4227.                        print $msg;
  4228.                        $model->printStatusMessage($msg);
  4229.                        last;
  4230.                    }
  4231.                    
  4232.                    # Ignore nodes with value == 0
  4233.                    # rayinvr interpolates them with value from other nodes and
  4234.                    # does not calculate a resolution for them
  4235.                    if ( $layer->{$nodetype}[$active] == 0 ) {
  4236.                        print "(D) ignore node index $nodetype [ $active ] = $layer->{$nodetype}[$active] "
  4237.                            ."for layer $layer->{number} at km $layer->{$nodepos{$nodetype}}[$active].\n";
  4238.                        next;
  4239.                    }
  4240.                    
  4241.                    #print "Look for value $value[$i]\n";
  4242.                    my $diff = $value[$i] - $layer->{$nodetype}[$active];
  4243.                    my $eps = 0.0051;
  4244.                    
  4245.                    if ( $resolution[$i] !~ /\d/ ) {
  4246.                        my $msg = "WARNING !! your resolution is no number!! res = $resolution[$i]. Set to zero\n";
  4247.                        print $msg;
  4248.                        $resolution[$i] = 0;
  4249.                    }
  4250.                    
  4251.                    if ($resolution[$i] < 0 || $resolution[$i] > 1){
  4252.                      
  4253.                        my $msg = "\n\n!! WARNING !!\n\n"
  4254.                            ."Problem with node in line @{$results[$i]}\n"
  4255.                            ."Resolution >$resolution[$i]< for node $value[$i] makes no sense!! Your rayinvr seems to have problems\n";
  4256.                        
  4257.                        # Setting to -1 will remove this value, when writing vin.
  4258.                        # Setting to 0 will keep it.
  4259.                        $resolution[$i]=-1;
  4260.                        #$resolution[$i]=0;
  4261.                            
  4262.                        $msg.="Set value to $resolution[$i] for output resolution file\n"
  4263.                            ."Node position: B$layer->{number}, block '$nodetype', node number $active "
  4264.                            ."km $layer->{$nodepos{$nodetype}}[$active]\n";
  4265.                        print $msg;
  4266.                        $model->printStatusMessage($msg);
  4267.                        
  4268.                        #return;
  4269.                    }
  4270.                    
  4271.                    # The node from the list is found in the model
  4272.                    if ( abs($diff) < $eps){
  4273.                        print "Found node $i (line $results[$i][0]) in B$layer->{number}, $nodetype, $active "
  4274.                         ."Values are equal $value[$i] == $layer->{$nodetype}[$active], resolution = $resolution[$i]\n" if $debug;
  4275.                        $dres[$active] = $resolution[$i];
  4276.                        $i++;   # Work on  next value
  4277.                        #print "(D) i=$i, total number of nodes $#type\n" if $debug;
  4278.                        last if ($i > $#type);
  4279.                    } else {
  4280.                        my $msg =
  4281.                            "\n\n!! WARNING !!\n\n"
  4282.                            ."Problem with node in line @{$results[$i]}\n"
  4283.                            ."Index $active, Values are not equal $value[$i] != $layer->{$nodetype}[$active], resolution = $resolution[$i]\n"
  4284.                            ."\nDiff is $diff, a difference of $eps is allowed for 'equal' values\n"
  4285.                            
  4286.                            ."'new val.' in d.out for $i.th node is >$value[$i]<\n"
  4287.                            ."current value in v.in for $i.th activated node is $layer->{$nodetype}[$active]\n"
  4288.                            ."Node position: B$layer->{number}, block '$nodetype', node number $active "
  4289.                            ."km $layer->{$nodepos{$nodetype}}[$active]"
  4290.                            ."\nblock abbreviations:\n"
  4291.                            ."depth = depth nodes (first block)\n"
  4292.                            ."vu = upper velocity nodes (second block)\n"
  4293.                            ."vl = lower velocity nodes (third block)\n"
  4294.                            ."\n\nYour v.in is not the v.in written by dmplsqr."
  4295.                            ." Resolutions from d.out are not valid for this v.in!\n"
  4296.                            ."Run dmplsqr and then try again to export resolutions\n"
  4297.                            ;
  4298.                            print $msg;
  4299.                            $model->printStatusMessage($msg);
  4300.                            
  4301.                            return;
  4302.                    }
  4303.                } # end foreach array with partial derivatives
  4304.                
  4305.                # Store resolutionarray in layer
  4306.                my $reskey = $nodetype.'res';
  4307.                print "Save resolutions >@dres< to >$layer->{number}< at >$reskey<\n" if $debug;
  4308.                $layer->{$reskey} = [@dres];
  4309.            } # foreach derivativekeys
  4310.  
  4311.            $j++;   # next layer
  4312.        } #end while $j < $n
  4313.        if ($j > $n) {
  4314.            my $msg = "Error, some values haven't been found\n";
  4315.            print $msg;
  4316.            $model->printStatusMessage($msg);
  4317.            return;
  4318.        }
  4319.        if ($i < $#type && $j == $n) {
  4320.            
  4321.            my $msg =  "\n\n WARNING !! \n\n"
  4322.                ."Could not find all nodes with partial derivative set in"
  4323.                ." your v.in !! d.out is not valid for this model\n";
  4324.            
  4325.            print $msg;
  4326.            $model->printStatusMessage($msg);
  4327.            return;
  4328.        }
  4329.        print "End while $i. $j\n";
  4330.        #$i++;
  4331.        
  4332.    } # while i < type
  4333.    
  4334. } # sub _readRes
  4335.  
  4336. sub writeXZV {
  4337.  
  4338. =PROGhead2 C<model::writeXZV()>
  4339.  
  4340. Writes a gmt-readable file with velocity nodes.
  4341. Function that calls writeXZV for each layer and writes the returned string
  4342. to file C<< $model->{config}->{exportpath}v.xzv >>
  4343.  
  4344. =cut
  4345.  
  4346.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4347.  
  4348.    my $model = shift;
  4349.    #my $file = "$model->{config}->{exportpath}/v.xzv";
  4350.    my $file = "v.xzv";
  4351.    
  4352.    open(FILE, ">$file") or die "Can't open $file";
  4353.    foreach my $layer (@{$model->{layers}}) {
  4354.        #print "Write layer $layer->{number}\n";
  4355.        printf FILE $layer->writeXZV();
  4356.    }
  4357.    close(FILE);    
  4358.    
  4359.    # Copy file to export path (do keep a copy in rayinvr folder for
  4360.    # running plots and stuff
  4361.    print "copy($file, $model->{config}->{exportpath}$file\n";
  4362.    copy("$file", "$model->{config}->{exportpath}$file");
  4363.    
  4364.    $model->printStatusMessage("exported velocity nodes to $file ");
  4365. }
  4366.  
  4367. sub exportPolygons {
  4368.  
  4369. =PROGhead2 C<model::exportPolygons()>
  4370.  
  4371. Writes a gmt-readable file with layer polygons.
  4372. Function that calls C<writePoly()> for each layer and writes the returned string
  4373. to file C<< $model->{config}->{exportpath}v.poly >>
  4374.  
  4375. =cut
  4376.  
  4377.    
  4378.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4379.  
  4380.    my $model = shift;
  4381.    #my $file = "$model->{config}->{exportpath}/v.xzv";
  4382.    my $file = "v.poly";
  4383.    
  4384.    open(FILE, ">$file") or die "Can't open $file";
  4385.    foreach my $layer (@{$model->{layers}}) {
  4386.        print "(DEV) Write layer $layer->{number}\n" if $dev;
  4387.        printf FILE $layer->writePoly();
  4388.    }
  4389.    close(FILE);    
  4390.    
  4391.    # Copy file to export path (do keep a copy in rayinvr folder for
  4392.    # running plots and stuff
  4393.    print "copy($file, $model->{config}->{exportpath}$file\n";
  4394.    copy("$file", "$model->{config}->{exportpath}$file");
  4395.    
  4396.    $model->printStatusMessage("\nExported layer polygons to $file ");
  4397.    
  4398. }
  4399.  
  4400.  
  4401. sub exportIgmas {
  4402.  
  4403. =PROGhead2 C<model::exportIgmas()>
  4404.  
  4405. Function that calls writeIgmas for each layer and writes the returned string
  4406. to file C<< $model->{config}->{exportpath}pVersion.mod >>
  4407.  
  4408. =cut
  4409.  
  4410.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4411.  
  4412.    my $model = shift;
  4413.    my $file = "$model->{config}->{exportpath}/igmas.mod";
  4414.    #my $file = "v.xzv";
  4415.  
  4416.    print "Export model to igmas format in file $file\n";
  4417.  
  4418.    open(FILE, ">$file") or die "Can't open $file";
  4419.    
  4420.    printf FILE "#gmdf_ascii\n\n\n";
  4421.    
  4422.    # Get densities
  4423.    foreach my $layer (@{$model->{layers}}) {
  4424.        #next if ( $layer->{number} ==  10 ); #????
  4425.        printf FILE $layer->igmasGetDensity();
  4426.    }
  4427.  
  4428.    printf FILE
  4429.         "\nreference_density    3.21\n\n";
  4430.  
  4431.    printf FILE $model->_igmasWriteSection('back');
  4432.    printf FILE $model->_igmasWriteSection('model');
  4433.    printf FILE $model->_igmasWriteSection('front');
  4434.    
  4435.    close(FILE);    
  4436.    
  4437.    $model->printStatusMessage("\nExported igmas model to $file");
  4438.    $model->printStatusMessage("\nNodes are reduced for clarity. Coordinates"
  4439.        ." for igmas model are still hardwired in this code. "
  4440.        ."Please manually edit your model file.");
  4441.  
  4442. }
  4443.  
  4444. sub _igmasWriteSection {
  4445.    printf "(T) %s(@_)\n", commons::whoami() if $tree;
  4446.  
  4447.    my $model = shift;
  4448.    my $section = shift;
  4449.    
  4450.    # Define two origin points
  4451.    #               x1       y1        x2       y2
  4452.    my @point = ( [453799, 7745287],[846635, 7902328] );    # P100
  4453.    #my @point = ( [ 67348, 7763403],[509778, 7563694] );    # P150
  4454.  
  4455.    print "# (I) Coordinates for igmas model are still hardwired in this code. "
  4456.        ."Please manually edit your model file.\n";
  4457.    
  4458.    if ( $section eq "back" ) {
  4459.        $point[0][1] += 10000; # 10 km north
  4460.        $point[1][1] += 10000; # 10 km north
  4461.        $point[0][1] += 200000; # 200 km north
  4462.        $point[1][1] += 200000; # 200 km north
  4463.        #$point[0][1] += 1000000; # 1000 km north
  4464.        #$point[1][1] += 1000000; # 1000 km north
  4465.        
  4466.    }
  4467.    
  4468.    if ( $section eq "front" ) {
  4469.        $point[0][1] -= 10000; # 10 km south
  4470.        $point[1][1] -= 10000; # 10 km south
  4471.        $point[0][1] -= 200000; # 200 km south
  4472.        $point[1][1] -= 200000; # 200 km south
  4473.       #$point[0][1] -= 1000000; # 1000 km south
  4474.        #$point[1][1] -= 1000000; # 1000 km south        
  4475.    }
  4476.  
  4477.    my $s =
  4478.         "\n\n"
  4479.        ."#####################################################\n"
  4480.        ."# SECTION $section\n"
  4481.        ."#####################################################\n"
  4482.        ."\nsection $section\n"
  4483.        ."point       $point[0][0]    $point[0][1]\n"
  4484.        ."point       $point[1][0]    $point[1][1]\n"
  4485.        ."\n\n"  
  4486.        ."coordinates\n";
  4487.    
  4488.    # Get coordintes of nodes
  4489.    my $n = @{$model->{layers}};
  4490.    #$n = 3;
  4491.    for (my $i = 1; $i <= $n ; $i++ ) {
  4492.        #print "########################################\nGet coordinates for layer $i\n" if ($debug);
  4493.        $s .= $model->getLayer($i)->igmasGetCoordinates($section);
  4494.    }
  4495.  
  4496.    #print "###############\nGET VERTICES for section $section\n" if ($debug);
  4497.    # Get vertices for each layer
  4498.    for (my $i = 1; $i <= $n-1; $i++ ) {
  4499.        $s .=   $model->getLayer($i)->igmasGetVertices($section);
  4500.    }
  4501.  
  4502.    # Clean up
  4503.    $model->{igmasCoords} = {};
  4504.    
  4505.    return $s;
  4506. }
  4507.  
  4508.  
  4509. 1;
  4510. } # end of model package
Advertisement
Add Comment
Please, Sign In to add comment