Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
127 lines (104 sloc) 4.73 KB

SEP-0007 - Lightcurve Factory Refactor

SEP 7
title Lightcurve Factory Refactor
author(s) Stuart Mumford
contact email stuart@cadair.com
date-creation 2014-04-23
type standard
discussion https://groups.google.com/forum/#!topic/sunpy/fZKcJsf6cnw
status accepted

Introduction:

We all knew this day was coming, Lightcurve cannot escape the spotlight any longer. Lightcurve moves away from conditional dispatch to a Factory based creation system so that it behaves like Map.

Reasoning:

This proposal makes an API change, which will move LightCurve to follow the API of the Map submodule. This will provide end users a consistent interface submodules and allow for cleaner and easier to read code for developers, much like the map refactor did for the map submodule. Also it will seperate the interests of the Lightcruve module, into the core datatype and the data downloaders which belong in the net submodule.

Relevant PRs:

  • PR #729 The update to the base factory class, currently used for Map.
  • PR #896 The work in progress implementation of this SEP.

Implementation:

Lightcurve Factory:

A factory instance (as proposed in #729) called LightCurve will be available in the top level of the sunpy.lightcurve which will allow creation of all registered LightCurve subclasses with the following API:

def LightCurve(*args, source=None, concatenate=True, **kwargs):
    """
    Parameters
    ----------------
    filename: string or File
        A file to read.
    source: string
        A string identifier for a registered subclass, matched by that
         subclasses `_is_source_for` method.
    concatenate :  boolean
        Concatenate all files into one Lightcurve object if True, or return
        one Lightcurve for each file if False.

    All other keywords are passed to _is_source_for and then __init__.
    """

This factory will be able to create lightcurves from one or multiple files, with the multiple file behavior being determined by the concatenate flag.

Examples:

  • Create a LightCurve from a file, not-autodetected:
>>> my_lc = LightCurve('filename.csv', source='goes')
  • Create a LightCurve from a file understood by sunpy.io:
>>> my_lc = LightCurve('filename.fits')
  • URLs are handled just like files, they are downloaded to the data dir:
>>> my_lc = LightCurve(url)
>>> my_lc = LightCurve(url, url, source='goes', concatenate=True)
  • Extra keyword arguments are passed to the _is_source_for and __init__ methods.
>>> my_lc = LightCurve('lyrafile.fits', source='lyra', date_events=[x,y,z])
  • Multiple files can be combined into one LightCurve, as long as they are the same source:
>>> my_lc = LightCurve(['goesfile1.fits', 'goesfile2.fits'], concatenate=True)

Which can then be cropped to a timerange:

>>> my_lc = LightCurve(['myfile1.fits', 'myfile2.fits']).truncate(atimerange)

LightCurve parsing order:

  1. Filename:
    1. Expand any iterable objects.
    2. Attempt to read with sunpy.io: (Like Map())
      1. Parse metadata to _is_source_for and find relevant subclass
      2. Create that LightCurve.
    3. Match ‘source’ flag to subclass and get subclass to read file:
      1. return data, meta pair, create instance.
    4. fail.
  2. Other kwargs are processed and passed to subclass class method for returning (data, meta).

Required class methods:

  1. Parse specific data files that cannot be read by the sunpy.io module, i.e. CSV or ASCII files. Class Method named _parse_file taking a filename and **kwargs which returns a (data,meta) pair.
  2. Provide a _is_source_for which if possible auto detects the data type from a (data, meta) pair, and also matches string names for the subclass i.e. 'goes' or 'lyra', which will be passed into the factory to specify type for download etc.

Backwards Compatibility:

None, due to the current implementation of LightCurve it will be very hard to maintain backwards compatibility. It may be possible to implement a .create() method that calls the Factory, however I would not recommend it.

Decision Rational

Accepted at the board meeting on 2015-12-07 by a vote of 6-0