
"""
@author Swarbhanu Chatterjee
@file ion/processes/data/transforms/ctdbp/ctdbp_L2_density.py
@description Transforms incoming L1 product into L2 product for density through the L2 stream
"""
from pyon.util.log import log
from pyon.core.exception import BadRequest
from ion.core.process.transform import TransformDataProcess
from ion.services.dm.utility.granule.record_dictionary import RecordDictionaryTool
from ion.core.function.transform_function import SimpleGranuleTransformFunction
from interface.services.dm.ipubsub_management_service import PubsubManagementServiceProcessClient

from seawater.gibbs import SP_from_cndr, rho, SA_from_SP, conservative_t
from seawater.gibbs import cte

import numpy as np

class CTDBP_DensityTransform(TransformDataProcess):
    """ A basic transform that receives input through a subscription,
    parses the input from a CTD, extracts the pressure value and scales it according to
    the defined algorithm. If the transform
    has an output_stream it will publish the output on the output stream.
    """
    output_bindings = ['density']

    def on_start(self):
        super(CTDBP_DensityTransform, self).on_start()

        if not self.CFG.process.publish_streams.has_key('density'):
            raise BadRequest("For CTD transforms, please send the stream_id "
                             "using a special keyword (ex: density)")
        self.dens_stream_id = self.CFG.process.publish_streams.density

        lat = self.CFG.lat
        lon = self.CFG.lon

        # Read the parameter dict from the stream def of the stream
        pubsub = PubsubManagementServiceProcessClient(process=self)
        self.stream_definition = pubsub.read_stream_definition(stream_id=self.dens_stream_id)
        
        self.params = {'stream_def' : self.stream_definition._id, 'lat': lat, 'lon' : lon}

    def recv_packet(self, packet, stream_route, stream_id):
        """
        Processes incoming data!!!!
        """
        if packet == {}:
            return
        log.debug("CTDBP L2 density transform received granule with record dict: %s", packet.record_dictionary)

        granule = CTDBP_DensityTransformAlgorithm.execute(packet, params=self.params)

        log.debug("CTDBP L2 density transform publishing granule with record dict: %s", granule.record_dictionary)

        self.density.publish(msg=granule)


class CTDBP_DensityTransformAlgorithm(SimpleGranuleTransformFunction):

    @staticmethod
    @SimpleGranuleTransformFunction.validate_inputs
    def execute(input=None, context=None, config=None, params=None, state=None):
        """
        Dependencies
        ------------
        PRACSAL, PRESWAT_L1, longitude, latitude, TEMPWAT_L1

        Algorithms used
        ------------
        1. PRACSAL = gsw_SP_from_C((CONDWAT_L1 * 10),TEMPWAT_L1,PRESWAT_L1)
        2. absolute_salinity = gsw_SA_from_SP(PRACSAL,PRESWAT_L1,longitude,latitude)
        3. conservative_temperature = gsw_CT_from_t(absolute_salinity,TEMPWAT_L1,PRESWAT_L1)
        4. DENSITY = gsw_rho(absolute_salinity,conservative_temperature,PRESWAT_L1)

        Reference
        ------------
        The calculations below are based on the following spreadsheet document:
        https://docs.google.com/spreadsheet/ccc?key=0Au7PUzWoCKU4dDRMeVI0RU9yY180Z0Y5U0hyMUZERmc#gid=0

        """
        lat = params['lat']
        lon = params['lon']
        stream_def_id = params['stream_def']


        rdt = RecordDictionaryTool.load_from_granule(input)
        out_rdt = RecordDictionaryTool(stream_definition_id=stream_def_id)

        out_rdt['time'] = rdt['time']

        conductivity = rdt['conductivity']
        pressure = rdt['pressure']
        temperature = rdt['temp']

        latitude = np.ones(len(conductivity)) * lat
        longitude = np.ones(len(conductivity)) * lon

        log.debug("Using latitude: %s,\n longitude: %s", latitude, longitude)

        # Doing: PRACSAL = gsw_SP_from_C((CONDWAT_L1 * 10),TEMPWAT_L1,PRESWAT_L1)
        pracsal = SP_from_cndr(conductivity * 10, t=temperature, p=pressure)

        log.debug("CTDBP Density algorithm calculated the pracsal (practical salinity) values: %s", pracsal)

        # Doing: absolute_salinity = gsw_SA_from_SP(PRACSAL,PRESWAT_L1,longitude,latitude)
        absolute_salinity = SA_from_SP(pracsal, pressure, longitude, latitude)

        log.debug("CTDBP Density algorithm calculated the absolute_salinity (actual salinity) values: %s", absolute_salinity)

        conservative_temperature = conservative_t(absolute_salinity, temperature, pressure)

        log.debug("CTDBP Density algorithm calculated the conservative temperature values: %s", conservative_temperature)

        # Doing: DENSITY = gsw_rho(absolute_salinity,conservative_temperature,PRESWAT_L1)
        dens_value = rho(absolute_salinity, conservative_temperature, pressure)

        log.debug("Calculated density values: %s", dens_value)

        for key, value in rdt.iteritems():
            if key in out_rdt:
                if key=='conductivity' or key=='temp' or key=='pressure':
                    continue
                out_rdt[key] = value[:]

        out_rdt['density'] = dens_value

        return out_rdt.to_granule()

@@ -1306,40 +1306,8 @@
 _id 
-%22%0A                             %22
 usin
@@ -1414,16 +1414,95 @@
 ensity%0A%0A
+        # should get these from the geo_constraints already on the DataProduct%0A
         
@@ -1778,24 +1778,16 @@
 eam_id)%0A
-        
 %0A       
@@ -3740,24 +3740,169 @@
 dt%5B'temp'%5D%0A%0A
+        log.debug('L2 transform using L1 values: temp %25f, pressure %25f, conductivity %25f',%0A                  temperature, pressure, conductivity)%0A%0A
         lati
@@ -3937,24 +3937,24 @@
 ity)) * lat%0A
-
         long
@@ -3991,24 +3991,24 @@
 ty)) * lon%0A%0A
+
         log.
@@ -4037,10 +4037,8 @@
  %25s,
-%5Cn
  lon
@@ -4507,24 +4507,208 @@
 e, latitude)
+%0A        log.debug('absolute_salinity = SA_from_SP(pracsal=%25s, pressure=%25s, longitude=%25s, latitude=%25s)=%25s',%0A                  pracsal, pressure, longitude, latitude, absolute_salinity)
 %0A%0A        lo

debug messages to help diagnose issues