Skip to content

Long gaps cause errors #62

@rannof

Description

@rannof

If the time window is small and gaps are long, a real-time display will crush.
I think it would be better to allow merging of segments, or even merge when adding a new segment.
Here are two functions that might be used for that. I'm not using the pull request since it's in Javascript and I'm not familiar with typescript.

Merging when adding a new segment

function appendSegment(seismogram, newSegment) {
  if (!seismogram.segments || seismogram.segments.length === 0) {
    seismogram._segmentArray = [newSegment];
    return seismogram;
  }

  const lastSegment = seismogram.segments[seismogram.segments.length - 1];
  const sampleInterval = 1000 / lastSegment.sampleRate; // in milliseconds
  
  // Calculate end time of last segment
  const lastEndTime = lastSegment.startTime.valueOf() + (lastSegment.y.length - 1) * sampleInterval;
  const newStartTime = newSegment.startTime.valueOf();
  
  // Calculate gap
  const gap = newStartTime - lastEndTime - sampleInterval;
  
  // If gap is less than half a sample interval, append to last segment
  if (gap < sampleInterval / 2) {
    // Handle overlap - discard overlapping data from new segment
    const timeDiff = newStartTime - lastEndTime - sampleInterval;
    let startIndex = 0;
    
    if (timeDiff < 0) {
      console.log(`Overlap detected for ${seismogram.codes()}: ${Math.abs(timeDiff)} ms`);
      // Overlap exists - calculate how many samples to skip
      const overlapSamples = Math.ceil(Math.abs(timeDiff) / sampleInterval);
      startIndex = overlapSamples;
    }
    
    // Append non-overlapping data for typed arrays
    if (startIndex < newSegment.y.length) {
      const newData = newSegment.y.slice(startIndex);
      const combined = new lastSegment.y.constructor(lastSegment.y.length + newData.length);
      combined.set(lastSegment.y, 0);
      combined.set(newData, lastSegment.y.length);
      lastSegment.y = combined;
    }
  } else {
    // Gap is too large, add as new segment
    console.log(`Gap detected for ${seismogram.codes()}: ${gap} ms`);
    seismogram._segmentArray.push(newSegment);
  }
  
  return seismogram;
}

And for merging all segments without gaps or overlays:

function mergeSegments(seismogram) {
  if (!seismogram.segments || seismogram.segments.length <= 1) {
    return seismogram;
  }

  // Sort segments by start time
  seismogram.segments.sort((a, b) => a.startTime.valueOf() - b.startTime.valueOf());

  const mergedSegments = [];
  let currentSegment = seismogram.segments[0];

  for (let i = 1; i < seismogram.segments.length; i++) {
    const nextSegment = seismogram.segments[i];
    
    // Calculate the end time of current segment based on start time, sample rate, and number of samples
    const sampleInterval = 1000 / currentSegment.sampleRate; // in milliseconds
    const currentEndTime = currentSegment.startTime.valueOf() + (currentSegment.y.length - 1) * sampleInterval;
    const nextStartTime = nextSegment.startTime.valueOf();
    
    // Calculate gap in milliseconds
    const gap = nextStartTime - currentEndTime - sampleInterval;
    
    // If gap is less than half a sample interval, merge
    if (gap < sampleInterval / 2) {
      // Handle overlap - keep only non-overlapping data from next segment
      const timeDiff = nextStartTime - currentEndTime - sampleInterval;
      let startIndex = 0;
      
      if (timeDiff < 0) {
        // Overlap exists - calculate how many samples to skip
        console.log(`Overlap detected for ${seismogram.codes()}: ${Math.abs(timeDiff)} ms`);
        const overlapSamples = Math.ceil(Math.abs(timeDiff) / sampleInterval);
        startIndex = overlapSamples;
      }
      
      // Concatenate data for typed arrays
      if (startIndex < nextSegment.y.length) {
        const newData = nextSegment.y.slice(startIndex);
        const combined = new currentSegment.y.constructor(currentSegment.y.length + newData.length);
        combined.set(currentSegment.y, 0);
        combined.set(newData, currentSegment.y.length);
        currentSegment.y = combined;
      }
      // Keep currentSegment for next iteration
    } else {
      // Gap is too large, save current segment and start new one
      console.log(`Gap detected for ${seismogram.codes()}: ${gap} ms`);
      mergedSegments.push(currentSegment);
      currentSegment = nextSegment;
    }
  }
  
  // Don't forget the last segment
  mergedSegments.push(currentSegment);
  
  seismogram._segmentArray = mergedSegments;
  return seismogram;`
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions