Difference between revisions of "Geopsy: Set header"

From GeopsyWiki
Jump to navigation Jump to search
 
(65 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This section explains how to modify header information stored in a [[Geopsy: Database|database]] in a very efficient way. Any information about signals can be viewed in a [[Geopsy: Table|table]]. Signals can be modified one by one by cell editing (Ctrl+K). For huge number of signals this is boring and time consuming. Instead, you can create formulas and apply them with one single click. The syntax for these formulas is rather simple.
+
This section explains how to modify header information stored in a [[Geopsy: Database|database]] in a very efficient way. Any information about signals can be viewed in a [[Geopsy: Table|table]]. Signals can be modified one by one by cell editing (Ctrl+K). For huge number of signals this is boring and time consuming. Instead, you can create small scripts and apply them with one single click. The syntax for these scripts is rather simple. They are written in Javascript like [[Geopsy: Waveform Scripting Language|waveform script language]].
  
 
== General presentation ==
 
== General presentation ==
[[Image:Setheaders.png|thumb|right|400px|Dialog box to editing header information]]
 
  
From any active [[Geopsy: Signal Viewer|signal viewer]] (which is by definition a list of signals), click on menu item ''Edit/Set headers''. A dialog box will appear. You can type any number of equations in the left editor. To assist you, for instance for a correct spelling of signal field names, you can use the combos ''Variables'', usual ''operators'' and ''Functions'' [[Image:SetHeadersCombos.png|text-top]]
+
This help refers to the latest development release (geopsypack>=3.0.0)
  
 +
[[Image:Setheaders.png|thumb|right|300px|Dialog box to editing header information]]
  
All formulas are separated by ''';''' (like in C). If a line begins with '''//''', all text is ignored until the end of the line (like C comments). The same way, all text included between '''/*''' and '''*/''' is considered as a comment. Commenting parts of an equation may be interesting to solve errors.
+
From any active [[Geopsy: Signal Viewer|signal viewer]] (which is by definition a list of signals), click on menu item ''Edit/Set headers''. A dialog box will appear. You can type any script in the left editor. A basic loop to assign a new name to all signals is proposed as the default script. Comment or remove this script and enter your own code.
  
The general syntax is :
+
All statements are separated by ''';''' (like in C or C++). If a line begins with '''//''', all text is ignored until the end of the line (like C or C++ comments). In the same way, all text included between '''/*''' and '''*/''' is considered as a comment. Commenting parts of a script may be interesting to solve errors.
SignalData = value.
 
  
 +
Upon starting the script, an array called ''signals'' contains the list of all signals of the current viewer. Each signal is indexed by its position in the current viewer, starting at index 0. For instance,
 +
 +
signals[i]
 +
 +
Refers to the (i+1)th signal in the current viewer. In a table, index are displayed on the left side starting at 1. Be careful that they start at 0 in array ''signals''. The number of signals in the current viewer is given by expression
 +
 +
signals.length
 +
 +
Hence, the basic loop to assign values to signal headers will have a structure similar to this one:
 +
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].samplingPeriod=0.01;
 +
}
 +
 +
In this example, ''samplingPeriod'' is set to 0.01 seconds or a sampling frequency of 100 Hz. Available signal attributes are those listed [[Geopsy: Database#Internal database structure|here]], replacing the first capital letter by its corresponding lower case:
 +
 +
ShortFileName becomes shortFileName
 +
 +
''print'' function might be useful to solve errors in scripts. Print output and errors are all directed to the main log message window.
 +
 +
for(i=0; i<signals.length; i++) {
 +
  print("Signal index "+i+" had a sampling period of "+
 +
        signals[i].samplingPeriod);
 +
}
 +
 +
Which results into the following message in the log window:
 +
 +
[SetHeader]Signal index 0 had a sampling period of 0.004
 +
[SetHeader]Signal index 1 had a sampling period of 0.004
 +
 +
To execute the current script click on '''Apply'''. The content of the editor can be saved or restored to a .headequ file (a simple text file in fact) by clicking on the button '''Save''' and '''Load''' respectively.
 +
 +
== Using functions ==
 +
 +
Usually, you would like to keep several handy scripts easily accessible. You can write each one in a separate function and comment/uncomment the function to be run.
 +
 +
  function set_samplingFrequency(f)
 +
  {
 +
    for(i=0; i<signals.length; i++) {
 +
      signals[i].samplingFrequency=f;
 +
    }
 +
  }
 +
  function set_receiver(dx)
 +
  {
 +
    for(i=0; i<signals.length; i++) {
 +
      signals[i].receiverX=i*dx;
 +
    }
 +
  }
 +
  //set_samplingFrequency(100);
 +
  set_receiver(2);
 +
 +
== Trouble shooting ==
 +
 +
A common mistake is a typo error for signal property name. For instance
 +
 +
  signals[i].smplingFrequency=100;
 +
 +
neither produces the expected effect nor generates an error message. To check the effect of this statement, add prints:
 +
 +
  print("before smplingFrequency "+signals[i].smplingFrequency);
 +
  signals[i].smplingFrequency=100;
 +
  print("after smplingFrequency "+signals[i].smplingFrequency);
 +
 +
Note that instead of altering the ''SamplingFrequency'', this script is simply adding a new property to the object ''signal[i]''.
 +
 +
== Examples ==
 +
 +
=== Modify signal names ===
 +
 +
[[Geopsy: Database#Internal database structure|ShortFileName]] is the original file name without its complete path. The [[Geopsy: Database#Internal database structure|name]] of the signal is extracted from the ShortFileName.
 +
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].name=signals[i].shortFileName.substring(3,8)
 +
}
 +
 +
'''substring(s, e)''' returns the characters starting at index '''s''' (counting from 0) and stops just before index '''e'''.
 +
 +
=== Set sampling frequency to 100 Hz ===
 +
 +
Set [[Geopsy: Database#Internal database structure|sampling frequency]] to 100 Hz. Can be useful when loading signal from text files without header information. The sampling frequency is the minimum field required to display signals.
 +
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].samplingFrequency=100;
 +
}
 +
 +
=== Set components ===
 +
 +
Set the [[Geopsy: Database#Internal database structure|component]] from the signal file name. [[Geopsy: Database#Internal database structure|ShortFileName]] is the original file name without its complete path. We assume that the file name contains a keyword indicating the component (e.g. ..._Z.sac, ..._N.sac or ..._E.sac).
 +
 +
for(i=0; i<signals.length; i++) {
 +
  s=signals[i].shortFileName
 +
  switch(signals[i].shortFileName.substring(s.length-5,s.length-4)) {
 +
  case "E":
 +
    signals[i].component="East";
 +
    break;
 +
  case "N":
 +
    signals[i].component="North";
 +
    break;
 +
  case "Z":
 +
    signals[i].component="Vertical";
 +
    break;
 +
  }
 +
}
 +
 +
From version 3.4.0, recognition of component names is more flexible (accepts lower case) and the above code can be simplified to
 +
 +
for(i=0; i<signals.length; i++) {
 +
  s=signals[i].shortFileName
 +
  signals[i].component=s.substring(s.length-5,s.length-4)
 +
}
 +
 +
=== Set name from the right end of ShortFileName ===
 +
 +
Set the signal name from [[Geopsy: Database#Internal database structure|shortFileName]]. [[Geopsy: Database#Internal database structure|ShortFileName]] is the original file name without its complete path. We assume that the file name ends with a file number written with 3 digits (i.e. typical files out of CityShark II).
 +
 +
for(i=0; i<signals.length; i++) {
 +
  s=signals[i].shortFileName;
 +
  signals[i].name=s.substring(s.length-3,s.length);
 +
}
 +
 +
=== Set comments ===
 +
 +
The [[Geopsy: Database#Internal database structure|comments]] contains here the name of the array.
 +
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].comments="RING01"
 +
}
 +
 +
The application of scripts shown is the examples No 1, 2, 3 and 4 modify the headers as follow:
 
<br style="clear: both"/>
 
<br style="clear: both"/>
 +
[[Image:SetHeadersExample.png|thumb|center|700px|Modified headers after applying the equations shown in examples 1 to 4]]
 +
 +
=== Set StartTime ===
 +
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].startTime="20230927103020.45";
 +
}
 +
 +
=== Round StartTime to sampling period ===
 +
 +
for(i=0; i<signals.length; i++) {
 +
  s0=signals[i].startTime;
 +
  s=s0.substring(12,s0.length)*1; // Extract seconds only
 +
  s0=addSeconds(s0, -s);          // Remove seconds from absolute time
 +
  f=signals[i].samplingFrequency;
 +
  s=Math.round(s*f)/f
 +
  s0=addSeconds(s0, s);          // Add rounded seconds to absolute time
 +
  signals[i].startTime=s0;
 +
}
 +
 +
=== Time arithmetics ===
 +
 +
Time specification is a string of characters with format 'YYYYMMddhhmmssz'. For example: 20200213123057.456, which stands for February 13th 2020 at 12:30:57.456.
 +
 +
Modify starting time of a signal
 +
  sig=signals[i];
 +
  sig.startTime=addSeconds(sig.startTime, 2.456);
 +
 +
Similar functions exist to add months and years: addMonths and addYears, respectively.
 +
 +
Get the time delay between two signal starting times
 +
  dt=elapsedSeconds(signals[i].startTime, signals[i+1].startTime);
 +
 +
=== Shift T0 by 3h20 ===
  
There are various assignment operators woking for numbers and character strings:
+
for(i=0; i<signals.length; i++) {
SignalData = value      // Set ''SignalData'' to ''value''
+
  signals[i].startTime=addSeconds(signals[i].startTime, 3*3600+20*60);
value1 + value2          // Sum or concatenation operator
+
  }
SignalData += value      // Set ''SignalData'' to the sum of its previous content with ''value''
 
value1 == value2  // Returns a bool value, true if ''value1'' and ''value2'' are equal
 
  value1 != value2  // Returns a bool value, true if ''value1'' and ''value2'' are not equal
 
  
Some assignment operators work only for numbers:
+
=== Converts from any date/time format ===
value1 - value2          // Difference operator
 
value1 - value2          // Multiplication operator
 
value1 / value2          // Floating point division operator
 
value1 DIV value2        // Integer division operator. E.g. 5 DIV 2 produces 2
 
value1 < value2  // Returns a bool value, true if ''value1'' is less than ''value2''
 
value1 ≤ value2  // Returns a bool value, true if ''value1'' is less than or equal to ''value2''
 
value1 > value2  // Returns a bool value, true if ''value1'' is greater than ''value2''
 
value1 ≥ value2  // Returns a bool value, true if ''value1'' is greater than or equal to ''value2''
 
SignalData -= value      // Set ''SignalData'' to the difference between its previous content and ''value''
 
SignalData *= value      // Set ''SignalData'' to the product of its previous content with ''value''
 
SignalData /= value      // Set ''SignalData'' to the ratio between its previous content and ''value''
 
                            A floating point division is performed
 
value1 [ value2 ]  // If ''value1'' is an array, the ''value2'' th  element is returned.
 
                            If ''value1'' is not an array, ''value2'' is ignored.
 
  
 +
for(i=0; i<signals.length; i++) {
 +
  signals[i].startTime=dateFrom("April 1 1984 13:15", "MMMM d yyyy h:m");
 +
}
  
 +
To get help about format specification run ''gptime -h all''
  
The equation list can be saved in file (*.headqu) by clicking on [[Image:SaveButton.png|middle]]. This allows to load the header equation file and set the header of other signals in the same way. To do this hit the button [[Image:LoadButton.png|middle]] and search for the file in the browser window.
+
=== Playing with time picks and comments ===
  
<br style="clear: both"/>
+
  for(i=0; i<signals.length; i++) {
 +
    signals[i].setTimePick("Vp", "20200624220722")
 +
    signals[i].comments="Vp set to "+signals[i].timePick("Vp");
 +
  }
 +
 
 +
=== Debug helper ===
 +
 
 +
Print messages to the message console.
 +
 
 +
  for(i=0; i<signals.length; i++) {
 +
    print("Vp set to "+signals[i].timePick("Vp"));
 +
  }
  
== Examples ==
+
=== Right or left justification ===
 +
 
 +
Build a signal name with 0 padding.
  
Modify the name of  signal
+
  for(i=0; i<signals.length; i++) {
Name=mid( ShortFileName,3,5 );
+
    signals[i].name="WA_WAU"+rightJustified(i+1, 2, "0");
 +
  }
  
Set the components
+
=== Start a system command ===
tmp=mid( ShortFileName, 12, 1 );
 
if(tmp=="E",Component="East",  if(tmp=="N", Component="North",  Component="Vertical"));
 
  
Set the comments
+
List files and directories in your home directory
   Comments="RING01"
+
   print(system("ls /home/username"));

Latest revision as of 22:27, 21 March 2025

This section explains how to modify header information stored in a database in a very efficient way. Any information about signals can be viewed in a table. Signals can be modified one by one by cell editing (Ctrl+K). For huge number of signals this is boring and time consuming. Instead, you can create small scripts and apply them with one single click. The syntax for these scripts is rather simple. They are written in Javascript like waveform script language.

General presentation

This help refers to the latest development release (geopsypack>=3.0.0)

Dialog box to editing header information

From any active signal viewer (which is by definition a list of signals), click on menu item Edit/Set headers. A dialog box will appear. You can type any script in the left editor. A basic loop to assign a new name to all signals is proposed as the default script. Comment or remove this script and enter your own code.

All statements are separated by ; (like in C or C++). If a line begins with //, all text is ignored until the end of the line (like C or C++ comments). In the same way, all text included between /* and */ is considered as a comment. Commenting parts of a script may be interesting to solve errors.

Upon starting the script, an array called signals contains the list of all signals of the current viewer. Each signal is indexed by its position in the current viewer, starting at index 0. For instance,

signals[i]

Refers to the (i+1)th signal in the current viewer. In a table, index are displayed on the left side starting at 1. Be careful that they start at 0 in array signals. The number of signals in the current viewer is given by expression

signals.length

Hence, the basic loop to assign values to signal headers will have a structure similar to this one:

for(i=0; i<signals.length; i++) {
  signals[i].samplingPeriod=0.01;
}

In this example, samplingPeriod is set to 0.01 seconds or a sampling frequency of 100 Hz. Available signal attributes are those listed here, replacing the first capital letter by its corresponding lower case:

ShortFileName becomes shortFileName 

print function might be useful to solve errors in scripts. Print output and errors are all directed to the main log message window.

for(i=0; i<signals.length; i++) {
  print("Signal index "+i+" had a sampling period of "+
        signals[i].samplingPeriod);
}

Which results into the following message in the log window:

[SetHeader]Signal index 0 had a sampling period of 0.004
[SetHeader]Signal index 1 had a sampling period of 0.004

To execute the current script click on Apply. The content of the editor can be saved or restored to a .headequ file (a simple text file in fact) by clicking on the button Save and Load respectively.

Using functions

Usually, you would like to keep several handy scripts easily accessible. You can write each one in a separate function and comment/uncomment the function to be run.

 function set_samplingFrequency(f)
 {
   for(i=0; i<signals.length; i++) {
     signals[i].samplingFrequency=f;
   }
 }
 function set_receiver(dx)
 {
   for(i=0; i<signals.length; i++) {
     signals[i].receiverX=i*dx;
   }
 }
 //set_samplingFrequency(100);
 set_receiver(2);

Trouble shooting

A common mistake is a typo error for signal property name. For instance

 signals[i].smplingFrequency=100;

neither produces the expected effect nor generates an error message. To check the effect of this statement, add prints:

 print("before smplingFrequency "+signals[i].smplingFrequency);
 signals[i].smplingFrequency=100;
 print("after smplingFrequency "+signals[i].smplingFrequency);

Note that instead of altering the SamplingFrequency, this script is simply adding a new property to the object signal[i].

Examples

Modify signal names

ShortFileName is the original file name without its complete path. The name of the signal is extracted from the ShortFileName.

for(i=0; i<signals.length; i++) {
  signals[i].name=signals[i].shortFileName.substring(3,8)
}

substring(s, e) returns the characters starting at index s (counting from 0) and stops just before index e.

Set sampling frequency to 100 Hz

Set sampling frequency to 100 Hz. Can be useful when loading signal from text files without header information. The sampling frequency is the minimum field required to display signals.

for(i=0; i<signals.length; i++) {
  signals[i].samplingFrequency=100;
}

Set components

Set the component from the signal file name. ShortFileName is the original file name without its complete path. We assume that the file name contains a keyword indicating the component (e.g. ..._Z.sac, ..._N.sac or ..._E.sac).

for(i=0; i<signals.length; i++) {
  s=signals[i].shortFileName
  switch(signals[i].shortFileName.substring(s.length-5,s.length-4)) {
  case "E":
    signals[i].component="East";
    break;
  case "N":
    signals[i].component="North";
    break;
  case "Z":
    signals[i].component="Vertical";
    break;
  }
}

From version 3.4.0, recognition of component names is more flexible (accepts lower case) and the above code can be simplified to

for(i=0; i<signals.length; i++) {
  s=signals[i].shortFileName
  signals[i].component=s.substring(s.length-5,s.length-4)
}

Set name from the right end of ShortFileName

Set the signal name from shortFileName. ShortFileName is the original file name without its complete path. We assume that the file name ends with a file number written with 3 digits (i.e. typical files out of CityShark II).

for(i=0; i<signals.length; i++) {
  s=signals[i].shortFileName;
  signals[i].name=s.substring(s.length-3,s.length);
}

Set comments

The comments contains here the name of the array.

for(i=0; i<signals.length; i++) {
  signals[i].comments="RING01"
}

The application of scripts shown is the examples No 1, 2, 3 and 4 modify the headers as follow:

Modified headers after applying the equations shown in examples 1 to 4

Set StartTime

for(i=0; i<signals.length; i++) {
  signals[i].startTime="20230927103020.45";
}

Round StartTime to sampling period

for(i=0; i<signals.length; i++) {
  s0=signals[i].startTime;
  s=s0.substring(12,s0.length)*1; // Extract seconds only
  s0=addSeconds(s0, -s);          // Remove seconds from absolute time
  f=signals[i].samplingFrequency;
  s=Math.round(s*f)/f
  s0=addSeconds(s0, s);           // Add rounded seconds to absolute time
  signals[i].startTime=s0;
}

Time arithmetics

Time specification is a string of characters with format 'YYYYMMddhhmmssz'. For example: 20200213123057.456, which stands for February 13th 2020 at 12:30:57.456.

Modify starting time of a signal

 sig=signals[i];
 sig.startTime=addSeconds(sig.startTime, 2.456);

Similar functions exist to add months and years: addMonths and addYears, respectively.

Get the time delay between two signal starting times

 dt=elapsedSeconds(signals[i].startTime, signals[i+1].startTime);

Shift T0 by 3h20

for(i=0; i<signals.length; i++) {
  signals[i].startTime=addSeconds(signals[i].startTime, 3*3600+20*60);
}

Converts from any date/time format

for(i=0; i<signals.length; i++) {
  signals[i].startTime=dateFrom("April 1 1984 13:15", "MMMM d yyyy h:m");
}

To get help about format specification run gptime -h all

Playing with time picks and comments

 for(i=0; i<signals.length; i++) {
   signals[i].setTimePick("Vp", "20200624220722")
   signals[i].comments="Vp set to "+signals[i].timePick("Vp");
 }

Debug helper

Print messages to the message console.

 for(i=0; i<signals.length; i++) {
   print("Vp set to "+signals[i].timePick("Vp"));
 }

Right or left justification

Build a signal name with 0 padding.

 for(i=0; i<signals.length; i++) {
   signals[i].name="WA_WAU"+rightJustified(i+1, 2, "0");
 }

Start a system command

List files and directories in your home directory

 print(system("ls /home/username"));