To remove a specific dependency, use the go get command, specifying the module’s module path and appending @none, as in the following example:

$go get example.com/theirmodule@none To stop tracking all unused modules, run the go mod tidy command. This command may also add missing dependencies needed to build packages in your module. $ go mod tidy

If you are really inclined to get rid of a package, uninstalling it (and installing it as needed) is possible for non-essential applications, but as with other Linux distributions, packages on Ubuntu depend on other packages, and have other packages that depend on them, so when you install or remove a package, other packages may be automatically installed as dependencies (or replacements) or removed because they depend on the package you remove. Removing a package with many dependencies or that is essential for the system to run properly may break the system very severely. All this is handled by the package management system. To see what is going to happen when you run a particular install or remove command, use the -s or --simulate option in APT, for example

apt remove <package> -s


You should be able to use dpkg -S (or equivalently dpkg-query -S) to identify the package to which a file belongs

AFAIK -dbg packages are only required if you need to debug into the corresponding library functions: if you are not developing / debugging webkit2gtk-3.0 applications I don't see why you shouldn't remove them. If in doubt, you can always run the package manager in 'dry run' mode to see if any important dependent packages are going to be removed as a result

dpkg -S /usr/lib/debug/usr/lib/x86_64-linux-gnu/libwebkit2gtk-3.0.so.25.10.11

sudo apt-get remove --dry-run libwebkit2gtk-3.0-25-dbg


If you want to have an automatized way of hidden devices removal via script - you can run the following PS script (found at blog);(credits go to Alexander Boersc and trententtye) - Please read the examples section of the script to find examples:

   .SYNOPSIS
Removes ghost devices from your system

.DESCRIPTION
This script will remove ghost devices from your system.  These are devices that are present but have a "InstallState" as false.  These devices are typically shown as 'faded'
in Device Manager, when you select "Show hidden and devices" from the view menu.  This script has been tested on Windows 2008 R2 SP2 with PowerShell 3.0, 5.1 and Server 2012R2
with Powershell 4.0.  There is no warranty with this script.  Please use cautiously as removing devices is a destructive process without an undo.

.PARAMETER filterByFriendlyName
This parameter will exclude devices that match the partial name provided. This paramater needs to be specified in an array format for all the friendly names you want to be excluded from removal.
"Intel" will match "Intel(R) Xeon(R) CPU E5-2680 0 @ 2.70GHz". "Loop" will match "Microsoft Loopback Adapter".

.PARAMETER filterByClass
This parameter will exclude devices that match the class name provided. This paramater needs to be specified in an array format for all the class names you want to be excluded from removal.
This is an exact string match so "Disk" will not match "DiskDrive".

.PARAMETER listDevicesOnly
listDevicesOnly will output a table of all devices found in this system.

.PARAMETER listGhostDevicesOnly
listGhostDevicesOnly will output a table of all 'ghost' devices found in this system.

.EXAMPLE
Lists all devices
. "removeGhosts.ps1" -listDevicesOnly

.EXAMPLE
Save the list of devices as an object
$Devices = . "removeGhosts.ps1" -listDevicesOnly .EXAMPLE Lists all 'ghost' devices . "removeGhosts.ps1" -listGhostDevicesOnly .EXAMPLE Save the list of 'ghost' devices as an object$ghostDevices = . "removeGhosts.ps1" -listGhostDevicesOnly

.EXAMPLE
Remove all ghost devices EXCEPT any devices that have "Intel" or "Citrix" in their friendly name
. "removeGhosts.ps1" -filterByFriendlyName @("Intel","Citrix")

.EXAMPLE
Remove all ghost devices EXCEPT any devices that are apart of the classes "LegacyDriver" or "Processor"
. "removeGhosts.ps1" -filterByClass @("LegacyDriver","Processor")

.EXAMPLE
Remove all ghost devices EXCEPT for devices with a friendly name of "Intel" or "Citrix" or with a class of "LegacyDriver" or "Processor"
. "removeGhosts.ps1" -filterByClass @("LegacyDriver","Processor") -filterByFriendlyName @("Intel","Citrix")

.NOTES
Permission level has not been tested.  It is assumed you will need to have sufficient rights to uninstall devices from device manager for this script to run properly.
#>

Param(
[array]$FilterByClass, [array]$FilterByFriendlyName,
[switch]$listDevicesOnly, [switch]$listGhostDevicesOnly
)

#parameter futzing
$removeDevices =$true
if ($FilterByClass -ne$null) {
write-host "FilterByClass: $FilterByClass" } if ($FilterByFriendlyName -ne $null) { write-host "FilterByFriendlyName:$FilterByFriendlyName"
}

if ($listDevicesOnly -eq$true) {
write-host "List devices without removal: $listDevicesOnly"$removeDevices = $false } if ($listGhostDevicesOnly -eq $true) { write-host "List ghost devices without removal:$listGhostDevicesOnly"
$removeDevices =$false
}

$setupapi = @" using System; using System.Diagnostics; using System.Text; using System.Runtime.InteropServices; namespace Win32 { public static class SetupApi { // 1st form using a ClassGUID only, with Enumerator = IntPtr.Zero [DllImport("setupapi.dll", CharSet = CharSet.Auto)] public static extern IntPtr SetupDiGetClassDevs( ref Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, int Flags ); // 2nd form uses an Enumerator only, with ClassGUID = IntPtr.Zero [DllImport("setupapi.dll", CharSet = CharSet.Auto)] public static extern IntPtr SetupDiGetClassDevs( IntPtr ClassGuid, string Enumerator, IntPtr hwndParent, int Flags ); [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool SetupDiEnumDeviceInfo( IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData ); [DllImport("setupapi.dll", SetLastError = true)] public static extern bool SetupDiDestroyDeviceInfoList( IntPtr DeviceInfoSet ); [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool SetupDiGetDeviceRegistryProperty( IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint property, out UInt32 propertyRegDataType, byte[] propertyBuffer, uint propertyBufferSize, out UInt32 requiredSize ); [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool SetupDiGetDeviceInstanceId( IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, int DeviceInstanceIdSize, out int RequiredSize ); [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool SetupDiRemoveDevice(IntPtr DeviceInfoSet,ref SP_DEVINFO_DATA DeviceInfoData); } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_DATA { public uint cbSize; public Guid classGuid; public uint devInst; public IntPtr reserved; } [Flags] public enum DiGetClassFlags : uint { DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE DIGCF_PRESENT = 0x00000002, DIGCF_ALLCLASSES = 0x00000004, DIGCF_PROFILE = 0x00000008, DIGCF_DEVICEINTERFACE = 0x00000010, } public enum SetupDiGetDeviceRegistryPropertyEnum : uint { SPDRP_DEVICEDESC = 0x00000000, // DeviceDesc (R/W) SPDRP_HARDWAREID = 0x00000001, // HardwareID (R/W) SPDRP_COMPATIBLEIDS = 0x00000002, // CompatibleIDs (R/W) SPDRP_UNUSED0 = 0x00000003, // unused SPDRP_SERVICE = 0x00000004, // Service (R/W) SPDRP_UNUSED1 = 0x00000005, // unused SPDRP_UNUSED2 = 0x00000006, // unused SPDRP_CLASS = 0x00000007, // Class (R--tied to ClassGUID) SPDRP_CLASSGUID = 0x00000008, // ClassGUID (R/W) SPDRP_DRIVER = 0x00000009, // Driver (R/W) SPDRP_CONFIGFLAGS = 0x0000000A, // ConfigFlags (R/W) SPDRP_MFG = 0x0000000B, // Mfg (R/W) SPDRP_FRIENDLYNAME = 0x0000000C, // FriendlyName (R/W) SPDRP_LOCATION_INFORMATION = 0x0000000D, // LocationInformation (R/W) SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E, // PhysicalDeviceObjectName (R) SPDRP_CAPABILITIES = 0x0000000F, // Capabilities (R) SPDRP_UI_NUMBER = 0x00000010, // UiNumber (R) SPDRP_UPPERFILTERS = 0x00000011, // UpperFilters (R/W) SPDRP_LOWERFILTERS = 0x00000012, // LowerFilters (R/W) SPDRP_BUSTYPEGUID = 0x00000013, // BusTypeGUID (R) SPDRP_LEGACYBUSTYPE = 0x00000014, // LegacyBusType (R) SPDRP_BUSNUMBER = 0x00000015, // BusNumber (R) SPDRP_ENUMERATOR_NAME = 0x00000016, // Enumerator Name (R) SPDRP_SECURITY = 0x00000017, // Security (R/W, binary form) SPDRP_SECURITY_SDS = 0x00000018, // Security (W, SDS form) SPDRP_DEVTYPE = 0x00000019, // Device Type (R/W) SPDRP_EXCLUSIVE = 0x0000001A, // Device is exclusive-access (R/W) SPDRP_CHARACTERISTICS = 0x0000001B, // Device Characteristics (R/W) SPDRP_ADDRESS = 0x0000001C, // Device Address (R) SPDRP_UI_NUMBER_DESC_FORMAT = 0X0000001D, // UiNumberDescFormat (R/W) SPDRP_DEVICE_POWER_DATA = 0x0000001E, // Device Power Data (R) SPDRP_REMOVAL_POLICY = 0x0000001F, // Removal Policy (R) SPDRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000020, // Hardware Removal Policy (R) SPDRP_REMOVAL_POLICY_OVERRIDE = 0x00000021, // Removal Policy Override (RW) SPDRP_INSTALL_STATE = 0x00000022, // Device Install State (R) SPDRP_LOCATION_PATHS = 0x00000023, // Device Location Paths (R) SPDRP_BASE_CONTAINERID = 0x00000024 // Base ContainerID (R) } } "@ Add-Type -TypeDefinition$setupapi

#Array for all removed devices report
$removeArray = @() #Array for all devices report$array = @()

$setupClass = [Guid]::Empty #Get all devices$devs = [Win32.SetupApi]::SetupDiGetClassDevs([ref]$setupClass, [IntPtr]::Zero, [IntPtr]::Zero, [Win32.DiGetClassFlags]::DIGCF_ALLCLASSES) #Initialise Struct to hold device info Data$devInfo = new-object Win32.SP_DEVINFO_DATA
$devInfo.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($devInfo)

#Device Counter
$devCount = 0 #Enumerate Devices while([Win32.SetupApi]::SetupDiEnumDeviceInfo($devs, $devCount, [ref]$devInfo)){

#Will contain an enum depending on the type of the registry Property, not used but required for call
$propType = 0 #Buffer is initially null and buffer size 0 so that we can get the required Buffer size first [byte[]]$propBuffer = $null$propBufferSize = 0
#Get Buffer size
[Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo, [Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_FRIENDLYNAME, [ref]$propType,$propBuffer, 0, [ref]$propBufferSize) | Out-null #Initialize Buffer with right size [byte[]]$propBuffer = New-Object byte[] $propBufferSize #Get HardwareID$propTypeHWID = 0
[byte[]]$propBufferHWID =$null
$propBufferSizeHWID = 0 [Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo, [Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_HARDWAREID, [ref]$propTypeHWID, $propBufferHWID, 0, [ref]$propBufferSizeHWID) | Out-null
[byte[]]$propBufferHWID = New-Object byte[]$propBufferSizeHWID

#Get DeviceDesc (this name will be used if no friendly name is found)
$propTypeDD = 0 [byte[]]$propBufferDD = $null$propBufferSizeDD = 0
[Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo, [Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_DEVICEDESC, [ref]$propTypeDD,$propBufferDD, 0, [ref]$propBufferSizeDD) | Out-null [byte[]]$propBufferDD = New-Object byte[] $propBufferSizeDD #Get Install State$propTypeIS = 0
[byte[]]$propBufferIS =$null
$propBufferSizeIS = 0 [Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo, [Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_INSTALL_STATE, [ref]$propTypeIS, $propBufferIS, 0, [ref]$propBufferSizeIS) | Out-null
[byte[]]$propBufferIS = New-Object byte[]$propBufferSizeIS

#Get Class
$propTypeCLSS = 0 [byte[]]$propBufferCLSS = $null$propBufferSizeCLSS = 0
[Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo, [Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_CLASS, [ref]$propTypeCLSS,$propBufferCLSS, 0, [ref]$propBufferSizeCLSS) | Out-null [byte[]]$propBufferCLSS = New-Object byte[] $propBufferSizeCLSS [Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo,[Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_CLASS, [ref]$propTypeCLSS, $propBufferCLSS,$propBufferSizeCLSS, [ref]$propBufferSizeCLSS) | out-null$Class = [System.Text.Encoding]::Unicode.GetString($propBufferCLSS) #Read FriendlyName property into Buffer if(![Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo,[Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_FRIENDLYNAME, [ref]$propType, $propBuffer,$propBufferSize, [ref]$propBufferSize)){ [Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo,[Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_DEVICEDESC, [ref]$propTypeDD, $propBufferDD,$propBufferSizeDD, [ref]$propBufferSizeDD) | out-null$FriendlyName = [System.Text.Encoding]::Unicode.GetString($propBufferDD) #The friendly Name ends with a weird character if ($FriendlyName.Length -ge 1) {
$FriendlyName =$FriendlyName.Substring(0,$FriendlyName.Length-1) } } else { #Get Unicode String from Buffer$FriendlyName = [System.Text.Encoding]::Unicode.GetString($propBuffer) #The friendly Name ends with a weird character if ($FriendlyName.Length -ge 1) {
$FriendlyName =$FriendlyName.Substring(0,$FriendlyName.Length-1) } } #InstallState returns true or false as an output, not text$InstallState = [Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo,[Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_INSTALL_STATE, [ref]$propTypeIS,$propBufferIS, $propBufferSizeIS, [ref]$propBufferSizeIS)

# Read HWID property into Buffer
if(![Win32.SetupApi]::SetupDiGetDeviceRegistryProperty($devs, [ref]$devInfo,[Win32.SetupDiGetDeviceRegistryPropertyEnum]::SPDRP_HARDWAREID, [ref]$propTypeHWID,$propBufferHWID, $propBufferSizeHWID, [ref]$propBufferSizeHWID)){
#Ignore if Error
$HWID = "" } else { #Get Unicode String from Buffer$HWID = [System.Text.Encoding]::Unicode.GetString($propBufferHWID) #trim out excess names and take first object$HWID = $HWID.split([char]0x0000)[0].ToUpper() } #all detected devices list$obj = New-Object System.Object
$obj | Add-Member -type NoteProperty -name FriendlyName -value$FriendlyName
$obj | Add-Member -type NoteProperty -name HWID -value$HWID
$obj | Add-Member -type NoteProperty -name InstallState -value$InstallState
$obj | Add-Member -type NoteProperty -name Class -value$Class
if ($array.count -le 0) { #for some reason the script will blow by the first few entries without displaying the output #this brief pause seems to let the objects get created/displayed so that they are in order. sleep 1 }$array += @($obj) <# We need to execute the filtering at this point because we are in the current device context where we can execute an action (eg, removal). InstallState : False == ghosted device #>$matchFilter = $false if ($removeDevices -eq $true) { #we want to remove devices so lets check the filters... if ($FilterByClass -ne $null) { foreach ($ClassFilter in $FilterByClass) { if ($ClassFilter -eq $Class) { Write-verbose "Class filter match$ClassFilter, skipping"
$matchFilter =$true
}
}
}
if ($FilterByFriendlyName -ne$null) {
foreach ($FriendlyNameFilter in$FilterByFriendlyName) {
if ($FriendlyName -like '*'+$FriendlyNameFilter+'*') {
Write-verbose "FriendlyName filter match $FriendlyName, skipping"$matchFilter = $true } } } if ($InstallState -eq $False) { if ($matchFilter -eq $false) { Write-Host "Attempting to removing device$FriendlyName" -ForegroundColor Yellow
$removeObj = New-Object System.Object$removeObj | Add-Member -type NoteProperty -name FriendlyName -value $FriendlyName$removeObj | Add-Member -type NoteProperty -name HWID -value $HWID$removeObj | Add-Member -type NoteProperty -name InstallState -value $InstallState$removeObj | Add-Member -type NoteProperty -name Class -value $Class$removeArray += @($removeObj) if([Win32.SetupApi]::SetupDiRemoveDevice($devs, [ref]$devInfo)){ Write-Host "Removed device$FriendlyName"  -ForegroundColor Green
} else {
Write-Host "Failed to remove device $FriendlyName" -ForegroundColor Red } } else { write-host "Filter matched. Skipping$FriendlyName" -ForegroundColor Yellow
}
}
}
$devcount++ } #output objects so you can take the output from the script if ($listDevicesOnly) {
$allDevices =$array | sort -Property FriendlyName | ft
$allDevices write-host "Total devices found :$($array.count)"$ghostDevices = ($array | where {$_.InstallState -eq $false} | sort -Property FriendlyName) write-host "Total ghost devices found :$($ghostDevices.count)" return$allDevices | out-null
}

if ($listGhostDevicesOnly) {$ghostDevices = ($array | where {$_.InstallState -eq $false} | sort -Property FriendlyName)$ghostDevices | ft
write-host "Total ghost devices found : $($ghostDevices.count)"
return $ghostDevices | out-null } if ($removeDevices -eq $true) { write-host "Removed devices:"$removeArray  | sort -Property FriendlyName | ft
write-host "Total removed devices     : $($removeArray.count)"
return $removeArray | out-null }  See below for a sample matplotlibrc file and see matplotlib.rcParams for a full list of configurable rcParams. #### MATPLOTLIBRC FORMAT ## NOTE FOR END USERS: DO NOT EDIT THIS FILE! ## ## This is a sample Matplotlib configuration file - you can find a copy ## of it on your system in site-packages/matplotlib/mpl-data/matplotlibrc ## (relative to your Python installation location). ## ## You should find a copy of it on your system at ## site-packages/matplotlib/mpl-data/matplotlibrc (relative to your Python ## installation location). DO NOT EDIT IT! ## ## If you wish to change your default style, copy this file to one of the ## following locations: ## Unix/Linux: ##$HOME/.config/matplotlib/matplotlibrc OR
##         $XDG_CONFIG_HOME/matplotlib/matplotlibrc (if$XDG_CONFIG_HOME is set)
##     Other platforms:
##         HOME/.matplotlib/matplotlibrc ## and edit that copy. ## ## See https://matplotlib.org/users/customizing.html#the-matplotlibrc-file ## for more details on the paths which are checked for the configuration file. ## ## Blank lines, or lines starting with a comment symbol, are ignored, as are ## trailing comments. Other lines must have the format: ## key: val # optional comment ## ## Formatting: Use PEP8-like style (as enforced in the rest of the codebase). ## All lines start with an additional '#', so that removing all leading '#'s ## yields a valid style file. ## ## Colors: for the color values below, you can either use ## - a Matplotlib color string, such as r, k, or b ## - an RGB tuple, such as (1.0, 0.5, 0.0) ## - a hex string, such as ff00ff ## - a scalar grayscale intensity such as 0.75 ## - a legal html color name, e.g., red, blue, darkslategray ## ## Matplotlib configuration are currently divided into following parts: ## - BACKENDS ## - LINES ## - PATCHES ## - HATCHES ## - BOXPLOT ## - FONT ## - TEXT ## - LaTeX ## - AXES ## - DATES ## - TICKS ## - GRIDS ## - LEGEND ## - FIGURE ## - IMAGES ## - CONTOUR PLOTS ## - ERRORBAR PLOTS ## - HISTOGRAM PLOTS ## - SCATTER PLOTS ## - AGG RENDERING ## - PATHS ## - SAVING FIGURES ## - INTERACTIVE KEYMAPS ## - ANIMATION ##### CONFIGURATION BEGINS HERE ## *************************************************************************** ## * BACKENDS * ## *************************************************************************** ## The default backend. If you omit this parameter, the first working ## backend from the following list is used: ## MacOSX QtAgg Gtk4Agg Gtk3Agg TkAgg WxAgg Agg ## Other choices include: ## QtCairo GTK4Cairo GTK3Cairo TkCairo WxCairo Cairo ## Qt5Agg Qt5Cairo Wx # deprecated. ## PS PDF SVG Template ## You can also deploy your own backend outside of Matplotlib by referring to ## the module name (which must be in the PYTHONPATH) as 'module://my_backend'. ##backend: Agg ## The port to use for the web server in the WebAgg backend. #webagg.port: 8988 ## The address on which the WebAgg web server should be reachable #webagg.address: 127.0.0.1 ## If webagg.port is unavailable, a number of other random ports will ## be tried until one that is available is found. #webagg.port_retries: 50 ## When True, open the web browser to the plot that is shown #webagg.open_in_browser: True ## If you are running pyplot inside a GUI and your backend choice ## conflicts, we will automatically try to find a compatible one for ## you if backend_fallback is True #backend_fallback: True #interactive: False #toolbar: toolbar2 # {None, toolbar2, toolmanager} #timezone: UTC # a pytz timezone string, e.g., US/Central or Europe/Paris ## *************************************************************************** ## * LINES * ## *************************************************************************** ## See https://matplotlib.org/api/artist_api.html#module-matplotlib.lines ## for more information on line properties. #lines.linewidth: 1.5 # line width in points #lines.linestyle: - # solid line #lines.color: C0 # has no affect on plot(); see axes.prop_cycle #lines.marker: None # the default marker #lines.markerfacecolor: auto # the default marker face color #lines.markeredgecolor: auto # the default marker edge color #lines.markeredgewidth: 1.0 # the line width around the marker symbol #lines.markersize: 6 # marker size, in points #lines.dash_joinstyle: round # {miter, round, bevel} #lines.dash_capstyle: butt # {butt, round, projecting} #lines.solid_joinstyle: round # {miter, round, bevel} #lines.solid_capstyle: projecting # {butt, round, projecting} #lines.antialiased: True # render lines in antialiased (no jaggies) ## The three standard dash patterns. These are scaled by the linewidth. #lines.dashed_pattern: 3.7, 1.6 #lines.dashdot_pattern: 6.4, 1.6, 1, 1.6 #lines.dotted_pattern: 1, 1.65 #lines.scale_dashes: True #markers.fillstyle: full # {full, left, right, bottom, top, none} #pcolor.shading: auto #pcolormesh.snap: True # Whether to snap the mesh to pixel boundaries. This is # provided solely to allow old test images to remain # unchanged. Set to False to obtain the previous behavior. ## *************************************************************************** ## * PATCHES * ## *************************************************************************** ## Patches are graphical objects that fill 2D space, like polygons or circles. ## See https://matplotlib.org/api/artist_api.html#module-matplotlib.patches ## for more information on patch properties. #patch.linewidth: 1 # edge width in points. #patch.facecolor: C0 #patch.edgecolor: black # if forced, or patch is not filled #patch.force_edgecolor: False # True to always use edgecolor #patch.antialiased: True # render patches in antialiased (no jaggies) ## *************************************************************************** ## * HATCHES * ## *************************************************************************** #hatch.color: black #hatch.linewidth: 1.0 ## *************************************************************************** ## * BOXPLOT * ## *************************************************************************** #boxplot.notch: False #boxplot.vertical: True #boxplot.whiskers: 1.5 #boxplot.bootstrap: None #boxplot.patchartist: False #boxplot.showmeans: False #boxplot.showcaps: True #boxplot.showbox: True #boxplot.showfliers: True #boxplot.meanline: False #boxplot.flierprops.color: black #boxplot.flierprops.marker: o #boxplot.flierprops.markerfacecolor: none #boxplot.flierprops.markeredgecolor: black #boxplot.flierprops.markeredgewidth: 1.0 #boxplot.flierprops.markersize: 6 #boxplot.flierprops.linestyle: none #boxplot.flierprops.linewidth: 1.0 #boxplot.boxprops.color: black #boxplot.boxprops.linewidth: 1.0 #boxplot.boxprops.linestyle: - #boxplot.whiskerprops.color: black #boxplot.whiskerprops.linewidth: 1.0 #boxplot.whiskerprops.linestyle: - #boxplot.capprops.color: black #boxplot.capprops.linewidth: 1.0 #boxplot.capprops.linestyle: - #boxplot.medianprops.color: C1 #boxplot.medianprops.linewidth: 1.0 #boxplot.medianprops.linestyle: - #boxplot.meanprops.color: C2 #boxplot.meanprops.marker: ^ #boxplot.meanprops.markerfacecolor: C2 #boxplot.meanprops.markeredgecolor: C2 #boxplot.meanprops.markersize: 6 #boxplot.meanprops.linestyle: -- #boxplot.meanprops.linewidth: 1.0 ## *************************************************************************** ## * FONT * ## *************************************************************************** ## The font properties used by text.Text. ## See https://matplotlib.org/api/font_manager_api.html for more information ## on font properties. The 6 font properties used for font matching are ## given below with their default values. ## ## The font.family property can take either a concrete font name (not supported ## when rendering text with usetex), or one of the following five generic ## values: ## - 'serif' (e.g., Times), ## - 'sans-serif' (e.g., Helvetica), ## - 'cursive' (e.g., Zapf-Chancery), ## - 'fantasy' (e.g., Western), and ## - 'monospace' (e.g., Courier). ## Each of these values has a corresponding default list of font names ## (font.serif, etc.); the first available font in the list is used. Note that ## for font.serif, font.sans-serif, and font.monospace, the first element of ## the list (a DejaVu font) will always be used because DejaVu is shipped with ## Matplotlib and is thus guaranteed to be available; the other entries are ## left as examples of other possible values. ## ## The font.style property has three values: normal (or roman), italic ## or oblique. The oblique style will be used for italic, if it is not ## present. ## ## The font.variant property has two values: normal or small-caps. For ## TrueType fonts, which are scalable fonts, small-caps is equivalent ## to using a font size of 'smaller', or about 83%% of the current font ## size. ## ## The font.weight property has effectively 13 values: normal, bold, ## bolder, lighter, 100, 200, 300, ..., 900. Normal is the same as ## 400, and bold is 700. bolder and lighter are relative values with ## respect to the current weight. ## ## The font.stretch property has 11 values: ultra-condensed, ## extra-condensed, condensed, semi-condensed, normal, semi-expanded, ## expanded, extra-expanded, ultra-expanded, wider, and narrower. This ## property is not currently implemented. ## ## The font.size property is the default font size for text, given in points. ## 10 pt is the standard value. ## ## Note that font.size controls default text sizes. To configure ## special text sizes tick labels, axes, labels, title, etc., see the rc ## settings for axes and ticks. Special text sizes can be defined ## relative to font.size, using the following values: xx-small, x-small, ## small, medium, large, x-large, xx-large, larger, or smaller #font.family: sans-serif #font.style: normal #font.variant: normal #font.weight: normal #font.stretch: normal #font.size: 10.0 #font.serif: DejaVu Serif, Bitstream Vera Serif, Computer Modern Roman, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif #font.sans-serif: DejaVu Sans, Bitstream Vera Sans, Computer Modern Sans Serif, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif #font.cursive: Apple Chancery, Textile, Zapf Chancery, Sand, Script MT, Felipa, Comic Neue, Comic Sans MS, cursive #font.fantasy: Chicago, Charcoal, Impact, Western, Humor Sans, xkcd, fantasy #font.monospace: DejaVu Sans Mono, Bitstream Vera Sans Mono, Computer Modern Typewriter, Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace ## *************************************************************************** ## * TEXT * ## *************************************************************************** ## The text properties used by text.Text. ## See https://matplotlib.org/api/artist_api.html#module-matplotlib.text ## for more information on text properties #text.color: black ## FreeType hinting flag ("foo" corresponds to FT_LOAD_FOO); may be one of the ## following (Proprietary Matplotlib-specific synonyms are given in parentheses, ## but their use is discouraged): ## - default: Use the font's native hinter if possible, else FreeType's auto-hinter. ## ("either" is a synonym). ## - no_autohint: Use the font's native hinter if possible, else don't hint. ## ("native" is a synonym.) ## - force_autohint: Use FreeType's auto-hinter. ("auto" is a synonym.) ## - no_hinting: Disable hinting. ("none" is a synonym.) #text.hinting: force_autohint #text.hinting_factor: 8 # Specifies the amount of softness for hinting in the # horizontal direction. A value of 1 will hint to full # pixels. A value of 2 will hint to half pixels etc. #text.kerning_factor: 0 # Specifies the scaling factor for kerning values. This # is provided solely to allow old test images to remain # unchanged. Set to 6 to obtain previous behavior. # Values other than 0 or 6 have no defined meaning. #text.antialiased: True # If True (default), the text will be antialiased. # This only affects raster outputs. ## *************************************************************************** ## * LaTeX * ## *************************************************************************** ## For more information on LaTeX properties, see ## https://matplotlib.org/tutorials/text/usetex.html #text.usetex: False # use latex for all text handling. The following fonts # are supported through the usual rc parameter settings: # new century schoolbook, bookman, times, palatino, # zapf chancery, charter, serif, sans-serif, helvetica, # avant garde, courier, monospace, computer modern roman, # computer modern sans serif, computer modern typewriter #text.latex.preamble: # IMPROPER USE OF THIS FEATURE WILL LEAD TO LATEX FAILURES # AND IS THEREFORE UNSUPPORTED. PLEASE DO NOT ASK FOR HELP # IF THIS FEATURE DOES NOT DO WHAT YOU EXPECT IT TO. # text.latex.preamble is a single line of LaTeX code that # will be passed on to the LaTeX system. It may contain # any code that is valid for the LaTeX "preamble", i.e. # between the "\documentclass" and "\begin{document}" # statements. # Note that it has to be put on a single line, which may # become quite long. # The following packages are always loaded with usetex, # so beware of package collisions: # geometry, inputenc, type1cm. # PostScript (PSNFSS) font packages may also be # loaded, depending on your font settings. ## The following settings allow you to select the fonts in math mode. #mathtext.fontset: dejavusans # Should be 'dejavusans' (default), # 'dejavuserif', 'cm' (Computer Modern), 'stix', # 'stixsans' or 'custom' (unsupported, may go # away in the future) ## "mathtext.fontset: custom" is defined by the mathtext.bf, .cal, .it, ... ## settings which map a TeX font name to a fontconfig font pattern. (These ## settings are not used for other font sets.) #mathtext.bf: sans:bold #mathtext.cal: cursive #mathtext.it: sans:italic #mathtext.rm: sans #mathtext.sf: sans #mathtext.tt: monospace #mathtext.fallback: cm # Select fallback font from ['cm' (Computer Modern), 'stix' # 'stixsans'] when a symbol can not be found in one of the # custom math fonts. Select 'None' to not perform fallback # and replace the missing character by a dummy symbol. #mathtext.default: it # The default font to use for math. # Can be any of the LaTeX font names, including # the special name "regular" for the same font # used in regular text. ## *************************************************************************** ## * AXES * ## *************************************************************************** ## Following are default face and edge colors, default tick sizes, ## default font sizes for tick labels, and so on. See ## https://matplotlib.org/api/axes_api.html#module-matplotlib.axes #axes.facecolor: white # axes background color #axes.edgecolor: black # axes edge color #axes.linewidth: 0.8 # edge line width #axes.grid: False # display grid or not #axes.grid.axis: both # which axis the grid should apply to #axes.grid.which: major # grid lines at {major, minor, both} ticks #axes.titlelocation: center # alignment of the title: {left, right, center} #axes.titlesize: large # font size of the axes title #axes.titleweight: normal # font weight of title #axes.titlecolor: auto # color of the axes title, auto falls back to # text.color as default value #axes.titley: None # position title (axes relative units). None implies auto #axes.titlepad: 6.0 # pad between axes and title in points #axes.labelsize: medium # font size of the x and y labels #axes.labelpad: 4.0 # space between label and axis #axes.labelweight: normal # weight of the x and y labels #axes.labelcolor: black #axes.axisbelow: line # draw axis gridlines and ticks: # - below patches (True) # - above patches but below lines ('line') # - above all (False) #axes.formatter.limits: -5, 6 # use scientific notation if log10 # of the axis range is smaller than the # first or larger than the second #axes.formatter.use_locale: False # When True, format tick labels # according to the user's locale. # For example, use ',' as a decimal # separator in the fr_FR locale. #axes.formatter.use_mathtext: False # When True, use mathtext for scientific # notation. #axes.formatter.min_exponent: 0 # minimum exponent to format in scientific notation #axes.formatter.useoffset: True # If True, the tick label formatter # will default to labeling ticks relative # to an offset when the data range is # small compared to the minimum absolute # value of the data. #axes.formatter.offset_threshold: 4 # When useoffset is True, the offset # will be used when it can remove # at least this number of significant # digits from tick labels. #axes.spines.left: True # display axis spines #axes.spines.bottom: True #axes.spines.top: True #axes.spines.right: True #axes.unicode_minus: True # use Unicode for the minus symbol rather than hyphen. See # https://en.wikipedia.org/wiki/Plus_and_minus_signs#Character_codes #axes.prop_cycle: cycler('color', ['1f77b4', 'ff7f0e', '2ca02c', 'd62728', '9467bd', '8c564b', 'e377c2', '7f7f7f', 'bcbd22', '17becf']) # color cycle for plot lines as list of string color specs: # single letter, long name, or web-style hex # As opposed to all other parameters in this file, the color # values must be enclosed in quotes for this parameter, # e.g. '1f77b4', instead of 1f77b4. # See also https://matplotlib.org/tutorials/intermediate/color_cycle.html # for more details on prop_cycle usage. #axes.xmargin: .05 # x margin. See axes.Axes.margins #axes.ymargin: .05 # y margin. See axes.Axes.margins #axes.zmargin: .05 # z margin. See axes.Axes.margins #axes.autolimit_mode: data # If "data", use axes.xmargin and axes.ymargin as is. # If "round_numbers", after application of margins, axis # limits are further expanded to the nearest "round" number. #polaraxes.grid: True # display grid on polar axes #axes3d.grid: True # display grid on 3D axes ## *************************************************************************** ## * AXIS * ## *************************************************************************** #xaxis.labellocation: center # alignment of the xaxis label: {left, right, center} #yaxis.labellocation: center # alignment of the yaxis label: {bottom, top, center} ## *************************************************************************** ## * DATES * ## *************************************************************************** ## These control the default format strings used in AutoDateFormatter. ## Any valid format datetime format string can be used (see the python ## datetime for details). For example, by using: ## - '%%x' will use the locale date representation ## - '%%X' will use the locale time representation ## - '%%c' will use the full locale datetime representation ## These values map to the scales: ## {'year': 365, 'month': 30, 'day': 1, 'hour': 1/24, 'minute': 1 / (24 * 60)} #date.autoformatter.year: %Y #date.autoformatter.month: %Y-%m #date.autoformatter.day: %Y-%m-%d #date.autoformatter.hour: %m-%d %H #date.autoformatter.minute: %d %H:%M #date.autoformatter.second: %H:%M:%S #date.autoformatter.microsecond: %M:%S.%f ## The reference date for Matplotlib's internal date representation ## See https://matplotlib.org/examples/ticks_and_spines/date_precision_and_epochs.py #date.epoch: 1970-01-01T00:00:00 ## 'auto', 'concise': #date.converter: auto ## For auto converter whether to use interval_multiples: #date.interval_multiples: True ## *************************************************************************** ## * TICKS * ## *************************************************************************** ## See https://matplotlib.org/api/axis_api.html#matplotlib.axis.Tick #xtick.top: False # draw ticks on the top side #xtick.bottom: True # draw ticks on the bottom side #xtick.labeltop: False # draw label on the top #xtick.labelbottom: True # draw label on the bottom #xtick.major.size: 3.5 # major tick size in points #xtick.minor.size: 2 # minor tick size in points #xtick.major.width: 0.8 # major tick width in points #xtick.minor.width: 0.6 # minor tick width in points #xtick.major.pad: 3.5 # distance to major tick label in points #xtick.minor.pad: 3.4 # distance to the minor tick label in points #xtick.color: black # color of the ticks #xtick.labelcolor: inherit # color of the tick labels or inherit from xtick.color #xtick.labelsize: medium # font size of the tick labels #xtick.direction: out # direction: {in, out, inout} #xtick.minor.visible: False # visibility of minor ticks on x-axis #xtick.major.top: True # draw x axis top major ticks #xtick.major.bottom: True # draw x axis bottom major ticks #xtick.minor.top: True # draw x axis top minor ticks #xtick.minor.bottom: True # draw x axis bottom minor ticks #xtick.alignment: center # alignment of xticks #ytick.left: True # draw ticks on the left side #ytick.right: False # draw ticks on the right side #ytick.labelleft: True # draw tick labels on the left side #ytick.labelright: False # draw tick labels on the right side #ytick.major.size: 3.5 # major tick size in points #ytick.minor.size: 2 # minor tick size in points #ytick.major.width: 0.8 # major tick width in points #ytick.minor.width: 0.6 # minor tick width in points #ytick.major.pad: 3.5 # distance to major tick label in points #ytick.minor.pad: 3.4 # distance to the minor tick label in points #ytick.color: black # color of the ticks #ytick.labelcolor: inherit # color of the tick labels or inherit from ytick.color #ytick.labelsize: medium # font size of the tick labels #ytick.direction: out # direction: {in, out, inout} #ytick.minor.visible: False # visibility of minor ticks on y-axis #ytick.major.left: True # draw y axis left major ticks #ytick.major.right: True # draw y axis right major ticks #ytick.minor.left: True # draw y axis left minor ticks #ytick.minor.right: True # draw y axis right minor ticks #ytick.alignment: center_baseline # alignment of yticks ## *************************************************************************** ## * GRIDS * ## *************************************************************************** #grid.color: b0b0b0 # grid color #grid.linestyle: - # solid #grid.linewidth: 0.8 # in points #grid.alpha: 1.0 # transparency, between 0.0 and 1.0 ## *************************************************************************** ## * LEGEND * ## *************************************************************************** #legend.loc: best #legend.frameon: True # if True, draw the legend on a background patch #legend.framealpha: 0.8 # legend patch transparency #legend.facecolor: inherit # inherit from axes.facecolor; or color spec #legend.edgecolor: 0.8 # background patch boundary color #legend.fancybox: True # if True, use a rounded box for the # legend background, else a rectangle #legend.shadow: False # if True, give background a shadow effect #legend.numpoints: 1 # the number of marker points in the legend line #legend.scatterpoints: 1 # number of scatter points #legend.markerscale: 1.0 # the relative size of legend markers vs. original #legend.fontsize: medium #legend.labelcolor: None #legend.title_fontsize: None # None sets to the same as the default axes. ## Dimensions as fraction of font size: #legend.borderpad: 0.4 # border whitespace #legend.labelspacing: 0.5 # the vertical space between the legend entries #legend.handlelength: 2.0 # the length of the legend lines #legend.handleheight: 0.7 # the height of the legend handle #legend.handletextpad: 0.8 # the space between the legend line and legend text #legend.borderaxespad: 0.5 # the border between the axes and legend edge #legend.columnspacing: 2.0 # column separation ## *************************************************************************** ## * FIGURE * ## *************************************************************************** ## See https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure #figure.titlesize: large # size of the figure title (Figure.suptitle()) #figure.titleweight: normal # weight of the figure title #figure.figsize: 6.4, 4.8 # figure size in inches #figure.dpi: 100 # figure dots per inch #figure.facecolor: white # figure face color #figure.edgecolor: white # figure edge color #figure.frameon: True # enable figure frame #figure.max_open_warning: 20 # The maximum number of figures to open through # the pyplot interface before emitting a warning. # If less than one this feature is disabled. #figure.raise_window : True # Raise the GUI window to front when show() is called. ## The figure subplot parameters. All dimensions are a fraction of the figure width and height. #figure.subplot.left: 0.125 # the left side of the subplots of the figure #figure.subplot.right: 0.9 # the right side of the subplots of the figure #figure.subplot.bottom: 0.11 # the bottom of the subplots of the figure #figure.subplot.top: 0.88 # the top of the subplots of the figure #figure.subplot.wspace: 0.2 # the amount of width reserved for space between subplots, # expressed as a fraction of the average axis width #figure.subplot.hspace: 0.2 # the amount of height reserved for space between subplots, # expressed as a fraction of the average axis height ## Figure layout #figure.autolayout: False # When True, automatically adjust subplot # parameters to make the plot fit the figure # using tight_layout #figure.constrained_layout.use: False # When True, automatically make plot # elements fit on the figure. (Not # compatible with autolayout, above). #figure.constrained_layout.h_pad: 0.04167 # Padding around axes objects. Float representing #figure.constrained_layout.w_pad: 0.04167 # inches. Default is 3/72 inches (3 points) #figure.constrained_layout.hspace: 0.02 # Space between subplot groups. Float representing #figure.constrained_layout.wspace: 0.02 # a fraction of the subplot widths being separated. ## *************************************************************************** ## * IMAGES * ## *************************************************************************** #image.aspect: equal # {equal, auto} or a number #image.interpolation: antialiased # see help(imshow) for options #image.cmap: viridis # A colormap name, gray etc... #image.lut: 256 # the size of the colormap lookup table #image.origin: upper # {lower, upper} #image.resample: True #image.composite_image: True # When True, all the images on a set of axes are # combined into a single composite image before # saving a figure as a vector graphics file, # such as a PDF. ## *************************************************************************** ## * CONTOUR PLOTS * ## *************************************************************************** #contour.negative_linestyle: dashed # string or on-off ink sequence #contour.corner_mask: True # {True, False, legacy} #contour.linewidth: None # {float, None} Size of the contour line # widths. If set to None, it falls back to # line.linewidth. ## *************************************************************************** ## * ERRORBAR PLOTS * ## *************************************************************************** #errorbar.capsize: 0 # length of end cap on error bars in pixels ## *************************************************************************** ## * HISTOGRAM PLOTS * ## *************************************************************************** #hist.bins: 10 # The default number of histogram bins or 'auto'. ## *************************************************************************** ## * SCATTER PLOTS * ## *************************************************************************** #scatter.marker: o # The default marker type for scatter plots. #scatter.edgecolors: face # The default edge colors for scatter plots. ## *************************************************************************** ## * AGG RENDERING * ## *************************************************************************** ## Warning: experimental, 2008/10/10 #agg.path.chunksize: 0 # 0 to disable; values in the range # 10000 to 100000 can improve speed slightly # and prevent an Agg rendering failure # when plotting very large data sets, # especially if they are very gappy. # It may cause minor artifacts, though. # A value of 20000 is probably a good # starting point. ## *************************************************************************** ## * PATHS * ## *************************************************************************** #path.simplify: True # When True, simplify paths by removing "invisible" # points to reduce file size and increase rendering # speed #path.simplify_threshold: 0.111111111111 # The threshold of similarity below # which vertices will be removed in # the simplification process. #path.snap: True # When True, rectilinear axis-aligned paths will be snapped # to the nearest pixel when certain criteria are met. # When False, paths will never be snapped. #path.sketch: None # May be None, or a 3-tuple of the form: # (scale, length, randomness). # - *scale* is the amplitude of the wiggle # perpendicular to the line (in pixels). # - *length* is the length of the wiggle along the # line (in pixels). # - *randomness* is the factor by which the length is # randomly scaled. #path.effects: ## *************************************************************************** ## * SAVING FIGURES * ## *************************************************************************** ## The default savefig parameters can be different from the display parameters ## e.g., you may want a higher resolution, or to make the figure ## background white #savefig.dpi: figure # figure dots per inch or 'figure' #savefig.facecolor: auto # figure face color when saving #savefig.edgecolor: auto # figure edge color when saving #savefig.format: png # {png, ps, pdf, svg} #savefig.bbox: standard # {tight, standard} # 'tight' is incompatible with pipe-based animation # backends (e.g. 'ffmpeg') but will work with those # based on temporary files (e.g. 'ffmpeg_file') #savefig.pad_inches: 0.1 # Padding to be used when bbox is set to 'tight' #savefig.directory: ~ # default directory in savefig dialog box, # leave empty to always use current working directory #savefig.transparent: False # setting that controls whether figures are saved with a # transparent background by default #savefig.orientation: portrait # Orientation of saved figure ### tk backend params #tk.window_focus: False # Maintain shell focus for TkAgg ### ps backend params #ps.papersize: letter # {auto, letter, legal, ledger, A0-A10, B0-B10} #ps.useafm: False # use of AFM fonts, results in small files #ps.usedistiller: False # {ghostscript, xpdf, None} # Experimental: may produce smaller files. # xpdf intended for production of publication quality files, # but requires ghostscript, xpdf and ps2eps #ps.distiller.res: 6000 # dpi #ps.fonttype: 3 # Output Type 3 (Type3) or Type 42 (TrueType) ### PDF backend params #pdf.compression: 6 # integer from 0 to 9 # 0 disables compression (good for debugging) #pdf.fonttype: 3 # Output Type 3 (Type3) or Type 42 (TrueType) #pdf.use14corefonts: False #pdf.inheritcolor: False ### SVG backend params #svg.image_inline: True # Write raster image data directly into the SVG file #svg.fonttype: path # How to handle SVG fonts: # path: Embed characters as paths -- supported # by most SVG renderers # None: Assume fonts are installed on the # machine where the SVG will be viewed. #svg.hashsalt: None # If not None, use this string as hash salt instead of uuid4 ### pgf parameter ## See https://matplotlib.org/tutorials/text/pgf.html for more information. #pgf.rcfonts: True #pgf.preamble: # See text.latex.preamble for documentation #pgf.texsystem: xelatex ### docstring params #docstring.hardcopy: False # set this when you want to generate hardcopy docstring ## *************************************************************************** ## * INTERACTIVE KEYMAPS * ## *************************************************************************** ## Event keys to interact with figures/plots via keyboard. ## See https://matplotlib.org/users/navigation_toolbar.html for more details on ## interactive navigation. Customize these settings according to your needs. ## Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '') #keymap.fullscreen: f, ctrl+f # toggling #keymap.home: h, r, home # home or reset mnemonic #keymap.back: left, c, backspace, MouseButton.BACK # forward / backward keys #keymap.forward: right, v, MouseButton.FORWARD # for quick navigation #keymap.pan: p # pan mnemonic #keymap.zoom: o # zoom mnemonic #keymap.save: s, ctrl+s # saving current figure #keymap.help: f1 # display help about active tools #keymap.quit: ctrl+w, cmd+w, q # close the current figure #keymap.quit_all: # close all figures #keymap.grid: g # switching on/off major grids in current axes #keymap.grid_minor: G # switching on/off minor grids in current axes #keymap.yscale: l # toggle scaling of y-axes ('log'/'linear') #keymap.xscale: k, L # toggle scaling of x-axes ('log'/'linear') #keymap.copy: ctrl+c, cmd+c # copy figure to clipboard ## *************************************************************************** ## * ANIMATION * ## *************************************************************************** #animation.html: none # How to display the animation as HTML in # the IPython notebook: # - 'html5' uses HTML5 video tag # - 'jshtml' creates a JavaScript animation #animation.writer: ffmpeg # MovieWriter 'backend' to use #animation.codec: h264 # Codec to use for writing movie #animation.bitrate: -1 # Controls size/quality trade-off for movie. # -1 implies let utility auto-determine #animation.frame_format: png # Controls frame format used by temp files #animation.ffmpeg_path: ffmpeg # Path to ffmpeg binary. Without full path #PATH is searched
#animation.ffmpeg_args:           # Additional arguments to pass to ffmpeg
#animation.convert_path: convert  # Path to ImageMagick's convert binary.
# On Windows use the full path since convert
# is also the name of a system tool.
#animation.convert_args:          # Additional arguments to pass to convert
#animation.embed_limit:  20.0     # Limit, in MB, of size of base64 encoded
# animation in HTML (i.e. IPython notebook)

Well I found out what happened. It is due to work with two different fragment managers (FragmentManager and SupportFragmentManager).
Depend on the fragment type (support or normal) you want to remove or replace you have to use one or another fragment manager.
I have created an enum to know what kind of fragment is active (in order to remove) and what kind of fragment is going to start (in order to replace).
More or less I made a function like this:

private void manageFragment (FragmentEnum nextFragment) {

switch (activedFragment) {
case SUPPORT:
getSupportFragmentManager().beginTransaction().remove(fragmentSupport).commit();
break;
case NORMAL:
getFragmentManager().beginTransaction().remove(fragmentNormal).commit();
break;
}

activedFragment = nextFragment;

switch (nextFragment) {
case SUPPORT:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentSupport).commit();
break;
case NORMAL:
getFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentNormal).commit();
break;
}
}


As it says you have a duplicate in your sources list. How you fix this can depend on the Package Manager(s) that you use. To go straight to the sources list, open a Terminal and issue the command:

Look for the duplicate. You can disable one by putting a # at the beginning of the line or removing duplicate lines.

gksudo gedit /etc/apt/sources.list

http://archive.canonical.com/ubuntu/ oneiric/partner

This FFmeeting was hosted on ​irc://irc.freenode.net/ffmpeg-meeting on January 11, 2014, at 16 UTC.

**** BEGIN LOGGING AT Sat Jan 11 14:53:47 2014

Jan 11 14:53:47 *	Now talking on #ffmpeg-meeting
Jan 11 14:53:48 *	cameron.freenode.net sets mode +n #ffmpeg-meeting
Jan 11 14:53:48 *	cameron.freenode.net sets mode +s #ffmpeg-meeting
Jan 11 14:55:26 *	BBB (~rbultje <at> abraxo.bluebottle.net.au) has joined #ffmpeg-meeting
Jan 11 14:58:54 *	Compn (~notabot <at> 97.69.215.70) has joined #ffmpeg-meeting
Jan 11 14:59:02 <Compn>	how many hours til it starts again ?
Jan 11 15:01:32 *	ubitux (~ux <at> did75-21-88-189-231-41.fbx.proxad.net) has joined #ffmpeg-meeting
Jan 11 15:08:22 *	michaelni (~michael <at> chello084114129144.4.15.vie.surfer.at) has joined #ffmpeg-meeting
Jan 11 15:12:26 <michaelni>	saste, do we have some list of topics for the meeting today ? if so maybe link to it in the /topic
Jan 11 15:31:31 *	easyfab (~chatzilla <at> 213-245-142-93.rev.numericable.fr) has joined #ffmpeg-meeting
Jan 11 15:31:39 *	easyfab (~chatzilla <at> 213-245-142-93.rev.numericable.fr) has left #ffmpeg-meeting
Jan 11 15:34:24 *	easyfab (~chatzilla <at> 213-245-142-93.rev.numericable.fr) has joined #ffmpeg-meeting
Jan 11 15:35:36 *	kriegerod (~krieger <at> vpk-vityaz.od.ua) has joined #ffmpeg-meeting
Jan 11 15:35:41 *	beastd (~Akero7 <at> p5B06F187.dip0.t-ipconnect.de) has joined #ffmpeg-meeting
Jan 11 15:36:08 <beastd>	hi all. sorry i misremembered the time to be an hour later :(
Jan 11 15:40:09 *	wm4 (~wm4 <at> ip-static-94-242-209-206.as5577.net) has joined #ffmpeg-meeting
Jan 11 15:42:12 *	nevcairiel (quassel <at> WoWUIDev/WoWAce/Ace3/nevcairiel) has joined #ffmpeg-meeting
Jan 11 15:42:31 <michaelni>	saste, please add "this channel is publically logged in the topic" to the topic, i think IIRC thats supposed to be there for such channels
Jan 11 15:42:52 <michaelni>	s/ in the topic//
Jan 11 15:43:14 *	kurosu_ (5545746f <at> gateway/web/freenode/ip.85.69.116.111) has joined #ffmpeg-meeting
Jan 11 15:49:43 *	cbsrobot_ (~cbsrobot <at> 147.88.200.144) has joined #ffmpeg-meeting
Jan 11 15:49:49 *	cbsrobot_ has quit (Client Quit)
Jan 11 15:50:11 *	cbsrobot_ (~cbsrobot <at> 147.88.200.144) has joined #ffmpeg-meeting
Jan 11 16:07:41 *	saste has changed the topic to: The meeting will begin at 16 UTC - this channel is publically logged
Jan 11 16:07:59 <saste>	michaelni, done
Jan 11 16:08:26 <michaelni>	thx
Jan 11 16:17:08 *	Topic for #ffmpeg-meeting is: The meeting will begin at 16 UTC - this channel is publically logged
Jan 11 16:17:08 *	Topic for #ffmpeg-meeting set by saste!~saste___ <at> dynamic-adsl-78-15-163-248.clienti.tiscali.it at Sat Jan 11 16:07:41 2014
Jan 11 16:17:17 *	smarter (~smarter <at> ubuntu/member/smarter) has joined #ffmpeg-meeting
Jan 11 16:18:14 *	saste has changed the topic to: The meeting will begin at 16 UTC - Topics: http://paste.org/69739 - This channel is publically logged, the log will be published on ffmpeg-devel
Jan 11 16:31:08 *	kurosu_ has quit (Quit: Page closed)
Jan 11 16:49:23 *	Cigaes (cigaes <at> ssecem.salle-s.org) has joined #ffmpeg-meeting
Jan 11 16:50:12 *	Timothy_Gu (~Timothy_G <at> ip70-187-186-217.oc.oc.cox.net) has joined #ffmpeg-meeting
Jan 11 16:53:08 *	Eventh- (5f22de4b <at> gateway/web/freenode/ip.95.34.222.75) has joined #ffmpeg-meeting
Jan 11 16:54:31 <saste>	5 minutes to go
Jan 11 16:58:26 *	rmklp (~krueger <at> ip-178-200-241-251.unitymediagroup.de) has joined #ffmpeg-meeting
Jan 11 16:59:43 *	pross-au (~xbmc <at> c114-76-138-51.sunsh2.vic.optusnet.com.au) has joined #ffmpeg-meeting
Jan 11 17:00:53 *	j-b (~jb <at> videolan/developer/j-b) has joined #ffmpeg-meeting
Jan 11 17:02:17 <saste>	hi all, thanks for joining
Jan 11 17:02:25 <saste>	i think it is time to start
Jan 11 17:02:52 <saste>	you can find the list of topics here:  http://paste.org/69739
Jan 11 17:03:16 <saste>	first topic: 1. technical issues, TODOs, long term projects
Jan 11 17:03:30 <saste>	who wants to start?
Jan 11 17:05:18 <kriegerod>	maybe the one who added this item to list?
Jan 11 17:05:51 <saste>	i have a list of topics left from the previous meeting, nothing specifically i want to discuss
Jan 11 17:06:12 <kriegerod>	seems others are idle, too
Jan 11 17:06:14 <pross-au>	re long term stuff. are there any such projects active atm?
Jan 11 17:06:17 <saste>	there were some devs who wanted to talk about some technical issues, but i think they are missing
Jan 11 17:06:31 <michaelni>	i wanted to ask beastd& lou about the status of backups (i think thats technical
Jan 11 17:06:36 <michaelni>	but lou isnt here
Jan 11 17:06:36 <saste>	from the list in the previous meeting:
Jan 11 17:06:40 <saste>	1. mpegts/H.264 muxing/timestamp issues
Jan 11 17:06:54 <saste>	2.  playlist design issues and issues related to chained muxers option passing
Jan 11 17:07:04 <saste>	3.  ffserver generic issues
Jan 11 17:07:17 <saste>	4. ffserver RTMP/HLS missing output support
Jan 11 17:07:26 <saste>	btw anyone interested in working with ffserver?
Jan 11 17:07:52 <wm4>	I thought everyone hated ffserver and wanted to remove it
Jan 11 17:08:13 <michaelni>	i like ffserver but my todo is too long to really work on it
Jan 11 17:08:20 <saste>	i did some documentation/cleanup work on ffserver, it's not as bad as I thought
Jan 11 17:08:24 <Cigaes>	ffserver is useful. Removing something useful just because nobody wants to maintain it is not something to do.
Jan 11 17:08:36 <saste>	most open tickets can be easily reproduced
Jan 11 17:08:42 <wm4>	then it'll have to continue sucking, I guess
Jan 11 17:08:46 <kriegerod>	i could, but cannot afford doing anything such unpaid
Jan 11 17:09:10 <saste>	the network problem I talkled about on list, I couldn't still resolve it
Jan 11 17:09:28 <ubitux>	i'd like to know what's going on with fate btw
Jan 11 17:09:38 <ubitux>	didn't someone planed some stuff about it?
Jan 11 17:09:40 <saste>	ffserver could be the object of some crowdfunding campaign, we can talk about it later
Jan 11 17:09:52 <saste>	ubitux, what's the problem with fate?
Jan 11 17:10:20 <ubitux>	i remember michaelni wanting someone to maintain it/upgrade our fate
Jan 11 17:10:32 <ubitux>	maybe related to recent security issues
Jan 11 17:10:39 <saste>	is baptiste still maintaining fate?
Jan 11 17:10:58 *	saste knows nothing about the recent security issues
Jan 11 17:11:17 <michaelni>	cross site scripting, no real issue AFAIK
Jan 11 17:11:24 <saste>	any news about the re-styling burek was working on?
Jan 11 17:12:19 <michaelni>	but even if its not a real issue a volunteer to maintain the fateserver code would be great to have
Jan 11 17:12:31 <saste>	michaelni, what needs to be done?
Jan 11 17:12:45 <saste>	in other words, what the volunteer is supposed to do specifically?
Jan 11 17:13:05 <michaelni>	update it to the latest of mans code and have time to fix&debug any thing that goes wrong
Jan 11 17:13:22 <saste>	any taker?
Jan 11 17:13:23 <michaelni>	and then if the cross site scripting issue is still there, fix it
Jan 11 17:15:38 <michaelni>	"fix&debug any thing that goes wrong" == "anything that goes wrong because of the update"
Jan 11 17:16:08 <saste>	michaelni, where the fate source code can be found?
Jan 11 17:16:27 <saste>	should we advertise it on the website/download page?
Jan 11 17:16:59 <michaelni>	ours at https://github.com/ffmpeg/fateserver / git://git.ffmpeg.org/fateserver
Jan 11 17:17:17 <saste>	is it listed on the download page?
Jan 11 17:17:17 <Compn>	ask mans if you link to mans' repo of course
Jan 11 17:18:11 <michaelni>	saste, seems not listed
Jan 11 17:18:17 <Compn>	it would also be neat if we added the ffmpeg header page to fate page, if possible
Jan 11 17:18:26 <Compn>	so people can get back to ffmpeg homepage? maybe?
Jan 11 17:18:30 <saste>	nor could i find the link in doc/fate.texi
Jan 11 17:18:49 <saste>	Compn, yes
Jan 11 17:18:51 <michaelni>	does someone take notes of these todo things ?
Jan 11 17:19:12 <saste>	currently the FATE interface is rather "spartan"
Jan 11 17:19:30 <saste>	michaelni, we have a TODO file and trac
Jan 11 17:19:48 <saste>	no TODO was killed IIRC
Jan 11 17:20:17 <michaelni>	i meant someone should make a list of todo items from this meeting, maybe open trac tickets for each
Jan 11 17:21:29 <saste>	michaelni, i can send a patch to add FATE source repo to the download page
Jan 11 17:21:54 <saste>	anyway, so far for point 1.  technical issues, TODOs, long term projects
Jan 11 17:22:10 <beastd>	TODO file inside source repo is often not useful in my experience. tracking things in one or more tickets usually works better.
Jan 11 17:22:13 <michaelni>	saste, ok for patch
Jan 11 17:22:28 <saste>	anyone wants to discuss his TODO/long term projects?
Jan 11 17:22:47 <saste>	beastd, TODO was removed for that reason indeed
Jan 11 17:23:01 <Cigaes>	beastd: I agree, but there should be a link to "all open TODO tickets" easily accessible, for anyone wanting to work on something.
Jan 11 17:23:26 <saste>	Cigaes, TODO list = enhancements?
Jan 11 17:23:28 <beastd>	Cigaes: that should be done with a report
Jan 11 17:23:49 <saste>	BTW there is a reason for the "wish" priority on trac?
Jan 11 17:24:18 <saste>	I don't think "wish" is a priority", anyway that's not a very important issue and should probably not discussed here
Jan 11 17:24:48 <Cigaes>	saste: yes, something like that. But possibly only enhancements deemed worthy enough by... enough competent people.
Jan 11 17:25:13 <saste>	anyway i'd prefer to remove that priority level (indeed an enhancement can have several priority levels)
Jan 11 17:25:42 <michaelni>	we could add a todo keyword for these and a report for tickets with that keyword could be linke dto
Jan 11 17:26:08 <saste>	Cigaes, enhancements tickets can be reviewed and edited by competent developers
Jan 11 17:26:11 <Compn>	michaelni : after the meeting we will collect ideas and make bug reports, yes
Jan 11 17:26:17 <kriegerod>	a list of all unresolved tickets can be considered a TODO
Jan 11 17:26:29 *	Compn backlogged
Jan 11 17:26:45 <kriegerod>	what's strict criteria for inclusion of ticket to TODO category?
Jan 11 17:27:00 <saste>	any ticket is a TODO
Jan 11 17:27:04 <kriegerod>	project infracstructure related?
Jan 11 17:27:04 <Compn>	do we need strict criteria ? :P
Jan 11 17:27:15 <saste>	but there are some tickets which are more important than others
Jan 11 17:27:31 <saste>	"todo" as a tag is misleading imo
Jan 11 17:27:42 <kriegerod>	ok, so TODO = critical level tickets
Jan 11 17:27:56 <Cigaes>	saste: there are also tickets that are more demanding than other.
Jan 11 17:28:13 <Compn>	difficulty and importance
Jan 11 17:28:14 <beastd>	maybe the idea from michaelni is quite pragmatic. we could tag things with todo and list all tickets tagged todo with https://trac.ffmpeg.org/tags?q=%27todo%27
Jan 11 17:28:18 *	Compn runs from the bikeshed
Jan 11 17:29:02 <saste>	discussion slided from discussion about todos to discussion about what is "todo" ;)
Jan 11 17:29:47 <beastd>	yes, which ist the hardest part. but some fuzzy solution could be sufficient
Jan 11 17:29:59 <Cigaes>	beastd: this looks like a good solution, provided the "todo" tag is not added by a wandering user for their own whims.
Jan 11 17:30:28 <michaelni>	wandering users prefer to mark their tickets as critical
Jan 11 17:30:32 <saste>	beastd, btw what about a difficulty level or tag in trac?
Jan 11 17:31:00 <saste>	so wannabee ffdevs (assuming there are some) can easily spot the easy tickets to work on
Jan 11 17:31:31 <michaelni>	small age of a ticket might work for this too btw
Jan 11 17:31:38 <michaelni>	old tickets tend to be harder
Jan 11 17:32:14 <kriegerod>	...or less important
Jan 11 17:32:34 <michaelni>	yes
Jan 11 17:32:52 <saste>	Cigaes, what's the status of the lavd probing API?
Jan 11 17:33:24 <saste>	is lukasz still working on it or is it blocked for some reason?
Jan 11 17:33:38 <beastd>	saste: dfficulty can be done. either we add a new custom ticket field or now with tags. we would need on a convention either way
Jan 11 17:33:43 <Cigaes>	saste: that was more Lukasz's work. I did not have personal communication with him.
Jan 11 17:33:54 <saste>	Cigaes, ok
Jan 11 17:34:27 <saste>	so far for what concerns point 1. technical issues, TODOs, long term projects
Jan 11 17:34:38 <saste>	?
Jan 11 17:35:08 <saste>	do we have comments from external users?
Jan 11 17:35:30 <Cigaes>	I can mention the few items I have in my personal TODO list, if anyone is interested.
Jan 11 17:35:38 <saste>	Cigaes, go on
Jan 11 17:35:57 <Cigaes>	I have started working on frame-accurate EDL.
Jan 11 17:36:23 <saste>	status?
Jan 11 17:36:24 <Cigaes>	For now, it works without threads but not at all with threads. I am a bit stuck there, but I had no time to really investigate the issue yet.
Jan 11 17:37:22 <Compn>	so you can seek to a frame number ?
Jan 11 17:37:29 <Compn>	thats a highly requested feature
Jan 11 17:37:30 <ubitux>	what about the subtitles charset thing?
Jan 11 17:37:46 <Compn>	Cigaes : even without threads support it would be useful ...
Jan 11 17:37:47 <ubitux>	Cigaes: i think at least wm4 holds a grudge about your plan
Jan 11 17:37:57 <Cigaes>	Compn: to a timestamp. But for now only in selected muxers.
Jan 11 17:38:02 <Compn>	ah
Jan 11 17:38:28 <ubitux>	in the subtitles charset project i'm mainly interested in the utf-16 supports
Jan 11 17:38:33 <Cigaes>	ubitux: I am still convinced that his plan do not work at all.
Jan 11 17:38:35 <ubitux>	i think that's what mpv is expecting the most
Jan 11 17:39:00 <Compn>	rather hear what vlc wants charset wise
Jan 11 17:39:07 <Compn>	j-b : what charsets does vlc require ?
Jan 11 17:39:11 <Cigaes>	... but I am not motivated for arguing the issue.
Jan 11 17:39:12 <Compn>	for subs
Jan 11 17:39:38 <ubitux>	Cigaes: question is, do you have some WIP and plans about it?
Jan 11 17:39:55 <j-b>	Compn: none. We support everything. We prefer that the decoder outputs UTF-8, of course, but it does not matter.
Jan 11 17:40:23 <j-b>	Compn: iconv is a hard dependency of vlccore.
Jan 11 17:40:23 <Cigaes>	ubitux: all I have WIP was posted on the mailing-list a long time ago and buried under bikeshedding.
Jan 11 17:40:49 <michaelni>	Cigaes, ubitux my main concern with the "charset issue" is that it appeared deadlocked with noone working on it
Jan 11 17:41:07 <ubitux>	ok
Jan 11 17:41:48 <michaelni>	Cigaes, or said diferently it appeared IIRC that noone wanted to work on your design and you also where too busy
Jan 11 17:41:55 <Cigaes>	I am willing to work on it, but I can not progress if the only voice on the ML says I am doing wrong.
Jan 11 17:42:43 <michaelni>	its difficult for me ATM to argue about it as iam a bit unprepared and half forgot the details of the "charset issue"
Jan 11 17:43:28 *	cbsrobot_ has quit (Remote host closed the connection)
Jan 11 17:43:53 <Cigaes>	I can try to write a summary about the status of the thing on the mailing list.
Jan 11 17:44:44 <saste>	Cigaes, or you ping people if you need someone to review/comment on your work
Jan 11 17:44:48 <saste>	that sometimes work
Jan 11 17:45:18 <saste>	other medium/long term projects were mentioned in the previous meeting:
Jan 11 17:45:20 <michaelni>	what i remember and that may be unrelated actually is that i felt it would be nice if decoders/demuxers could return subtitles without knowing the charset and leaving it to players to detect/interpret the text
Jan 11 17:45:24 <Cigaes>	saste: I will see if there are pingable pending mails.
Jan 11 17:45:32 <saste>	1. remaining mp filters port
Jan 11 17:45:43 <saste>	2. language binding creation (through SWIG or similar)
Jan 11 17:45:51 <michaelni>	Cigaes, and yes, a summary would be nice, it would be a pitty if the thing is deadlocked in bikeshed
Jan 11 17:45:52 <saste>	3. high level API creation
Jan 11 17:46:03 <saste>	4.  EDL support
Jan 11 17:46:20 <beastd>	I have another proposal for TODO
Jan 11 17:47:05 <beastd>	concerning ffmpeg CLI there is the frequent need to concatenate files. ffmpeg has gotten much better in doing it, but at least we lack a simple-to-use user interface. (short term the faq entry should be rewritten once more.) Long/mid term would be designing and implementing a user interface in ffmpeg to allow for easy concatenation.
Jan 11 17:47:08 <Cigaes>	saste: is 4 what I was talking abut a bit earlier.
Jan 11 17:47:45 <michaelni>	beastd, this sounds related to playlists
Jan 11 17:47:49 <saste>	Cigaes, yes I noticed
Jan 11 17:47:56 <beastd>	it is something users frequently do. a start would be someone thinking about a design and sending it as RFC to ffmpeg-devel ML
Jan 11 17:48:05 <beastd>	michaelni: could be related
Jan 11 17:48:12 <Compn>	beastd : make it as easy as multiple files with mencoder ?
Jan 11 17:48:21 <michaelni>	beastd, if you could specify a list of files to play then you basically have concatenation
Jan 11 17:48:23 <wm4>	about subtitles, yes, the only thing that's missing is utf-16 support
Jan 11 17:48:32 <Compn>	we need playlist support :)
Jan 11 17:49:08 <ubitux>	what do you mean by "playlist support"? don't we support already various playlists?
Jan 11 17:49:10 <Compn>	wm4 : do we have rar subs support? (playing files in rars or rar'd vobsubs) ?
Jan 11 17:49:21 <wm4>	no
Jan 11 17:49:24 <Cigaes>	Compn: we already have a lot of playlist formats support,
Jan 11 17:49:24 <kriegerod>	beastd, i think there's a class of existing apps that do that. Maybe we could google them up and highlight on some page? Anyway GUI tends to be standalone, that's different from "doing it by ffmpeg"
Jan 11 17:49:25 <saste>	about playlist, can't the concat demuxer be extended to support more playlist formats?
Jan 11 17:49:37 <wm4>	I know mplayer contains some extremely hideous code to invoke unrar on the fly
Jan 11 17:49:38 <Cigaes>	just no consistent way of validating access to other files.
Jan 11 17:49:43 <Compn>	saste : there was a patch in 2009 for that playlist api
Jan 11 17:49:59 <saste>	Compn, was that work on Anton?
Jan 11 17:50:04 <Compn>	no
Jan 11 17:50:05 <beastd>	kriegerod: true, we should look at other implementations
Jan 11 17:50:06 <wm4>	playlist parsers (as demuxers) would be nice
Jan 11 17:50:06 <Compn>	geza iirc
Jan 11 17:50:10 <saste>	we had a GSOC at some point, maybe it was after the fork
Jan 11 17:50:13 <Compn>	but i dont know who did original patch
Jan 11 17:50:25 <Compn>	someone said anton was working on it , but ... i dont see anything
Jan 11 17:50:37 <nevcairiel>	Antons GSOC was playlist support, before the fork, but it never really went anywhere :d
Jan 11 17:50:53 <Cigaes>	The concat demuxer can only work for files with very similar characteristics.
Jan 11 17:51:12 <Cigaes>	With "playlist support", users may want to mix very different files.
Jan 11 17:51:26 <Compn>	saste / ubitux / Cigaes : http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/94761
Jan 11 17:51:40 <Compn>	is the patch from 2009
Jan 11 17:52:47 <ubitux>	i'd better have ordered chapters in mkv…
Jan 11 17:52:52 <Compn>	i dont know if its the right thing.
Jan 11 17:52:59 <saste>	ah: ffmpeg -conc -i audio1,audio2,audio3 audiofull
Jan 11 17:53:02 <Compn>	right api or whatever. at least its something
Jan 11 17:53:06 <j-b>	I still have bounties for FFmpeg, btw, notably on DTS-HD and AAC-encoder
Jan 11 17:53:12 <saste>	seems what beastd  was talking about
Jan 11 17:53:40 <saste>	about AAC encoding, any news from the epic ticket's guys?
Jan 11 17:53:43 <wm4>	ubitux: all what's needed is exporting the ordered chapters info
Jan 11 17:53:52 <Compn>	saste : well, i think beastd wants ffmpeg concat to be as easy as mencoders' multiple file support.
Jan 11 17:53:59 <Cigaes>	(the "-conc -i 1,3,3" syntax looks like it will lead to yet another level of escaping madness)
Jan 11 17:54:00 <ubitux>	wm4: don't we already?
Jan 11 17:54:05 <wm4>	ubitux: no
Jan 11 17:54:09 <ubitux>	maybe not enough information in the chapters?
Jan 11 17:54:25 <wm4>	I doubt it
Jan 11 17:54:26 *	llogan (~llogan <at> pdpc/supporter/student/pasteeater) has joined #ffmpeg-meeting
Jan 11 17:54:33 <Compn>	lou is here :)
Jan 11 17:54:46 <wm4>	and you need a nice/fast way to scan for segment files too
Jan 11 17:54:53 <llogan>	ok. now we can start....
Jan 11 17:55:05 <nevcairiel>	even if the information was exported, i'm not sure you could make it play ordered chapter files seamlessly without a lot of magic in user code as well
Jan 11 17:55:10 <wm4>	also, what's so hard about concatenating arbitrary files?
Jan 11 17:55:10 <Compn>	wm4 : whats mplayer2's mkv ordered chapter support look like ?
Jan 11 17:55:22 <llogan>	i forgot i was -9 UTC...not -8. damn it
Jan 11 17:55:27 <Cigaes>	nevcairiel: can ordered chapters point to files with different codecs?
Jan 11 17:55:29 <beastd>	i think my concern was captured closely enough. and IIRC mencoder has a rather intuitive interface for concat but lots of other problems. anyway extending the CLI syntax can be very challenging
Jan 11 17:55:31 <ubitux>	wm4: AVChapter seems to have id, timestamps, and metadata
Jan 11 17:55:44 <ubitux>	and our mkv demuxer seems to create them
Jan 11 17:55:53 <saste>	beastd, mind to show an example?
Jan 11 17:56:03 <nevcairiel>	Cigaes: the spec doesnt necessarily disallow it, but it doesnt work in any implementation today, so...
Jan 11 17:56:04 <saste>	(about the mencoder syntax)
Jan 11 17:56:25 <wm4>	ubitux: does it export segment id? does it support editions in any way?
Jan 11 17:56:26 <nevcairiel>	(the "spec" really doesn't define many details about the whole process)
Jan 11 17:56:44 <ubitux>	wm4: i can't tell, sorry
Jan 11 17:56:45 <wm4>	also, ordered chapters are an abomination
Jan 11 17:56:52 <wm4>	(just saying)
Jan 11 17:57:05 <Compn>	saste : mencoder -vf scale=640:480 file1.rm file2.avi file3.mpg -oac lavc -ovc xvid -o file.avi  , will make one output file , all the same resolution and codec. its very easy to hand write , no escaping command lines, no brackets or commas...
Jan 11 17:57:07 <ubitux>	it's somehow related to the mov edit list btw
Jan 11 17:57:08 <Cigaes>	nevcairiel: then it looks like what I am implementing in the concat demuxer;
Jan 11 17:57:12 <nevcairiel>	its not that terrible, at least it wouldnt be if it was documented somewhere
Jan 11 17:57:27 <Cigaes>	for now it is a proof of concept, but once it is done it can be shared with other formats.
Jan 11 17:57:28 <michaelni>	llogan, beastd when the concat/playlist discussion finishes, can you update us on the server backup status ? (i think we still need a system that does full backups of both our servers and each time sends on email or so to either ML or root so we notice if something makes it stop working)
Jan 11 17:57:40 <nevcairiel>	trying to reverse engineer how haalis thing handles certain weird files was annoying =p
Jan 11 17:58:24 <wm4>	Compn: yeah, I never understood why weird fragile things like the concat demuxer are needed...
Jan 11 17:58:33 <Compn>	right
Jan 11 17:59:50 <saste>	wm4, concat demuxer was needed, at least until we don't have proper playlist support
Jan 11 18:00:10 <wm4>	so you admit it was a hack because ffmpeg.c is too much of a hack?
Jan 11 18:00:28 <beastd>	Please pardon me. Will need to leave in now.
Jan 11 18:00:51 <saste>	wm4, it makes sense to implement it as a component for library users, not only for ffmpeg.c
Jan 11 18:01:17 <wm4>	I myself am annoyed that a demuxer might suddenly open random files I didn't ask it to open
Jan 11 18:01:28 <wm4>	it might even be a security issue
Jan 11 18:01:34 <Compn>	what demuxer does that wm4 ?
Jan 11 18:01:41 <wm4>	Compn: concat
Jan 11 18:01:48 <saste>	wm4, you can disable it from the build if it annoys you
Jan 11 18:01:52 <Compn>	i mean, how would that happen wm4 ?
Jan 11 18:02:03 <kriegerod>	what's wrong with concat demuxer? it does its job in specific required manner, and fits in demuxer interface. Its fragileness is consequence of its requirement to work without reencoding.
Jan 11 18:02:05 <wm4>	saste: can I make distros to disable it?
Jan 11 18:02:31 <Compn>	concat is for copying video , got it
Jan 11 18:02:45 <Compn>	mencoder would do it, but also would break most of the time when copying video in containers
Jan 11 18:02:50 <Compn>	because it wasnt precise
Jan 11 18:02:50 <Cigaes>	kriegerod: it still lacks a few consistency checks, like matching streams in different order from different files.
Jan 11 18:03:07 *	kierank (uid5955 <at> gateway/web/irccloud.com/x-ooeiaqndiqxjeuob) has joined #ffmpeg-meeting
Jan 11 18:03:22 *	pross-au has quit (Quit: Z)
Jan 11 18:03:24 *	beastd has quit (Quit: So many things, so little time...)
Jan 11 18:03:55 <Compn>	i have to go soon as well.
Jan 11 18:04:35 <llogan>	since trac moved remote backups are basically non-existant because, AFAIK, i do not have permissions to make the database dump and/or the daily local database dumps have not occurred last time i checked.
Jan 11 18:05:13 <llogan>	unfortunately, i do not have the resources to perform daily, full backups of the whole machine
Jan 11 18:05:25 <michaelni>	llogan, ok, tell me after the meeting what permissions you need
Jan 11 18:06:03 <saste>	llogan, you could run a backup script from another ffmpeg server
Jan 11 18:06:51 <llogan>	saste: which server? i do not think the web host has enough drive space, IIRC
Jan 11 18:07:01 <michaelni>	also we need full backups, my problem ironically is not that i lack diskspace or net bandwidth but iam too scetterbrained so i know i will forget doing them
Jan 11 18:07:16 <saste>	llogan, ok, was only an idea
Jan 11 18:07:24 <saste>	michaelni, script and conquer
Jan 11 18:07:26 <llogan>	saste: it was a good idea
Jan 11 18:07:56 <llogan>	michaelni: (ana)cron and rsync might be good enough.
Jan 11 18:08:09 <Cigaes>	llogan: what kind of rsync setup?
Jan 11 18:09:46 <llogan>	Cigaes: good question. daily/weekly/monthly? depends on the required complexity i guess. currently i'm doing irregular backups with duplicity.
Jan 11 18:10:13 <Cigaes>	llogan: I was asking more about the --delete-* kind of options. rsync alone is not suitable for a backup,
Jan 11 18:10:32 <Cigaes>	since it will either leave obsolete files there or delete files that may need to be restoring later.
Jan 11 18:11:28 <llogan>	that's one reason i am using duplicity, but rsync was just a more simple recommendation (more for the trac database file for example)
Jan 11 18:12:02 *	michaelni would be using tar+*zip+(gpg)+ssh
Jan 11 18:12:36 <Cigaes>	llogan: rsync can do the work like duplicity, provided the correct options are chosen. rsnapshot, for example, is a good script to do that.
Jan 11 18:13:03 <llogan>	i will unvolunteer myself from the backups. i do not have to time, resources, or experience to do an adequate job
Jan 11 18:14:09 <michaelni>	llogan, ok, anyone else who wants to volunteer ?
Jan 11 18:14:43 <michaelni>	note beastd didnt ever really volunteer, he just did some work on it ...
Jan 11 18:14:49 <saste>	michaelni, maybe ask on mailing-list or in private mails
Jan 11 18:15:39 <saste>	should we move to point 2.?
Jan 11 18:15:46 <michaelni>	saste, ok, ok
Jan 11 18:15:57 <llogan>	is trac also on a VPS or VM or something? if so can images be made too?
Jan 11 18:16:23 <Cigaes>	saste: before moving to point 2, I may mention a few more projects.
Jan 11 18:16:34 <michaelni>	llogan, trac is on a virtual machine
Jan 11 18:16:36 <Cigaes>	Regarding lavfi:
Jan 11 18:16:43 <saste>	Cigaes, sure (I'm just a bit worried that we run out of time)
Jan 11 18:17:12 <Cigaes>	The pull-based nature of EOF annoys me. I am thinking of adding some kind of filter_message() method along with filter_frame(),
Jan 11 18:17:29 <Cigaes>	to let the library process EOF and more in a push-based manner.
Jan 11 18:17:46 <Cigaes>	One of the benefits would be to have a timestamp for EOF, and therefore a duration for the last frame.
Jan 11 18:18:02 <michaelni>	saste, note for the future, if these meetings become too long, maybe they should be split in technical / non technical or something
Jan 11 18:18:12 <michaelni>	or maybe more frequent so theres less to discuss
Jan 11 18:18:17 <Cigaes>	Regarding network:
Jan 11 18:18:26 <j-b>	and you should use a collaborative note
Jan 11 18:18:37 <saste>	michaelni, probably
Jan 11 18:18:52 <saste>	this is the second meeting in one year
Jan 11 18:18:52 <Cigaes>	The recent discussion on the ML makes me want to implement some kind of global solution
Jan 11 18:19:06 <Cigaes>	for protocols that require subprotocols.
Jan 11 18:19:12 <saste>	j-b, do you suggest a specific platform/software for that?
Jan 11 18:19:57 <saste>	Cigaes, about EOF in lavfi, yes although maybe mailing-list is a better place where to discuss it
Jan 11 18:20:42 <Cigaes>	saste: I do not want to annoy people on the mailing list with ideas that are just maturating.
Jan 11 18:20:54 <Cigaes>	I will post something once I have at least a proof of concept.
Jan 11 18:21:08 <j-b>	saste: sure, etherpad.
Jan 11 18:21:17 <j-b>	saste: it's live, and allows everyone to edit
Jan 11 18:21:37 <saste>	j-b, noted for the next time
Jan 11 18:21:56 <saste>	but if someone wants to create a shared document right now, he's welcome
Jan 11 18:22:26 <j-b>	https://etherpad.mozilla.org/MmPk7vQSVT
Jan 11 18:22:26 <saste>	Cigaes, ok and thanks
Jan 11 18:23:16 <j-b>	saste: something like that
Jan 11 18:23:28 <j-b>	saste: it avoids having the load on only one person
Jan 11 18:24:21 <saste>	j-b, thx
Jan 11 18:24:54 <saste>	second point: 2. crowdfunding, donation system improvements, merchandising etc.
Jan 11 18:25:17 <saste>	about crowdfunding, it was discussed in the previous meeting and nothing has been done in the meanwhile
Jan 11 18:25:57 <saste>	crowdfunding and donations can have different targets
Jan 11 18:26:28 <saste>	donations are for generic donations to the whole project, while crowdfunding seems more oriented for specific  features development
Jan 11 18:26:58 <saste>	basically from what i can see we lack developers wanting to create such a project
Jan 11 18:27:21 <kriegerod>	which project?
Jan 11 18:27:44 <michaelni>	improve / maintain ffserver would be a random example :)
Jan 11 18:27:52 <saste>	kriegerod, ffmpeg, or a specific feature implementation project
Jan 11 18:28:19 <saste>	we had a few platform proposals the last time and in several discussions on m-l, irc, rl
Jan 11 18:28:23 <kriegerod>	well, crowdfunding is about having idea and having donated money to implement the idea
Jan 11 18:28:41 <saste>	kickstart, indiego, freedomsponsor and other ones i forgot about
Jan 11 18:28:41 <kriegerod>	when these two are there, i think it would be no problem to find implementor(s)
Jan 11 18:28:54 <rmklp>	I think to attract someone to pay a certain amount in a crowd-funding project a well-defined goal is crucial for the success.
Jan 11 18:29:03 <saste>	kriegerod, no in practice we never had volunteers for doing that
Jan 11 18:29:16 <rmklp>	just improving ffserver will not work IMHO
Jan 11 18:29:18 <llogan>	saste: there was an additional one i mentioned that gimp is/was using too but i forgot the name and i'm not at my ususal machine
Jan 11 18:29:30 <kriegerod>	saste: for doing what and for which amount of money? that's important
Jan 11 18:29:33 <saste>	what i propose is to make projects involving at least two developers
Jan 11 18:29:42 <llogan>	i can make a wiki page for crowdfunding ideas if that could be useful
Jan 11 18:29:53 <saste>	i'd like to do that for implementing DVD reading support, and/or high-level scripting
Jan 11 18:30:02 <michaelni>	rmklp, maybe "fix all ffserver bugs that where on trac at date X"
Jan 11 18:30:13 <saste>	the principle is that i don't find enough motivation if i have to do it alone, but i could if i have a partner for it
Jan 11 18:30:23 <saste>	it should also be more fun for the involved developers
Jan 11 18:30:48 <llogan>	something along the lines of rht GSoC ideas page might be helpful.
Jan 11 18:30:55 <saste>	if we manage to find volunteers for this, then we may create a page on the website listing the on-going projects
Jan 11 18:30:58 <llogan>	s/rht/the
Jan 11 18:31:22 <wm4>	how do you plan to handle DVD reading technically?
Jan 11 18:31:35 <wm4>	or maybe that's offtopic right now
Jan 11 18:31:54 <saste>	wm4, I did some work about it, but it was not still working
Jan 11 18:31:54 <rmklp>	michaelni: probably. I don't know how many companies use ffserver commercially, though.
Jan 11 18:32:27 <saste>	it was a dvd reader, i can send you the thread link later in case you're interested
Jan 11 18:32:41 <wm4>	somewhat
Jan 11 18:32:49 <wm4>	though I doubt it'll be useful for playback use
Jan 11 18:33:07 <saste>	wm4, main objective and target would be backup transcoding of DVD
Jan 11 18:33:37 <rmklp>	michaelni: If the goal is to raise money then there are probably projects that would attract more companies (aac encoder, fast j2k encoder to name two which I guess there will be interest for)
Jan 11 18:34:06 <llogan>	RFC for crowdfunding ideas on -devel might get the ball rolling
Jan 11 18:34:32 <saste>	rmklp, the problem is that usually a single company is not willing to sponsor the whole project
Jan 11 18:34:41 <llogan>	or maybe j-b can describe their process/experience
Jan 11 18:35:08 <rmklp>	saste: yes, of course. I thought we are talking about crowd funding.
Jan 11 18:35:26 <j-b>	llogan: CrowdFunding is very hard to do for people like us
Jan 11 18:35:35 <michaelni>	rmklp, to raise more money making the description more spicy wth hls, rtmp, html5 should attract more interrest compared to "fixing issues"
Jan 11 18:35:41 <j-b>	llogan: a kind of bounty system would be more clever, IMHO
Jan 11 18:35:47 <rmklp>	saste: there was another crowd funding platform that I sent you an email about. one that was specialized on open source. I can'tr find it right now.
Jan 11 18:36:10 <rmklp>	https://www.bountysource.com/
Jan 11 18:36:14 <saste>	j-b, we have a rudimental form of bounty system
Jan 11 18:36:18 <llogan>	j-b: your VLC metro (IIRC) project seemed fairly successful to me
Jan 11 18:36:25 <saste>	we add the tag "bounty" to a ticket
Jan 11 18:36:33 <j-b>	llogan: fairly not.
Jan 11 18:36:40 <j-b>	llogan: and we targetted normal users
Jan 11 18:36:44 <saste>	but this is not very practical/effective, if not for small projects/bugfixes
Jan 11 18:36:55 <j-b>	saste: this is not a correct way
Jan 11 18:37:10 <saste>	we need a platform to coordinate several donors
Jan 11 18:37:29 <saste>	assuming we have some competent developers wanting to propose a project
Jan 11 18:37:32 <j-b>	yes, like bountysource
Jan 11 18:37:37 <rmklp>	yes and at first glance bountysource looks ok
Jan 11 18:37:50 <j-b>	it's not proper crowdsourcing
Jan 11 18:37:54 <kierank>	many companies won't do bountysource in public
Jan 11 18:37:56 <j-b>	but it's more what you'd need
Jan 11 18:38:22 <kierank>	mainly because for differing reasons they need to hide they are using ffmpeg
Jan 11 18:38:54 <rmklp>	kierank: maybe the big ones won't but I believe small ones will and I guess there are hundreds of smaller ones building products on top of ffmpeg
Jan 11 18:38:59 <kierank>	and because bounties are an indeirect form of expenditure
Jan 11 18:39:04 <saste>	kierank, most ffmpeg users are service providers, AFAIK
Jan 11 18:39:22 <kierank>	yeah and they need to hide the fact that their service is a script on top of ffmpeg
Jan 11 18:39:22 <saste>	so the fact that they're using or contributing to ffmpeg shouldn't hurt them
Jan 11 18:39:41 <llogan>	i agree with kierank about many of them wanting to hide
Jan 11 18:39:57 <kierank>	the others (e.g BBC) need to hide for different reasons
Jan 11 18:40:47 <saste>	can bountysource donations be anonymous?
Jan 11 18:40:47 <rmklp>	I know of sponsors who explicitly want to be known as ffmpeg sponsors
Jan 11 18:41:15 <saste>	rmklp, we discussed about a sponsor page, still never was done
Jan 11 18:41:27 <kierank>	rmklp: wait for marketing to find out the new super patented technology that the company claimed to invent is just ffmpeg
Jan 11 18:41:30 <saste>	i guess for lack of interest/motivation/manpower/you name it
Jan 11 18:41:32 <kierank>	and that will get quashed easily
Jan 11 18:42:44 <michaelni>	saste, it seems they can be annoymous, i see a "Anonymous" at https://www.bountysource.com/fundraisers/506-help-make-zoneminder-better/backers for example
Jan 11 18:43:12 <rmklp>	kierank: yes those exist but e.g. at least 2, probably three of the yadif sponsors don't fall into that category. there are a number of companies who build bigger applications on top of ffmpeg and who want to be known as "fair" commercial open source users (whatever that is)
Jan 11 18:43:28 <saste>	rmklp: the idea was to have a sort of sponsor advertised on the website, in a "Sponsors" page or something
Jan 11 18:43:30 <rmklp>	and are willing to pay money
Jan 11 18:43:43 <kierank>	there is money available for mxf
Jan 11 18:43:47 <kierank>	always is...
Jan 11 18:43:50 <saste>	I'm not of any company willing to do that
Jan 11 18:43:54 <saste>	ATM
Jan 11 18:44:07 <saste>	indeed most donations are from private users
Jan 11 18:44:13 <rmklp>	you mean something along the lines of gold, silver, bronzw sponsor?
Jan 11 18:44:24 <saste>	rmklp, yes, kind of
Jan 11 18:45:21 <rmklp>	saste: IMHO the key is to give them an easy package (defined price, conditions) that they can choose. if they have to think how they can sponsor, it will probably not happen.
Jan 11 18:45:42 <saste>	rmklp, sure
Jan 11 18:45:46 <kierank>	certainly I can ask encoding.com and zencoder and probably others
Jan 11 18:46:34 <rmklp>	michael mentioned something from, I think, a linux distro where they had conditions for becoming a gold/silver/bronze sponsor and those were based on money and company size and I think that is a good approach.
Jan 11 18:47:04 <saste>	maybe something like http://xbmc.org/
Jan 11 18:47:06 <rmklp>	I can talk to the companies I was in touch with for the yadif sponsoring and ask them as soon as there are conditions.
Jan 11 18:47:22 <rmklp>	and probably some more in the future.
Jan 11 18:48:06 <saste>	rmklp, yes thanks
Jan 11 18:48:07 <michaelni>	rmklp, i meant http://www.linuxfoundation.org/about/members / http://en.wikipedia.org/wiki/Linux_Foundation
Jan 11 18:48:17 *	iive (~iive <at> unaffiliated/iive) has joined #ffmpeg-meeting
Jan 11 18:49:10 <j-b>	Sorry, to ask, but before asking for money, do you have enough people to "eat" this money?
Jan 11 18:49:22 <saste>	the other problem is that we don't have a formal entity representing the project, so that could be from problematic to impossible
Jan 11 18:49:48 <saste>	j-b, right now we got around 2500-3000$in 1,5 years of donations from SPI Jan 11 18:49:58 <saste> we spent around 500$
Jan 11 18:50:16 <saste>	so no for the moment we don't have much money need
Jan 11 18:50:37 <michaelni>	saste, pay new hw for all devels who need it
Jan 11 18:50:38 <saste>	what we could spend the money for: paying travel tickets to attend events, paying for hw
Jan 11 18:51:06 <saste>	also offer some opportunity to developers to pay some expenses when doing ffmpeg development
Jan 11 18:51:19 <saste>	but this is probably better addressed with bounties
Jan 11 18:51:34 <rmklp>	saste: yes, the legal entity thing is a big one and probably the most work
Jan 11 18:52:00 <llogan>	is fate missing any hardwares we can buy?
Jan 11 18:52:36 *	michaelni has stuff laying around he wanted to install fate on but didnt yet have time
Jan 11 18:53:40 <saste>	about donations, SPI will proably migrate to a different pay-by-credit-card system (current one if Pay&Pledge)
Jan 11 18:54:06 <saste>	and they're moving to have paypal support for Debian donations, if that work that will be extended to other associate projects as well
Jan 11 18:54:06 <michaelni>	or pay someone to update and maintain fateserver for example as a random small thing, that someone should do and that would only be a few hours work so could easily be payed for if we had a few k
Jan 11 18:55:34 <kierank>	I don't know if ubitux, BBB, smarter and others who write ASM would be interested in getting my AVX2 server colocated somewhere?
Jan 11 18:55:49 <kierank>	I have it lying around doing nothing in storage at the moment
Jan 11 18:56:10 <ubitux>	no particular interest myself in it right now
Jan 11 18:56:22 <llogan>	feel free to ask on -devel too
Jan 11 18:56:27 <rmklp>	saste: do you know if anyone has done research on the options regarding the legal entity thing? wasn't ffmtech founded for that purpose and would it fulfill it legally, if there were no other problems with it.
Jan 11 18:57:00 <saste>	rmklp, the main issue with ffmtech, apart the fork thing, was the no-profit status
Jan 11 18:57:23 <saste>	which was never recognized and was pending since the organization was created
Jan 11 18:57:32 <saste>	i don't know what's the current status
Jan 11 18:57:33 <llogan>	what is the status on ffmtech? does it still exist?
Jan 11 18:57:56 <saste>	llogan, you can check it by yourself: http://www.ffmtech.org/
Jan 11 18:58:04 <rmklp>	judjing by what diego wrote to me just recently, very much so.
Jan 11 18:58:05 <smarter>	I'm not concerned about AVX2 yet, there's plenty to do before that :)
Jan 11 18:58:37 <kierank>	smarter: useful for benchmarking on modern hardware though
Jan 11 18:59:17 <llogan>	saste: are there any FFmpeg devs involved?
Jan 11 18:59:35 <saste>	llogan, reimar is still part of the board i think
Jan 11 18:59:41 <rmklp>	I though at least Reimar was on their board
Jan 11 19:01:06 <llogan>	http://ffmtech.org/board.html
Jan 11 19:01:32 <llogan>	shall we move on to the next topic?
Jan 11 19:01:38 <rmklp>	Another hypothetical question: Is there anyone interested in doing this differently, if the non-profit way does not work, i.e. found a company that offers stuff around ffmpeg, like JBoss inc. did for the jboss application server? Disclaimer: I am not interested in being part of this. I am merely listing options.
Jan 11 19:02:38 <kierank>	That's not easy because there's a lot of things to deal with
Jan 11 19:02:38 <saste>	michaelni, about small maintenance tasks, we have some donation money we could spend on that, if we have a proposal
Jan 11 19:02:46 <kierank>	rmklp: on site visits, patents, etc
Jan 11 19:02:49 <rmklp>	but may be completely not what people here want but it is a theoretical option, requiring a lot of work
Jan 11 19:03:01 <rmklp>	kierank: absolutely
Jan 11 19:03:09 <kierank>	the reality is people who choose ffmpeg do it because they have no money anyway
Jan 11 19:03:18 <kierank>	or are competent enough to do things themselves
Jan 11 19:03:46 <rmklp>	kierank: there may be some that match that description but there are others. But I don't have numbers.
Jan 11 19:04:43 <rmklp>	I would guess that there are a lot of api users out there who would even pay for support but of course I might be wrong. I just know I would (depending on the price).
Jan 11 19:05:14 <kierank>	API users are orders of magnitude lower than ffmpeg users
Jan 11 19:05:31 <kierank>	since it's easier to write scripts around ffmpeg than to try and understand the api
Jan 11 19:05:38 <rmklp>	I am not saying this would become a 500M enterprise like jboss but ffmpeg is used by a lot of companies as a library in products
Jan 11 19:06:20 <rmklp>	you are focusing on transcoding. there are tons of other uses of the library.
Jan 11 19:06:39 <rmklp>	but of course you are right.
Jan 11 19:06:58 <kierank>	the biggest use of ffmpeg by far is transcoding
Jan 11 19:07:14 <wm4>	often I think it focuses on transcoding too much...
Jan 11 19:07:23 <wm4>	the library, at least
Jan 11 19:07:24 <kierank>	direct use of ffmepg I mean
Jan 11 19:07:43 <wm4>	yeah, ffmpeg.c isn't much of use for other things
Jan 11 19:08:32 <kriegerod>	rmklp, your idea of company doing ffmpeg support is viable. I have seen there are some such companies around GStreamer, e.g. http://www.centricular.com/, also some theirs devs are at Collabora, which is a company of that sort
Jan 11 19:08:53 <rmklp>	yes but if you would get just 20 companies that use ffmpeg in players, analysis software etc. to pay 1000$a year for sponsoring or a little higher priority in support, you would certainly increase the generated money considerably compared to knwo and that is not very optimistic. Jan 11 19:10:10 <rmklp> as I said, I have so far only talked to a handful of fellow companies that develop software that uses ffmpeg as a library and more than half seemed open to something like that. Jan 11 19:10:46 <kierank> the number of companies that use ffmpeg as a library is quite small imo Jan 11 19:10:53 <rmklp> but it needs a lot of work an dedication and has a lot of potential for bad things Jan 11 19:11:13 <kierank> most of the mainstream features work well Jan 11 19:11:19 <kierank> people will pay money for niche stuff Jan 11 19:11:29 <kierank> (e.g mxf) but the problem with niche stuff is there are few people to do it Jan 11 19:11:29 <michaelni> i think we should provide the option for companies who want to sponsor ffmpeg to do so Jan 11 19:11:50 <kierank> michaelni: there have to be pacakages Jan 11 19:11:59 <kierank> and some clear message as to where money is going Jan 11 19:12:02 <saste> or in alternative to pay for bounties, which would avoid the need for a formal entity/company behind it Jan 11 19:12:11 <michaelni> kierank, money goes to SPI-ffmpeg Jan 11 19:12:18 <kierank> michaelni: i mean what for Jan 11 19:12:37 <kierank> michaelni: people show this to their managers Jan 11 19:12:55 <kierank> managers don't give a shit about SPI. they care about the money going to things which help the project (hw, fate etc) Jan 11 19:13:00 <saste> michaelni, so it would be DONOR -> SPI -> CONTRIBUTOR Jan 11 19:13:19 <saste> the problem is that we need approval from the SPI treasurer Jan 11 19:13:20 <rmklp> kierank: I think I know companies who would pay just to get on the list of companies that support ffmpeg regardless of where the money goes but it is of course better to write something about that Jan 11 19:13:20 <michaelni> kierank, yes, we would need a list Jan 11 19:13:46 <michaelni> saste, can we try to pay some small development via SPI to see if this is possible or not ? Jan 11 19:13:58 <saste> michaelni, i think it is already possible Jan 11 19:14:10 <saste> but it is decided on a case-by-case basis Jan 11 19:14:19 <rmklp> by SPI Jan 11 19:14:20 <rmklp> ? Jan 11 19:14:34 <saste> SPI is a non-profit, and thus must be very careful about how the money is spent Jan 11 19:15:06 <saste> rmklp, yes, basically when we decide about a refund request, it must be approved by the SPI treasurer Jan 11 19:15:15 <saste> so we have no direct control over the donation money Jan 11 19:15:32 <rmklp> if that is only a theoretical hurdle and easy in practice, it would be a good thing. what do you think? Jan 11 19:15:56 <saste> rmklp, i think it can be done for internal developments Jan 11 19:16:30 <saste> but in case it is a company requesting some work, we can't go through SPI (in that case it would be better to use an independent bounty platform) Jan 11 19:16:56 <saste> otherwise you can't guarantee the company that the donated money will be spent for the task Jan 11 19:18:25 <rmklp> legally doing something like a bountysource project is a contract. do you know, how in the case of ffmpeg would be the parties? would have to be the individual developers who pledge to implement the feature, wouldn't it? Jan 11 19:18:38 <rmklp> s/how/who Jan 11 19:19:06 <saste> rmklp, yes, but in that case it is a matter between individual ffmpeg developers and the pledgers/donors Jan 11 19:19:15 <saste> ffmpeg as a formal entity is not involved at all Jan 11 19:19:33 <saste> indeed the developers could also not be ffmpeg developers at all Jan 11 19:20:49 <saste> about merchandising we basically have the same issues, lacking a formal entity Jan 11 19:20:55 <saste> but I might be wrong Jan 11 19:22:14 <rmklp> hypothetical example just for understanding: If I thought having a fast j2k encoder that supports a certain pixel format would be a project that could generate some money, I would try to convince someone like michael to offer that and he would say, he needed 20000 dollars for the implementation and then would open the bountysource project? Jan 11 19:22:28 <saste> rmklp, yes Jan 11 19:22:55 <saste> or the other way around, random developer propose a task, and an individual/company fund it in case of interest Jan 11 19:23:15 <rmklp> yes. Jan 11 19:24:43 <rmklp> so what is going to happen now? Someone is going to "test" paying a developer via SPI to find out if that works? What else? Is someone going to propose a sponsorship program? Jan 11 19:25:06 <saste> rmklp, this is point 3. development task proposals Jan 11 19:25:13 <saste> should we go on? Jan 11 19:25:45 <rmklp> saste: I did not understand that. how is it related to 3.? Jan 11 19:25:59 <saste> also we will probably discuss the topic on the mailing-list, to see if there are volunteers for setting up bounty projects Jan 11 19:26:14 <rmklp> ok Jan 11 19:26:30 <saste> rmklp, > Someone is going to "test" paying a developer via SPI to find out if that works? Jan 11 19:26:56 <saste> right now we have 2K$ of donated money, so maybe it is not enough for a complex project
Jan 11 19:27:14 <saste>	(and we should probably spend that money for other stuff, like travel refunds)
Jan 11 19:27:28 <rmklp>	once yadif is committed it will be a bit more
Jan 11 19:28:22 <saste>	but that works that a developer proposes a funded task, then it is discussed and approved on list and finally the money is sent if approved by SPI
Jan 11 19:28:39 <rmklp>	ok
Jan 11 19:28:56 <saste>	to follow that path we first need a contributor proposing the task
Jan 11 19:29:54 <saste>	should we skip to point 3.?
Jan 11 19:31:11 <saste>	so it is: 3. development task proposals
Jan 11 19:31:17 <kierank>	does that include gsoc?
Jan 11 19:31:42 <saste>	kierank, also
Jan 11 19:31:57 <saste>	although I mostly intended that as "funded development task proposals"
Jan 11 19:32:15 <saste>	about gsoc, I'm not sure we will be accepted for gsoc even this year
Jan 11 19:32:40 <saste>	indeed i'm not even sure it is a good idea to apply
Jan 11 19:32:53 <kierank>	saste: afaik google are ok with ffmpeg/libav now
Jan 11 19:33:30 <saste>	kierank, good to know
Jan 11 19:34:42 <kriegerod>	couple of days ago on maillist there was a request for DVB subtitles support. I said i'll check that, but i'm ok if anybody else takes it, or if we try this issue as a polygon to experiment with above discussed things
Jan 11 19:34:56 <saste>	we talked about an internal ffmpeg summer of code, but we probably lack the organization/money
Jan 11 19:35:29 <saste>	we could do it together with videolan if there is some interest and it's not too complicate for them
Jan 11 19:35:41 <saste>	kriegerod, sure
Jan 11 19:35:53 <saste>	about that, i also want to propose some candidate funding tasks
Jan 11 19:36:09 <saste>	namely: DVD reading support, and high-level scripting binding
Jan 11 19:36:25 <saste>	but: I only do that if I find a partner to work with me
Jan 11 19:36:28 <kierank>	dvd reading?
Jan 11 19:36:28 <kierank>	wow
Jan 11 19:36:40 <kierank>	someone's crazy :)
Jan 11 19:37:18 <j-b>	kierank: I don't know where you get this information from, tbh
Jan 11 19:37:35 <kierank>	j-b: mentor summit
Jan 11 19:37:37 <kierank>	av500 asked
Jan 11 19:37:45 <kierank>	VLC is not in a good position however
Jan 11 19:37:46 <j-b>	like they said last year
Jan 11 19:37:56 <j-b>	kierank: we won't apply, anyway
Jan 11 19:38:12 <j-b>	kierank: bored of this PC bullshit
Jan 11 19:39:20 <saste>	anyway, more proposals?
Jan 11 19:40:01 <saste>	but discussion and proposals can go on on other channels...
Jan 11 19:40:39 <saste>	next point?
Jan 11 19:41:02 <kierank>	j2k encoder is probably the only large thing missing from the pro perspective, as much as i hate j2k
Jan 11 19:41:21 <saste>	kierank, would you work on that?
Jan 11 19:41:33 <kierank>	no, don't have time
Jan 11 19:41:39 <llogan>	saste: i'm personally not excited about GSoC
Jan 11 19:41:57 *	rmklp has quit (Quit: rmklp)
Jan 11 19:42:06 <saste>	kierank, or can you find someone who will?
Jan 11 19:42:22 <kierank>	don't think so
Jan 11 19:43:17 <saste>	if there is not anything else we can go to the next and last point
Jan 11 19:43:33 <saste>	4. miscellanea
Jan 11 19:43:55 <saste>	ubitux, any news about the website restyling?
Jan 11 19:44:34 <ubitux>	not much progress, but i'll keep you up-to-date
Jan 11 19:44:51 <saste>	ubitux, mh, okay
Jan 11 19:44:57 <michaelni>	someone should contact apple and ask them about details / bug reports of the prores issues they mentioned on that page
Jan 11 19:45:10 <llogan>	what's this on the web site restyling?
Jan 11 19:45:55 <ubitux>	llogan: http://db0.galo.pe/ffmpeg-web/htdocs/
Jan 11 19:46:11 <ubitux>	"WIP"
Jan 11 19:46:19 <llogan>	i am unaware of any work to update the site
Jan 11 19:46:21 <saste>	also it would be nice if we add a goodies section
Jan 11 19:46:48 <saste>	with designs we collected from past logo contests
Jan 11 19:46:58 <saste>	i'll probably try to find some time about that
Jan 11 19:47:00 <llogan>	who is doing the redesign?
Jan 11 19:47:12 <saste>	we should also define the license of the content
Jan 11 19:47:33 <saste>	but if someone wants to do that he's welcome
Jan 11 19:47:51 <michaelni>	goodies section maybe best on the wiki so work on it can be shared with more people
Jan 11 19:48:14 <saste>	michaelni, that works for me as well
Jan 11 19:48:29 <saste>	although it would have more visibility on the official website
Jan 11 19:48:38 <saste>	btw what's the license of the wiki content?
Jan 11 19:48:43 <saste>	what if we add artwork?
Jan 11 19:48:43 <michaelni>	the official site could link to the wiki
Jan 11 19:49:16 <llogan>	The materials within the Community Contributed Documentation section of the FFmpeg Wiki are released under the ​Creative Commons Attribution-ShareAlike 3.0 License.
Jan 11 19:49:49 <saste>	about logo contests, did we specify the required license?
Jan 11 19:49:59 <ubitux>	llogan: db0 on #ffmpeg-devel
Jan 11 19:50:13 <saste>	otherwise we'll need to get in touch directly with the various contributors
Jan 11 19:50:34 <saste>	also herve flores suggested to adopt a commercial license for artwork/logos
Jan 11 19:50:36 <llogan>	ubitux: i don't know who that is
Jan 11 19:51:10 <ubitux>	someone i know
Jan 11 19:51:18 <ubitux>	not involved in ffmpeg developement so far
Jan 11 19:51:22 <ubitux>	except for this
Jan 11 19:52:03 <saste>	other misc topics?
Jan 11 19:52:09 <llogan>	i don't prefer the dark look but i guess we can see how it turns out
Jan 11 19:53:55 <michaelni>	what shall we do with libavfilter.net, libavcodec.net, libavutil.net, libswresample.net and others ?
Jan 11 19:54:08 <michaelni>	we are in control of them but they cost money
Jan 11 19:54:11 <llogan>	saste: no specific logo license has been selected IIRC for submissions
Jan 11 19:54:21 <llogan>	michaelni: dump them.
Jan 11 19:55:01 <saste>	michaelni, same from me, if we don't have appealing reasons to keep them
Jan 11 19:55:30 <saste>	is someone planning to attend some FLOSS event this year?
Jan 11 19:55:47 <michaelni>	if noone wants to use them (for ffmpeg stuff) and noone wants to sponsor it then ill let them expire
Jan 11 19:56:48 <saste>	i'll probably try to attend some if we are enough to man an ffmpeg booth
Jan 11 19:57:16 <saste>	fosdem is probably too close, so the next viable event is probably linuxtag
Jan 11 19:57:33 <llogan>	i bet beastd will go to that
Jan 11 19:57:38 <llogan>	maybe thilo too
Jan 11 19:57:42 *	j-b (~jb <at> videolan/developer/j-b) has left #ffmpeg-meeting
Jan 11 19:58:24 <saste>	llogan, part of the donation money could be spent for paying (at least part) of the travel tickets
Jan 11 19:59:21 <saste>	if there is nothing more we can close the meeting
Jan 11 20:00:06 *	rmklp (~krueger <at> ip-178-200-241-251.unitymediagroup.de) has joined #ffmpeg-meeting
Jan 11 20:00:33 <llogan>	saste: thanks for organizing and herding cats
Jan 11 20:00:46 <saste>	michaelni, anything else?
Jan 11 20:01:18 <michaelni>	not really, noone wants to ask apple about the prores issues ?
Jan 11 20:01:27 <Cigaes>	Thanks indeed for the organization.
Jan 11 20:01:37 <michaelni>	saste, thx as well from me
Jan 11 20:02:12 <saste>	michaelni, about the prores thing, a private mail is probably better
Jan 11 20:02:48 <michaelni>	you volunteer to send apple a private mail ? or you mean i should ?
Jan 11 20:03:19 <saste>	michaelni, yes, probably doing it yourself would be faster
Jan 11 20:03:39 <saste>	as for me, i'm not even sure what the issues are about
Jan 11 20:03:46 <michaelni>	ok then
Jan 11 20:04:04 <saste>	then i suppose we can close the meeting
Jan 11 20:04:17 <saste>	thanks all for your time
Jan 11 20:04:24 <Cigaes>	Good bye.
Jan 11 20:04:38 <saste>	i'm going to send the meeting log later today
Jan 11 20:05:00 <saste>	(...to the ffmpeg-devel mailing list)
Jan 11 20:05:12 <saste>	good bye!
Jan 11 20:05:49 <michaelni>	good bye all, until the next meeting ...
Jan 11 20:05:56 *	Cigaes has quit (Quit: leaving)
Jan 11 20:05:57 *	michaelni (~michael <at> chello084114129144.4.15.vie.surfer.at) has left #ffmpeg-meeting ("Leaving")
Jan 11 20:06:35 *	ubitux (~ux <at> did75-21-88-189-231-41.fbx.proxad.net) has left #ffmpeg-meeting
Jan 11 20:06:38 *	llogan (~llogan <at> pdpc/supporter/student/pasteeater) has left #ffmpeg-meeting ("WeeChat 0.3.2")
Jan 11 20:08:43 *	wm4 (~wm4 <at> ip-static-94-242-209-206.as5577.net) has left #ffmpeg-meeting ("Leaving")
**** ENDING LOGGING AT Sat Jan 11 20:14:28 2014
Shortcuts

import torch
from torch.nn.modules.container import ModuleList, ModuleDict, Module
from torch.nn.parameter import Parameter
from torch import Tensor

import collections
from contextlib import contextmanager
from typing import Union, Optional, Dict, Tuple, Sequence

_cache_enabled = 0
_cache: Dict[Tuple[int, str], Optional[Tensor]] = {}

[docs]@contextmanager
def cached():
r"""Context manager that enables the caching system within parametrizations
registered with :func:register_parametrization.

The value of the parametrized objects is computed and cached the first time
they are required when this context manager is active. The cached values are
discarded when leaving the context manager.

This is useful when using a parametrized parameter more than once in the forward pass.
An example of this is when parametrizing the recurrent kernel of an RNN or when
sharing weights.

The simplest way to activate the cache is by wrapping the forward pass of the neural network

.. code-block:: python

import torch.nn.utils.parametrize as P
...
with P.cached():
output = model(inputs)

in training and evaluation. One may also wrap the parts of the modules that use
several times the parametrized tensors. For example, the loop of an RNN with a
parametrized recurrent kernel:

.. code-block:: python

with P.cached():
for x in xs:
out_rnn = self.rnn_cell(x, out_rnn)
"""
global _cache
global _cache_enabled
_cache_enabled += 1
try:
yield
finally:
_cache_enabled -= 1
if not _cache_enabled:
_cache = {}

def _register_parameter_or_buffer(module, name, X):
if isinstance(X, Parameter):
module.register_parameter(name, X)
else:
module.register_buffer(name, X)

[docs]class ParametrizationList(ModuleList):
r"""A sequential container that holds and manages the original or original0, original1, ...
parameters or buffers of a parametrized :class:torch.nn.Module.

It is the type of module.parametrizations[tensor_name] when module[tensor_name]
has been parametrized with :func:register_parametrization.

If the first registered parmetrization has a right_inverse that returns one tensor or
does not have a right_inverse (in which case we assume that right_inverse is the identity),
it will hold the tensor under the name original.
If it has a right_inverse that returns more than one tensor, these will be registered as
original0, original1, ...

.. warning::
This class is used internally by :func:register_parametrization. It is documented
here for completeness. It shall not be instantiated by the user.

Args:
modules (sequence): sequence of modules representing the parametrizations
original (Parameter or Tensor): parameter or buffer that is parametrized
unsafe (bool): a boolean flag that denotes whether the parametrization
may change the dtype and shape of the tensor. Default: False
Warning: the parametrization is not checked for consistency upon registration.
Enable this flag at your own risk.
"""
original: Tensor
unsafe: bool

def __init__(
self, modules: Sequence[Module], original: Union[Tensor, Parameter], unsafe: bool = False
) -> None:
# We require this because we need to treat differently the first parametrization
# This should never throw, unless this class is used from the outside
if len(modules) == 0:
raise ValueError("ParametrizationList requires one or more modules.")

super().__init__(modules)
self.unsafe = unsafe

# In plain words:
# module.weight must keep its dtype and shape.
# Furthermore, if there is no right_inverse or the right_inverse returns a tensor,
# this should be of the same dtype as the original tensor
#
# We check that the following invariants hold:
#    X = module.weight
#    Y = param.right_inverse(X)
#    assert isinstance(Y, Tensor) or
#           (isinstance(Y, collections.abc.Sequence) and all(isinstance(t, Tensor) for t in Y))
#    Z = param(Y) if isisntance(Y, Tensor) else param(*Y)
#    # Consistency checks
#    assert X.dtype == Z.dtype and X.shape == Z.shape
#    # If it has one input, this allows to be able to use set_ to be able to
#    # move data to/from the original tensor without changing its id (which is what the
#    # optimiser uses to track parameters)
#    if isinstance(Y, Tensor)
#      assert X.dtype == Y.dtype
# Below we use original = X, new = Y

original_shape = original.shape
original_dtype = original.dtype

# Compute new
new = original
for module in reversed(self):  # type: ignore[call-overload]
if hasattr(module, "right_inverse"):
try:
new = module.right_inverse(new)
except NotImplementedError:
pass
# else, or if it throws, we assume that right_inverse is the identity

if not isinstance(new, Tensor) and not isinstance(new, collections.abc.Sequence):
raise ValueError("'right_inverse' must return a Tensor or a Sequence of tensors (list, tuple...). "
f"Got {type(new).__name__}")

# Set the number of original tensors
self.is_tensor = isinstance(new, Tensor)
self.ntensors = 1 if self.is_tensor else len(new)

# Register the tensor(s)
if self.is_tensor:
if original.dtype != new.dtype:
raise ValueError(
"When right_inverse outputs one tensor, it may not change the dtype.\n"
f"original.dtype: {original.dtype}\n"
f"right_inverse(original).dtype: {new.dtype}"
)
# Set the original to original so that the user does not need to re-register the parameter
# manually in the optimiser
original.set_(new)  # type: ignore[call-overload]
_register_parameter_or_buffer(self, "original", original)
else:
for i, originali in enumerate(new):
if not isinstance(originali, Tensor):
raise ValueError("'right_inverse' must return a Tensor or a Sequence of tensors "
"(list, tuple...). "
f"Got element {i} of the sequence with type {type(originali).__name__}.")

# If the original tensor was a Parameter that required grad, we expect the user to
# add the new parameters to the optimizer after registering the parametrization
# (this is documented)
if isinstance(original, Parameter):
originali = Parameter(originali)
_register_parameter_or_buffer(self, f"original{i}", originali)

if not self.unsafe:
# Consistency checks:
# Since f : A -> B, right_inverse : B -> A, Z and original should live in B
# Z = forward(right_inverse(original))
Z = self()
if not isinstance(Z, Tensor):
raise ValueError(
f"A parametrization must return a tensor. Got {type(Z).__name__}."
)
if Z.dtype != original_dtype:
raise ValueError(
"Registering a parametrization may not change the dtype of the tensor, unless unsafe flag is enabled.\n"
f"unparametrized dtype: {original_dtype}\n"
f"parametrized dtype: {Z.dtype}"
)
if Z.shape != original_shape:
raise ValueError(
"Registering a parametrization may not change the shape of the tensor, unless unsafe flag is enabled.\n"
f"unparametrized shape: {original_shape}\n"
f"parametrized shape: {Z.shape}"
)

[docs]    def right_inverse(self, value: Tensor) -> None:
r"""Calls the methods right_inverse (see :func:register_parametrization)
of the parametrizations in the inverse order they were registered in.
Then, it stores the result in self.original if right_inverse outputs one tensor
or in self.original0, self.original1, ... if it outputs several.

Args:
value (Tensor): Value to which initialize the module
"""
# All the exceptions in this function should almost never throw.
# They could throw if, for example, right_inverse function returns a different
# dtype when given a different input, which should most likely be caused by a
# bug in the user's code

# See https://github.com/pytorch/pytorch/issues/53103
for module in reversed(self):  # type: ignore[call-overload]
if hasattr(module, "right_inverse"):
value = module.right_inverse(value)
else:
raise RuntimeError(f"parametrization {type(module).__name__} does not implement "
"right_inverse.")
if self.is_tensor:
# These exceptions should only throw when a right_inverse function does not
# return the same dtype for every input, which should most likely be caused by a bug
if not isinstance(value, Tensor):
raise ValueError(
f"right_inverse should return a tensor. Got {type(value).__name__}"
)
if value.dtype != self.original.dtype:
raise ValueError(
f"The tensor returned by right_inverse has dtype {value.dtype} "
f"while original has dtype {self.original.dtype}"
)
# We know that the result is going to have the same dtype
self.original.set_(value)  # type: ignore[call-overload]
else:
if not isinstance(value, collections.abc.Sequence):
raise ValueError(
"'right_inverse' must return a sequence of tensors. "
f"Got {type(value).__name__}."
)
if len(value) != self.ntensors:
raise ValueError(
"'right_inverse' must return a sequence of tensors of length "
f"{self.ntensors}. Got a sequence of lenght {len(value)}."
)
for i, tensor in enumerate(value):
original_i = getattr(self, f"original{i}")
if not isinstance(tensor, Tensor):
raise ValueError(
f"right_inverse must return a sequence of tensors. "
f"Got element {i} of type {type(tensor).__name__}"
)
if original_i.dtype != tensor.dtype:
raise ValueError(
f"Tensor {i} returned by right_inverse has dtype {tensor.dtype} "
f"while original{i} has dtype {original_i.dtype}"
)
original_i.set_(tensor)

def forward(self) -> Tensor:
# Unpack the originals for the first parametrization
if self.is_tensor:
x = self[0](self.original)
else:
originals = (getattr(self, f"original{i}") for i in range(self.ntensors))
x = self[0](*originals)
# It's not possible to call self[1:] here, so we have to be a bit more cryptic
# Also we want to skip all non-integer keys
curr_idx = 1
while hasattr(self, str(curr_idx)):
x = self[curr_idx](x)
curr_idx += 1
return x

def _inject_new_class(module: Module) -> None:
r"""Sets up a module to be parametrized.

This works by substituting the class of the module by a class
that extends it to be able to inject a property

Args:
module (nn.Module): module into which to inject the property
"""
cls = module.__class__

def getstate(self):
raise RuntimeError(
"Serialization of parametrized modules is only "
"supported through state_dict(). See:\n"
)

param_cls = type(
f"Parametrized{cls.__name__}",
(cls,),
{
"__getstate__": getstate,
},
)

module.__class__ = param_cls

def _inject_property(module: Module, tensor_name: str) -> None:
r"""Injects a property into module[tensor_name].

It assumes that the class in the module has already been modified from its
original one using _inject_new_class and that the tensor under :attr:tensor_name
has already been moved out

Args:
module (nn.Module): module into which to inject the property
tensor_name (str): name of the name of the property to create
"""
# We check the precondition.
# This should never fire if register_parametrization is correctly implemented
assert not hasattr(module, tensor_name)

@torch.jit.unused
def get_cached_parametrization(parametrization) -> Tensor:
global _cache
key = (id(module), tensor_name)
tensor = _cache.get(key)
if tensor is None:
tensor = parametrization()
_cache[key] = tensor
return tensor

def get_parametrized(self) -> Tensor:
parametrization = self.parametrizations[tensor_name]
if _cache_enabled:
if torch.jit.is_scripting():
# Scripting
raise RuntimeError('Caching is not implemented for scripting. '
'Either disable caching or avoid scripting.')
elif torch._C._get_tracing_state() is not None:
# Tracing
raise RuntimeError('Cannot trace a model while caching parametrizations.')
else:
return get_cached_parametrization(parametrization)
else:
# If caching is not active, this function just evaluates the parametrization
return parametrization()

def set_original(self, value: Tensor) -> None:
self.parametrizations[tensor_name].right_inverse(value)

setattr(module.__class__, tensor_name, property(get_parametrized, set_original))

[docs]def register_parametrization(
module: Module, tensor_name: str, parametrization: Module, *, unsafe: bool = False,
) -> Module:
r"""Adds a parametrization to a tensor in a module.

Assume that tensor_name="weight" for simplicity. When accessing module.weight,
the module will return the parametrized version parametrization(module.weight).
If the original tensor requires a gradient, the backward pass will differentiate
through :attr:parametrization, and the optimizer will update the tensor accordingly.

The first time that a module registers a parametrization, this function will add an attribute
parametrizations to the module of type :class:~ParametrizationList.

The list of parametrizations on the tensor weight will be accessible under
module.parametrizations.weight.

The original tensor will be accessible under
module.parametrizations.weight.original.

Parametrizations may be concatenated by registering several parametrizations
on the same attribute.

The training mode of a registered parametrization is updated on registration
to match the training mode of the host module

Parametrized parameters and buffers have an inbuilt caching system that can be activated
using the context manager :func:cached.

A :attr:parametrization may optionally implement a method with signature

.. code-block:: python

def right_inverse(self, X: Tensor) -> Union[Tensor, Sequence[Tensor]]

This method is called on the unparametrized tensor when the first parametrization
is registered to compute the initial value of the original tensor.
If this method is not implemented, the original tensor will be just the unparametrized tensor.

If all the parametrizations registered on a tensor implement right_inverse it is possible
to initialize a parametrized tensor by assigning to it, as shown in the example below.

It is possible for the first parametrization to depend on several inputs.
This may be implemented returning a tuple of tensors from right_inverse
(see the example implementation of a RankOne parametrization below).

In this case, the unconstrained tensors are also located under module.parametrizations.weight
with names original0, original1,...

.. note::

If unsafe=False (default) both the forward and right_inverse methods will be called
once to perform a number of consistency checks.
If unsafe=True, then right_inverse will be called if the tensor is not parametrized,
and nothing will be called otherwise.

.. note::

In most situations, right_inverse will be a function such that
forward(right_inverse(X)) == X (see
right inverse <https://en.wikipedia.org/wiki/Inverse_function#Right_inverses>_).
Sometimes, when the parametrization is not surjective, it may be reasonable
to relax this.

.. warning::

If a parametrization depends on several inputs, :func:~register_parametrization
will register a number of new parameters. If such parametrization is registered
after the optimizer is created, these new parameters will need to be added manually
to the optimizer. See :meth:torch.Optimizer.add_param_group.

Args:
module (nn.Module): module on which to register the parametrization
tensor_name (str): name of the parameter or buffer on which to register
the parametrization
parametrization (nn.Module): the parametrization to register
Keyword args:
unsafe (bool): a boolean flag that denotes whether the parametrization
may change the dtype and shape of the tensor. Default: False
Warning: the parametrization is not checked for consistency upon registration.
Enable this flag at your own risk.

Raises:
ValueError: if the module does not have a parameter or a buffer named :attr:tensor_name

Examples:
>>> import torch
>>> import torch.nn as nn
>>> import torch.nn.utils.parametrize as P
>>>
>>> class Symmetric(nn.Module):
>>>     def forward(self, X):
>>>         return X.triu() + X.triu(1).T  # Return a symmetric matrix
>>>
>>>     def right_inverse(self, A):
>>>         return A.triu()
>>>
>>> m = nn.Linear(5, 5)
>>> P.register_parametrization(m, "weight", Symmetric())
>>> print(torch.allclose(m.weight, m.weight.T))  # m.weight is now symmetric
True
>>> A = torch.rand(5, 5)
>>> A = A + A.T   # A is now symmetric
>>> m.weight = A  # Initialize the weight to be the symmetric matrix A
>>> print(torch.allclose(m.weight, A))
True

>>> class RankOne(nn.Module):
>>>     def forward(self, x, y):
>>>         # Form a rank 1 matrix multiplying two vectors
>>>         return x.unsqueeze(-1) @ y.unsqueeze(-2)
>>>
>>>     def right_inverse(self, Z):
>>>         # Project Z onto the rank 1 matrices
>>>         U, S, Vh = torch.linalg.svd(Z, full_matrices=False)
>>>         # Return rescaled singular vectors
>>>         s0_sqrt = S[0].sqrt().unsqueeze(-1)
>>>         return U[..., :, 0] * s0_sqrt, Vh[..., 0, :] * s0_sqrt
>>>
>>> linear_rank_one = P.register_parametrization(nn.Linear(4, 4), "weight", RankOne())
>>> print(torch.linalg.matrix_rank(linear_rank_one.weight).item())
1

"""
parametrization.train(module.training)
if is_parametrized(module, tensor_name):
# Correctness checks.
# If A is the space of tensors with shape and dtype equal to module.weight
# we check that parametrization.forward and parametrization.right_inverse are
# functions from A to A
if not unsafe:
Y = getattr(module, tensor_name)
X = parametrization(Y)
if not isinstance(X, Tensor):
raise ValueError(
f"A parametrization must return a tensor. Got {type(X).__name__}."
)
if X.dtype != Y.dtype:
raise ValueError(
"Registering a parametrization may not change the dtype of the tensor, unless the unsafe flag is enabled.\n"
f"module.{tensor_name}.dtype: {Y.dtype}\n"
f"parametrization(module.{tensor_name}).dtype: {X.dtype}"
)
if X.shape != Y.shape:
raise ValueError(
"Registering a parametrization may not change the shape of the tensor, unless the unsafe flag is enabled.\n"
f"module.{tensor_name}.shape: {Y.shape}\n"
f"parametrization(module.{tensor_name}).shape: {X.shape}"
)
if hasattr(parametrization, "right_inverse"):
try:
Z = parametrization.right_inverse(X)  # type: ignore[operator]
except NotImplementedError:
pass
else:
if not isinstance(Z, Tensor):
raise ValueError(
f"parametrization.right_inverse must return a tensor. Got: {type(Z).__name__}"
)
if Z.dtype != Y.dtype:
raise ValueError(
"The tensor returned by parametrization.right_inverse must have the same dtype "
f"as module.{tensor_name}, unless the unsafe flag is enabled.\n"
f"module.{tensor_name}.dtype: {Y.dtype}\n"
f"returned dtype: {Z.dtype}"
)
if Z.shape != Y.shape:
raise ValueError(
"The tensor returned by parametrization.right_inverse must have the same shape "
f"as module.{tensor_name}, unless the unsafe flag is enabled.\n"
f"module.{tensor_name}.shape: {Y.shape}\n"
f"returned shape: {Z.shape}"
)
# else right_inverse is assumed to be the identity

# add the new parametrization to the parametrization list
assert isinstance(module.parametrizations, ModuleDict)  # Make mypy happy
module.parametrizations[tensor_name].append(parametrization)
# If unsafe was True in previous parametrization, keep it enabled
module.parametrizations[tensor_name].unsafe |= unsafe  # type: ignore[index, union-attr]
elif tensor_name in module._buffers or tensor_name in module._parameters:
# Set the parametrization mechanism
# Fetch the original buffer or parameter
original = getattr(module, tensor_name)
# We create this early to check for possible errors
parametrizations = ParametrizationList([parametrization], original, unsafe=unsafe)
# Delete the previous parameter or buffer
delattr(module, tensor_name)
# If this is the first parametrization registered on the module,
# we prepare the module to inject the property
if not is_parametrized(module):
# Change the class
_inject_new_class(module)
# Inject a ModuleDict into the instance under module.parametrizations
module.parametrizations = ModuleDict()
# Add a property into the class
_inject_property(module, tensor_name)
# Add a ParametrizationList
assert isinstance(module.parametrizations, ModuleDict)  # Make mypy happy
module.parametrizations[tensor_name] = parametrizations
else:
raise ValueError(
f"Module '{module}' does not have a parameter, a buffer, or a "
f"parametrized element with name '{tensor_name}'"
)
return module

[docs]def is_parametrized(module: Module, tensor_name: Optional[str] = None) -> bool:
r"""Returns True if module has an active parametrization.

If the argument :attr:tensor_name is specified, returns True if
module[tensor_name] is parametrized.

Args:
module (nn.Module): module to query
name (str, optional): attribute in the module to query
Default: None
"""
parametrizations = getattr(module, "parametrizations", None)
if parametrizations is None or not isinstance(parametrizations, ModuleDict):
return False
if tensor_name is None:
# Check that there is at least one parametrized buffer or Parameter
return len(parametrizations) > 0
else:
return tensor_name in parametrizations

[docs]def remove_parametrizations(
module: Module, tensor_name: str, leave_parametrized: bool = True
) -> Module:
r"""Removes the parametrizations on a tensor in a module.

- If leave_parametrized=True, module[tensor_name] will be set to
its current output. In this case, the parametrization shall not change the dtype
of the tensor.
- If leave_parametrized=False, module[tensor_name] will be set to
the unparametrised tensor in module.parametrizations[tensor_name].original.
This is only possible when the parametrization depends on just one tensor.

Args:
module (nn.Module): module from which remove the parametrization
tensor_name (str): name of the parametrization to be removed
leave_parametrized (bool, optional): leave the attribute :attr:tensor_name parametrized.
Default: True

Returns:
Module: module

Raises:
ValueError: if module[tensor_name] is not parametrized
ValueError: if leave_parametrized=False and the parametrization depends on several tensors
"""

if not is_parametrized(module, tensor_name):
raise ValueError(f"Module {module} does not have a parametrization on {tensor_name}")

# Fetch the original tensor
assert isinstance(module.parametrizations, ModuleDict)  # Make mypy happy
parametrizations = module.parametrizations[tensor_name]
if parametrizations.is_tensor:
original = parametrizations.original
if leave_parametrized:
t = getattr(module, tensor_name)
# We know they have the same dtype because we have checked this when registering the
# parametrizations. As such, we can use set_
# We do this so that the parameter does not to change the id()
# This way the user does not need to update the optimizer
original.set_(t)
else:
if leave_parametrized:
# We cannot use no_grad because we need to know whether one or more
# original tensors required grad
t = getattr(module, tensor_name)
# We'll have to trust the user to add it to the optimizer
original = Parameter(t) if t.requires_grad else t
else:
raise ValueError("Cannot leave unparametrized (leave_parametrized=False) a tensor "
"that is parametrized in terms of a sequence of tensors.")

# Delete the property that manages the parametrization
delattr(module.__class__, tensor_name)
# Delete the ParametrizationList
del module.parametrizations[tensor_name]

# Restore the parameter / buffer into the main class
_register_parameter_or_buffer(module, tensor_name, original)

# Roll back the parametrized class if no other buffer or parameter
# is currently parametrized in this class
if not is_parametrized(module):
delattr(module, "parametrizations")
# Restore class
orig_cls = module.__class__.__bases__[0]
module.__class__ = orig_cls
return module