Пример #1
0
def test_else():
    f = ConditionalDispatch()
    # Multiply even numbers by two.
    f.add(lambda x: 2 * x, lambda x: x % 2 == 0)
    f.add(lambda x: 3 * x)
    assert f(2) == 4
    assert f(3) == 9
Пример #2
0
class Parent(object):
    _create = ConditionalDispatch()

    @classmethod
    def read(cls, filename):
        raise NotImplementedError

    @classmethod
    def read_many(cls, filenames):
        return list(map(cls.read, filenames))

    @classmethod
    def from_glob(cls, pattern):
        """ Read out files using glob (e.g., ~/BIR_2011*) pattern. Returns
        list of objects made from all matched files.
        """
        return cls.read_many(glob.glob(pattern))

    @classmethod
    def from_single_glob(cls, singlepattern):
        """ Read out a single file using glob (e.g., ~/BIR_2011*) pattern.
        If more than one file matches the pattern, raise ValueError.
        """
        matches = glob.glob(os.path.expanduser(singlepattern))
        if len(matches) != 1:
            raise ValueError("Invalid number of matches: {0:d}".format(len(matches)))
        return cls.read(matches[0])

    @classmethod
    def from_files(cls, filenames):
        """ Return list of object read from given list of
        filenames. """
        filenames = list(map(os.path.expanduser, filenames))
        return cls.read_many(filenames)

    @classmethod
    def from_file(cls, filename):
        """ Return object from file. """
        filename = os.path.expanduser(filename)
        return cls.read(filename)

    @classmethod
    def from_dir(cls, directory):
        """ Return list that contains all files in the directory read in. """
        directory = os.path.expanduser(directory)
        return cls.read_many(
            (os.path.join(directory, elem) for elem in os.listdir(directory))
        )

    @classmethod
    def from_url(cls, url):
        """ Return object read from URL.

        Parameters
        ----------
        url : str
            URL to retrieve the data from
        """
        path = download_file(url, get_and_create_download_dir())
        return cls.read(path)
Пример #3
0
def oddeven(request):
    f = ConditionalDispatch()
    # Multiply even numbers by two.
    f.add(lambda x: 2 * x, lambda x: x % 2 == 0)
    # Multiply odd numbers by three.
    f.add(lambda x: 3 * x, lambda x: x % 2 == 1)
    return f
Пример #4
0
def test_nocond():
    f = ConditionalDispatch()
    # Multiply even numbers by two.
    f.add(lambda x: 2 * x, lambda x: x % 2 == 0)
    with pytest.raises(TypeError) as exc_info:
        f(3)
        assert "Your input did not fulfill the condition for any function." in str(exc_info.value)
Пример #5
0
def test_else2():
    # This verifies else branches do not catch cases that are covered
    # by cases added later.
    f = ConditionalDispatch()
    # Because gcd(2, 3) == 1, 2 | x and 3 | x are mutually exclusive.
    f.add(lambda x: 2 * x, lambda x: x % 2 == 0)
    f.add(lambda x: 3 * x)
    f.add(lambda x: 4 * x, lambda x: x % 3 == 0)
    assert f(2) == 4
    assert f(3) == 12
    assert f(5) == 15
Пример #6
0
class LightCurve(object):
    """
    LightCurve(filepath)

    A generic light curve object.

    Parameters
    ----------
    args : filepath, url, or start and end dates
        The input for a LightCurve object should either be a filepath, a URL,
        or a date range to be queried for the particular instrument.

    Attributes
    ----------
    meta : string, dict
        The comment string or header associated with the light curve input
    data : pandas.DataFrame
        An pandas DataFrame prepresenting one or more fields as they vary with 
        respect to time.

    Examples
    --------
    >>> import sunpy
    >>> import datetime
    >>> import numpy as np

    >>> base = datetime.datetime.today()
    >>> dates = [base - datetime.timedelta(minutes=x) for x in range(0, 24 * 60)]

    >>> intensity = np.sin(np.arange(0, 12 * np.pi, step=(12 * np.pi) / 24 * 60))

    >>> light_curve = sunpy.lightcurve.LightCurve.create(
    ...    {"param1": intensity}, index=dates
    ... )

    >>> light_curve.peek()

    References
    ----------
    | http://pandas.pydata.org/pandas-docs/dev/dsintro.html

    """
    _cond_dispatch = ConditionalDispatch()
    create = classmethod(_cond_dispatch.wrapper())

    def __init__(self, data, meta=None):
        self.data = pandas.DataFrame(data)
        if meta == '' or meta is None:
            self.meta = OrderedDict()
        else:
            self.meta = OrderedDict(meta)

    @property
    def header(self):
        """
        Return the lightcurves metadata

        .. deprecated:: 0.4.0
            Use .meta instead
        """
        warnings.warn(
            """lightcurve.header has been renamed to lightcurve.meta
for compatability with map, please use meta instead""", Warning)
        return self.meta

    @classmethod
    def from_time(cls, time, **kwargs):
        '''Called by Conditional Dispatch object when valid time is passed as input to create method.'''
        date = parse_time(time)
        url = cls._get_url_for_date(date, **kwargs)
        filepath = cls._download(
            url, kwargs, err="Unable to download data for specified date")
        return cls.from_file(filepath)

    @classmethod
    def from_range(cls, start, end, **kwargs):
        '''Called by Conditional Dispatch object when start and end time are passed as input to create method.'''
        url = cls._get_url_for_date_range(parse_time(start), parse_time(end))
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        result = cls.from_file(filepath)
        result.data = result.data.truncate(start, end)
        return result

    @classmethod
    def from_timerange(cls, timerange, **kwargs):
        '''Called by Conditional Dispatch object when time range is passed as input to create method.'''
        url = cls._get_url_for_date_range(timerange)
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        result = cls.from_file(filepath)
        result.data = result.data.truncate(timerange.start(), timerange.end())
        return result

    @classmethod
    def from_file(cls, filename):
        '''Used to return Light Curve object by reading the given filename

	Parameters:
	    filename: Path of the file to be read.

	'''

        filename = os.path.expanduser(filename)
        meta, data = cls._parse_filepath(filename)
        if data.empty:
            raise ValueError("No data found!")
        else:
            return cls(data, meta)

    @classmethod
    def from_url(cls, url, **kwargs):
        '''
	Downloads a file from the given url, reads and returns a Light Curve object.

	Parameters:
	    url : string 
	        Uniform Resource Locator pointing to the file.

	    kwargs :Dict
	        Dict object containing other related parameters to assist in download.

        '''
        try:
            filepath = cls._download(url, kwargs)
        except (urllib2.HTTPError, urllib2.URLError, ValueError):
            err = ("Unable to read location %s.") % url
            raise ValueError(err)
        return cls.from_file(filepath)

    @classmethod
    def from_data(cls, data, index=None, meta=None):
        '''
	Called by Conditional Dispatch object to create Light Curve object when corresponding data is passed
	to create method.
	'''

        return cls(pandas.DataFrame(data, index=index), meta)

    @classmethod
    def from_yesterday(cls):
        return cls.from_url(cls._get_default_uri())

    @classmethod
    def from_dataframe(cls, dataframe, meta=None):
        '''
	Called by Conditional Dispatch object to create Light Curve object when Pandas DataFrame is passed
	to create method.
	'''

        return cls(dataframe, meta)

    def plot(self, axes=None, **plot_args):
        """Plot a plot of the light curve

        Parameters
        ----------
        axes: matplotlib.axes object or None
            If provided the image will be plotted on the given axes. Else the 
            current matplotlib axes will be used.

        **plot_args : dict
            Any additional plot arguments that should be used
            when plotting the image.

        """

        #Get current axes
        if axes is None:
            axes = plt.gca()

        axes = self.data.plot(ax=axes, **plot_args)

        return axes

    def peek(self, **kwargs):
        """Displays the light curve in a new figure"""

        figure = plt.figure()

        self.plot(**kwargs)

        figure.show()

        return figure

    @staticmethod
    def _download(uri, kwargs, err='Unable to download data at specified URL'):
        """Attempts to download data at the specified URI"""

        _filename = os.path.basename(uri).split("?")[0]

        # user specifies a download directory
        if "directory" in kwargs:
            download_dir = os.path.expanduser(kwargs["directory"])
        else:
            download_dir = sunpy.config.get("downloads", "download_dir")

        # overwrite the existing file if the keyword is present
        if "overwrite" in kwargs:
            overwrite = kwargs["overwrite"]
        else:
            overwrite = False

        # If the file is not already there, download it
        filepath = os.path.join(download_dir, _filename)

        if not (os.path.isfile(filepath)) or (overwrite
                                              and os.path.isfile(filepath)):
            try:
                response = urllib2.urlopen(uri)
            except (urllib2.HTTPError, urllib2.URLError):
                raise urllib2.URLError(err)
            with open(filepath, 'wb') as fp:
                shutil.copyfileobj(response, fp)
        else:
            warnings.warn(
                "Using existing file rather than downloading, use overwrite=True to override.",
                RuntimeWarning)

        return filepath

    @classmethod
    def _get_default_uri(cls):
        """Default data to load when none is specified"""
        msg = "No default action set for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date(cls, date, **kwargs):
        """Returns a URL to the data for the specified date"""
        msg = "Date-based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date_range(cls, *args, **kwargs):
        """Returns a URL to the data for the specified date range"""
        msg = "Date-range based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @staticmethod
    def _parse_csv(filepath):
        """Place holder method to parse CSV files."""
        msg = "Generic CSV parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @staticmethod
    def _parse_fits(filepath):
        """Place holder method to parse FITS files."""
        msg = "Generic FITS parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @classmethod
    def _parse_filepath(cls, filepath):
        """Check the file extension to see how to parse the file"""
        filename, extension = os.path.splitext(filepath)

        if extension.lower() in (".csv", ".txt"):
            return cls._parse_csv(filepath)
        else:
            return cls._parse_fits(filepath)

    def truncate(self, a, b=None):
        """Returns a truncated version of the timeseries object"""
        if isinstance(a, TimeRange):
            time_range = a
        else:
            time_range = TimeRange(a, b)

        truncated = self.data.truncate(time_range.start(), time_range.end())
        return self.__class__.create(truncated, self.meta.copy())

    def extract(self, a):
        """Extract a set of particular columns from the DataFrame"""
        # TODO allow the extract function to pick more than one column
        if isinstance(self, pandas.Series):
            return self
        else:
            return LightCurve(self.data[a], self.meta.copy())

    def time_range(self):
        """Returns the start and end times of the LightCurve as a TimeRange
        object"""
        return TimeRange(self.data.index[0], self.data.index[-1])
Пример #7
0
class LightCurve(object):
    """
    LightCurve(filepath)

    A generic light curve object.

    Parameters
    ----------
    args : filepath, url, or start and end dates
        The input for a LightCurve object should either be a filepath, a URL,
        or a date range to be queried for the particular instrument.

    Attributes
    ----------
    data : pandas.DataFrame
        An pandas DataFrame prepresenting one or more fields as they vary with 
        respect to time.
    header : string, dict
        The comment string or header associated with the light curve input

    Examples
    --------
    import sunpy
    import datetime
    base = datetime.datetime.today()
    dates = [base - datetime.timedelta(minutes=x) for x in range(0, 24 * 60)]
    light_curve = sunpy.lightcurve.LightCurve.create(
    {"param1": range(24 * 60)}, index=dates)
    light_curve.show()

    References
    ----------
    | http://pandas.pydata.org/pandas-docs/dev/dsintro.html

    """
    _cond_dispatch = ConditionalDispatch()
    create = classmethod(_cond_dispatch.wrapper())

    def __init__(self, data, header=None):
        self.data = data
        self.header = header

    @classmethod
    def from_time(cls, time, **kwargs):
        date = parse_time(time)
        url = cls._get_url_for_date(date)
        filepath = cls._download(
            url, kwargs, err="Unable to download data for specified date")
        return cls.from_file(filepath)

    @classmethod
    def from_range(cls, from_, to, **kwargs):
        url = cls._get_url_for_date_range(from_, to)
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        return cls.from_file(filepath)

    @classmethod
    def from_timerange(cls, timerange, **kwargs):
        url = cls._get_url_for_date_range(timerange)
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        return cls.from_file(filepath)

    @classmethod
    def from_file(cls, filename):
        filename = os.path.expanduser(filename)

        header, data = cls._parse_filepath(filename)
        return cls(data, header)

    @classmethod
    def from_url(cls, url, **kwargs):
        try:
            filepath = cls._download(url, kwargs)
        except (urllib2.HTTPError, urllib2.URLError, ValueError):
            err = ("Unable to read location. Did you "
                   "specify a valid filepath or URL?")
            raise ValueError(err)
        return cls.from_file(filepath)

    @classmethod
    def from_data(cls, data, index=None, header=None):
        return cls(pandas.DataFrame(data, index=index), header)

    @classmethod
    def from_yesterday(cls):
        return cls.from_url(cls._get_default_uri())

    @classmethod
    def from_dataframe(cls, dataframe, header=None):
        return cls(dataframe, header)

    def plot(self, axes=None, **plot_args):
        """Plot a plot of the light curve
        
        Parameters
        ----------            
        axes: matplotlib.axes object or None
            If provided the image will be plotted on the given axes. Else the 
            current matplotlib axes will be used.
        
        **plot_args : dict
            Any additional plot arguments that should be used
            when plotting the image.
        
        """

        #Get current axes
        if axes is None:
            axes = plt.gca()

        axes = self.data.plot(ax=axes, **plot_args)

        return axes

    def peek(self, **kwargs):
        """Displays the light curve in a new figure"""

        figure = plt.figure()

        self.plot(**kwargs)

        figure.show()

        return figure

    @staticmethod
    def _download(uri, kwargs, err='Unable to download data at specified URL'):
        """Attempts to download data at the specified URI"""
        _filename = os.path.basename(uri).split("?")[0]

        # user specifies a download directory
        if "directory" in kwargs:
            download_dir = os.path.expanduser(kwargs["directory"])
        else:
            download_dir = sunpy.config.get("downloads", "download_dir")

        # overwrite the existing file if the keyword is present
        if "overwrite" in kwargs:
            overwrite = kwargs["overwrite"]
        else:
            overwrite = False

        # If the file is not already there, download it
        filepath = os.path.join(download_dir, _filename)

        if not (os.path.isfile(filepath)) or (overwrite
                                              and os.path.isfile(filepath)):
            try:
                response = urllib2.urlopen(uri)
            except (urllib2.HTTPError, urllib2.URLError):
                raise urllib2.URLError(err)
            with open(filepath, 'wb') as fp:
                shutil.copyfileobj(response, fp)

        return filepath

    @classmethod
    def _get_default_uri(cls):
        """Default data to load when none is specified"""
        msg = "No default action set for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date(cls, date):
        """Returns a URL to the data for the specified date"""
        msg = "Date-based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date_range(cls, *args, **kwargs):
        """Returns a URL to the data for the specified date range"""
        msg = "Date-range based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @staticmethod
    def _parse_csv(filepath):
        """Place holder method to parse CSV files."""
        msg = "Generic CSV parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @staticmethod
    def _parse_fits(filepath):
        """Place holder method to parse FITS files."""
        msg = "Generic FITS parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @classmethod
    def _parse_filepath(cls, filepath):
        filename, extension = os.path.splitext(filepath)

        if extension.lower() in (".csv", ".txt"):
            return cls._parse_csv(filepath)
        else:
            return cls._parse_fits(filepath)

    def truncate(self, a, b=None):
        """Returns a truncated version of the timeseries object"""
        if isinstance(a, TimeRange):
            time_range = a
        else:
            time_range = TimeRange(a, b)

        truncated = self.data.truncate(time_range.start(), time_range.end())
        return LightCurve(truncated, self.header.copy())

    def extract(self, a):
        """Extract a set of particular columns from the DataFrame"""
        # TODO allow the extract function to pick more than one column
        if isinstance(self, pandas.Series):
            return self
        else:
            return LightCurve(self.data[a], self.header.copy())

    def time_range(self):
        """Returns the start and end times of the LightCurve as a TimeRange
        object"""
        return TimeRange(self.data.index[0], self.data.index[-1])
Пример #8
0
class LightCurve(object):
    """
    LightCurve(filepath)

    A generic light curve object.

    Attributes
    ----------

    meta : `str` or `dict`
        The comment string or header associated with the data.
    data : `~pandas.DataFrame`
        An pandas DataFrame prepresenting one or more fields as a function of time.

    Examples
    --------
    >>> import sunpy
    >>> import datetime
    >>> import numpy as np
    >>> base = datetime.datetime.today()
    >>> dates = [base - datetime.timedelta(minutes=x) for x in range(0, 24 * 60)]
    >>> intensity = np.sin(np.arange(0, 12 * np.pi, step=(12 * np.pi) / 24 * 60))
    >>> light_curve = sunpy.lightcurve.LightCurve.create({"param1": intensity}, index=dates)
    >>> light_curve.peek()   # doctest: +SKIP

    References
    ----------
    * `Pandas Documentation <http://pandas.pydata.org/pandas-docs/dev/dsintro.html>`_

    """
    _cond_dispatch = ConditionalDispatch()
    create = classmethod(_cond_dispatch.wrapper())

    def __init__(self, data, meta=None):
        self.data = pandas.DataFrame(data)
        if meta == '' or meta is None:
            self.meta = OrderedDict()
        else:
            self.meta = OrderedDict(meta)

    @property
    def header(self):
        """
        Return the lightcurves metadata

        .. deprecated:: 0.4.0
            Use .meta instead
        """
        warnings.warn(
            """lightcurve.header has been renamed to lightcurve.meta
for compatibility with map, please use meta instead""", Warning)
        return self.meta

    @classmethod
    def from_time(cls, time, **kwargs):
        """
        Called by Conditional Dispatch object when valid time is passed as
        input to create method.
        """
        date = parse_time(time)
        url = cls._get_url_for_date(date, **kwargs)
        filepath = cls._download(
            url, kwargs, err="Unable to download data for specified date")
        return cls.from_file(filepath)

    @classmethod
    def from_range(cls, start, end, **kwargs):
        """Called by Conditional Dispatch object when start and end time are
        passed as input to create method.

        :param start:
        :param end:
        :param kwargs:
        :return:
        """
        url = cls._get_url_for_date_range(parse_time(start), parse_time(end),
                                          **kwargs)
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        result = cls.from_file(filepath)
        result.data = result.data.truncate(start, end)
        return result

    @classmethod
    def from_timerange(cls, timerange, **kwargs):
        """
        Called by Conditional Dispatch object when time range is passed as
        input to create method.
        """
        url = cls._get_url_for_date_range(timerange, **kwargs)
        filepath = cls._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        result = cls.from_file(filepath)
        result.data = result.data.truncate(timerange.start, timerange.end)
        return result

    @classmethod
    def from_file(cls, filename):
        """Used to return Light Curve object by reading the given filename.

        Parameters
        ----------
        filename: `str`
            Path of the file to be read.

        Returns
        -------
        Lightcurve object.
        """
        filename = os.path.expanduser(filename)
        meta, data = cls._parse_filepath(filename)
        if data.empty:
            raise ValueError("No data found!")
        else:
            return cls(data, meta)

    @classmethod
    def from_url(cls, url, **kwargs):
        """
        Called by Conditional Dispatch object to create Light Curve object when
        given a url. Downloads a file from the given url, attemps to read it
        and returns a Light Curve object.

        Parameters
        ----------
        url : str
            A url given as a string.
        """
        try:
            filepath = cls._download(url, kwargs)
        except (urllib.error.HTTPError, urllib.error.URLError, ValueError):
            err = "Unable to read location {!s}.".format(url)
            raise ValueError(err)
        return cls.from_file(filepath)

    @classmethod
    def from_data(cls, data, index=None, meta=None):
        """
        Called by Conditional Dispatch object to create Light Curve object when
        corresponding data is passed to create method.

        Parameters
        ----------
        data : `~numpy.ndarray`
            The data array
        index : `~datetime.datetime` array
            The time values
        """

        return cls(pandas.DataFrame(data, index=index), meta)

    @classmethod
    def from_yesterday(cls):
        """
        Called by Conditional Dispatch object if no input if given
        """
        return cls.from_url(cls._get_default_uri())

    @classmethod
    def from_dataframe(cls, dataframe, meta=None):
        """
        Called by Conditional Dispatch object to create Light Curve object when
        Pandas DataFrame is passed to create method.

        Parameters
        ----------
        dataframe : `~pandas.DataFrame`
            The data.
        meta : `str` or `dict`
            The metadata.
        """

        return cls(dataframe, meta)

    def plot(self, axes=None, **plot_args):
        """Plot a plot of the light curve

        Parameters
        ----------
        axes : `~matplotlib.axes.Axes` or None
            If provided the image will be plotted on the given axes. Otherwise
            the current axes will be used.

        **plot_args : `dict`
            Any additional plot arguments that should be used
            when plotting.

        Returns
        -------
        axes : `~matplotlib.axes.Axes`
            The plot axes.
        """

        # Get current axes
        if axes is None:
            axes = plt.gca()

        axes = self.data.plot(ax=axes, **plot_args)

        return axes

    def peek(self, **kwargs):
        """Displays the light curve in a new figure.

        Parameters
        ----------
        **kwargs : `dict`
            Any additional plot arguments that should be used
            when plotting.

        Returns
        -------
        fig : `~matplotlib.Figure`
            A plot figure.
        """

        figure = plt.figure()
        self.plot(**kwargs)
        figure.show()

        return figure

    @staticmethod
    def _download(uri, kwargs, err='Unable to download data at specified URL'):
        """Attempts to download data at the specified URI.

        Parameters
        ----------
        **kwargs : uri
            A url
        """

        _filename = os.path.basename(uri).split("?")[0]

        # user specifies a download directory
        if "directory" in kwargs:
            download_dir = os.path.expanduser(kwargs["directory"])
        else:
            download_dir = config.get("downloads", "download_dir")

        # overwrite the existing file if the keyword is present
        if "overwrite" in kwargs:
            overwrite = kwargs["overwrite"]
        else:
            overwrite = False

        # If the file is not already there, download it
        filepath = os.path.join(download_dir, _filename)

        if not (os.path.isfile(filepath)) or (overwrite
                                              and os.path.isfile(filepath)):
            try:
                response = urllib.request.urlopen(uri)
            except (urllib.error.HTTPError, urllib.error.URLError):
                raise urllib.error.URLError(err)
            with open(filepath, 'wb') as fp:
                shutil.copyfileobj(response, fp)
        else:
            warnings.warn(
                "Using existing file rather than downloading, use "
                "overwrite=True to override.", RuntimeWarning)

        return filepath

    @classmethod
    def _get_default_uri(cls):
        """Default data to load when none is specified."""
        msg = "No default action set for {}"
        raise NotImplementedError(msg.format(cls.__name__))

    @classmethod
    def _get_url_for_date(cls, date, **kwargs):
        """Returns a URL to the data for the specified date."""
        msg = "Date-based downloads not supported for for {}"
        raise NotImplementedError(msg.format(cls.__name__))

    @classmethod
    def _get_url_for_date_range(cls, *args, **kwargs):
        """Returns a URL to the data for the specified date range."""
        msg = "Date-range based downloads not supported for for {}"
        raise NotImplementedError(msg.format(cls.__name__))

    @staticmethod
    def _parse_csv(filepath):
        """Place holder method to parse CSV files."""
        msg = "Generic CSV parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @staticmethod
    def _parse_fits(filepath):
        """Place holder method to parse FITS files."""
        msg = "Generic FITS parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @classmethod
    def _parse_filepath(cls, filepath):
        """Check the file extension to see how to parse the file."""
        filename, extension = os.path.splitext(filepath)

        if extension.lower() in (".csv", ".txt"):
            return cls._parse_csv(filepath)
        else:
            return cls._parse_fits(filepath)

    def truncate(self, a, b=None):
        """Returns a truncated version of the timeseries object.

        Parameters
        ----------
        a : `sunpy.time.TimeRange`
            A time range to truncate to.

        Returns
        -------
        newlc : `~sunpy.lightcurve.LightCurve`
            A new lightcurve with only the selected times.
        """
        if isinstance(a, TimeRange):
            time_range = a
        else:
            time_range = TimeRange(a, b)

        truncated = self.data.truncate(time_range.start, time_range.end)
        return self.__class__.create(truncated, self.meta.copy())

    def extract(self, column_name):
        """Returns a new lightcurve with the chosen column.

        Parameters
        ----------
        column_name : `str`
            A valid column name

        Returns
        -------
        newlc : `~sunpy.lightcurve.LightCurve`
            A new lightcurve with only the selected column.
        """
        # TODO allow the extract function to pick more than one column
        if isinstance(self, pandas.Series):
            return self
        else:
            return LightCurve(self.data[column_name], self.meta.copy())

    def time_range(self):
        """Returns the start and end times of the LightCurve as a `~sunpy.time.TimeRange`
        object"""
        return TimeRange(self.data.index[0], self.data.index[-1])
Пример #9
0
def test_types():
    f = ConditionalDispatch()
    f.add(lambda x: 2 * x, lambda x: x % 2 == 0, [int])
    with pytest.raises(TypeError):
        f(2.0)
Пример #10
0
class LightCurve(object):
    """
    LightCurve(filepath)

    A generic light curve object.

    Parameters
    ----------
    args : filepath, url, or start and end dates
        The input for a LightCurve object should either be a filepath, a URL,
        or a date range to be queried for the particular instrument.

    Attributes
    ----------
    data : pandas.DataFrame
        An pandas DataFrame prepresenting one or more fields as they vary with 
        respect to time.
    header : string, dict
        The comment string or header associated with the light curve input

    Examples
    --------
    >>> import sunpy
    >>> import datetime
    >>> base = datetime.datetime.today()
    >>> dates = [base - datetime.timedelta(minutes=x) for x in 
    range(0, 24 * 60)]
    >>> light_curve = sunpy.lightcurve.LightCurve({"param1": range(24 * 60)}, 
    index=dates)
    >>> light_curve.show()

    References
    ----------
    | http://pandas.pydata.org/pandas-docs/dev/dsintro.html

    """
    _cond_dispatch = ConditionalDispatch()
    create = classmethod(_cond_dispatch.wrapper())

    def __init__(self, data, header=None):
        self.data = data
        self.header = header

    @classmethod
    def from_time(cls, time, **kwargs):
        date = sunpy.time.parse_time(time)
        url = cls._get_url_for_date(date)
        filepath = cls._download(
            url, kwargs, err="Unable to download data for  specified date")
        return cls.from_file(filepath)

    @classmethod
    def from_range(cls, from_, to, **kwargs):
        url = cls._get_url_for_date_range(from_, to)
        filepath = self._download(
            url,
            kwargs,
            err="Unable to download data for specified date range")
        return cls.from_file(filepath)

    @classmethod
    def from_timerange(cls, timerange, **kwargs):
        url = cls._get_url_for_date_range(timerange)
        err = "Unable to download data for specified date range"
        filepath = self._download(url, err, kwargs)
        return cls.from_file(filepath)

    @classmethod
    def from_file(cls, filename):
        filename = os.path.expanduser(filename)

        header, data = cls._parse_filepath(filename)
        return cls(data, header)

    @classmethod
    def from_url(cls, url, **kwargs):
        try:
            filepath = cls._download(url, kwargs)
        except (urllib2.HTTPError, urllib2.URLError, ValueError):
            err = ("Unable to read location. Did you "
                   "specify a valid filepath or URL?")
            raise ValueError(err)
        return cls.from_file(filepath)

    @classmethod
    def from_data(cls, data, index=None, header=None):
        return cls(pandas.DataFrame(data, index=index), header)

    @classmethod
    def from_yesterday(cls):
        return cls.from_url(cls._get_default_uri())

    @classmethod
    def from_dataframe(cls, dataframe, header=None):
        return cls(dataframe, header)

    def plot(self, **kwargs):
        """Plot a plot of the light curve"""
        axes = self.data.plot(**kwargs)
        return axes.get_figure()

    def show(self, **kwargs):
        """Shows a plot of the light curve"""
        fig = self.plot(**kwargs)
        fig.show()

        return fig

    @staticmethod
    def _download(uri, kwargs, err='Unable to download data at specified URL'):
        """Attempts to download data at the specified URI"""
        _filename = os.path.basename(uri).split("?")[0]

        # user specifies a download directory
        if "directory" in kwargs:
            download_dir = os.path.expanduser(kwargs["directory"])
        else:
            download_dir = sunpy.config.get("downloads", "download_dir")

        # overwrite the existing file if the keyword is present
        if "overwrite" in kwargs:
            overwrite = kwargs["overwrite"]
        else:
            overwrite = False

        # If the file is not already there, download it
        filepath = os.path.join(download_dir, _filename)

        if not (os.path.isfile(filepath)) or (overwrite
                                              and os.path.isfile(filepath)):
            try:
                response = urllib2.urlopen(uri)
            except (urllib2.HTTPError, urllib2.URLError):
                raise urllib2.URLError(err)
            with open(filepath, 'wb') as fp:
                shutil.copyfileobj(response, fp)

        return filepath

    @classmethod
    def _get_default_uri(cls):
        """Default data to load when none is specified"""
        msg = "No default action set for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date(cls, date):
        """Returns a URL to the data for the specified date"""
        msg = "Date-based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @classmethod
    def _get_url_for_date_range(cls, *args, **kwargs):
        """Returns a URL to the data for the specified date range"""
        msg = "Date-range based downloads not supported for for %s"
        raise NotImplementedError(msg % cls.__name__)

    @staticmethod
    def _parse_csv(filepath):
        """Place holder method to parse CSV files."""
        msg = "Generic CSV parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @staticmethod
    def _parse_fits(filepath):
        """Place holder method to parse FITS files."""
        msg = "Generic FITS parsing not yet implemented for LightCurve"
        raise NotImplementedError(msg)

    @classmethod
    def _parse_filepath(cls, filepath):
        filename, extension = os.path.splitext(filepath)

        if extension.lower() in (".csv", ".txt"):
            return cls._parse_csv(filepath)
        else:
            return cls._parse_fits(filepath)

    def discrete_boxcar_average(self, seconds=1):
        """Computes a discrete boxcar average for the DataFrame"""
        date_range = pandas.DateRange(self.data.index[0],
                                      self.data.index[-1],
                                      offset=pandas.datetools.Second(seconds))
        grouped = self.data.groupby(date_range.asof)
        subsampled = grouped.mean()

        return LightCurve(subsampled, self.header.copy())

    def truncate(self, start=None, end=None):
        """Returns a truncated version of the Lyra object"""
        if start is None:
            start = self.data.index[0]
        if end is None:
            end = self.data.index[-1]

        truncated = self.data.truncate(sunpy.time.parse_time(start),
                                       sunpy.time.parse_time(end))
        return LightCurve(truncated, self.header.copy())