Added more PyTorch wrapper nodes.
This commit is contained in:
@@ -15,35 +15,29 @@ I hope you find it useful and engaging for data exploration.
|
||||
<hr>
|
||||
|
||||

|
||||
**ComfyUI-Data-Analysis** is an extension for ComfyUI that provides custom nodes for data analysis using Pandas, Seaborn, and Matplotlib within ComfyUI.
|
||||
|
||||
ComfyUI-Data-Analysis is an extension for ComfyUI consisting of many custom nodes for analyzing data using Pandas, Seaborn and Matplotlib within ComfyUI.
|
||||
Originally designed for structural data analysis, this extension is for you if you:
|
||||
- Want access to PyTorch's low-level methods (e.g., `add`, `div`, `max`, `where`, `scatter`, `gather`) to manipulate PyTorch tensors or extract information.
|
||||
- Are comfortable with ComfyUI and want to learn foundational PyTorch methods **without writing a single line of code**.
|
||||
- Want to analyze structural data (tabular data) using ComfyUI's node system.
|
||||
|
||||
ComfyUI-Data-Analysis supports a wide range of custom nodes in the categories below. For a complete list, see [Node Reference](docs/reference/node_reference.md):
|
||||
* Aggregation
|
||||
* Arithmetic method
|
||||
* Cumulative calculations
|
||||
* Data cleansing
|
||||
* Data subset selection
|
||||
* Data type conversion
|
||||
* DataFrame information
|
||||
* Date and time processing
|
||||
* Display data
|
||||
* IO
|
||||
* Math
|
||||
* Plot
|
||||
* Summary statistics
|
||||
* Data transformation
|
||||
## Features
|
||||
|
||||
You can connect these nodes to conduct complex analysis in an intuitive graphical way.
|
||||
You can also use other Comfy custom nodes to fit your needs (e.g., combining images).
|
||||
**ComfyUI-Data-Analysis** includes numerous custom nodes that wrap Pandas and PyTorch.
|
||||
For a complete list, see the [Node Reference](docs/reference/node_reference.md).
|
||||
|
||||
These custom nodes enhance efficiency and usability in data exploration and analysis.
|
||||
These nodes allow you to conduct complex analyses in an intuitive, graphical way. You can also combine them with other ComfyUI custom nodes to fit your workflow needs (e.g., integrating images).
|
||||
|
||||
Creating sample data and plotting it is incredibly simple, as shown below:
|
||||

|
||||
An example plot
|
||||
## Visualization & Analysis
|
||||
|
||||
These custom nodes enhance efficiency and usability in data exploration and visualization. Creating sample data and plotting it is incredibly simple:
|
||||
|
||||

|
||||
*Example plot*
|
||||
|
||||
Additionally, you can analyze images generated in ComfyUI’s workflows. Below is an example of a histogram showing the red channel pixel distribution:
|
||||
|
||||
You can also analyze images generated in ComfyUI's image generation workflows. Below screenshot shows a histogram of red channel pixels.
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
+51
@@ -121,6 +121,8 @@ from .modules.pandas_wrapper.pandas_xs import PandasXs
|
||||
from .modules.pytorch_wrapper.pt_abs import PtAbs
|
||||
from .modules.pytorch_wrapper.pt_acos import PtAcos
|
||||
from .modules.pytorch_wrapper.pt_add import PtAdd
|
||||
from .modules.pytorch_wrapper.pt_argmax import PtArgmax
|
||||
from .modules.pytorch_wrapper.pt_argmin import PtArgmin
|
||||
from .modules.pytorch_wrapper.pt_asin import PtAsin
|
||||
from .modules.pytorch_wrapper.pt_atan import PtAtan
|
||||
from .modules.pytorch_wrapper.pt_bitwise_and import PtBitwiseAnd
|
||||
@@ -144,8 +146,10 @@ from .modules.pytorch_wrapper.pt_from_image import PtFromImage
|
||||
from .modules.pytorch_wrapper.pt_from_latent import PtFromLatent
|
||||
from .modules.pytorch_wrapper.pt_from_numpy import PtFromNumpy
|
||||
from .modules.pytorch_wrapper.pt_full import PtFull
|
||||
from .modules.pytorch_wrapper.pt_gather import PtGather
|
||||
from .modules.pytorch_wrapper.pt_ge import PtGe
|
||||
from .modules.pytorch_wrapper.pt_gt import PtGt
|
||||
from .modules.pytorch_wrapper.pt_index_select import PtIndexSelect
|
||||
from .modules.pytorch_wrapper.pt_int_create import PtIntCreate
|
||||
from .modules.pytorch_wrapper.pt_le import PtLe
|
||||
from .modules.pytorch_wrapper.pt_log import PtLog
|
||||
@@ -154,7 +158,12 @@ from .modules.pytorch_wrapper.pt_logical_not import PtLogicalNot
|
||||
from .modules.pytorch_wrapper.pt_logical_or import PtLogicalOr
|
||||
from .modules.pytorch_wrapper.pt_logical_xor import PtLogicalXor
|
||||
from .modules.pytorch_wrapper.pt_lt import PtLt
|
||||
from .modules.pytorch_wrapper.pt_masked_select import PtMaskedSelect
|
||||
from .modules.pytorch_wrapper.pt_matmul import PtMatMul
|
||||
from .modules.pytorch_wrapper.pt_max import PtMax
|
||||
from .modules.pytorch_wrapper.pt_mean import PtMean
|
||||
from .modules.pytorch_wrapper.pt_median import PtMedian
|
||||
from .modules.pytorch_wrapper.pt_min import PtMin
|
||||
from .modules.pytorch_wrapper.pt_mm import PtMm
|
||||
from .modules.pytorch_wrapper.pt_mul import PtMul
|
||||
from .modules.pytorch_wrapper.pt_ne import PtNe
|
||||
@@ -162,10 +171,13 @@ from .modules.pytorch_wrapper.pt_neg import PtNeg
|
||||
from .modules.pytorch_wrapper.pt_ones import PtOnes
|
||||
from .modules.pytorch_wrapper.pt_permute import PtPermute
|
||||
from .modules.pytorch_wrapper.pt_pow import PtPow
|
||||
from .modules.pytorch_wrapper.pt_prod import PtProd
|
||||
from .modules.pytorch_wrapper.pt_rand import PtRand
|
||||
from .modules.pytorch_wrapper.pt_rand_int import PtRandInt
|
||||
from .modules.pytorch_wrapper.pt_randn import PtRandn
|
||||
from .modules.pytorch_wrapper.pt_remainder import PtRemainder
|
||||
from .modules.pytorch_wrapper.pt_reshape import PtReshape
|
||||
from .modules.pytorch_wrapper.pt_scatter import PtScatter
|
||||
from .modules.pytorch_wrapper.pt_show_text import PtShowText
|
||||
from .modules.pytorch_wrapper.pt_sin import PtSin
|
||||
from .modules.pytorch_wrapper.pt_sinh import PtSinh
|
||||
@@ -173,8 +185,11 @@ from .modules.pytorch_wrapper.pt_size import PtSize
|
||||
from .modules.pytorch_wrapper.pt_size_create import PtSizeCreate
|
||||
from .modules.pytorch_wrapper.pt_size_to_numpy import PtSizeToNumpy
|
||||
from .modules.pytorch_wrapper.pt_size_to_string import PtSizeToString
|
||||
from .modules.pytorch_wrapper.pt_sqrt import PtSqrt
|
||||
from .modules.pytorch_wrapper.pt_squeeze import PtSqueeze
|
||||
from .modules.pytorch_wrapper.pt_std import PtStd
|
||||
from .modules.pytorch_wrapper.pt_sub import PtSub
|
||||
from .modules.pytorch_wrapper.pt_sum import PtSum
|
||||
from .modules.pytorch_wrapper.pt_tan import PtTan
|
||||
from .modules.pytorch_wrapper.pt_tanh import PtTanh
|
||||
from .modules.pytorch_wrapper.pt_to_image import PtToImage
|
||||
@@ -182,7 +197,9 @@ from .modules.pytorch_wrapper.pt_to_latent import PtToLatent
|
||||
from .modules.pytorch_wrapper.pt_to_numpy import PtToNumpy
|
||||
from .modules.pytorch_wrapper.pt_to_rgb_tensors import PtToRgbTensors
|
||||
from .modules.pytorch_wrapper.pt_unsqueeze import PtUnsqueeze
|
||||
from .modules.pytorch_wrapper.pt_var import PtVar
|
||||
from .modules.pytorch_wrapper.pt_view import PtView
|
||||
from .modules.pytorch_wrapper.pt_where import PtWhere
|
||||
from .modules.pytorch_wrapper.pt_zeros import PtZeros
|
||||
from .modules.seaborn_wrapper.sns_bar import SNSBar
|
||||
from .modules.seaborn_wrapper.sns_boxplot import SNSBoxplot
|
||||
@@ -316,6 +333,8 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtAbs": PtAbs,
|
||||
"PtAcos": PtAcos,
|
||||
"PtAdd": PtAdd,
|
||||
"PtArgmax": PtArgmax,
|
||||
"PtArgmin": PtArgmin,
|
||||
"PtAsin": PtAsin,
|
||||
"PtAtan": PtAtan,
|
||||
"PtBitwiseAnd": PtBitwiseAnd,
|
||||
@@ -339,8 +358,10 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtFromLatent": PtFromLatent,
|
||||
"PtFromNumpy": PtFromNumpy,
|
||||
"PtFull": PtFull,
|
||||
"PtGather": PtGather,
|
||||
"PtGe": PtGe,
|
||||
"PtGt": PtGt,
|
||||
"PtIndexSelect": PtIndexSelect,
|
||||
"PtIntCreate": PtIntCreate,
|
||||
"PtLe": PtLe,
|
||||
"PtLog": PtLog,
|
||||
@@ -349,7 +370,12 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtLogicalOr": PtLogicalOr,
|
||||
"PtLogicalXor": PtLogicalXor,
|
||||
"PtLt": PtLt,
|
||||
"PtMaskedSelect": PtMaskedSelect,
|
||||
"PtMatMul": PtMatMul,
|
||||
"PtMax": PtMax,
|
||||
"PtMean": PtMean,
|
||||
"PtMedian": PtMedian,
|
||||
"PtMin": PtMin,
|
||||
"PtMm": PtMm,
|
||||
"PtMul": PtMul,
|
||||
"PtNe": PtNe,
|
||||
@@ -357,10 +383,13 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtOnes": PtOnes,
|
||||
"PtPermute": PtPermute,
|
||||
"PtPow": PtPow,
|
||||
"PtProd": PtProd,
|
||||
"PtRand": PtRand,
|
||||
"PtRandInt": PtRandInt,
|
||||
"PtRandn": PtRandn,
|
||||
"PtRemainder": PtRemainder,
|
||||
"PtReshape": PtReshape,
|
||||
"PtScatter": PtScatter,
|
||||
"PtShowText": PtShowText,
|
||||
"PtSin": PtSin,
|
||||
"PtSinh": PtSinh,
|
||||
@@ -368,8 +397,11 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtSizeCreate": PtSizeCreate,
|
||||
"PtSizeToNumpy": PtSizeToNumpy,
|
||||
"PtSizeToString": PtSizeToString,
|
||||
"PtSqrt": PtSqrt,
|
||||
"PtSqueeze": PtSqueeze,
|
||||
"PtStd": PtStd,
|
||||
"PtSub": PtSub,
|
||||
"PtSum": PtSum,
|
||||
"PtTan": PtTan,
|
||||
"PtTanh": PtTanh,
|
||||
"PtToImage": PtToImage,
|
||||
@@ -377,7 +409,9 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PtToNumpy": PtToNumpy,
|
||||
"PtToRgbTensors": PtToRgbTensors,
|
||||
"PtUnsqueeze": PtUnsqueeze,
|
||||
"PtVar": PtVar,
|
||||
"PtView": PtView,
|
||||
"PtWhere": PtWhere,
|
||||
"PtZeros": PtZeros,
|
||||
"PyKvFloatCreate": PyKvFloatCreate,
|
||||
"PyKvIntCreate": PyKvIntCreate,
|
||||
@@ -514,6 +548,8 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtAbs": "Pt Abs",
|
||||
"PtAcos": "Pt Acos",
|
||||
"PtAdd": "Pt Add",
|
||||
"PtArgmax": "Pt Argmax",
|
||||
"PtArgmin": "Pt Argmin",
|
||||
"PtAsin": "Pt Asin",
|
||||
"PtAtan": "Pt Atan",
|
||||
"PtBitwiseAnd": "Pt Bitwise And",
|
||||
@@ -537,8 +573,10 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtFromLatent": "Pt From Latent",
|
||||
"PtFromNumpy": "Pt From Numpy",
|
||||
"PtFull": "Pt Full",
|
||||
"PtGather": "Pt Gather",
|
||||
"PtGe": "Pt Ge",
|
||||
"PtGt": "Pt Gt",
|
||||
"PtIndexSelect": "Pt Index Select",
|
||||
"PtIntCreate": "Pt Int Create",
|
||||
"PtLe": "Pt Le",
|
||||
"PtLog": "Pt Log",
|
||||
@@ -547,7 +585,12 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtLogicalOr": "Pt Logical Or",
|
||||
"PtLogicalXor": "Pt Logical Xor",
|
||||
"PtLt": "Pt Lt",
|
||||
"PtMaskedSelect": "Pt Masked Select",
|
||||
"PtMatMul": "Pt Mat Mul",
|
||||
"PtMax": "Pt Max",
|
||||
"PtMean": "Pt Mean",
|
||||
"PtMedian": "Pt Median",
|
||||
"PtMin": "Pt Min",
|
||||
"PtMm": "Pt Mm",
|
||||
"PtMul": "Pt Mul",
|
||||
"PtNe": "Pt Ne",
|
||||
@@ -555,10 +598,13 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtOnes": "Pt Ones",
|
||||
"PtPermute": "Pt Permute",
|
||||
"PtPow": "Pt Pow",
|
||||
"PtProd": "Pt Prod",
|
||||
"PtRand": "Pt Rand",
|
||||
"PtRandInt": "Pt Rand Int",
|
||||
"PtRandn": "Pt Randn",
|
||||
"PtRemainder": "Pt Remainder",
|
||||
"PtReshape": "Pt Reshape",
|
||||
"PtScatter": "Pt Scatter",
|
||||
"PtShowText": "Pt Show Text",
|
||||
"PtSin": "Pt Sin",
|
||||
"PtSinh": "Pt Sinh",
|
||||
@@ -566,8 +612,11 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtSizeCreate": "Pt Size Create",
|
||||
"PtSizeToNumpy": "Pt Size To Numpy",
|
||||
"PtSizeToString": "Pt Size To String",
|
||||
"PtSqrt": "Pt Sqrt",
|
||||
"PtSqueeze": "Pt Squeeze",
|
||||
"PtStd": "Pt Std",
|
||||
"PtSub": "Pt Sub",
|
||||
"PtSum": "Pt Sum",
|
||||
"PtTan": "Pt Tan",
|
||||
"PtTanh": "Pt Tanh",
|
||||
"PtToImage": "Pt To Image",
|
||||
@@ -575,7 +624,9 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PtToNumpy": "Pt To Numpy",
|
||||
"PtToRgbTensors": "Pt To Rgb Tensors",
|
||||
"PtUnsqueeze": "Pt Unsqueeze",
|
||||
"PtVar": "Pt Var",
|
||||
"PtView": "Pt View",
|
||||
"PtWhere": "Pt Where",
|
||||
"PtZeros": "Pt Zeros",
|
||||
"PyKvFloatCreate": "Py Kv Float Create",
|
||||
"PyKvIntCreate": "Py Kv Int Create",
|
||||
|
||||
@@ -168,6 +168,14 @@
|
||||
| [Pt Le](pt_le.md) | Tests whether elements in the first PyTorch tensor are less than or equal to the corresponding elements in the second tensor. |
|
||||
| [Pt Lt](pt_lt.md) | Tests whether elements in the first PyTorch tensor are less than the corresponding elements in the second tensor. |
|
||||
| [Pt Ne](pt_ne.md) | Tests whether two PyTorch tensors are not equal element-wise. |
|
||||
## PyTorch wrapper - Indexing and Slicing Operations
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
| [Pt Gather](pt_gather.md) | Generates a tensor based on the index tensor using PyTorch's `gather` function. |
|
||||
| [Pt Index Select](pt_index_select.md) | Extracts elements from the input tensor along a specified dimension using an index tensor. |
|
||||
| [Pt Masked Select](pt_masked_select.md) | Extracts elements from the input tensor whose corresponding value in `masked_tens` is `True`. |
|
||||
| [Pt Scatter](pt_scatter.md) | Generates a new tensor by replacing values at specified positions using an index tensor. |
|
||||
| [Pt Where](pt_where.md) | Generates a new tensor by selecting values based on a condition tensor. |
|
||||
## PyTorch wrapper - Logical operations
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
@@ -189,6 +197,7 @@
|
||||
| [Pt Neg](pt_neg.md) | Computes the negation of each element in a PyTorch tensor. |
|
||||
| [Pt Sin](pt_sin.md) | Computes the sine of a PyTorch tensor element-wise. |
|
||||
| [Pt Sinh](pt_sinh.md) | Computes the hyperbolic sine of a PyTorch tensor element-wise. |
|
||||
| [Pt Sqrt](pt_sqrt.md) | Computes the square root of each element in a PyTorch tensor. |
|
||||
| [Pt Tan](pt_tan.md) | Computes the tangent of a PyTorch tensor element-wise. |
|
||||
| [Pt Tanh](pt_tanh.md) | Computes the hyperbolic tangent of a PyTorch tensor element-wise. |
|
||||
## PyTorch wrapper - Matrix operations
|
||||
@@ -198,6 +207,19 @@
|
||||
| [Pt Einsum](pt_einsum.md) | Performs Tensor operations specified in the Einstein summation equation. |
|
||||
| [Pt Mat Mul](pt_matmul.md) | Performs matrix multiplication on two PyTorch tensors. |
|
||||
| [Pt Mm](pt_mm.md) | Performs 2D matrix multiplication on two PyTorch tensors. |
|
||||
## PyTorch wrapper - Reduction operation & Summary statistics
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
| [Pt Argmax](pt_argmax.md) | Computes the indices of the maximum values of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Argmin](pt_argmin.md) | Computes the indices of the minimum values of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Max](pt_max.md) | Computes the maximum values of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Mean](pt_mean.md) | Computes the mean of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Median](pt_median.md) | Computes the median of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Min](pt_min.md) | Computes the minimum values of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Prod](pt_prod.md) | Computes the product of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Std](pt_std.md) | Computes the standard deviation of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Sum](pt_sum.md) | Computes the sum of a PyTorch tensor along the specified dimension(s). |
|
||||
| [Pt Var](pt_var.md) | Computes the variance of a PyTorch tensor along the specified dimension(s). |
|
||||
## PyTorch wrapper - Size object support
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
@@ -231,6 +253,7 @@
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
| [Pt Permute](pt_permute.md) | Permutes the dimensions of a PyTorch tensor according to the specified order. |
|
||||
| [Pt Reshape](pt_reshape.md) | Reshapes a PyTorch tensor into a specified shape using `torch.reshape()`. |
|
||||
| [Pt Squeeze](pt_squeeze.md) | Removes a dimension at the specified position in the input tensor if it is of size 1. |
|
||||
| [Pt Unsqueeze](pt_unsqueeze.md) | Adds a singleton dimension at the specified position in the input tensor. |
|
||||
| [Pt View](pt_view.md) | Reshapes a PyTorch tensor into a specified shape using `torch.view()`. |
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Argmax
|
||||
Computes the indices of the maximum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Argmin
|
||||
Computes the indices of the minimum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Pt Gather
|
||||
Generates a tensor based on the index tensor using PyTorch's `gather` function.
|
||||
|
||||
Specify the `dim` field using an integer to indicate the axis along which to gather elements.
|
||||
Each input tensor element is selected based on the index tensor.
|
||||
|
||||
For example, consider the following input tensor:
|
||||
```
|
||||
[ [10, 20, 30, 40, 50],
|
||||
[100, 200, 300, 400, 500]]
|
||||
```
|
||||
|
||||
and the corresponding index tensor:
|
||||
|
||||
```
|
||||
[ [0, 4, 3, 2, 0],
|
||||
[4, 3, 0, 0, 0]]
|
||||
```
|
||||
|
||||
If `dim = 0`, the function scans row-wise, treating each index value as a row index.
|
||||
If `dim = 1`, it scans column-wise, interpreting each index value as a column index.
|
||||
|
||||
Let's analyze the case where `dim = 1`:
|
||||
|
||||
* Start at row 0, column 0.
|
||||
* The index at this position is `index[0, 0] = 0`.
|
||||
* PyTorch selects the value at position 0 from the array `[10, 20, 30, 40, 50]`, which is `10`.
|
||||
* The result at this stage is:
|
||||
```
|
||||
[[10, ?, ?, ?, ?]
|
||||
[?, ?, ?, ?, ?]]
|
||||
```
|
||||
|
||||
* Moving to column 1: `index[0, 1] = 4`.
|
||||
* The value at index 4 in `[10, 20, 30, 40, 50]` is `50`.
|
||||
* The updated result is:
|
||||
```
|
||||
[[10, 50, ?, ?, ?]
|
||||
[?, ?, ?, ?, ?]]
|
||||
```
|
||||
|
||||
* Repeating this process for all elements constructs the final gathered tensor.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | Int |
|
||||
| index | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Pt Index Select
|
||||
Extracts elements from the input tensor along a specified dimension using an index tensor.
|
||||
|
||||
`dim` specifies the dimension along which the selection occurs.
|
||||
* For example, for 2D tensors:
|
||||
** If `dim=0`, `index` selects rows.
|
||||
** If `dim=1`, `index` selects columns (for 2D tensors).
|
||||
|
||||
`index` is a list of indices that will be converted into a tensor.
|
||||
|
||||
Example:
|
||||
```
|
||||
Input Tensor:
|
||||
[[1, 2, 3],
|
||||
[40, 50, 60],
|
||||
[700, 800, 900]]
|
||||
|
||||
index = "[0, 2]"
|
||||
dim = 0
|
||||
|
||||
Output Tensor:
|
||||
[[1, 2, 3],
|
||||
[700, 800, 900]]
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | Int |
|
||||
| index | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Pt Masked Select
|
||||
Extracts elements from the input tensor whose corresponding value in `masked_tens` is `True`.
|
||||
|
||||
Example:
|
||||
```
|
||||
Input Tensor:
|
||||
[[1, 2, 3],
|
||||
[40, 50, 60],
|
||||
[700, 800, 900]]
|
||||
|
||||
Masked Tensor:
|
||||
[[True, False, False],
|
||||
[False, True, False],
|
||||
[False, False, True]]
|
||||
|
||||
Output Tensor:
|
||||
[1, 50, 900]
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| masked_tens | Tensor |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Max
|
||||
Computes the maximum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Pt Mean
|
||||
Computes the mean of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
This node supports only floating-point or complex tensors as input.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Pt Median
|
||||
Computes the median of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
or
|
||||
```
|
||||
1
|
||||
```
|
||||
Note that PtMedian calls torch.median(), which returns the lower of the two numbers when the true median falls between them.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Min
|
||||
Computes the minimum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pt Prod
|
||||
Computes the product of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
or
|
||||
```
|
||||
1
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Pt Reshape
|
||||
Reshapes a PyTorch tensor into a specified shape using `torch.reshape()`.
|
||||
The total number of elements must remain unchanged.
|
||||
|
||||
For example, if a tensor has shape (2, 3, 4), and `new_shape="[6, 4]"`,
|
||||
the output will have shape (6, 4).
|
||||
|
||||
Use -1 to automatically infer a dimension, e.g.:
|
||||
```
|
||||
[2, -1]
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| new_shape | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Transform
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Scatter
|
||||
Generates a new tensor by replacing values at specified positions using an index tensor.
|
||||
|
||||
* Target tensor (tens): Some of whose values are replaced.
|
||||
* Source tensor (src): Values from this tensor replace a part or whole of the target tensor.
|
||||
* Index tensor (index): Specifies the positions in the target tensor for replacement.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | Int |
|
||||
| index | String |
|
||||
| src | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Pt Sqrt
|
||||
Computes the square root of each element in a PyTorch tensor.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens_a | Tensor |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Math operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pt Std
|
||||
Computes the standard deviation of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify 1 to use Bessel's correction (N-1) for sample standard deviation.
|
||||
Specify 0 to compute population standard deviation.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| correction | Int |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pt Sum
|
||||
Computes the sum of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pt Var
|
||||
Computes the variance of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify 1 to use Bessel's correction (N-1) for sample variance.
|
||||
Specify 0 to compute population variance.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| tens | Tensor |
|
||||
| correction | Int |
|
||||
| dim | String |
|
||||
| keepdim | Boolean |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Pt Where
|
||||
Generates a new tensor by selecting values based on a condition tensor.
|
||||
|
||||
* `condition_tens` (torch.Tensor): Boolean tensor that determines which values are selected.
|
||||
* `true_tens` (torch.Tensor): Values to use where the condition is `True`.
|
||||
* `false_tens` (torch.Tensor): Values to use where the condition is `False`.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| condition_tens | Tensor |
|
||||
| true_tens | Tensor |
|
||||
| false_tens | Tensor |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| Tensor |
|
||||
|
||||
<HR>
|
||||
Category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,59 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtArgmax:
|
||||
"""
|
||||
Computes the indices of the maximum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the indices of the maximum values along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute argmax,
|
||||
e.g., "0" or "".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the tensor with indices of maximum values.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the argmax along the specified dimension(s)
|
||||
tens = torch.argmax(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,59 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtArgmin:
|
||||
"""
|
||||
Computes the indices of the minimum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the indices of the minimum values along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute argmin,
|
||||
e.g., "0" or "".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the tensor with indices of minimum values.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the argmin along the specified dimension(s)
|
||||
tens = torch.argmin(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,94 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
import ast
|
||||
|
||||
|
||||
class PtGather:
|
||||
"""
|
||||
Generates a tensor based on the index tensor using PyTorch's `gather` function.
|
||||
|
||||
Specify the `dim` field using an integer to indicate the axis along which to gather elements.
|
||||
Each input tensor element is selected based on the index tensor.
|
||||
|
||||
For example, consider the following input tensor:
|
||||
```
|
||||
[ [10, 20, 30, 40, 50],
|
||||
[100, 200, 300, 400, 500]]
|
||||
```
|
||||
|
||||
and the corresponding index tensor:
|
||||
|
||||
```
|
||||
[ [0, 4, 3, 2, 0],
|
||||
[4, 3, 0, 0, 0]]
|
||||
```
|
||||
|
||||
If `dim = 0`, the function scans row-wise, treating each index value as a row index.
|
||||
If `dim = 1`, it scans column-wise, interpreting each index value as a column index.
|
||||
|
||||
Let's analyze the case where `dim = 1`:
|
||||
|
||||
* Start at row 0, column 0.
|
||||
* The index at this position is `index[0, 0] = 0`.
|
||||
* PyTorch selects the value at position 0 from the array `[10, 20, 30, 40, 50]`, which is `10`.
|
||||
* The result at this stage is:
|
||||
```
|
||||
[[10, ?, ?, ?, ?]
|
||||
[?, ?, ?, ?, ?]]
|
||||
```
|
||||
|
||||
* Moving to column 1: `index[0, 1] = 4`.
|
||||
* The value at index 4 in `[10, 20, 30, 40, 50]` is `50`.
|
||||
* The updated result is:
|
||||
```
|
||||
[[10, 50, ?, ?, ?]
|
||||
[?, ?, ?, ?, ?]]
|
||||
```
|
||||
|
||||
* Repeating this process for all elements constructs the final gathered tensor.
|
||||
|
||||
category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("INT", {"default": 0, "min": -10, "max": 10}),
|
||||
"index": ("STRING", {"multiline": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: int, index: str) -> tuple:
|
||||
"""
|
||||
Gathers elements along the specified dimension using an index tensor.
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (int): The dimension along which to gather values.
|
||||
index (str): A string representation of the index tensor, provided in list format.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the gathered tensor.
|
||||
"""
|
||||
# Parse the index string to a Python list
|
||||
index = ast.literal_eval(index)
|
||||
|
||||
# Convert the parsed list to a tensor
|
||||
index_tensor = torch.tensor(index, dtype=torch.long, device=tens.device)
|
||||
|
||||
# Perform the gather operation
|
||||
gathered_tens = torch.gather(tens, dim=dim, index=index_tensor)
|
||||
|
||||
return (gathered_tens,)
|
||||
@@ -0,0 +1,78 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
import ast
|
||||
|
||||
|
||||
class PtIndexSelect:
|
||||
"""
|
||||
Extracts elements from the input tensor along a specified dimension using an index tensor.
|
||||
|
||||
`dim` specifies the dimension along which the selection occurs.
|
||||
* For example, for 2D tensors:
|
||||
** If `dim=0`, `index` selects rows.
|
||||
** If `dim=1`, `index` selects columns (for 2D tensors).
|
||||
|
||||
`index` is a list of indices that will be converted into a tensor.
|
||||
|
||||
Example:
|
||||
```
|
||||
Input Tensor:
|
||||
[[1, 2, 3],
|
||||
[40, 50, 60],
|
||||
[700, 800, 900]]
|
||||
|
||||
index = "[0, 2]"
|
||||
dim = 0
|
||||
|
||||
Output Tensor:
|
||||
[[1, 2, 3],
|
||||
[700, 800, 900]]
|
||||
```
|
||||
|
||||
category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("INT", {"default": 0, "min": -10, "max": 10}),
|
||||
"index": ("STRING", {"multiline": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: int, index: str) -> tuple:
|
||||
"""
|
||||
Extracts elements from the input tensor along the specified dimension.
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (int): The dimension along which elements are selected.
|
||||
index (str): A string representation of a list of indices, e.g., "[0, 2]".
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the selected tensor.
|
||||
"""
|
||||
# Convert the string index to a Python list
|
||||
index_list = ast.literal_eval(index)
|
||||
if not isinstance(index_list, list):
|
||||
raise ValueError("Index must be a list of integers.")
|
||||
|
||||
# Convert the index list to a tensor
|
||||
index_tensor = torch.tensor(index_list, dtype=torch.long)
|
||||
|
||||
# Perform index selection
|
||||
result = torch.index_select(tens, dim=dim, index=index_tensor)
|
||||
|
||||
return (result,)
|
||||
@@ -0,0 +1,62 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
|
||||
|
||||
class PtMaskedSelect:
|
||||
"""
|
||||
Extracts elements from the input tensor whose corresponding value in `masked_tens` is `True`.
|
||||
|
||||
Example:
|
||||
```
|
||||
Input Tensor:
|
||||
[[1, 2, 3],
|
||||
[40, 50, 60],
|
||||
[700, 800, 900]]
|
||||
|
||||
Masked Tensor:
|
||||
[[True, False, False],
|
||||
[False, True, False],
|
||||
[False, False, True]]
|
||||
|
||||
Output Tensor:
|
||||
[1, 50, 900]
|
||||
```
|
||||
|
||||
category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"masked_tens": ("TENSOR", {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, masked_tens: torch.Tensor) -> tuple:
|
||||
"""
|
||||
Extracts elements from `tens` where `masked_tens` is `True`.
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
masked_tens (torch.Tensor): A boolean tensor specifying which elements to select.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the selected tensor.
|
||||
"""
|
||||
if masked_tens.dtype != torch.bool:
|
||||
raise ValueError("masked_tens must be a boolean tensor (dtype=torch.bool)")
|
||||
|
||||
result = torch.masked_select(tens, masked_tens)
|
||||
return (result,)
|
||||
@@ -0,0 +1,59 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
import ast
|
||||
from .utils import str_to_dim
|
||||
|
||||
class PtMax:
|
||||
"""
|
||||
Computes the maximum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the maximum values along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the maximum,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the tensor with maximum values.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the max along the specified dimension(s)
|
||||
tens = torch.amax(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtMean:
|
||||
"""
|
||||
Computes the mean of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
This node supports only floating-point or complex tensors as input.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the mean along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the mean,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the mean tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the mean along the specified dimension(s)
|
||||
tens = torch.mean(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,66 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtMedian:
|
||||
"""
|
||||
Computes the median of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
or
|
||||
```
|
||||
1
|
||||
```
|
||||
Note that PtMedian calls torch.median(), which returns the lower of the two numbers when the true median falls between them.
|
||||
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the median along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the median,
|
||||
e.g., "0", or "1".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the median tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
if not isinstance(dim, int):
|
||||
raise TypeError(f"Invalid type for dim: {dim}. Must be a integer.")
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the median along the specified dimension(s)
|
||||
tens, _ = torch.median(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,59 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtMin:
|
||||
"""
|
||||
Computes the minimum values of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the minimum values along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the minimum,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the tensor with minimum values.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the min along the specified dimension(s)
|
||||
tens = torch.amin(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,65 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtProd:
|
||||
"""
|
||||
Computes the product of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer as shown below:
|
||||
```
|
||||
0
|
||||
```
|
||||
or
|
||||
```
|
||||
1
|
||||
```
|
||||
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the product along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the product,
|
||||
e.g., "0" or "1".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the product tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
if not isinstance(dim, int):
|
||||
raise TypeError(f"Invalid type for dim: {dim}. Must be a integer.")
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the product along the specified dimension(s)
|
||||
tens = torch.prod(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,62 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
import ast
|
||||
|
||||
|
||||
class PtReshape:
|
||||
"""
|
||||
Reshapes a PyTorch tensor into a specified shape using `torch.reshape()`.
|
||||
The total number of elements must remain unchanged.
|
||||
|
||||
For example, if a tensor has shape (2, 3, 4), and `new_shape="[6, 4]"`,
|
||||
the output will have shape (6, 4).
|
||||
|
||||
Use -1 to automatically infer a dimension, e.g.:
|
||||
```
|
||||
[2, -1]
|
||||
```
|
||||
category: PyTorch wrapper - Transform
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"new_shape": ("STRING", {"multiline": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, new_shape: str) -> tuple:
|
||||
"""
|
||||
Reshapes the input tensor based on the specified shape.
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
new_shape (str): A string representation of the desired shape,
|
||||
e.g., "[2, -1]" or "(6, 4)".
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the reshaped PyTorch tensor.
|
||||
"""
|
||||
# Convert string to a tuple of integers
|
||||
shape_order = tuple(ast.literal_eval(new_shape))
|
||||
|
||||
# Ensure the parsed shape is valid
|
||||
if not isinstance(shape_order, tuple) or not all(isinstance(i, int) for i in shape_order):
|
||||
raise ValueError(f"Invalid format for new_shape: {new_shape}. Must be a tuple or list of integers.")
|
||||
|
||||
# Apply reshape operation
|
||||
tens = tens.reshape(*shape_order)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,69 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
import ast
|
||||
|
||||
class PtScatter:
|
||||
"""
|
||||
Generates a new tensor by replacing values at specified positions using an index tensor.
|
||||
|
||||
* Target tensor (tens): Some of whose values are replaced.
|
||||
* Source tensor (src): Values from this tensor replace a part or whole of the target tensor.
|
||||
* Index tensor (index): Specifies the positions in the target tensor for replacement.
|
||||
|
||||
category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("INT", {"default": 0, "min": -10, "max": 10}),
|
||||
"index": ("STRING", {"multiline": True}),
|
||||
"src": ("STRING", {"multiline": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self,
|
||||
tens: torch.Tensor,
|
||||
dim: int,
|
||||
index: str,
|
||||
src: str) -> tuple:
|
||||
"""
|
||||
Replaces elements in the target tensor along the specified dimension using an index tensor.
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The target tensor whose values will be replaced.
|
||||
dim (int): The dimension along which values are replaced.
|
||||
index (str): A string representation of the index tensor (list format).
|
||||
src (str): A string representation of the source tensor (list format).
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the modified tensor.
|
||||
"""
|
||||
# Parse the input index and source tensors from string representations
|
||||
index_list = ast.literal_eval(index)
|
||||
src_list = ast.literal_eval(src)
|
||||
|
||||
# Convert to tensors
|
||||
index_tensor = torch.tensor(index_list, dtype=torch.long, device=tens.device)
|
||||
src_tensor = torch.tensor(src_list, dtype=tens.dtype, device=tens.device)
|
||||
|
||||
# Ensure index and src shapes match
|
||||
if index_tensor.shape != src_tensor.shape:
|
||||
raise ValueError(f"Shape mismatch: index tensor {index_tensor.shape} and src tensor {src_tensor.shape} must match.")
|
||||
|
||||
# Perform the scatter operation
|
||||
updated_tens = torch.scatter(tens.clone(), dim=dim, index=index_tensor, src=src_tensor)
|
||||
|
||||
return (updated_tens,)
|
||||
@@ -0,0 +1,39 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
|
||||
class PtSqrt:
|
||||
"""
|
||||
Computes the square root of each element in a PyTorch tensor.
|
||||
|
||||
category: PyTorch wrapper - Math operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the required input types.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary of required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens_a": ("TENSOR", {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens_a: torch.Tensor) -> tuple:
|
||||
"""
|
||||
Computes the square root of a PyTorch tensor element-wise.
|
||||
|
||||
Args:
|
||||
tens_a (torch.Tensor): A PyTorch tensor of numerical type.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the resultant tensor after applying the square root function.
|
||||
"""
|
||||
return (torch.sqrt(tens_a),)
|
||||
@@ -0,0 +1,68 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtStd:
|
||||
"""
|
||||
Computes the standard deviation of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify 1 to use Bessel's correction (N-1) for sample standard deviation.
|
||||
Specify 0 to compute population standard deviation.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"correction": ("INT", {"default": 1, "min": 0, "max": 1}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, correction: int, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the standard deviation along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the standard deviation,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
correction (int): 0 for population standard deviation, 1 for sample standard deviation (Bessel's correction).
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the standard deviation tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure correction is valid (0 or 1)
|
||||
if correction not in (0, 1):
|
||||
raise ValueError(f"Invalid correction value: {correction}. Must be 0 (population) or 1 (sample).")
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the standard deviation along the specified dimension(s)
|
||||
tens = torch.std(tens, dim=dim, correction=correction, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,59 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtSum:
|
||||
"""
|
||||
Computes the sum of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the sum along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the sum,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the summed tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the sum along the specified dimension(s)
|
||||
tens = torch.sum(tens, dim=dim, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,68 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
from .utils import str_to_dim
|
||||
|
||||
|
||||
class PtVar:
|
||||
"""
|
||||
Computes the variance of a PyTorch tensor along the specified dimension(s).
|
||||
|
||||
Specify 1 to use Bessel's correction (N-1) for sample variance.
|
||||
Specify 0 to compute population variance.
|
||||
|
||||
Specify the dimension(s) in the `dim` field using an integer, a list, or a tuple, as shown below:
|
||||
```
|
||||
0, [0], or (1, 2)
|
||||
```
|
||||
category: PyTorch wrapper - Reduction operation & Summary statistics
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"tens": ("TENSOR", {}),
|
||||
"correction": ("INT", {"default": 1, "min": 0, "max": 1}),
|
||||
"dim": ("STRING", {"multiline": True}),
|
||||
"keepdim": ("BOOLEAN", {"default": False})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, tens: torch.Tensor, dim: str, correction: int, keepdim: bool) -> tuple:
|
||||
"""
|
||||
Computes the variance along the specified dimension(s).
|
||||
|
||||
Args:
|
||||
tens (torch.Tensor): The input tensor.
|
||||
dim (str): A string representation of the dimension(s) along which to compute the variance,
|
||||
e.g., "0", "[0]", or "(1, 2)".
|
||||
correction (int): 0 for population variance, 1 for sample variance (Bessel's correction).
|
||||
keepdim (bool): Whether to retain reduced dimensions.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the variance tensor.
|
||||
"""
|
||||
dim = str_to_dim(dim)
|
||||
|
||||
# Ensure correction is valid (0 or 1)
|
||||
if correction not in (0, 1):
|
||||
raise ValueError(f"Invalid correction value: {correction}. Must be 0 (population) or 1 (sample).")
|
||||
|
||||
# Ensure keepdim is a boolean
|
||||
if not isinstance(keepdim, bool):
|
||||
raise TypeError(f"Invalid type for keepdim: {keepdim}. Must be a boolean.")
|
||||
|
||||
# Compute the variance along the specified dimension(s)
|
||||
tens = torch.var(tens, dim=dim, correction=correction, keepdim=keepdim)
|
||||
|
||||
return (tens,)
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import Any, Dict
|
||||
import torch
|
||||
|
||||
class PtWhere:
|
||||
"""
|
||||
Generates a new tensor by selecting values based on a condition tensor.
|
||||
|
||||
* `condition_tens` (torch.Tensor): Boolean tensor that determines which values are selected.
|
||||
* `true_tens` (torch.Tensor): Values to use where the condition is `True`.
|
||||
* `false_tens` (torch.Tensor): Values to use where the condition is `False`.
|
||||
|
||||
category: PyTorch wrapper - Indexing and Slicing Operations
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"condition_tens": ("TENSOR", {}),
|
||||
"true_tens": ("TENSOR", {}),
|
||||
"false_tens": ("TENSOR", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("TENSOR",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self,
|
||||
condition_tens: torch.Tensor,
|
||||
true_tens: torch.Tensor,
|
||||
false_tens: torch.Tensor) -> tuple:
|
||||
"""
|
||||
Selects values from `true_tens` or `false_tens` based on `condition_tens`.
|
||||
|
||||
Args:
|
||||
condition_tens (torch.Tensor): Boolean tensor indicating selection conditions.
|
||||
true_tens (torch.Tensor): Values used where condition is True.
|
||||
false_tens (torch.Tensor): Values used where condition is False.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the modified tensor.
|
||||
"""
|
||||
# Ensure condition_tens is a boolean tensor
|
||||
if condition_tens.dtype != torch.bool:
|
||||
raise TypeError(f"Expected `condition_tens` to be a boolean tensor, got {condition_tens.dtype}")
|
||||
|
||||
# Ensure all tensors are compatible in shape
|
||||
if not torch.broadcast_shapes(condition_tens.shape, true_tens.shape, false_tens.shape):
|
||||
raise ValueError(f"Shape mismatch: condition {condition_tens.shape}, true {true_tens.shape}, false {false_tens.shape}")
|
||||
|
||||
# Perform the conditional selection
|
||||
tens_out = torch.where(condition_tens, true_tens, false_tens)
|
||||
|
||||
return (tens_out,)
|
||||
@@ -1,3 +1,5 @@
|
||||
import ast
|
||||
from typing import Optional, Tuple, Union
|
||||
import torch
|
||||
|
||||
DTYPE_MAPPING = {
|
||||
@@ -11,4 +13,40 @@ DTYPE_MAPPING = {
|
||||
"int32": torch.int32,
|
||||
"int64": torch.int64,
|
||||
"bool": torch.bool
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def str_to_dim(dim: str) -> Optional[Union[int, Tuple[int, ...]]]:
|
||||
"""
|
||||
Converts a string representation of a dimension into an integer or a tuple of integers.
|
||||
|
||||
Args:
|
||||
dim (str): A string representing an integer or a tuple of integers.
|
||||
|
||||
Returns:
|
||||
Optional[Union[int, Tuple[int, ...]]]:
|
||||
- An integer if the input represents a single integer.
|
||||
- A tuple of integers if the input represents a list or tuple.
|
||||
- None if the input is empty.
|
||||
|
||||
Raises:
|
||||
ValueError: If the parsed value is not an integer or a tuple of integers.
|
||||
"""
|
||||
if dim:
|
||||
# Convert string to an integer, list, or tuple of integers
|
||||
parsed_dim = ast.literal_eval(dim)
|
||||
|
||||
# Convert list to tuple
|
||||
if isinstance(parsed_dim, list):
|
||||
parsed_dim = tuple(parsed_dim)
|
||||
|
||||
# Ensure the parsed dim is valid
|
||||
if not isinstance(parsed_dim, (int, tuple)) or (
|
||||
isinstance(parsed_dim, tuple) and not all(isinstance(i, int) for i in parsed_dim)
|
||||
):
|
||||
raise ValueError(f"Invalid format for dim: {parsed_dim}. Must be an integer or a tuple of integers.")
|
||||
|
||||
return parsed_dim
|
||||
|
||||
return None
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "data-analysis"
|
||||
description = "Data analysis custom modules for ComfyUI - Use Pandas & Matplotlib within ComfyUI"
|
||||
version = "1.4.1"
|
||||
version = "1.4.2"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_argmax import PtArgmax
|
||||
|
||||
|
||||
class TestPtArgmax(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtArgmax()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(torch.tensor([[1, 3, 2], [4, 0, 5]]), "0", False, torch.tensor([1, 0, 1])),
|
||||
(torch.tensor([[1, 3, 2], [4, 0, 5]]), "1", True, torch.tensor([[1], [2]])),
|
||||
(torch.tensor([[10, 3, 2], [123, 0, 5]]), "", False, torch.tensor(3)),
|
||||
]
|
||||
|
||||
def test_argmax(self):
|
||||
"""Test torch.argmax behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected indices
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,39 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_argmin import PtArgmin
|
||||
|
||||
|
||||
class TestPtArgmin(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtArgmin()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(torch.tensor([[1, 3, 2], [4, 0, 5]]), "0", False, torch.tensor([0, 1, 0])),
|
||||
(torch.tensor([[1, 3, 2], [4, 0, 5]]), "1", True, torch.tensor([[0], [1]])),
|
||||
(torch.tensor([[1, 3, 2], [4, 0, 5]]), "", False, torch.tensor(4)),
|
||||
]
|
||||
|
||||
def test_argmin(self):
|
||||
"""Test torch.argmin behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected indices
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,48 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_gather import PtGather
|
||||
|
||||
|
||||
class TestPtGather(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtGather()
|
||||
|
||||
# Test cases: (Tensor, Dim, Index (as string), Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[10, 20, 30, 40, 50], [100, 200, 300, 400, 500]]),
|
||||
1,
|
||||
"[[0, 4, 3, 2, 0], [4, 3, 0, 0, 0]]",
|
||||
torch.tensor([[10, 50, 40, 30, 10], [500, 400, 100, 100, 100]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 2], [3, 4]]),
|
||||
0,
|
||||
"[[1, 0], [0, 1]]",
|
||||
torch.tensor([[3, 2], [1, 4]])
|
||||
),
|
||||
]
|
||||
|
||||
def test_gather(self):
|
||||
"""Test torch.gather behavior."""
|
||||
for tens, dim, index, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, index=index):
|
||||
result, = self.node.f(tens, dim, index)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected gathered values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,48 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_index_select import PtIndexSelect
|
||||
|
||||
|
||||
class TestPtIndexSelect(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtIndexSelect()
|
||||
|
||||
# Test cases: (Tensor, Dim, Index (as string), Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 2, 3], [40, 50, 60], [700, 800, 900]]),
|
||||
0,
|
||||
"[0, 2]",
|
||||
torch.tensor([[1, 2, 3], [700, 800, 900]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 2, 3], [40, 50, 60], [700, 800, 900]]),
|
||||
1,
|
||||
"[1, 2]",
|
||||
torch.tensor([[2, 3], [50, 60], [800, 900]])
|
||||
),
|
||||
]
|
||||
|
||||
def test_index_select(self):
|
||||
"""Test torch.index_select behavior."""
|
||||
for tens, dim, index, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, index=index):
|
||||
result, = self.node.f(tens, dim, index)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected selected values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,40 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_masked_select import PtMaskedSelect
|
||||
|
||||
|
||||
class TestPtMaskedSelect(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtMaskedSelect()
|
||||
|
||||
# Test cases: (Tensor, Masked Tensor, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 2, 3], [40, 50, 60], [700, 800, 900]]),
|
||||
torch.tensor([[True, False, False], [False, True, False], [False, False, True]]),
|
||||
torch.tensor([1, 50, 900])
|
||||
),
|
||||
]
|
||||
|
||||
def test_masked_select(self):
|
||||
"""Test torch.masked_select behavior."""
|
||||
for tens, masked_tens, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, masked_tens=masked_tens):
|
||||
result, = self.node.f(tens, masked_tens)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected selected values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,61 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_max import PtMax
|
||||
|
||||
|
||||
class TestPtMax(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtMax()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([4, 3, 5])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[3], [5]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[[1, 5], [2, 8]], [[3, 4], [6, 7]]]),
|
||||
"(0, 1)",
|
||||
False,
|
||||
torch.tensor([6, 8])
|
||||
),
|
||||
(
|
||||
# Reduce across all axes
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"", # Passing empty string to reduce across all dimensions
|
||||
False,
|
||||
torch.tensor(5)
|
||||
)
|
||||
]
|
||||
|
||||
def test_max(self):
|
||||
"""Test torch.max behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected max values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,87 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_mean import PtMean
|
||||
|
||||
|
||||
class TestPtMean(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtMean()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
# Float tensor cases
|
||||
(
|
||||
torch.tensor([[1.0, 3.0, 2.0], [4.0, 0.0, 5.0]], dtype=torch.float),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([2.5, 1.5, 3.5], dtype=torch.float)
|
||||
),
|
||||
(
|
||||
torch.tensor([[1.0, 3.0, 2.0], [4.0, 0.0, 5.0]], dtype=torch.float),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[2.], [3.]], dtype=torch.float)
|
||||
),
|
||||
(
|
||||
torch.tensor([[[1.0, 5.0], [2.0, 8.0]], [[3.0, 4.0], [6.0, 7.0]]], dtype=torch.float),
|
||||
"(0, 1)",
|
||||
False,
|
||||
torch.tensor([3.0, 6.0], dtype=torch.float)
|
||||
),
|
||||
(
|
||||
# Reduce across all axes
|
||||
torch.tensor([[1.0, 3.0, 2.0], [4.0, 0.0, 5.0]], dtype=torch.float),
|
||||
"", # Passing empty string to reduce across all dimensions
|
||||
False,
|
||||
torch.tensor(2.5, dtype=torch.float)
|
||||
),
|
||||
# Complex tensor cases
|
||||
(
|
||||
torch.tensor([[1 + 1j, 3 + 3j, 2 + 2j], [4 + 4j, 0 + 0j, 5 + 5j]], dtype=torch.complex64),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([2.5 + 2.5j, 1.5 + 1.5j, 3.5 + 3.5j], dtype=torch.complex64)
|
||||
),
|
||||
(
|
||||
torch.tensor([[1 + 1j, 3 + 3j, 2 + 2j], [4 + 4j, 0 + 0j, 5 + 5j]], dtype=torch.complex64),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[2. + 2j], [3. + 3j]], dtype=torch.complex64)
|
||||
),
|
||||
(
|
||||
torch.tensor([[[1 + 1j, 5 + 5j], [2 + 2j, 8 + 8j]], [[3 + 3j, 4 + 4j], [6 + 6j, 7 + 7j]]], dtype=torch.complex64),
|
||||
"(0, 1)",
|
||||
False,
|
||||
torch.tensor([3. + 3j, 6. + 6j], dtype=torch.complex64)
|
||||
),
|
||||
(
|
||||
# Reduce across all axes
|
||||
torch.tensor([[1 + 1j, 3 + 3j, 2 + 2j], [4 + 4j, 0 + 0j, 5 + 5j]], dtype=torch.complex64),
|
||||
"", # Passing empty string to reduce across all dimensions
|
||||
False,
|
||||
torch.tensor(2.5 + 2.5j, dtype=torch.complex64)
|
||||
)
|
||||
]
|
||||
|
||||
def test_mean(self):
|
||||
"""Test torch.mean behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected mean values
|
||||
self.assertTrue(torch.allclose(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,66 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_median import PtMedian
|
||||
|
||||
|
||||
class TestPtMedian(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtMedian()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [2, 1, 3], [4, 0, 5]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([2, 1, 3])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([1, 0, 2]) # Fix: torch.median returns the lower value when between two numbers
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[2], [4]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5], [7, 8, 6], [9, 2, 10]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([4, 2, 5])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2, 8], [4, 0, 5, 6], [7, 8, 6, 9]]),
|
||||
"1",
|
||||
False,
|
||||
torch.tensor([2, 4, 7])
|
||||
)
|
||||
]
|
||||
|
||||
def test_median(self):
|
||||
"""Test torch.median behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected median values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,61 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_min import PtMin
|
||||
|
||||
|
||||
class TestPtMin(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtMin()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([1, 0, 2])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[1], [0]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[[1, 5], [2, 8]], [[3, 4], [6, 7]]]),
|
||||
"(0, 1)",
|
||||
False,
|
||||
torch.tensor([1, 4])
|
||||
),
|
||||
(
|
||||
# Reduce across all axes
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"", # Passing empty string to reduce across all dimensions
|
||||
False,
|
||||
torch.tensor(0)
|
||||
)
|
||||
]
|
||||
|
||||
def test_amin(self):
|
||||
"""Test torch.amin behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected min values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_prod import PtProd
|
||||
|
||||
|
||||
class TestPtProd(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtProd()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [2, 1, 3]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([2, 3, 6])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[6], [0]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 5, 6]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([4, 15, 12])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 5, 6], [7, 8, 9]]),
|
||||
"1",
|
||||
False,
|
||||
torch.tensor([6, 120, 504])
|
||||
)
|
||||
]
|
||||
|
||||
def test_prod(self):
|
||||
"""Test torch.prod behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected product values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,60 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_reshape import PtReshape # Importing the PtReshape class
|
||||
|
||||
|
||||
class TestPtReshape(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtReshape()
|
||||
|
||||
# Define test cases: (input_tensor, new_shape, expected_shape)
|
||||
self.test_cases = [
|
||||
# Case 1: Reshape a 2D tensor
|
||||
(torch.ones(2, 3), "[3, 2]", (3, 2)), # (2,3) -> (3,2)
|
||||
|
||||
# Case 2: Reshape a 3D tensor
|
||||
(torch.ones(2, 3, 4), "[6, 4]", (6, 4)), # (2,3,4) -> (6,4)
|
||||
|
||||
# Case 3: Using -1 for automatic inference
|
||||
(torch.ones(2, 3, 4), "[2, -1]", (2, 12)), # (2,3,4) -> (2,12)
|
||||
(torch.ones(6, 4), "[-1, 4]", (6, 4)), # (6,4) -> (6,4)
|
||||
|
||||
# Case 4: Flattening a multi-dimensional tensor
|
||||
(torch.ones(2, 3, 4), "[-1]", (24,)), # (2,3,4) -> (24,)
|
||||
|
||||
# Case 5: Expanding dimensions
|
||||
(torch.ones(6,), "[2, 3]", (2, 3)), # (6,) -> (2,3)
|
||||
|
||||
# Case 6: Reshaping a 4D tensor
|
||||
(torch.ones(2, 3, 4, 5), "[6, -1, 5]", (6, 4, 5)), # (2,3,4,5) -> (6,4,5)
|
||||
|
||||
# Case 7: Edge case with 1D tensor
|
||||
(torch.ones(10,), "[10, 1]", (10, 1)), # (10,) -> (10,1)
|
||||
]
|
||||
|
||||
def test_reshape(self):
|
||||
"""Test tensor reshape operation with various shape orders."""
|
||||
for input_tensor, new_shape, expected_shape in self.test_cases:
|
||||
with self.subTest(input_shape=input_tensor.shape, new_shape=new_shape):
|
||||
result, = self.node.f(input_tensor, new_shape)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result has correct shape
|
||||
self.assertEqual(result.shape, torch.Size(expected_shape), f"Expected shape {expected_shape}, got {result.shape}")
|
||||
|
||||
# Ensure result has the same dtype
|
||||
self.assertEqual(result.dtype, input_tensor.dtype, "Dtype mismatch after reshape operation")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,51 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_scatter import PtScatter
|
||||
|
||||
|
||||
class TestPtScatter(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtScatter()
|
||||
|
||||
# Test cases: (Target Tensor, Dim, Index Tensor (as string), Source Tensor (as string), Expected Output)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([
|
||||
[10, 11, 12],
|
||||
[21, 22, 23],
|
||||
[31, 32, 33],
|
||||
]),
|
||||
0,
|
||||
"[[0, 1, 0], [1, 1, 2]]",
|
||||
"[[2, 4, 6], [4, 4, 2]]",
|
||||
torch.tensor([
|
||||
[2, 11, 6],
|
||||
[4, 4, 23],
|
||||
[31, 32, 2],
|
||||
])
|
||||
)
|
||||
]
|
||||
|
||||
def test_scatter(self):
|
||||
"""Test torch.scatter behavior."""
|
||||
for tens, dim, index, src, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, index=index, src=src):
|
||||
result, = self.node.f(tens, dim, index, src)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,39 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_sqrt import PtSqrt # Updated import to PtSqrt
|
||||
|
||||
|
||||
class TestPtSqrt(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtSqrt()
|
||||
|
||||
# Test cases: (Tensor A, Expected result)
|
||||
self.test_cases = [
|
||||
(torch.tensor([1.0, 4.0, 9.0], dtype=torch.float32), torch.sqrt(torch.tensor([1.0, 4.0, 9.0], dtype=torch.float32))), # Perfect squares
|
||||
(torch.tensor([0.5, 2.0, 3.0], dtype=torch.float32), torch.sqrt(torch.tensor([0.5, 2.0, 3.0], dtype=torch.float32))), # Common values
|
||||
(torch.tensor([[1.5, 3.2], [4.7, 5.9]], dtype=torch.float32), torch.sqrt(torch.tensor([[1.5, 3.2], [4.7, 5.9]], dtype=torch.float32))), # 2D case
|
||||
(torch.full((2, 2), 2.5, dtype=torch.float32), torch.sqrt(torch.full((2, 2), 2.5, dtype=torch.float32))), # Constant matrix
|
||||
]
|
||||
|
||||
def test_sqrt(self):
|
||||
"""Test tensor element-wise square root using torch.sqrt()."""
|
||||
for tens_a, expected in self.test_cases:
|
||||
with self.subTest(tens_a=tens_a):
|
||||
result, = self.node.f(tens_a)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected sqrt values
|
||||
self.assertTrue(torch.allclose(result, expected, atol=1e-6), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,84 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_std import PtStd
|
||||
|
||||
|
||||
class TestPtStd(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtStd()
|
||||
|
||||
# Define test cases with string-based dimensions
|
||||
self.test_cases = [
|
||||
# Sample standard deviation (Bessel's correction) along dim=0
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"0",
|
||||
1,
|
||||
False,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=0, correction=1, keepdim=False)
|
||||
),
|
||||
# Sample standard deviation along dim=1, with keepdim=True
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"1",
|
||||
1,
|
||||
True,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=1, correction=1, keepdim=True)
|
||||
),
|
||||
# Sample standard deviation across both axes (dim=(0,1))
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"(0, 1)",
|
||||
1,
|
||||
False,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=(0, 1), correction=1, keepdim=False)
|
||||
),
|
||||
# Sample standard deviation across all elements (dim=None) - Entire tensor
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"",
|
||||
1,
|
||||
False,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), correction=1, keepdim=False)
|
||||
),
|
||||
# Population standard deviation along dim=0 (correction=0)
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"0",
|
||||
0,
|
||||
False,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=0, correction=0, keepdim=False)
|
||||
),
|
||||
# Population standard deviation along dim=1 with keepdim=True (correction=0)
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"1",
|
||||
0,
|
||||
True,
|
||||
torch.std(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=1, correction=0, keepdim=True)
|
||||
)
|
||||
]
|
||||
|
||||
def test_std(self):
|
||||
"""Test torch.std behavior."""
|
||||
for tens, dim, correction, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, correction=correction, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, correction, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected standard deviation values
|
||||
self.assertTrue(torch.allclose(result, expected, atol=1e-6), f"Expected {expected}, got {result}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,71 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_sum import PtSum
|
||||
|
||||
|
||||
class TestPtSum(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtSum()
|
||||
|
||||
# Test cases: (Tensor, Dim (as string), keepdim, Expected result)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [2, 1, 3]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([3, 4, 5])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 0, 5]]),
|
||||
"1",
|
||||
True,
|
||||
torch.tensor([[6], [9]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 5, 6]]),
|
||||
"0",
|
||||
False,
|
||||
torch.tensor([5, 8, 8])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 3, 2], [4, 5, 6], [7, 8, 9]]),
|
||||
"1",
|
||||
False,
|
||||
torch.tensor([6, 15, 24])
|
||||
),
|
||||
(
|
||||
torch.tensor([[1, 2], [3, 4]]),
|
||||
"",
|
||||
False,
|
||||
torch.tensor(10) # Sum of all elements
|
||||
),
|
||||
(
|
||||
torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
|
||||
"(0, 1)",
|
||||
False,
|
||||
torch.tensor([16, 20]) # Sum over dimensions (0, 1)
|
||||
)
|
||||
]
|
||||
|
||||
def test_sum(self):
|
||||
"""Test torch.sum behavior."""
|
||||
for tens, dim, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected sum values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_var import PtVar
|
||||
|
||||
|
||||
class TestPtVar(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtVar()
|
||||
|
||||
# Define test cases with string-based dimensions
|
||||
self.test_cases = [
|
||||
# Sample variance (Bessel's correction) along dim=0
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"0",
|
||||
1,
|
||||
False,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=0, correction=1, keepdim=False)
|
||||
),
|
||||
# Sample variance along dim=1, with keepdim=True
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"1",
|
||||
1,
|
||||
True,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=1, correction=1, keepdim=True)
|
||||
),
|
||||
# Sample variance across both axes (dim=(0,1))
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"(0, 1)",
|
||||
1,
|
||||
False,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=(0, 1), correction=1, keepdim=False)
|
||||
),
|
||||
# Sample variance across all elements (dim=None) - Entire tensor
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"",
|
||||
1,
|
||||
False,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), correction=1, keepdim=False)
|
||||
),
|
||||
# Population variance along dim=0 (correction=0)
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"0",
|
||||
0,
|
||||
False,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=0, correction=0, keepdim=False)
|
||||
),
|
||||
# Population variance along dim=1 with keepdim=True (correction=0)
|
||||
(
|
||||
torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]),
|
||||
"1",
|
||||
0,
|
||||
True,
|
||||
torch.var(torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), dim=1, correction=0, keepdim=True)
|
||||
)
|
||||
]
|
||||
|
||||
def test_var(self):
|
||||
"""Test torch.var behavior."""
|
||||
for tens, dim, correction, keepdim, expected in self.test_cases:
|
||||
with self.subTest(tens=tens, dim=dim, correction=correction, keepdim=keepdim):
|
||||
result, = self.node.f(tens, dim, correction, keepdim)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected variance values
|
||||
self.assertTrue(torch.allclose(result, expected, atol=1e-6), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.pt_where import PtWhere
|
||||
|
||||
|
||||
class TestPtWhere(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
self.node = PtWhere()
|
||||
|
||||
# Test cases: (Condition Tensor, True Tensor, False Tensor, Expected Output)
|
||||
self.test_cases = [
|
||||
(
|
||||
torch.tensor([[True, False], [False, True]]),
|
||||
torch.tensor([[1, 2], [3, 4]]),
|
||||
torch.tensor([[5, 6], [7, 8]]),
|
||||
torch.tensor([[1, 6], [7, 4]])
|
||||
),
|
||||
(
|
||||
torch.tensor([True, False, True]),
|
||||
torch.tensor([10, 20, 30]),
|
||||
torch.tensor([100, 200, 300]),
|
||||
torch.tensor([10, 200, 30])
|
||||
),
|
||||
(
|
||||
torch.tensor([[False, False], [True, True]]),
|
||||
torch.tensor([[1.5, 2.5], [3.5, 4.5]]),
|
||||
torch.tensor([[5.5, 6.5], [7.5, 8.5]]),
|
||||
torch.tensor([[5.5, 6.5], [3.5, 4.5]])
|
||||
),
|
||||
(
|
||||
torch.tensor([[[True, False], [False, True]], [[False, True], [True, False]]]),
|
||||
torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
|
||||
torch.tensor([[[9, 10], [11, 12]], [[13, 14], [15, 16]]]),
|
||||
torch.tensor([[[1, 10], [11, 4]], [[13, 6], [7, 16]]])
|
||||
),
|
||||
]
|
||||
|
||||
def test_where(self):
|
||||
"""Test torch.where behavior."""
|
||||
for condition_tens, true_tens, false_tens, expected in self.test_cases:
|
||||
with self.subTest(condition_tens=condition_tens, true_tens=true_tens, false_tens=false_tens):
|
||||
result, = self.node.f(condition_tens, true_tens, false_tens)
|
||||
|
||||
# Ensure return value is a tensor
|
||||
self.assertTrue(isinstance(result, torch.Tensor), "Output is not a tensor")
|
||||
|
||||
# Ensure result matches expected values
|
||||
self.assertTrue(torch.equal(result, expected), f"Expected {expected}, got {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
import sys
|
||||
import unittest
|
||||
import torch
|
||||
import ast
|
||||
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
|
||||
from pytorch_wrapper.utils import str_to_dim
|
||||
|
||||
|
||||
class TestStrToDim(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test instance."""
|
||||
pass
|
||||
|
||||
def test_valid_integer(self):
|
||||
"""Test parsing a valid integer string."""
|
||||
self.assertEqual(str_to_dim("5"), 5)
|
||||
|
||||
def test_valid_tuple(self):
|
||||
"""Test parsing a valid tuple string."""
|
||||
self.assertEqual(str_to_dim("(1, 2, 3)"), (1, 2, 3))
|
||||
|
||||
def test_valid_list(self):
|
||||
"""Test parsing a valid list string (should be converted to tuple)."""
|
||||
self.assertEqual(str_to_dim("[4, 5, 6]"), (4, 5, 6))
|
||||
|
||||
def test_empty_string(self):
|
||||
"""Test empty string input should return None."""
|
||||
self.assertIsNone(str_to_dim(""))
|
||||
|
||||
def test_invalid_string(self):
|
||||
"""Test invalid string input should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
str_to_dim("invalid")
|
||||
|
||||
def test_mixed_type_list(self):
|
||||
"""Test a list with mixed types should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
str_to_dim("[1, 'a', 3]")
|
||||
|
||||
def test_nested_tuple(self):
|
||||
"""Test a nested tuple should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
str_to_dim("((1, 2), 3)")
|
||||
|
||||
def test_dict_input(self):
|
||||
"""Test a dictionary input should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
str_to_dim("{'a': 1, 'b': 2}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user