Skip to content

Commit

Permalink
Validate the declaration of event detection and wire in to a placehol…
Browse files Browse the repository at this point in the history
…der method that returns the universal time window, #130
  • Loading branch information
james-d-brown committed Dec 10, 2024
1 parent b648481 commit 6e3fcdc
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 75 deletions.
76 changes: 71 additions & 5 deletions src/wres/pipeline/pooling/PoolFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import wres.statistics.generated.GeometryTuple;
import wres.statistics.generated.SummaryStatistic;
import wres.statistics.generated.TimeScale;
import wres.statistics.generated.TimeWindow;

/**
* A factory class for generating the pools of pairs associated with an evaluation.
Expand Down Expand Up @@ -438,11 +439,12 @@ public List<PoolRequest> getPoolRequests( Evaluation evaluation )
// Get the desired timescale
TimeScaleOuter desiredTimeScale = innerProject.getDesiredTimeScale();

// Get the time windows and sort them
Set<TimeWindowOuter> timeWindows = DeclarationUtilities.getTimeWindows( declaration )
.stream()
.map( TimeWindowOuter::of )
.collect( Collectors.toCollection( TreeSet::new ) );
// Get the declared time windows and sort them
Set<TimeWindowOuter> timeWindows = this.getTimeWindows( declaration,
innerProject )
.stream()
.map( TimeWindowOuter::of )
.collect( Collectors.toCollection( TreeSet::new ) );

return featureGroups.stream()
.flatMap( nextGroup -> this.getPoolRequests( evaluation,
Expand All @@ -454,6 +456,55 @@ public List<PoolRequest> getPoolRequests( Evaluation evaluation )
.toList();
}

/**
* Generates the time windows for evaluation, including both the declared time windows from a pool sequence or
* explicit list of time pools and those associated with event detection.
*
* @param declaration the declaration
* @param project the project
* @return the time windows
*/

private Set<TimeWindow> getTimeWindows( EvaluationDeclaration declaration,
Project project )
{
// Declared time windows
Set<TimeWindow> timeWindows = DeclarationUtilities.getTimeWindows( declaration );

// Time windows associated with event detection
if ( Objects.nonNull( declaration.eventDetection() ) )
{
Set<TimeWindow> events = this.doEventDetection( project );

// Add the lead time and reference date constraints to each event, if defined
if ( !timeWindows.isEmpty() )
{
Set<TimeWindow> adjustedEvents = new HashSet<>();
for ( TimeWindow next : events )
{
for ( TimeWindow adjust : timeWindows )
{
TimeWindow adjusted = next.toBuilder()
.setEarliestReferenceTime( adjust.getEarliestReferenceTime() )
.setLatestReferenceTime( adjust.getLatestReferenceTime() )
.setEarliestLeadDuration( adjust.getEarliestLeadDuration() )
.setLatestLeadDuration( adjust.getLatestLeadDuration() )
.build();
adjustedEvents.add( adjusted );
}

timeWindows = Collections.unmodifiableSet( adjustedEvents );
}
}
else
{
timeWindows = events;
}
}

return timeWindows;
}

/**
* <p>Create pools for single-valued data. This method will attempt to retrieve and re-use data that is common to
* multiple pools. Thus, it is generally better to provide a list of pool requests that represent connected pools,
Expand Down Expand Up @@ -1066,6 +1117,21 @@ private List<SupplierWithPoolRequest<Pool<TimeSeries<Pair<Double, Ensemble>>>>>
return this.getComposedSuppliers( poolRequests, rawSuppliers );
}

/**
* Performs event detection on one or more declared time-series datasets.
* @param project the project whose time-series data should be used
* @return the detected events
*/
private Set<TimeWindow> doEventDetection( Project project )
{
LOGGER.debug( "Performing event detection." );



// Unbounded time window, placeholder
return Set.of( wres.statistics.MessageFactory.getTimeWindow() );
}

/**
* Composes the raw suppliers with feature group information based on the pool requests, which are ordered
* identically to the suppliers.
Expand Down
8 changes: 4 additions & 4 deletions wres-config/src/wres/config/yaml/DeclarationInterpolator.java
Original file line number Diff line number Diff line change
Expand Up @@ -943,14 +943,14 @@ private static Outputs.GraphicFormat getGraphicsFormatOptions( Outputs.GraphicFo

// Reference date pools?
if ( ( Objects.nonNull( builder.referenceDatePools() )
|| DeclarationInterpolator.hasExplicitReferenceDatePools( builder.timeWindows() ) )
|| DeclarationInterpolator.hasExplicitReferenceDatePools( builder.timePools() ) )
&& options.getShape() == Outputs.GraphicFormat.GraphicShape.DEFAULT )
{
newOptions.setShape( Outputs.GraphicFormat.GraphicShape.ISSUED_DATE_POOLS );
}
// Valid date pools?
else if ( ( Objects.nonNull( builder.validDatePools() )
|| DeclarationInterpolator.hasExplicitValidDatePools( builder.timeWindows() ) )
|| DeclarationInterpolator.hasExplicitValidDatePools( builder.timePools() ) )
&& options.getShape() == Outputs.GraphicFormat.GraphicShape.DEFAULT )
{
newOptions.setShape( Outputs.GraphicFormat.GraphicShape.VALID_DATE_POOLS );
Expand Down Expand Up @@ -1246,7 +1246,7 @@ private static void interpolateOutputFormatsWhenNoneDeclared( EvaluationDeclarat
*/
private static void interpolateTimeWindows( EvaluationDeclarationBuilder builder )
{
Set<TimeWindow> timeWindows = builder.timeWindows();
Set<TimeWindow> timeWindows = builder.timePools();
Set<TimeWindow> adjustedTimeWindows = new HashSet<>();

// Set the earliest and latest lead durations
Expand Down Expand Up @@ -1303,7 +1303,7 @@ private static void interpolateTimeWindows( EvaluationDeclarationBuilder builder
adjustedTimeWindows.add( nextAdjusted );
}

builder.timeWindows( adjustedTimeWindows );
builder.timePools( adjustedTimeWindows );
}

/**
Expand Down
139 changes: 82 additions & 57 deletions wres-config/src/wres/config/yaml/DeclarationUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ public class DeclarationUtilities
+ "declaration.";

/**
* Consumes a {@link EvaluationDeclaration} and returns a {@link Set} of {@link TimeWindow} for evaluation.
* Returns at least one {@link TimeWindow}.
* Consumes a {@link EvaluationDeclaration} and returns a {@link Set} of {@link TimeWindow} for evaluation. Only
* returns the time windows that can be inferred from the declaration alone and not from any ingested data sources,
* notably those associated with event detection.
*
* @param declaration the declaration, cannot be null
* @return a set of one or more time windows for evaluation
Expand All @@ -134,60 +135,12 @@ public static Set<TimeWindow> getTimeWindows( EvaluationDeclaration declaration
|| Objects.nonNull( referenceDatesPools )
|| Objects.nonNull( validDatesPools ) )
{
// All dimensions
if ( Objects.nonNull( referenceDatesPools ) && Objects.nonNull( validDatesPools )
&& Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for reference dates and valid dates and lead durations." );

timeWindows = DeclarationUtilities.getReferenceDatesValidDatesAndLeadDurationTimeWindows( declaration );
}
// Reference dates and valid dates
else if ( Objects.nonNull( referenceDatesPools ) && Objects.nonNull( validDatesPools ) )
{
LOGGER.debug( "Building time windows for reference dates and valid dates." );

timeWindows = DeclarationUtilities.getReferenceDatesAndValidDatesTimeWindows( declaration );
}
// Reference dates and lead durations
else if ( Objects.nonNull( referenceDatesPools ) && Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for reference dates and lead durations." );

timeWindows = DeclarationUtilities.getReferenceDatesAndLeadDurationTimeWindows( declaration );
}
// Valid dates and lead durations
else if ( Objects.nonNull( validDatesPools ) && Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for valid dates and lead durations." );

timeWindows = DeclarationUtilities.getValidDatesAndLeadDurationTimeWindows( declaration );
}
// Reference dates
else if ( Objects.nonNull( referenceDatesPools ) )
{
LOGGER.debug( "Building time windows for reference dates." );

timeWindows = DeclarationUtilities.getReferenceDatesTimeWindows( declaration );
}
// Lead durations
else if ( Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for lead durations." );

timeWindows = DeclarationUtilities.getLeadDurationTimeWindows( declaration );
}
// Valid dates
else
{
LOGGER.debug( "Building time windows for valid dates." );

timeWindows = DeclarationUtilities.getValidDatesTimeWindows( declaration );
}
timeWindows = DeclarationUtilities.getTimeWindowsFromPoolSequence( declaration );
}
// One big pool if no explicitly declared time windows
else if ( declaration.timeWindows()
.isEmpty() )
// One big pool if no explicitly declared time windows and no event detection
else if ( declaration.timePools()
.isEmpty()
&& Objects.isNull( declaration.eventDetection() ) )
{
LOGGER.debug( "Building one big time window." );

Expand All @@ -198,10 +151,10 @@ else if ( declaration.timeWindows()
Set<TimeWindow> finalWindows = new HashSet<>( timeWindows );

LOGGER.debug( "Added {} explicitly declared time pools to the overall group of time pools.",
declaration.timeWindows()
declaration.timePools()
.size() );

finalWindows.addAll( declaration.timeWindows() );
finalWindows.addAll( declaration.timePools() );

return Collections.unmodifiableSet( finalWindows );
}
Expand Down Expand Up @@ -1499,6 +1452,78 @@ static String getFirstLine( String lines )
return line;
}

/**
* Generates time windows from an explicit pool sequence.
*
* @param declaration the declaration
* @return the time windows
*/
private static Set<TimeWindow> getTimeWindowsFromPoolSequence( EvaluationDeclaration declaration )
{
TimePools leadDurationPools = declaration.leadTimePools();
TimePools referenceDatesPools = declaration.referenceDatePools();
TimePools validDatesPools = declaration.validDatePools();

Set<TimeWindow> timeWindows;

// All dimensions
if ( Objects.nonNull( referenceDatesPools )
&& Objects.nonNull( validDatesPools )
&& Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for reference dates and valid dates and lead durations." );

timeWindows = DeclarationUtilities.getReferenceDatesValidDatesAndLeadDurationTimeWindows( declaration );
}
// Reference dates and valid dates
else if ( Objects.nonNull( referenceDatesPools )
&& Objects.nonNull( validDatesPools ) )
{
LOGGER.debug( "Building time windows for reference dates and valid dates." );

timeWindows = DeclarationUtilities.getReferenceDatesAndValidDatesTimeWindows( declaration );
}
// Reference dates and lead durations
else if ( Objects.nonNull( referenceDatesPools )
&& Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for reference dates and lead durations." );

timeWindows = DeclarationUtilities.getReferenceDatesAndLeadDurationTimeWindows( declaration );
}
// Valid dates and lead durations
else if ( Objects.nonNull( validDatesPools )
&& Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for valid dates and lead durations." );

timeWindows = DeclarationUtilities.getValidDatesAndLeadDurationTimeWindows( declaration );
}
// Reference dates
else if ( Objects.nonNull( referenceDatesPools ) )
{
LOGGER.debug( "Building time windows for reference dates." );

timeWindows = DeclarationUtilities.getReferenceDatesTimeWindows( declaration );
}
// Lead durations
else if ( Objects.nonNull( leadDurationPools ) )
{
LOGGER.debug( "Building time windows for lead durations." );

timeWindows = DeclarationUtilities.getLeadDurationTimeWindows( declaration );
}
// Valid dates
else
{
LOGGER.debug( "Building time windows for valid dates." );

timeWindows = DeclarationUtilities.getValidDatesTimeWindows( declaration );
}

return timeWindows;
}

/**
* @param builder the builder
* @param groupType the group the metric should be part of
Expand Down
Loading

0 comments on commit 6e3fcdc

Please sign in to comment.