loci.formats

## Class Memoizer

- java.lang.Object
- - loci.formats.ReaderWrapper
  - - loci.formats.Memoizer

- All Implemented Interfaces:
    java.io.Closeable, java.lang.AutoCloseable, ICompressedTileReader, IFormatHandler, IFormatReader, IMetadataConfigurable, IPyramidHandler

      public class Memoizer
      extends ReaderWrapper

  `ReaderWrapper` implementation which caches the state of the delegate (including and other `ReaderWrapper` instances) after `setId(String)` has been called. Initializing a Bio-Formats reader can consume substantial time and memory. Most of the initialization time is spent in the `setId(String)` call. Various factors can impact the performance of this step including the file size, the amount of metadata in the image and also the file format itself. With the `Memoizer` reader wrapper, if the time required to call the `setId(String)` method is larger than `minimumElapsed`, the initialized reader including all reader wrappers will be cached in a memo file via `saveMemo()`. Any subsequent call to `setId(String)` with a reader decorated by the Memoizer on the same input file will load the reader from the memo file using `loadMemo()` instead of performing a full reader initialization. In essence, the speed-up gained from memoization will happen only after the first initialization of the reader for a particular file.

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static interface` | `Memoizer.Deser`
    `static class` | `Memoizer.KryoDeser`
    `private static class` | `Memoizer.RandomAccessDeser` Helper implementation that can be used to implement `Memoizer.Deser` classes for libraries working solely with byte arrays.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static long` | `DEFAULT_MINIMUM_ELAPSED` Default value for `minimumElapsed` if none is provided in the constructor.
    `private java.io.File` | `directory` Directory where all memo files should be created.
    `private boolean` | `doInPlaceCaching` If `true`, then all memo files will be created in the same directory as the original file.
    `private boolean` | `loadedFromMemo` Whether the `ReaderWrapper.reader` instance currently active was loaded from the memo file during `setId(String)`.
    `private static org.slf4j.Logger` | `LOGGER` Default `Logger` for the memoizer class
    `private java.io.File` | `memoFile`
    `private long` | `minimumElapsed` Minimum number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created.
    `private loci.common.Location` | `realFile`
    `private MetadataStore` | `replacementMetadataStore` `MetadataStore` created internally.
    `private boolean` | `savedToMemo` Whether the `ReaderWrapper.reader` instance was saved to a memo file on `setId(String)`.
    `protected Memoizer.Deser` | `ser`
    `private OMEXMLService` | `service`
    `private boolean` | `skipLoad`
    `private boolean` | `skipSave`
    `private java.io.File` | `tempFile`
    `private MetadataStore` | `userMetadataStore` `MetadataStore` set by the caller.
    `static java.lang.Integer` | `VERSION` Default file version.
    `private boolean` | `versionChecking` Boolean specifying whether to invalidate the memo file based upon mismatched major/minor version numbers.

    - ### Fields inherited from class loci.formats.ReaderWrapper

      `reader`

    - ### Fields inherited from interface loci.formats.IFormatReader

      `CAN_GROUP, CANNOT_GROUP, MUST_GROUP`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Memoizer()` Constructs a memoizer around a new `ImageReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.
    `Memoizer(IFormatReader r)` Constructs a memoizer around the given `IFormatReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.
    `Memoizer(IFormatReader r, java.io.File directory)` Constructs a memoizer around the given `IFormatReader` creating memo file under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.
    `Memoizer(IFormatReader r, long minimumElapsed)` Constructs a memoizer around the given `IFormatReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
    `Memoizer(IFormatReader r, long minimumElapsed, java.io.File directory)` Constructs a memoizer around the given `IFormatReader` creating memo files under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
    `Memoizer(long minimumElapsed)` Constructs a memoizer around a new `ImageReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
    `Memoizer(long minimumElapsed, java.io.File directory)` Constructs a memoizer around a new `ImageReader` creating memo files under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected void` | `cleanup()`
    `void` | `close()`
    `void` | `close(boolean fileOnly)` Closes the currently open file.
    `boolean` | `deleteMemo()` Force the current memo file to be deleted, if it exists.
    `protected boolean` | `deleteQuietly(java.io.File file)` Attempts to delete an existing file, logging at warn if the deletion returns false or at error if an exception is thrown.
    `boolean` | `generateMemo(java.lang.String file)` Convenience method to generate (or regenerate) the memo file for a given file.
    `protected Memoizer.Deser` | `getDeser()` Returns a configured `Kryo` instance.
    `java.io.File` | `getMemoFile()`
    `java.io.File` | `getMemoFile(java.lang.String id)` Constructs a `File` object from `id` string.
    `MetadataStore` | `getMetadataStore()` Retrieves the current metadata store for this reader.
    `protected OMEXMLService` | `getService()`
    `protected IFormatReader` | `handleMetadataStore(IFormatReader memo)` Return the `IFormatReader` instance that is passed in or null if it has been invalidated, which will include the instance being closed.
    `boolean` | `isLoadedFromMemo()` Returns whether the `ReaderWrapper.reader` instance currently active was loaded from the memo file during `setId(String)`.
    `boolean` | `isSavedToMemo()` Returns whether the `ReaderWrapper.reader` instance currently active was saved to the memo file during `setId(String)`.
    `boolean` | `isVersionChecking()` Returns whether or not version checking is done based upon major/minor version numbers.
    `protected boolean` | `isWritableDirectory(java.io.File writeDirectory)` Test if the given `File` instance is a writable directory.
    `private static void` | `load(java.lang.String id, java.io.File tmp, boolean delete)`
    `IFormatReader` | `loadMemo()` Load a memo file if possible, returning a null if not.
    `static void` | `main(java.lang.String[] args)`
    `boolean` | `saveMemo()` Save a reader including all reader wrappers inside a memo file.
    `void` | `setId(java.lang.String id)` Sets the current file name.
    `void` | `setMetadataStore(MetadataStore store)` Sets the default metadata store for this reader.
    `void` | `setVersionChecking(boolean version)` Set whether version checking is done based upon major/minor version numbers.
    `void` | `skipSave(boolean skip)` Set whether a memo file should be saved if a valid file is not present.
    `protected org.perf4j.slf4j.Slf4JStopWatch` | `stopWatch()`
    `boolean` | `versionMismatch()` Returns `true` if the version of the memo file as returned by `Memoizer.Deser.loadReleaseVersion()` and `Memoizer.Deser.loadRevision()` do not match the current version as specified by `FormatTools.VERSION`.

    - ### Methods inherited from class loci.formats.ReaderWrapper

      `coreIndexToSeries, duplicate, fileGroupOption, get16BitLookupTable, get8BitLookupTable, getAdvancedSeriesUsedFiles, getAdvancedUsedFiles, getBitsPerPixel, getCoreIndex, getCoreMetadataList, getCurrentFile, getDatasetStructureDescription, getDimensionOrder, getDomains, getEffectiveSizeC, getFillColor, getFormat, getGlobalMetadata, getImageCount, getIndex, getIndex, getMetadataOptions, getMetadataStoreRoot, getMetadataValue, getModuloC, getModuloT, getModuloZ, getNativeDataType, getOptimalTileHeight, getOptimalTileWidth, getPixelType, getPossibleDomains, getReader, getRequiredDirectories, getResolution, getResolutionCount, getRGBChannelCount, getSeries, getSeriesCount, getSeriesMetadata, getSeriesMetadataValue, getSeriesUsedFiles, getSeriesUsedFiles, getSizeC, getSizeT, getSizeX, getSizeY, getSizeZ, getSuffixes, getSupportedMetadataLevels, getThumbSizeX, getThumbSizeY, getTileCodec, getTileCodecOptions, getTileColumns, getTileRows, getUnderlyingReaders, getUsedFiles, getUsedFiles, getZCTCoords, getZCTModuloCoords, hasCompanionFiles, hasFlattenedResolutions, isFalseColor, isGroupFiles, isIndexed, isInterleaved, isInterleaved, isLittleEndian, isMetadataComplete, isMetadataFiltered, isNormalized, isOrderCertain, isOriginalMetadataPopulated, isRGB, isSingleFile, isThisType, isThisType, isThisType, isThisType, isThumbnailSeries, openBytes, openBytes, openBytes, openBytes, openCompressedBytes, openCompressedBytes, openPlane, openThumbBytes, reopenFile, seriesToCoreIndex, setCoreIndex, setFillColor, setFlattenedResolutions, setGroupFiles, setMetadataFiltered, setMetadataOptions, setNormalized, setOriginalMetadataPopulated, setResolution, setSeries, unwrap, unwrap, unwrap`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### VERSION

          public static final java.lang.Integer VERSION

      Default file version. Bumping this number will invalidate all other cached items. This should happen when the order and type of objects stored in the memo file changes.

    - #### DEFAULT_MINIMUM_ELAPSED

          public static final long DEFAULT_MINIMUM_ELAPSED

      Default value for `minimumElapsed` if none is provided in the constructor.
      See Also:
        Constant Field Values

    - #### LOGGER

          private static final org.slf4j.Logger LOGGER

      Default `Logger` for the memoizer class

    - #### minimumElapsed

          private final long minimumElapsed

      Minimum number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created. Default to `DEFAULT_MINIMUM_ELAPSED` if not specified via the constructor.

    - #### directory

          private final java.io.File directory

      Directory where all memo files should be created. If this value is non-null, then all memo files will be created under it. Can be overriden by `doInPlaceCaching`.

    - #### doInPlaceCaching

          private boolean doInPlaceCaching

      If `true`, then all memo files will be created in the same directory as the original file.

    - #### ser

          protected transient Memoizer.Deser ser

    - #### service

          private transient OMEXMLService service

    - #### realFile

          private loci.common.Location realFile

    - #### memoFile

          private java.io.File memoFile

    - #### tempFile

          private java.io.File tempFile

    - #### skipLoad

          private boolean skipLoad

    - #### skipSave

          private boolean skipSave

    - #### versionChecking

          private boolean versionChecking

      Boolean specifying whether to invalidate the memo file based upon mismatched major/minor version numbers. By default, the Git commit hash is used to invalidate the memo file.

    - #### loadedFromMemo

          private boolean loadedFromMemo

      Whether the `ReaderWrapper.reader` instance currently active was loaded from the memo file during `setId(String)`.

    - #### savedToMemo

          private boolean savedToMemo

      Whether the `ReaderWrapper.reader` instance was saved to a memo file on `setId(String)`.

    - #### userMetadataStore

          private MetadataStore userMetadataStore

      `MetadataStore` set by the caller. This value will be held locally and not set on the `ReaderWrapper.reader` delegate until the execution of `setId(String)`. If no value has been set by the caller, then no special actions are taken during `setId(String)`. If a value is set, however, we must be careful with attempting to serialize it
      See Also:
        `handleMetadataStore(IFormatReader)`

    - #### replacementMetadataStore

          private MetadataStore replacementMetadataStore

      `MetadataStore` created internally.
      See Also:
        `handleMetadataStore(IFormatReader)`

  - ### Constructor Detail

    - #### Memoizer

          public Memoizer()

      Constructs a memoizer around a new `ImageReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.

    - #### Memoizer

          public Memoizer(long minimumElapsed)

      Constructs a memoizer around a new `ImageReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
      Parameters:
        `minimumElapsed` - a long specifying the number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created.

    - #### Memoizer

          public Memoizer(long minimumElapsed,
                          java.io.File directory)

      Constructs a memoizer around a new `ImageReader` creating memo files under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
      Parameters:
        `minimumElapsed` - a long specifying the number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created.
        `directory` - a `File` specifying the directory where all memo files should be created. If `null`, disable memoization.

    - #### Memoizer

          public Memoizer(IFormatReader r)

      Constructs a memoizer around the given `IFormatReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.
      Parameters:
        `r` - an `IFormatReader` instance. If `null`, a new `ImageReader` is created.

    - #### Memoizer

          public Memoizer(IFormatReader r,
                          long minimumElapsed)

      Constructs a memoizer around the given `IFormatReader` creating memo files under the same directory as the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
      Parameters:
        `r` - an `IFormatReader` instance If `null`, a new `ImageReader` is created.
        `minimumElapsed` - a long specifying the number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created.

    - #### Memoizer

          public Memoizer(IFormatReader r,
                          java.io.File directory)

      Constructs a memoizer around the given `IFormatReader` creating memo file under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than 100L in milliseconds.
      Parameters:
        `r` - an `IFormatReader` instance If `null`, a new `ImageReader` is created.
        `directory` - a `File` specifying the directory where all memo files should be created. If `null`, disable memoization.

    - #### Memoizer

          public Memoizer(IFormatReader r,
                          long minimumElapsed,
                          java.io.File directory)

      Constructs a memoizer around the given `IFormatReader` creating memo files under the `directory` argument including the full path of the original file only if the call to `setId(java.lang.String)` takes longer than `minimumElapsed` in milliseconds.
      Parameters:
        `r` - an `IFormatReader` instance If `null`, a new `ImageReader` is created.
        `minimumElapsed` - a long specifying the number of milliseconds which must elapse during the call to `setId(java.lang.String)` before a memo file will be created.
        `directory` - a `File` specifying the directory where all memo files should be created. If `null`, disable memoization.

  - ### Method Detail

    - #### isLoadedFromMemo

          public boolean isLoadedFromMemo()

      Returns whether the `ReaderWrapper.reader` instance currently active was loaded from the memo file during `setId(String)`.
      Returns:
        `true` if the reader was loaded from the memo file, `false` otherwise.

    - #### isSavedToMemo

          public boolean isSavedToMemo()

      Returns whether the `ReaderWrapper.reader` instance currently active was saved to the memo file during `setId(String)`.
      Returns:
        `true` if the reader was saved to the memo file, `false` otherwise.

    - #### isVersionChecking

          public boolean isVersionChecking()

      Returns whether or not version checking is done based upon major/minor version numbers.
      Returns:
        `true` if version checking is done based upon major/minor version numbers, `false` otherwise.

    - #### versionMismatch

          public boolean versionMismatch()
                                  throws java.io.IOException

      Returns `true` if the version of the memo file as returned by `Memoizer.Deser.loadReleaseVersion()` and `Memoizer.Deser.loadRevision()` do not match the current version as specified by `FormatTools.VERSION`.
      Throws:
        `java.io.IOException`

    - #### setVersionChecking

          public void setVersionChecking(boolean version)

      Set whether version checking is done based upon major/minor version numbers. If `true`, then a mismatch between the major/minor version of the calling code (e.g. 4.4) and the major/minor version saved in the memo file (e.g. 5.0) will result in the memo file being invalidated. If `false` (default), a mismatch in the Git commit hashes will invalidate the memo file. This method allows for less strict version checking.
      Parameters:
        `version` - a boolean specifying whether version checking is done based upon major/minor version numbers to invalidate the memo file

    - #### skipSave

          public void skipSave(boolean skip)

      Set whether a memo file should be saved if a valid file is not present. If `false` (default), then a memo file will be saved. This may cause an existing memo file to be overwritten. If `true`, then a memo file will not be saved. This effectively makes the current Memoizer read-only.

    - #### cleanup

          protected void cleanup()

    - #### close

          public void close()
                     throws java.io.IOException

      Specified by:
        `close` in interface `java.io.Closeable`
      Specified by:
        `close` in interface `java.lang.AutoCloseable`
      Overrides:
        `close` in class `ReaderWrapper`
      Throws:
        `java.io.IOException`

    - #### close

          public void close(boolean fileOnly)
                     throws java.io.IOException

      Description copied from interface: `IFormatReader`
      Closes the currently open file. If the flag is set, this is all that happens; if unset, it is equivalent to calling `Closeable.close()`.
      Specified by:
        `close` in interface `IFormatReader`
      Overrides:
        `close` in class `ReaderWrapper`
      Throws:
        `java.io.IOException`

    - #### setId

          public void setId(java.lang.String id)
                     throws FormatException,
                            java.io.IOException

      Description copied from interface: `IFormatHandler`
      Sets the current file name.
      Specified by:
        `setId` in interface `IFormatHandler`
      Overrides:
        `setId` in class `ReaderWrapper`
      Throws:
        `FormatException`
        `java.io.IOException`

    - #### setMetadataStore

          public void setMetadataStore(MetadataStore store)

      Description copied from interface: `IFormatReader`
      Sets the default metadata store for this reader.
      Specified by:
        `setMetadataStore` in interface `IFormatReader`
      Overrides:
        `setMetadataStore` in class `ReaderWrapper`
      Parameters:
        `store` - a metadata store implementation.

    - #### getMetadataStore

          public MetadataStore getMetadataStore()

      Description copied from interface: `IFormatReader`
      Retrieves the current metadata store for this reader. You can be assured that this method will never return a `null` metadata store.
      Specified by:
        `getMetadataStore` in interface `IFormatReader`
      Overrides:
        `getMetadataStore` in class `ReaderWrapper`
      Returns:
        A metadata store implementation.

    - #### deleteQuietly

          protected boolean deleteQuietly(java.io.File file)

      Attempts to delete an existing file, logging at warn if the deletion returns false or at error if an exception is thrown.
      Returns:
        the result from `File.delete()` or `false` if an exception is thrown.

    - #### getDeser

          protected Memoizer.Deser getDeser()

      Returns a configured `Kryo` instance. This method can be modified by consumers. The returned instance is not thread-safe.
      Returns:
        a non-null `Kryo` instance.

    - #### getService

          protected OMEXMLService getService()
                                      throws MissingLibraryException

      Throws:
        `MissingLibraryException`

    - #### stopWatch

          protected org.perf4j.slf4j.Slf4JStopWatch stopWatch()

    - #### getMemoFile

          public java.io.File getMemoFile(java.lang.String id)

      Constructs a `File` object from `id` string. This method can be modified by consumers, but then existing memo files will not be found.
      Parameters:
        `id` - the path passed to `setId(java.lang.String)`
      Returns:
        a `File` object pointing at the location of the memo file

    - #### isWritableDirectory

          protected boolean isWritableDirectory(java.io.File writeDirectory)

      Test if the given `File` instance is a writable directory.
      Parameters:
        `writeDirectory` - a possible writable directory
      Returns:
        if the given `File` is indeed a writable directory

    - #### loadMemo

          public IFormatReader loadMemo()
                                 throws java.io.IOException,
                                        FormatException

      Load a memo file if possible, returning a null if not. Corrupt memo files will be deleted if possible. Kryo exceptions should never propagate to the caller. Only the regular Bio-Formats exceptions should be thrown.
      Throws:
        `java.io.IOException`
        `FormatException`

    - #### saveMemo

          public boolean saveMemo()

      Save a reader including all reader wrappers inside a memo file.

    - #### deleteMemo

          public boolean deleteMemo()

      Force the current memo file to be deleted, if it exists.
      Returns:
        true if the delete succeeded

    - #### getMemoFile

          public java.io.File getMemoFile()

      Returns:
        current memo file (may be null)

    - #### handleMetadataStore

          protected IFormatReader handleMetadataStore(IFormatReader memo)
                                               throws MissingLibraryException

      Return the `IFormatReader` instance that is passed in or null if it has been invalidated, which will include the instance being closed.
      - Serialization: If an unknown `MetadataStore` implementation is passed in when no memo file exists, then a replacement `MetadataStore` will be created and set on the `ReaderWrapper.reader` delegate before calling `ReaderWrapper.setId(String)`. This stack will then be serialized, before any values are copied into `userMetadataStore`.
      - Deserialization: If an unknown `MetadataStore` implementation is set before calling `setId(String)` then ...
      Throws:
        `MissingLibraryException`

    - #### generateMemo

          public boolean generateMemo(java.lang.String file)
                               throws java.io.IOException

      Convenience method to generate (or regenerate) the memo file for a given file. Uses the cache directory and timing settings passed via Memoizer's constructor.
      Parameters:
        `file` - the file for which to generate a memo file
      Returns:
        true if a memo file was saved
      Throws:
        `java.io.IOException`

    - #### main

          public static void main(java.lang.String[] args)
                           throws java.lang.Exception

      Throws:
        `java.lang.Exception`

    - #### load

          private static void load(java.lang.String id,
                                   java.io.File tmp,
                                   boolean delete)
                            throws java.lang.Exception

      Throws:
        `java.lang.Exception`

Copyright © 2026 Open Microscopy Environment