Class ACurve

java.lang.Object
edu.cnu.mdi.splot.pdata.ACurve
Direct Known Subclasses:
Curve, HistoCurve, StripChartCurve

public abstract class ACurve extends Object
Base class for all plottable curves (XY curves, histogram curves, strip-chart curves, etc.).

Responsibilities

  • State: name, visibility, style, drawing method, per-curve fit “order” knob.
  • Computed artifacts: fit results/evaluator and spline cache.
  • Notifications: curve-level change events for data/style/fit.
  • Batching: coalescing multiple changes into a single notification burst.

Thread-safety policy

This library is Swing-based. Curve change notifications commonly lead (directly or indirectly) to repaint() on a plot canvas. Swing requires UI updates to occur on the Event Dispatch Thread (EDT). Therefore:

  • All methods that notify listeners must be called on the EDT.
  • Data integrity within a curve is typically protected by lock in subclasses, but lock does not make Swing notifications thread-safe by itself.

For streaming / DAQ scenarios, the recommended pattern is:

 producer threads → enqueue points (lock-free queue) → EDT drains → curve.add(...)
 

Dirty flag and cache invalidation

The curve may cache computed artifacts such as a FitResult or CubicSpline. When data or relevant rendering parameters change, those artifacts must be invalidated and the curve marked dirty.

Use:

Author:
heddle
  • Field Details

    • lock

      protected final Object lock
      Lock object intended for subclasses to synchronize data mutation and snapshot creation.

      This lock is about data consistency (e.g., keeping x/y arrays aligned). It does not automatically make Swing notifications safe; notifications are enforced to be EDT-only.

  • Constructor Details

    • ACurve

      public ACurve(String name)
      Create a curve with the given name.
      Parameters:
      name - curve name (legend label)
  • Method Details

    • doFit

      public abstract void doFit(boolean force)
      Perform a curve fit (or compute derived artifacts like splines), depending on the configured curve drawing method.
      Parameters:
      force - true to force a refit even if not dirty
    • length

      public abstract int length()
      Get curve length (number of points or effective points in the data columns).
      Returns:
      curve length
    • clearData

      public abstract void clearData()
      Clear all data from this curve and fire a DATA change event.

      Thread-safe: may be called from any thread. If called off the EDT, the clear is performed later on the EDT and coalesced with other scheduled drains.

      Note: this also clears any queued (not-yet-applied) points so the curve truly becomes empty.

    • createFitterForCurrentMethod

      protected IFitter createFitterForCurrentMethod()
      Hook: subclasses may override to provide an appropriate fitter for the current drawing method and per-curve knobs.
      Returns:
      a fitter for the current method, or null if not applicable
    • name

      public final String name()
      Returns:
      the curve name (legend label)
    • setName

      public final void setName(String name)
      Set curve name.

      This is a UI/style-affecting change. Must be called on the EDT.

      Parameters:
      name - curve name
    • isVisible

      public boolean isVisible()
      Returns:
      true if visible
    • setVisible

      public void setVisible(boolean visible)
      Set curve visibility.

      This is a UI/style-affecting change. Must be called on the EDT.

      Parameters:
      visible - visibility flag
    • fitResult

      public FitResult fitResult()
      Returns:
      the current fit result (may be null)
    • getFitValueGetter

      public final Evaluator getFitValueGetter()
      Get the cached fit evaluator y(x) for the current fit.
      Returns:
      evaluator for the current fit, or null if none
    • setFitResult

      public final void setFitResult(FitResult fitResult)
      Set the fit result and notify listeners that the fit has changed.

      Must be called on the EDT.

      Parameters:
      fitResult - fit result (may be null)
    • getStyle

      public Styled getStyle()
      Returns:
      the curve style
    • setStyle

      public void setStyle(Styled style)
      Set the curve style.

      This is a UI/style-affecting change. Must be called on the EDT.

      Parameters:
      style - new style
    • isDirty

      public boolean isDirty()
      Returns:
      true if curve is dirty
    • setDirty

      public void setDirty(boolean dirty)
      Set dirty flag.

      This method does not notify listeners. Prefer markDataChanged() or markStyleChanged() when you want notifications.

      Parameters:
      dirty - dirty flag
    • getCubicSpline

      public CubicSpline getCubicSpline()
      Returns:
      cached cubic spline (may be null)
    • setCubicSpline

      public void setCubicSpline(CubicSpline cubicSpline)
      Set cached cubic spline.

      This does not notify listeners; it is typically called during doFit(boolean).

      Parameters:
      cubicSpline - cubic spline to cache (may be null)
    • getCurveDrawingMethod

      public CurveDrawingMethod getCurveDrawingMethod()
      Returns:
      curve drawing method
    • isHistogram

      public boolean isHistogram()
      Convenience method to determine if this curve is a histogram curve.
      Returns:
      true if histogram curve
    • isStripChart

      public boolean isStripChart()
      Convenience method to determine if this curve is a strip chart curve.
      Returns:
      true if strip chart curve
    • isXYCurve

      public boolean isXYCurve()
      Convenience method to determine if this curve is an XY curve.
      Returns:
      true if XY curve
    • setCurveDrawingMethod

      public void setCurveDrawingMethod(CurveDrawingMethod method)
      Set curve drawing method.

      This is a style/configuration change and invalidates computed artifacts. Must be called on the EDT.

      Parameters:
      method - method (null treated as NONE)
    • getFitOrder

      public int getFitOrder()
      Get the per-curve order/count knob for fit methods that need an integer order.
      Returns:
      per-curve order/count (>= 1)
    • setFitOrder

      public void setFitOrder(int order)
      Set the per-curve order/count knob for fit methods that need an integer order.

      This affects fitting/drawing behavior, so it is treated as a style/config change and invalidates computed artifacts. Must be called on the EDT.

      Parameters:
      order - per-curve order/count (>= 1)
    • fitWithOptionalWeights

      protected FitResult fitWithOptionalWeights(IFitter fitter, FitVectors v)
      Common pattern: if weights exist, call the weighted fit overload; otherwise call fit(x,y).

      This utility performs small sanity checks on FitVectors before delegating to the fitter.

    • markDataChanged

      protected final void markDataChanged()
      Mark data changed: invalidate computed artifacts and notify listeners.

      Must be called on the EDT (notifications typically lead to repaint).

    • dataChanged

      public final void dataChanged()
      Notify listeners that data has changed (EDT-only).
    • markStyleChanged

      protected final void markStyleChanged()
      Mark style/configuration changed: invalidate computed artifacts and notify listeners.

      Must be called on the EDT. Style/config changes may affect derived artifacts (fit/spline), so this method clears computed artifacts as well.

    • styleChanged

      public final void styleChanged()
      Notify listeners that style has changed (EDT-only).
    • markFitChanged

      protected final void markFitChanged()
      Mark fit changed: notify listeners.

      Must be called on the EDT.

    • beginUpdate

      public final void beginUpdate()
      Begin batching curve change notifications.

      While batching (depth > 0), calls to fireCurveChanged(CurveChangeType) do not notify listeners immediately; instead they set pending flags. When endUpdate() returns the depth to 0, pending flags are flushed.

      Must be called on the EDT.

    • endUpdate

      public final void endUpdate()
      End batching curve change notifications.

      When the batch depth returns to 0, pending changes are flushed. Must be called on the EDT.

    • xMin

      public abstract double xMin()
      Returns:
      the minimum x value for this curve
    • xMax

      public abstract double xMax()
      Returns:
      the maximum x value for this curve
    • yMin

      public abstract double yMin()
      Returns:
      the minimum y value for this curve
    • yMax

      public abstract double yMax()
      Returns:
      the maximum y value for this curve
    • addCurveChangeListener

      public final void addCurveChangeListener(CurveChangeListener listener)
      Add a curve change listener.
      Parameters:
      listener - listener to add (ignored if null)
    • removeCurveChangeListener

      public final void removeCurveChangeListener(CurveChangeListener listener)
      Remove a curve change listener.
      Parameters:
      listener - listener to remove (ignored if null)
    • fireCurveChanged

      protected final void fireCurveChanged(CurveChangeType type)
      Notify listeners of a curve change.

      This method assumes EDT usage; higher-level methods enforce EDT. When batching is active (updateDepth > 0), the change is recorded as pending.

      Parameters:
      type - change type (ignored if null)
    • initStyle

      protected void initStyle()
      Initialize style with a unique style ID.
    • getFitSummary

      public String getFitSummary()
      Returns:
      single-line summary of the current fit result, or null if none
    • snapshot

      public abstract Snapshot snapshot()
      Obtain a consistent snapshot of the current data, suitable for plotting without locking.

      Subclasses should return copies of their internal primitive arrays (or equivalent immutable state), typically while synchronizing on lock.

      Returns:
      snapshot of plot-ready data
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • requireEdt

      protected static void requireEdt(String operation)
      Ensure that the current thread is the Swing EDT.
      Parameters:
      operation - operation name used in the exception message
      Throws:
      IllegalStateException - if not on EDT
    • scheduleDrainOnce

      protected final void scheduleDrainOnce(Runnable drainOnEdt)
      Schedule a drain operation to run later on the Swing EDT, coalescing multiple requests into a single posted runnable.

      This is intended for curves whose add(...) methods are safe to call from any thread: background calls enqueue data, then call this method to ensure the queued data is applied on the EDT.

      If many threads call this repeatedly, only the first call posts a runnable; subsequent calls are coalesced until the posted runnable begins execution.

      Parameters:
      drainOnEdt - code that must execute on the EDT (typically calls drainPendingOnEDT(...) in the subclass)