Skip to content

[seismology] Add DepthLookup abstract interface#199

Draft
comoglu wants to merge 2 commits into
SeisComP:mainfrom
comoglu:feature/defaultdepthsetter-interface
Draft

[seismology] Add DepthLookup abstract interface#199
comoglu wants to merge 2 commits into
SeisComP:mainfrom
comoglu:feature/defaultdepthsetter-interface

Conversation

@comoglu
Copy link
Copy Markdown
Contributor

@comoglu comoglu commented May 20, 2026

Summary

Introduces an abstract DepthLookup interface for region- and slab-based
depth lookup in SeisComP processing modules (primarily scautoloc).

Interface (libs/seiscomp/seismology/depthlookup.h):

class DepthLookup : public Core::BaseObject {
  virtual bool   init(const Config::Config &) = 0;
  virtual double fetch(double lat, double lon) const = 0;
  virtual double fetchMaxDepth(double lat, double lon) const = 0;
};
DEFINE_INTERFACE_FACTORY(DepthLookup);
#define REGISTER_DEPTH_LOOKUP(Class, Service) ...

Each backend owns all depth knowledge including fallback; no fallback
parameter on the caller side.

Two built-in backends (depthlookup.cpp):

  • "Constant" — returns depths.constant.value for any location
  • "Polygon" — queries GeoFeatureSet polygons (each must carry a
    defaultDepth attribute); fallback from depths.polygon.fallback;
    regions listed in depths.polygon.regions

A third "Slab2" backend ships in SeisComP/main as the dlslab2
plugin (see SeisComP/main#121).

Test plan

  • Build seiscomp_core — clean compile, no errors
  • Unit test: DepthLookupConstant returns depths.constant.value
  • Unit test: DepthLookupPolygon returns polygon depth inside region, fallback outside

@cla-bot cla-bot Bot added the cla-signed The CLA has been signed by all contributors label May 20, 2026
@@ -0,0 +1,161 @@
/***************************************************************************
* Copyright (C) GFZ Potsdam *
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong copyright header for code in common. Please see ttt.h for example.

const std::string &key) {
const auto &attrs = f->attributes();
auto it = attrs.find(key);
if ( it == attrs.end() || it->second.empty() )
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use brackets also for blocks containing just one statement.

namespace Seismology {


DEFINE_SMARTPOINTER(DefaultDepthSetter);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to resolve the class name discussion first.

@gempa-jabe
Copy link
Copy Markdown
Contributor

I am not in favour of the name DefaultDepthSetter. This is very specific to the intended use-case but it should be a versatile interface to be used by other components as well. As you describe the interface as "depth-lookup" why not calling it DepthLookup or DepthQuery or DepthProvider?. I would appreciate if we could discuss such ideas and names prior to a PR to avoid discussions and additional work later on for you as well.

Comment thread libs/seiscomp/seismology/depthlookup.h Outdated
* @param fallback Returned when no region/slab matches.
*/
virtual double getDefaultDepth(double lat, double lon,
double fallback) const = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually return a success flag or throw an exception if a value is present. We do not follow the "fallback" approach. The latter can be implemented by a utility function.

class DepthLookup {
    public:
        double fetch(double lat, double lon) {
            throw runtime_error("Some error");
        }
}

double getDepth(DepthLookup *provider, double lat, double lon, double fallback) {
    try {
        return provider->fetch(lat, lon);
    }
    catch ( ... ) {
        return fallback;
    }
}

But we can discuss whether such behaviour is necessary or not. A depth-provider could always return something based on its configuration and implement the fallback itself. If you use the "constant" provider, it does not make sense to always return the fallback as this does not come from the provider itself but from the client. So it is actually not a constant-provider but a fallback- or none-provider which could be easily accomplished by using no provider and always use the client-side configured fallback.

The question is, how much "knowledge" about depths you would like to add to the client (e.g. scautoloc) itself and/or to the provider. If we have such provider interface, I prefer to keep the entire depth knowledge encapsulated there and the client itself does not have any configuration regarding default depths and so on. It just requests a depth from the provider and done. It is guaranteed that it will return a value in any case. That will make the configuration consistent across different clients and removes the additional client-specific fallback configuration.

I could envision the following configuration:

defaultDepth = constant://10

or

defaultDepth = polygon:///path/to/poly?fallback=10

If URLs are not the way to go, then, e.g.:

defaultDepth = polygon

# Configure polygon backend
depths.polygon.file = /path/to/poly
depths.polygon.fallback = 10

# Configure constant backend
depths.constant.value = 10

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed feedback. A few follow-up questions before I rework the interface:
Happy to go with DepthLookup.

API / fallback ownership: I understand the preference, the provider owns all depth knowledge, and fetch(lat, lon) always returns a value with no fallback parameter on the client side.
Two questions on that:

Config namespace: would you prefer a shared depths..key prefix (as in your example) or is it fine for each backend has their own namespace (e.g. ddslab2.directory, ddslab2.fallback)?

maxDepth: scautoloc uses a maximum depth cut-off in its origin acceptance check . Should the interface carry a second fetchMaxDepth(lat, lon) method, or is that out of scope for this interface and better handled separately?

No-provider case: if autoloc.depthLookup is unset, should the factory return nullptr and scautoloc fall back to its own single constant, or should there always be a configured provider (e.g. constant as the required default)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config namespace: would you prefer a shared depths..key prefix (as in your example) or is it fine for each backend has their own namespace (e.g. ddslab2.directory, ddslab2.fallback)?

Each backend should have definitely its own namespace. In addition to, e.g. the travel time table configuration, a global depths namespace would make sense. Also w.r.t. to the configuration XML to avoid name clashes with existing parameter names.

maxDepth: scautoloc uses a maximum depth cut-off in its origin acceptance check . Should the interface carry a second fetchMaxDepth(lat, lon) method, or is that out of scope for this interface and better handled separately?

Here I don't have the experience to answer that. The question is for me, how is that maximum depth handled? Is it more that a client is interested in a valid depths range in a particular region?

No-provider case: if autoloc.depthLookup is unset, should the factory return nullptr and scautoloc fall back to its own single constant, or should there always be a configured provider (e.g. constant as the required default)?

Exactly my point. I would remove the default depth configuration from scautoloc entirely and rely on a configured backend. No backend, no running scautoloc instance.

@comoglu
Copy link
Copy Markdown
Contributor Author

comoglu commented May 21, 2026

I am not in favour of the name DefaultDepthSetter. This is very specific to the intended use-case but it should be a versatile interface to be used by other components as well. As you describe the interface as "depth-lookup" why not calling it DepthLookup or DepthQuery or DepthProvider?. I would appreciate if we could discuss such ideas and names prior to a PR to avoid discussions and additional work later on for you as well.

Yeah you are right. Which one you prefer me to go with?
DepthLookup looks good to me?

@gempa-jabe
Copy link
Copy Markdown
Contributor

Just thinking, if we already have a class doing a similar thing ... Regions comes into my mind, so not very helpful ;)
Yes, DepthLookup sounds reasonable. At least not Setter because it does not set anything, it just replies to a query.

Adds an extensible depth-lookup interface used by scautoloc and other
processing modules to select region- or slab-specific default and maximum
depths instead of a single global value.

Two built-in implementations: "Constant" (passthrough) and "Polygon"
(named GeoFeatureSet regions with defaultDepth/maxDepth attributes).
Third-party backends register via REGISTER_DEPTH_LOOKUP in a plugin.
@comoglu comoglu force-pushed the feature/defaultdepthsetter-interface branch from 051c31b to 744ed10 Compare May 21, 2026 10:15
@comoglu comoglu changed the title [seismology] Add DefaultDepthSetter abstract interface [seismology] Add DepthLookup abstract interface May 21, 2026
Rename getDefaultDepth/getMaxDepth → fetch/fetchMaxDepth; remove
caller-supplied fallback parameter. Each backend now owns its full
depth knowledge including fallback via its own config namespace:
  depths.constant.value, depths.polygon.regions,
  depths.polygon.fallback.
@comoglu comoglu requested a review from gempa-jabe May 21, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The CLA has been signed by all contributors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants