Repository: skypyproject/skypy

Issue:
Galaxy property - star formation rate
## Description
A function to calculate the star formation rate of galaxies.

## Inputs
 - Galaxy spectral energy distribution

## Outputs
 - Galaxy star formation rate

## References


Discussion:

Patch:
diff --git a/skypy/galaxy/spectrum.py b/skypy/galaxy/spectrum.py
index e96d234..23fa997 100644
--- a/skypy/galaxy/spectrum.py
+++ b/skypy/galaxy/spectrum.py
@@ -340,8 +340,11 @@ class KCorrectTemplates(SpectrumTemplates):
         with fits.open(filename) as hdul:
             self.templates = hdul[hdu].data * units.Unit('erg s-1 cm-2 angstrom-1')
             self.wavelength = hdul[11].data * units.Unit('angstrom')
+            self.mass = hdul[16].data
             self.mremain = hdul[17].data
             self.mets = hdul[18].data
+            self.mass300 = hdul[19].data
+            self.mass1000 = hdul[20].data
 
     def stellar_mass(self, coefficients, magnitudes, filter):
         r'''Compute stellar mass from absolute magnitudes in a reference filter.
@@ -388,10 +391,71 @@ class KCorrectTemplates(SpectrumTemplates):
         References
         ----------
         .. [1] M. R. Blanton and S. Roweis, 2007, AJ, 125, 2348
+
         '''
 
         return np.sum(coefficients * self.mremain * self.mets) / np.sum(coefficients * self.mremain)
 
+    def m300(self, coefficients, stellar_mass=None):
+        r'''Stellar mass formed in the last 300 Myr.
+
+        This function calculates the mass of new stars formed within the last
+        300 Myr for galaxies modelled as a linear combination of the kcorrect
+        templates [1]_.
+
+        Parameters
+        ----------
+        coefficients : (ng, 5) array_like
+            Array of template coefficients.
+        stellar_mass : (ng,) array_like, optional
+            Optional array of stellar masses for each galaxy.
+
+        Returns
+        -------
+        m300 : (ng,) array_like
+            Total mass of new stars formed in the last 300 Myr as a fraction of
+            the stellar mass of each galaxy. If stellar_mass is given, instead
+            returns the absolute mass of new stars.
+
+        References
+        ----------
+        .. [1] M. R. Blanton and S. Roweis, 2007, AJ, 125, 2348
+
+        '''
+
+        sm = stellar_mass if stellar_mass is not None else 1
+        return sm * np.sum(coefficients * self.mass300) / np.sum(coefficients * self.mass)
+
+    def m1000(self, coefficients, stellar_mass=None):
+        r'''Stellar mass formed in the last 1 Gyr.
+
+        This function calculates the mass of new stars formed within the last
+        1 Gyr for galaxies modelled as a linear combination of the kcorrect
+        templates [1]_.
+
+        Parameters
+        ----------
+        coefficients : (ng, 5) array_like
+            Array of template coefficients.
+        stellar_mass : (ng,) array_like, optional
+            Optional array of stellar masses for each galaxy.
+
+        Returns
+        -------
+        m1000 : (ng,) array_like
+            Total mass of new stars formed in the last 1 Gyr as a fraction of
+            the stellar mass of each galaxy. If stellar_mass is given, instead
+            returns the absolute mass of new stars.
+
+        References
+        ----------
+        .. [1] M. R. Blanton and S. Roweis, 2007, AJ, 125, 2348
+
+        '''
+
+        sm = stellar_mass if stellar_mass is not None else 1
+        return sm * np.sum(coefficients * self.mass1000) / np.sum(coefficients * self.mass)
+
 
 kcorrect = KCorrectTemplates(hdu=1)
 kcorrect.__doc__ = '''Galaxy spectra from kcorrect smoothed templates.'''


Test patch:
diff --git a/skypy/galaxy/tests/test_spectrum.py b/skypy/galaxy/tests/test_spectrum.py
index 942ef1e..0862351 100644
--- a/skypy/galaxy/tests/test_spectrum.py
+++ b/skypy/galaxy/tests/test_spectrum.py
@@ -295,6 +295,7 @@ def test_kcorrect_stellar_mass():
     truth = np.power(10, -0.4*(Mb-Mt))
     np.testing.assert_allclose(stellar_mass, truth)
 
+
 def test_kcorrect_metallicity():
 
     from skypy.galaxy.spectrum import kcorrect
@@ -304,3 +305,20 @@ def test_kcorrect_metallicity():
     mets = kcorrect.metallicity(coefficients)
     truth = np.sum(kcorrect.mremain * kcorrect.mets) / np.sum(kcorrect.mremain)
     np.testing.assert_allclose(mets, truth)
+
+
+def test_kcorrect_star_formation_rates():
+
+    from skypy.galaxy.spectrum import kcorrect
+
+    # Each test galaxy is exactly one of the templates
+    coefficients = np.eye(5)
+    m300 = np.sum(kcorrect.mass300) / np.sum(kcorrect.mass)
+    m1000 = np.sum(kcorrect.mass1000) / np.sum(kcorrect.mass)
+    np.testing.assert_allclose(kcorrect.m300(coefficients), m300)
+    np.testing.assert_allclose(kcorrect.m1000(coefficients), m1000)
+
+    # Test using stellar mass argument
+    sm = np.array([10, 20, 30, 40, 50])
+    np.testing.assert_allclose(kcorrect.m300(coefficients, sm), m300 * sm)
+    np.testing.assert_allclose(kcorrect.m1000(coefficients, sm), m1000 * sm)