Wednesday, 23 November 2022

Bed-o-nails interpolation with scipy's RBFInterpolator

I'm trying to interpolate a 2D data set with RBFInterpolator. The purpose of the interpolation is to convert the data set into a continuous function that can then be sampled between the points. Unfortunately, I'm getting a bed of nails result.

This is the dataset enter image description here

This is the interpolator shown as a pcolormesh (see vertical lines for bed of nails) enter image description here

These are two plots showing the data and the interpolator along the x axis (0, pi). In these the bed of nails nature of the interpolator is most clear. enter image description here enter image description here

Here is all of my code verbatim (sorry if it's messy). I'm using the RBFInterpolator defaults, and I'm not setting the shape parameter at all.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import RBFInterpolator
import seaborn as sns

if __name__ == "__main__":
    # get the two files and combine into one dataframe
    cols = ["a_test", "e_test", "a", "e", "lop", "dlop_dt"]
    large_dlop = pd.read_csv('epsilon-ring/all-to-all/dlop-dt.dat', delimiter='\t', names=cols)
    small_dlop = pd.read_csv('epsilon-ring/small-dlop/dlop-dt.dat', delimiter='\t', names=cols)
    df = pd.concat([large_dlop, small_dlop]).reset_index(drop=True)
    # go through and fit each line
    a_test = np.unique(df['a_test'])
    a = np.unique(df['a'])
    lop_grid = np.linspace(0., np.pi, num=1000)
    a_grid = np.linspace(a.min(), a.max(), num=50)
    lop_mgrid, a_mgrid = np.meshgrid(lop_grid, a_grid)
    grid = np.concatenate((lop_mgrid.flatten()[:,None], a_mgrid.flatten()[:,None]), axis=1)
    colors = sns.color_palette()
    interpolants = []
    for i in range(a_test.shape[0]):
        # select semi-major axis
        select_test = df['a_test'] == a_test[i]
        # intepolation
        points = np.concatenate((df[select_test]['lop'].to_numpy()[:,None], \
                                 df[select_test]['a'].to_numpy()[:,None]), axis=1)
        rbf = RBFInterpolator(points, df[select_test]['dlop_dt'])
        interpolants.append(rbf)
        # plot points
        fig = plt.figure()
        ax = plt.axes(projection='3d')
        ax.scatter3D(df[select_test]['lop'], df[select_test]['a'], df[select_test]['dlop_dt'])
        ax.set_xlabel(r'$\varpi$')
        ax.set_ylabel(r'$a$')
        ax.set_zlabel(r'$\dot{\varpi}$')
        plt.tight_layout()
        plt.show()
        # plot colormesh
        fig, ax = plt.subplots()
        pc = ax.pcolormesh(lop_grid, a_grid, rbf(grid).reshape(lop_mgrid.shape), shading='gouraud')
        ax.set_xlabel(r'$\varpi$')
        ax.set_ylabel(r'$a$')
        plt.colorbar(pc, label=r'$\dot{\varpi}$')
        plt.tight_layout()
        plt.show()
        # check if interpolant actually interpolates well
        colors = sns.color_palette()
        for j in range(a.shape[0]):
            select_disk = df[select_test]['a'] == a[j]
            small_grid = np.concatenate((lop_grid[:,None], a[j]*np.ones(lop_grid.shape)[:,None]), axis=1)
            plt.scatter(df[select_test][select_disk]['lop'], df[select_test][select_disk]['dlop_dt'], color=colors[0], label='data')
            plt.plot(lop_grid, rbf(small_grid), color=colors[1], label='interp')
            plt.xlabel(r'$\varpi$')
            plt.ylabel(r'$\dot{\varpi}$')
            plt.legend()
            plt.tight_layout()
            plt.show()

How do I get the RBFInterpolator to interpolate the function better? What is causing this wild interpolation result? The underlying data is smooth, though kinda steep close to zero.

EDIT:

I still haven't figured out why RBFInterpolator is giving me poor results. I've tried most of the different kernels ('linear', 'cubic', 'thin_plate_spline', 'gaussian', and 'multiquadric') with and without adjusting the smoothing or epsilon parameter (depending on if the kernel is compatible with smoothing or the shape parameter). I still haven't gotten a satisfactory interpolation.

Fortunately, it appears that scipy.interpolate.griddata is able to interpolate the data just fine.

Here are some plots of the griddata interpolation:

Data + contour3D from griddata interpolation enter image description here

pcolormesh of the griddata interpolation enter image description here

1D plots comparing the RBF to the griddata enter image description here enter image description here

I'd still love to know what's wrong with the RBFInterpolator. I've noticed that the RBFInterpolator seems to be trying to return to some function between the interpolation points (i.e. look at the last two plots, the 'bed' in the bed-of-nails interpolation result is the same for both plots).



from Bed-o-nails interpolation with scipy's RBFInterpolator

Android Auto: Media item gets stuck "Getting your selection..." instead of showing controls while playing

I've got a PlaybackService.kt class that implements MediaBrowserServiceCompat() since that is required for Android Auto support. The player itself works great in-app. The app is 95% used for HLS streams between a few different channels (5% is audio sample files).

I can successfully get my root view which is a simple list of channels ("Live", "80's", "90's", etc.) and when I click one, audio starts playing, but I get stuck on the "Getting your selection..." screen as shown below. When looking at the logcat, no errors are reported. One thing that may be odd, or perhaps is normal, onGetRoot is called again after selecting a channel.

Android Auto error

Here is my entire PlaybackService.kt file.

package <my-package>.audio.service

import android.app.Notification
import android.app.PendingIntent
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
import android.os.ResultReceiver
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaDescriptionCompat
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import androidx.annotation.MainThread
import androidx.core.content.ContextCompat
import androidx.media.MediaBrowserServiceCompat
import androidx.media.session.MediaButtonReceiver
import <my-package>.MainActivity
import <my-package>.R
import <my-package>.audio.api.ChannelApi
import <my-package>.audio.api.StreamApi
import <my-package>.audio.models.NetworkChannel
import <my-package>.audio.models.State
import <my-package>.audio.utils.StorageHelper
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame
import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.util.MimeTypes
import com.npaw.youbora.lib6.exoplayer2.Exoplayer2Adapter
import com.npaw.youbora.lib6.plugin.Options
import com.npaw.youbora.lib6.plugin.Plugin
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.*

open class PlaybackService : MediaBrowserServiceCompat() {
    var reactContext: ReactContext? = null
    private val binder = PlaybackBinder()
    private val scope = MainScope()
    private var sourceUrl: String? = null

    private var isForegroundService = false

    private val playerListener = playerListener()

    private val playbackAudioAttributes = AudioAttributes.Builder()
        .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
        .setUsage(C.USAGE_MEDIA)
        .build()

    private val player: ExoPlayer by lazy {
        ExoPlayer.Builder(this).build().apply {
            setAudioAttributes(playbackAudioAttributes, true)
            setHandleAudioBecomingNoisy(true)
            setWakeMode(C.WAKE_MODE_NETWORK)
            addListener(playerListener)
            setPlaybackSpeed(1.0f)
            playWhenReady = true
        }
    }

    private val youboraOptions = Options()
    private lateinit var youboraPlugin: Plugin

    private lateinit var notificationManager: NotificationManager
    private lateinit var mediaSession: MediaSessionCompat
    private lateinit var mediaSessionConnector: MediaSessionConnector

    private var autoStations: List<NetworkChannel>? = null

    private lateinit var appName: String

    // START: Audio Module actions
    fun play(streamName: String){
        Log.d(TAG, "Processing stream: $streamName")
        youboraOptions.contentChannel = streamName
        buildStreamAndPlay(streamName)
    }

    fun playHook(hookUri: String, songTitle: String, artistName: String){
        Log.d(TAG, "Process hook file: $hookUri")
        youboraOptions.contentTitle = "$songTitle-$artistName"
        buildMediaAndPlay(hookUri)
    }

    fun stop(){
        Log.d(TAG, "Stopping stream.")
        player.stop()
        player.clearMediaItems()
    }

    fun getPlaybackState(): Int {
        return player.playbackState
    }
    // END: Audio Module actions

    override fun onCreate() {
        Log.d(TAG, "onCreate")
        super.onCreate()

        appName = applicationContext.getString(R.string.app_name)

        val sessionActivityPendingIntent = PendingIntent.getActivity(
            /* context = */ reactContext ?: applicationContext,
            /* requestCode = */ 0,
            /* intent = */ Intent(reactContext ?: applicationContext, MainActivity::class.java),
            /* flags = */ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        mediaSession = MediaSessionCompat(this, TAG).apply {
            setSessionActivity(sessionActivityPendingIntent)
            isActive = true
        }

        sessionToken = mediaSession.sessionToken

        notificationManager = NotificationManager(
            this,
            mediaSession.sessionToken,
            PlayerNotificationListener()
        )

        mediaSessionConnector = MediaSessionConnector(mediaSession)
        mediaSessionConnector.setPlaybackPreparer(AudioServicePreparer())
        mediaSessionConnector.setPlayer(player)

        notificationManager.showNotificationForPlayer(player)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(TAG, "onStartCommand")
        MediaButtonReceiver.handleIntent(mediaSession, intent)
        return START_STICKY
    }

    override fun onBind(intent: Intent?): IBinder {
        if (intent != null) {
            if(SERVICE_INTERFACE == intent.action){
                return super.onBind(intent)!!
            }
        }
        return binder
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        player.stop()
        player.clearMediaItems()
    }

    override fun onGetRoot(
        clientPackageName: String,
        clientUid: Int,
        rootHints: Bundle?
    ): BrowserRoot? {
        Log.d(TAG, "onGetRoot called")
        return BrowserRoot(MEDIA_ROOT_ID, null)
    }

    override fun onLoadChildren(
        parentId: String,
        result: Result<List<MediaBrowserCompat.MediaItem>>
    ) {
        Log.d(TAG, "OnLoadChildren: parentMediaId = $parentId")

        if(EMPTY_MEDIA_ROOT_ID == parentId){
            result.sendResult(null)
            return
        }

        val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()

        if(MEDIA_ROOT_ID == parentId){
            // Build list of channels
            Log.d(TAG, "Building root items")
            if (autoStations != null) {
                Log.d(TAG, "Channels exist, creating media items...")
                for (i in 0 until autoStations!!.size) {
                    val station = autoStations!![i]
                    val mediaItem = createMediaItem(station)
                    if (mediaItem != null) {
                        mediaItems.add(mediaItem)
                    }
                }
                result.sendResult(mediaItems)
            } else {
                Log.d(TAG, "Making call to get channels...")
                result.detach()
                scope.launch {
                    try {
                        autoStations = ChannelApi.retrofitService.getChannels()

                        if (autoStations!!.isNotEmpty()) {
                            Log.d(TAG, "Stations fetched, creating media items...")
                            for (station in autoStations!!) {
                                val mediaItem = createMediaItem(station)
                                if (mediaItem != null) {
                                    mediaItems.add(mediaItem)
                                }
                            }
                            result.sendResult(mediaItems)
                        }else{
                            useFallbackStation()
                        }
                    } catch (err: Exception) {
                        Log.e(TAG, "Failed to get channels from API. Reason: ${err.message}")
                        result.sendResult(mediaItems)
                    }
                }
            }
        } else{
            result.sendResult(mediaItems)
        }
    }

    private fun createMediaItem(station: NetworkChannel): MediaBrowserCompat.MediaItem? {
        return try {
            val description = MediaDescriptionCompat.Builder()
                .setMediaId(station.streamName)
                .setTitle(station.title)

            val isDarkMode = (reactContext ?: applicationContext).resources.configuration.uiMode == Configuration.UI_MODE_NIGHT_YES

            if (isDarkMode) {
                description.setIconUri(
                    Uri.parse("<my-cdn>" + station.streamName + "/album-md.png")
                )
            } else {
                description.setIconUri(
                    Uri.parse("<my-cdn>" + station.streamName + "/album-md-dark.png")
                )
            }

            MediaBrowserCompat.MediaItem(
                description.build(),
                MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
            )
        } catch (ex: Exception) {
            null
        }
    }

    private fun useFallbackStation() {
        autoStations = List(1) {
            NetworkChannel(
                channelId = 5,
                title = appName,
                streamName = appName.lowercase(Locale.getDefault()),
                slug = "live",
                inactiveOn = null
            )
        }
    }

    override fun onDestroy() {
        scope.cancel()

        mediaSession.run {
            isActive = false
            release()
        }

        player.removeListener(playerListener)
        player.release()

        super.onDestroy()
    }

    private fun playStream(){
        Log.d(TAG, "playStream - sourceUrl: $sourceUrl")
        player.clearMediaItems()

        val mediaItem = MediaItem.Builder()
            .setUri(sourceUrl)
            .setMimeType(MimeTypes.APPLICATION_M3U8)
            .setLiveConfiguration(
                MediaItem.LiveConfiguration.Builder()
                    .setMaxPlaybackSpeed(1.02f)
                    .build()
            )
            .build()

        // Testing adding metadata for AA issue, no change...
        mediaSession.setMetadata(MediaMetadataCompat.Builder()
            .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "Test 1")
            .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "Test 2")
            .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, -1)
            .build())

        if (player.isPlaying || player.isLoading) {
            stop()
        }

        player.addMediaItem(mediaItem)
        player.prepare()
    }

    private fun buildStreamAndPlay(streamName: String) {
        scope.launch {
            sourceUrl = StreamApi.retrofitService.getStreamUrl(
                mapOf(
                    "encoding" to "hls",
                    "platform" to "android",
                    "network" to streamName,
                )
            ).data.streamUrl

            Log.d(TAG, "Got stream url: $sourceUrl")

            playStream()
        }
    }

    private fun buildMediaAndPlay(hookUri: String) = scope.launch {
        val userData = StorageHelper.getUserData(reactContext ?: applicationContext)

        if(!::youboraPlugin.isInitialized && reactContext != null){
            youboraPlugin = Plugin(youboraOptions, reactContext)
            youboraPlugin.activity = reactContext?.currentActivity

            Exoplayer2Adapter(player)
                .also { adapter ->
                    youboraPlugin.adapter = adapter
                }
        }

        if (player.isPlaying == true || player.isLoading == true) {
            stop()
        }

        val mediaItem = MediaItem.Builder()
            .setUri(hookUri)
            .build()

        player.addMediaItem(mediaItem)
        player.prepare()
        player.play()
    }

    @MainThread
    private fun playerListener() = object: Player.Listener {
        override fun onPlaybackStateChanged(playbackState: Int) {
            val state: State = when (playbackState){
                ExoPlayer.STATE_IDLE -> State.Idle
                ExoPlayer.STATE_BUFFERING -> State.Buffering
                ExoPlayer.STATE_READY -> State.Ready
                ExoPlayer.STATE_ENDED -> State.Stopped
                else -> State.Stopped
            }

            if(state != State.Buffering){
                notificationManager.hideNotification()
            }

            Log.d(TAG, "PlayerState: $state")
            sendEvent(EVENT_PLAYER_STATE, state.state )
        }

        override fun onIsPlayingChanged(isPlaying: Boolean) {
            if(isPlaying) {
                Log.d(TAG, "PlayerState: Playing")
                notificationManager.showNotificationForPlayer(player)
                sendEvent(EVENT_PLAYER_STATE, State.Playing.state)
            }else{
                Log.d(TAG, "PlayerState: Paused (Stopping and clearing)")
                sendEvent(EVENT_PLAYER_STATE, State.Paused.state)
                player.stop()
                player.clearMediaItems()
            }
        }

        override fun onPlayerError(error: PlaybackException) {
            sendEvent(EVENT_PLAYER_STATE, State.Error.state)
            super.onPlayerError(error)
        }

        override fun onMetadata(metadata: com.google.android.exoplayer2.metadata.Metadata) {
            var handled = false

            var id: String? = null
            var title: String? = null
            var artist: String? = null
            var isBreak = false

            Log.d(TAG, "Raw Meta: $metadata")

            (0 until metadata.length()).forEach { i ->
                when (val entry = metadata[i]) {
                    is TextInformationFrame -> {
                        when (entry.id.uppercase()) {
                            "TIT2", "TT2" -> {
                                if(entry.value.isNotEmpty()){ // Added to due current bug with empty metadata
                                    handled = true
                                    title = entry.value
                                }
                            }
                            "TOPE", "TPE1", "TP1" -> {
                                handled = true
                                artist = entry.value
                            }
                            "TUID" -> {
                                handled = true
                                id = entry.value
                            }
                        }
                    }
                    is UrlLinkFrame -> {
                        when (entry.id.uppercase()) {
                            "WXXX" -> {
                                handled = true
                                if (id == null) {
                                    id = entry.url
                                }
                            }
                        }
                    }
                }
            }

            if (handled){
                try {
                    UUID.fromString(id)
                } catch (ignored: Exception) {
                    Log.d(TAG, "Detected stream break.")
                    id = null
                    isBreak = true
                }

                notificationManager.currentArtist = artist.toString()
                notificationManager.currentSong = title.toString()

                youboraOptions.contentTitle = "$title-$artist"
                youboraOptions.contentId = "$id"

                youboraOptions.contentBitrate = player.audioFormat?.bitrate?.toLong()

                Arguments.createMap().apply {
                    putString("id", id)
                    putString("title", title)
                    putString("artist", artist)
                    putBoolean("isBreak", isBreak)
                    sendEvent(EVENT_METADATA, this)
                }
            }
        }
    }

    private fun sendEvent(eventName: String, params: WritableMap?){
        reactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
            ?.emit(eventName, params)
    }

    private fun sendEvent(eventName: String, eventValue: String){
        reactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
            ?.emit(eventName, eventValue)
    }

    inner class PlaybackBinder: Binder(){
        val service = this@PlaybackService
    }

    /**
     * Listen for notification events.
     */
    private inner class PlayerNotificationListener :
        PlayerNotificationManager.NotificationListener {
        override fun onNotificationPosted(
            notificationId: Int,
            notification: Notification,
            ongoing: Boolean
        ) {
            if (ongoing && !isForegroundService) {
                ContextCompat.startForegroundService(
                    applicationContext,
                    Intent(applicationContext, this@PlaybackService.javaClass)
                )

                startForeground(notificationId, notification)
                isForegroundService = true
            }
        }

        override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {
            stopForeground(true)
            isForegroundService = false
            stopSelf()
        }
    }

    private inner class AudioServicePreparer: MediaSessionConnector.PlaybackPreparer {
        override fun onCommand(
            player: Player,
            command: String,
            extras: Bundle?,
            cb: ResultReceiver?
        ): Boolean  = false

        override fun getSupportedPrepareActions(): Long =
            PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID or
            PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID or
            PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH or
            PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH


        override fun onPrepare(playWhenReady: Boolean) {
            Log.d(TAG, "[AudioServicePreparer] - onPrepare")
            // TODO: Should get last played station
            onPrepareFromMediaId("<default-media-id>", playWhenReady, null)
        }

        override fun onPrepareFromMediaId(
            mediaId: String,
            playWhenReady: Boolean,
            extras: Bundle?
        ) {
            Log.d(TAG, "[AudioServicePreparer] - onPrepareFromMediaId - $mediaId - playWhenReady? $playWhenReady")
            player.playWhenReady = playWhenReady
            play(mediaId)
        }

        override fun onPrepareFromSearch(query: String, playWhenReady: Boolean, extras: Bundle?) {
            Log.d(TAG, "[AudioServicePreparer] - onPrepareFromSearch")
            // TODO: Should search for station
            play("<default-media-id>")
        }

        override fun onPrepareFromUri(uri: Uri, playWhenReady: Boolean, extras: Bundle?) = Unit
    }

    companion object {
        const val TAG = "PlaybackService"

        const val EVENT_PLAYER_STATE = "onPlayerStateChanged"
        const val EVENT_METADATA = "onMetadataReceived"

        private const val MEDIA_ROOT_ID = "my_root"
        private const val EMPTY_MEDIA_ROOT_ID = "my_empty_root"
    }
}

Logcat output when selecting a station in Android Auto:

2022-11-22 17:11:08.293  2264-2264  PlaybackService         <my-package>                        D  [AudioServicePreparer] - onPrepareFromMediaId - <stream-name> - playWhenReady? true
2022-11-22 17:11:08.304  2264-2264  PlaybackService         <my-package>                        D  Processing stream: <stream-name>
2022-11-22 17:11:08.305  2264-2264  PlaybackService         <my-package>                        D  playStream - sourceUrl: <valid-url>
2022-11-22 17:11:08.395  2264-2264  PlaybackService         <my-package>                        D  PlayerState: Buffering
2022-11-22 17:11:08.397  2264-2476  ReactNativeJS           <my-package>                        I  'STATE:', 'buffering'
2022-11-22 17:11:11.102  2264-2521  DMCodecAdapterFactory   <my-package>                        I  Creating an asynchronous MediaCodec adapter for track type audio
2022-11-22 17:11:11.105  2264-9864  CCodec                  <my-package>                        I  state->set(ALLOCATING)
2022-11-22 17:11:11.105  2264-9864  CCodec                  <my-package>                        I  allocate(c2.android.aac.decoder)
2022-11-22 17:11:11.111  2264-9864  CCodec                  <my-package>                        I  setting up 'default' as default (vendor) store
2022-11-22 17:11:11.114  2264-9864  CCodec                  <my-package>                        I  Created component [c2.android.aac.decoder]
2022-11-22 17:11:11.114  2264-9864  CCodec                  <my-package>                        I  state->set(ALLOCATED)
2022-11-22 17:11:11.115  2264-9864  CCodecConfig            <my-package>                        D  read media type: audio/mp4a-latm
2022-11-22 17:11:11.123  2264-9864  CCodecConfig            <my-package>                        I  query failed after returning 19 values (BAD_INDEX)
2022-11-22 17:11:11.124  2264-9864  MediaCodec              <my-package>                        I  MediaCodec will operate in async mode
2022-11-22 17:11:11.125  2264-9864  CCodec                  <my-package>                        D  [c2.android.aac.decoder] buffers are bound to CCodec for this session
2022-11-22 17:11:11.125  2264-9864  CCodec                  <my-package>                        I  appPid(2264) width(0) height(0)
2022-11-22 17:11:11.125  2264-9864  CCodecConfig            <my-package>                        D  no c2 equivalents for log-session-id
2022-11-22 17:11:11.125  2264-9864  CCodecConfig            <my-package>                        D  no c2 equivalents for flags
2022-11-22 17:11:11.126  2264-9864  CCodecConfig            <my-package>                        D  c2 config diff is   c2::u32 raw.channel-count.value = 2
2022-11-22 17:11:11.126  2264-9864  Codec2Client            <my-package>                        W  query -- param skipped: index = 1107298332.
2022-11-22 17:11:11.126  2264-9864  CCodecConfig            <my-package>                        I  query failed after returning 19 values (BAD_INDEX)
2022-11-22 17:11:11.127  2264-2521  MediaCodec              <my-package>                        D  keep callback message for reclaim
2022-11-22 17:11:11.128  2264-9864  CCodec                  <my-package>                        I  state->set(STARTING)
2022-11-22 17:11:11.132  2264-9864  Codec2Client            <my-package>                        W  query -- param skipped: index = 1342179345.
2022-11-22 17:11:11.132  2264-9864  Codec2Client            <my-package>                        W  query -- param skipped: index = 2415921170.
2022-11-22 17:11:11.132  2264-9864  Codec2Client            <my-package>                        W  query -- param skipped: index = 1610614798.
2022-11-22 17:11:11.135  2264-9864  CCodec                  <my-package>                        I  state->set(RUNNING)
2022-11-22 17:11:11.135  2264-9864  CCodecBufferChannel     <my-package>                        I  [c2.android.aac.decoder#96] 4 initial input buffers available
2022-11-22 17:11:11.136  2264-2980  BufferPoolAccessor2.0   <my-package>                        D  bufferpool2 0xb40000701ca21d68 : 0(0 size) total buffers - 0(0 size) used buffers - 3845/3850 (recycle/alloc) - 5/3845 (fetch/transfer)
2022-11-22 17:11:11.136  2264-2980  BufferPoolAccessor2.0   <my-package>                        D  Destruction - bufferpool2 0xb40000701ca21d68 cached: 0/0M, 0/0% in use; allocs: 3850, 100% recycled; transfers: 3845, 100% unfetched
2022-11-22 17:11:11.140  2264-2264  PlaybackService         <my-package>                        D  PlayerState: Ready
2022-11-22 17:11:11.141  2264-2476  ReactNativeJS           <my-package>                        I  'STATE:', 'ready'
2022-11-22 17:11:11.147  2264-2264  PlaybackService         <my-package>                        D  PlayerState: Playing
2022-11-22 17:11:11.148  2264-2264  PlaybackService         <my-package>                        D  Raw Meta: entries=[PRIV: owner=com.apple.streaming.transportStreamTimestamp]
2022-11-22 17:11:11.149  2264-2264  PlaybackService         <my-package>                        D  Raw Meta: entries=[TIT2: description=null: value=]
2022-11-22 17:11:11.154  2264-9864  CCodecConfig            <my-package>                        D  c2 config diff is   c2::u32 raw.channel-mask.value = 12
2022-11-22 17:11:11.163  2264-2264  PlaybackService         <my-package>                        D  onStartCommand
2022-11-22 17:11:11.172  2264-2521  AudioTrack              <my-package>                        D  setVolume(1.000000, 1.000000) pid : 2264
2022-11-22 17:11:11.238  2264-2521  AudioTrack              <my-package>                        D  getTimestamp_l(74): device stall time corrected using current time 2384346281016
2022-11-22 17:11:11.274  2264-2476  ReactNativeJS           <my-package>                        I  'STATE:', 'playing'
2022-11-22 17:11:11.372  2264-2476  ReactNativeJS           <my-package>                        I  Metadata is undefined
2022-11-22 17:11:12.523  2264-2476  ReactNativeJS           <my-package>                        I  Token is not expired
2022-11-22 17:11:12.651  2264-2478  RNFBCrashlyticsInit     <my-package>                        D  isCrashlyticsCollectionEnabled via RNFBJSON: true
2022-11-22 17:11:12.652  2264-2478  RNFBCrashlyticsInit     <my-package>                        D  isCrashlyticsCollectionEnabled after checking crashlytics_debug_enabled: false
2022-11-22 17:11:12.652  2264-2478  RNFBCrashlyticsInit     <my-package>                        D  isCrashlyticsCollectionEnabled final value: false
2022-11-22 17:11:14.406  2264-2977  CCodecBufferChannel     <my-package>                        D  [c2.android.aac.decoder#96] DEBUG: elapsed: n=6 [in=0 pipeline=0 out=2]
2022-11-22 17:11:16.930  2264-2264  ViewRootIm...nActivity] <my-package>                        I  ViewPostIme pointer 0
2022-11-22 17:11:17.069  2264-2264  ViewRootIm...nActivity] <my-package>                        I  ViewPostIme pointer 1
2022-11-22 17:11:17.082  2264-2264  PlaybackService         <my-package>                        D  Stopping stream.
2022-11-22 17:11:17.086  2264-9864  CCodec                  <my-package>                        I  state->set(FLUSHING)
2022-11-22 17:11:17.086  2264-9864  CCodec                  <my-package>                        I  state->set(FLUSHED)
2022-11-22 17:11:17.087  2264-2521  MediaCodec              <my-package>                        D  keep callback message for reclaim
2022-11-22 17:11:17.087  2264-9864  CCodec                  <my-package>                        I  state->set(RESUMING)
2022-11-22 17:11:17.087  2264-9864  CCodecConfig            <my-package>                        I  query failed after returning 19 values (BAD_INDEX)
2022-11-22 17:11:17.088  2264-9864  CCodec                  <my-package>                        I  state->set(RUNNING)
2022-11-22 17:11:17.089  2264-9864  CCodec                  <my-package>                        I  state->set(RELEASING)
2022-11-22 17:11:17.090  2264-9929  CCodec                  <my-package>                        I  state->set(RELEASED)
2022-11-22 17:11:17.090  2264-9864  hw-BpHwBinder           <my-package>                        I  onLastStrongRef automatically unlinking death recipients
2022-11-22 17:11:17.090  2264-9864  MediaCodec              <my-package>                        I  Codec shutdown complete
2022-11-22 17:11:17.095  2264-2264  PlaybackService         <my-package>                        D  PlayerState: Idle
2022-11-22 17:11:17.097  2264-2476  ReactNativeJS           <my-package>                        I  'STATE:', 'idle'
2022-11-22 17:11:17.097  2264-2264  PlaybackService         <my-package>                        D  PlayerState: Paused (Stopping and clearing)
2022-11-22 17:11:17.134  2264-2979  BufferPoolAccessor2.0   <my-package>                        D  evictor expired: 1, evicted: 0
2022-11-22 17:11:17.201  2264-2476  ReactNativeJS           <my-package>                        I  'STATE:', 'paused'
2022-11-22 17:11:22.137  2264-2979  BufferPoolAccessor2.0   <my-package>                        D  bufferpool2 0xb40000701c6606a8 : 0(0 size) total buffers - 0(0 size) used buffers - 311/316 (recycle/alloc) - 5/311 (fetch/transfer)
2022-11-22 17:11:22.137  2264-2979  BufferPoolAccessor2.0   <my-package>                        D  evictor expired: 1, evicted: 1

If there are any other files that you think may be helpful in finding an answer, I will try to provide though I have to sanitize some things.



from Android Auto: Media item gets stuck "Getting your selection..." instead of showing controls while playing

Tracking claims using date/timestamp columns and creating a final count using pandas

I have an issue where I need to track the progression of patients insurance claim statuses based on the dates of those statuses. I also need to create a count of status based on certain conditions.

DF:

ClaimID New Accepted Denied Pending Expired Group
001 2021-01-01T09:58:35:335Z 2021-01-01T10:05:43:000Z A
002 2021-01-01T06:30:30:000Z 2021-03-01T04:11:45:000Z 2021-03-01T04:11:53:000Z A
003 2021-02-14T14:23:54:154Z 2021-02-15T11:11:56:000Z 2021-02-15T11:15:00:000Z A
004 2021-02-14T15:36:05:335Z 2021-02-14T17:15:30:000Z A
005 2021-02-14T15:56:59:009Z 2021-03-01T10:05:43:000Z A

In the above dataset, we have 6 columns. ClaimID is simple and just indicates the ID of the claim. New, Accepted, Denied, Pending, and Expired indicate the status of the claim and the day/time those statuses were set.

What I need to do is get a count of how many claims are New on each day and how many move out of new into a new status. For example, There are 2 new claims on 2021-01-01. On that same day 1 moved to Accepted about 7 minutes later. Thus on 2021-01-01 the table of counts would read:

DF_Count:

Date New Accepted Denied Pending Expired
2021-01-01 2 1 0 0 0
2021-01-02 1 0 0 0 0
2021-01-03 1 0 0 0 0
2021-01-04 1 0 0 0 0
2021-01-05 1 0 0 0 0
.... .... .... .... .... ....
2021-02-14 4 2 0 0 0
2021-02-15 2 3 0 0 1
2021-02-16 2 2 0 0 0

Few Conditions:

  1. If a claim moves from one status to the other on the same day (even if they are a minutes/hours apart) it would not be subtracted from the original status until the next day. This can be seen on 2021-01-01 where claim 001 moves from new to accepted on the same day but the claim is not subtracted from new until 2021-01-02.
  2. Until something happens to a claim, it should remain in its original status. Claim 002 will remain in new until 2021-03-01 when it is approved.
  3. If a claim changes status on a later date than its original status, it will be subtracted on that later date. For this, see status 003. It is new on 2/14 but accepted on 2/15. This is why New goes down by 2 on 2/15 (the other claim is the is 004 which is new and accepted on the same day)
  4. For certain statuses, I do not need to look at all columns. For example, For new I only look at the dates inside Accepted and Denied. Not Pending and Expired. When I do these same steps for approved, I no longer need to look at new, just the other columns. How would I do that?
  5. In the final DF_count table, the dates should start from the earliest date in 'New' and end on todays date.
  6. The code needs to be grouped by the Group Column as well. For example, patients in group B (not pictured) will have to have the same start and end date but for their own claims.
  7. I need to do this separately for all of the statuses. Not just new.

Current Solution:

My current solution has been to create an dataset with just dates from the min New Date to todays date. Then for each column, what I do is use the .loc method to find dates that are greater than New in each of the other columns. For example, in the code below I look for all cases where new is equal to approved.

df1 = df.loc[(df['New'] == df['Approved']) & 
((df['Expired'].isnull()) | (df['Expired'] >= df['Accepted'])) &
((df['Pending'].isnull()) | (df['Pending'] >= df['Accepted'])) &
((df['Denied'].isnull()) | (df['Denied'] >= df['Accepted']))]

newtoaccsday = df1.loc[:, ('Group', 'Accepted')]
newtoappsday['Date'] = newtoappsday['Accepted'] 
newtoappsday = newtoappsday.reset_index(drop = True)
newtoappsday= newtoappsday.groupby(['Date', 'Group'], as_index = False)['Approved'].value_counts()
newtoappsday.drop(columns = {'Accepted'}, inplace = True)
newtoappsday.rename(columns = {'count': 'NewAppSDay'}, inplace = True)
newtoappsday['Date'] = newtoappsday['Date'] + timedelta(1)
df_count= df_count.merge(newtoappsday, how = 'left', on = ['Date', 'Group']).fillna(0)


--After doing the above steps for all conditions (where new goes to accepted on a later date etc.) I will do the final calculation for new:

df_count['New'] = df_count.eval('New = New - (NewAccSDay + NewAccLater + NewDenSDay + NewDenLater + NewExpLater + NewPendSDay + NewPendLater)').groupby(['Tier2_ID', 'ClaimType'])['New'].cumsum()

Any and all help would be greatly appreciated. My method above is extremely inefficient and leading to some errors. Do I need to write a for loop for this? What is the best way to go about this.



from Tracking claims using date/timestamp columns and creating a final count using pandas