From 1ef976d1777d7a61cbe890c2ca140d2bd9010136 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 18:29:25 -0700 Subject: [PATCH 01/13] GenericDataContainer and AbstractDataloaderV2 --- pyrad/data/dataloader.py | 98 +++++++++++++++++++++++++++++++++++++++- pyrad/data/structs.py | 17 +++++++ 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 7bcbd837d..3034f1b53 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -16,6 +16,7 @@ Data loader. """ +from abc import abstractmethod import random from typing import Dict, List, Tuple, Union from omegaconf import ListConfig @@ -27,7 +28,7 @@ from pyrad.cameras.rays import RayBundle from pyrad.data.image_dataset import ImageDataset from pyrad.data.image_sampler import ImageSampler from pyrad.data.pixel_sampler import PixelSampler -from pyrad.data.structs import DatasetInputs +from pyrad.data.structs import DatasetInputs, GenericDataContainer from pyrad.data.utils import get_dataset_inputs_from_dataset_config from pyrad.utils import profiler from pyrad.utils.config import DataConfig @@ -81,6 +82,101 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl return dataset_inputs_eval, dataloader_eval +class AbstractDataloaderV2(nn.Module): + """Second version of the dataloader class + + This version of the dataloader is designed to subsume both the train and eval dataloaders, especially since + this may contain learnable parameters which need to be shared across the train and test dataloaders. The idea + is that we have setup methods for train and eval separatley and this can be a combined train/eval if you want. + + + Train Methods: + setup_train: sets up for being used as train + iter_train: returns an iterator of the train dataloader + next_train: will be called on __next__() for the training iterator + + Eval Methods: + setup_eval: sets up for being used as eval + iter_eval: returns an iterator of the eval dataloader + next_eval: will be called on __next__() for the eval iterator + + + Attributes: + image_sampler (ImageSampler): image sampler + pixel_sampler (PixelSampler): pixel sampler + intrinsics (TensorType): intrinsics + camera_to_world (TensorType): camera to world + ray_generator (RayBundle): ray generator + train_count (int): number of times train has been called + eval_count (int): number of times eval has been called + """ + + def __init__( + self, image_sampler: ImageSampler, pixel_sampler: PixelSampler, intrinsics, camera_to_world, ray_generator + ): + super().__init__() + self.image_sampler = image_sampler + self.pixel_sampler = pixel_sampler + self.iter_image_sampler = iter(self.image_sampler) + self.intrinsics = intrinsics + self.camera_to_world = camera_to_world + self.ray_generator = ray_generator + self.train_count = 0 + self.eval_count = 0 + + def iter_train(self): + """Returns an iterator that executes the self.next_train function""" + self.train_count = 0 + + class DataloaderIterable: + """A helper class for dataloader iterables. This class's __next__ function is determined by + the next() function passed into the __init__ function. It will assume the dataloader passed into + the __init__ function is the dataloader object we want to""" + + def __init__(self, dataloader: AbstractDataloaderV2, next: callable): + self.dataloader = dataloader + self.next = next + + def __next__(self): + return self.next(self.dataloader) + + return DataloaderIterable(self, self.next_train) + + def iter_eval(self): + """Returns an iterator that executes the self.next_eval function""" + self.train_count = 0 + + class DataloaderIterable: + """A helper class for dataloader iterables. This class's __next__ function is determined by + the next() function passed into the __init__ function. It will assume the dataloader passed into + the __init__ function is the dataloader object we want to""" + + def __init__(self, dataloader: AbstractDataloaderV2, next: callable): + self.dataloader = dataloader + self.next = next + + def __next__(self): + return self.next(self.dataloader) + + return DataloaderIterable(self, self.next_eval) + + @abstractmethod + def setup_train(self): + """Sets up the dataloader for training""" + + @abstractmethod + def setup_eval(self): + """Sets up the dataloader for evaluation""" + + @abstractmethod + def next_train(self) -> GenericDataContainer: + """Returns the next batch of data from the train dataloader""" + + @abstractmethod + def next_eval(self) -> GenericDataContainer: + """Returns the next batch of data from the eval dataloader""" + + class TrainDataloader: """Training dataloader base class.""" diff --git a/pyrad/data/structs.py b/pyrad/data/structs.py index 9b6733d67..f8cbb39ee 100644 --- a/pyrad/data/structs.py +++ b/pyrad/data/structs.py @@ -20,6 +20,7 @@ from dataclasses import dataclass from typing import List, Optional import torch +from pyrad.cameras.rays import RayBundle from torchtyping import TensorType @@ -106,3 +107,19 @@ class DatasetInputs: def as_dict(self) -> dict: """Returns the dataclass as a dictionary.""" return vars(self) + + +@dataclass +class GenericDataContainer: + """A container for data that is not specific to any dataset. It should be everything + needed by the renderer and loss calculation. Different datasets and models will probably + need to subclass from this differently, since different Field modules will require different + data. + + Args: + rays: The rays for the image. + ground_truth_pixels: The ground truth pixels for the image. + """ + + rays: RayBundle + ground_truth_pixels: TensorType["num_pixels", 3] = None From 7e23747c4151fbdaaac200eff80a7190564cc74b Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 19:24:01 -0700 Subject: [PATCH 02/13] Forgot to import nn.Module --- pyrad/data/dataloader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 3034f1b53..286f50684 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -23,6 +23,8 @@ from omegaconf import ListConfig from torchtyping import TensorType +import torch.nn as nn + from pyrad.cameras.cameras import Camera, get_camera from pyrad.cameras.rays import RayBundle from pyrad.data.image_dataset import ImageDataset From cff55d78360b11eef53199dcbeb6b47fe1b10722 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 22:42:35 -0700 Subject: [PATCH 03/13] Fixing nitpicks, clarifying documentation, updating dataloader params --- pyrad/data/dataloader.py | 86 +++++++++++++++++++++++----------------- pyrad/data/structs.py | 4 +- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 286f50684..ebf310378 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -23,7 +23,7 @@ from omegaconf import ListConfig from torchtyping import TensorType -import torch.nn as nn +from torch import nn from pyrad.cameras.cameras import Camera, get_camera from pyrad.cameras.rays import RayBundle @@ -32,6 +32,7 @@ from pyrad.data.image_sampler import ImageSampler from pyrad.data.pixel_sampler import PixelSampler from pyrad.data.structs import DatasetInputs, GenericDataContainer from pyrad.data.utils import get_dataset_inputs_from_dataset_config +from pyrad.graphs.modules.ray_generator import RayGenerator from pyrad.utils import profiler from pyrad.utils.config import DataConfig from pyrad.utils.misc import get_dict_to_torch, instantiate_from_dict_config @@ -84,6 +85,26 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl return dataset_inputs_eval, dataloader_eval +class IterableWrapper: + """A helper that will allow a class to return multiple kinds of iterables. + + To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in the + class method that you want to be the __next__() method of the iterable. The resulting instantiated object will + be an iterable that will use the passed in class method as the __next__() method.""" + + def __init__(self, instance: object, next: callable): + """ + Args: + instance (type): instance class we are wrapping + next (callable): function that will be called instead as the __next__() + """ + self.instance = instance + self.next = next + + def __next__(self): + return self.next(self.instance) + + class AbstractDataloaderV2(nn.Module): """Second version of the dataloader class @@ -103,64 +124,55 @@ class AbstractDataloaderV2(nn.Module): next_eval: will be called on __next__() for the eval iterator + Args: + image_sampler (ImageSampler): image sampler + pixel_sampler (PixelSampler): pixel sampler + ray_generator (RayGenerator): ray generator + is_train (bool): whether this is being used for training + is_eval (bool): whether this is being used for evaluation + + + Attributes: image_sampler (ImageSampler): image sampler pixel_sampler (PixelSampler): pixel sampler - intrinsics (TensorType): intrinsics - camera_to_world (TensorType): camera to world - ray_generator (RayBundle): ray generator + ray_generator (RayGenerator): ray generator train_count (int): number of times train has been called eval_count (int): number of times eval has been called """ def __init__( - self, image_sampler: ImageSampler, pixel_sampler: PixelSampler, intrinsics, camera_to_world, ray_generator + self, + image_sampler: ImageSampler, + pixel_sampler: PixelSampler, + ray_generator: RayGenerator, + is_train: bool, + is_eval: bool, ): super().__init__() self.image_sampler = image_sampler self.pixel_sampler = pixel_sampler self.iter_image_sampler = iter(self.image_sampler) - self.intrinsics = intrinsics - self.camera_to_world = camera_to_world self.ray_generator = ray_generator + self.is_train = is_train + self.is_eval = is_eval self.train_count = 0 self.eval_count = 0 + assert is_train or is_eval + if is_train: + self.setup_train() + if is_eval: + self.setup_eval() - def iter_train(self): + def iter_train(self) -> IterableWrapper: """Returns an iterator that executes the self.next_train function""" self.train_count = 0 + return IterableWrapper(self, self.next_train) - class DataloaderIterable: - """A helper class for dataloader iterables. This class's __next__ function is determined by - the next() function passed into the __init__ function. It will assume the dataloader passed into - the __init__ function is the dataloader object we want to""" - - def __init__(self, dataloader: AbstractDataloaderV2, next: callable): - self.dataloader = dataloader - self.next = next - - def __next__(self): - return self.next(self.dataloader) - - return DataloaderIterable(self, self.next_train) - - def iter_eval(self): + def iter_eval(self) -> IterableWrapper: """Returns an iterator that executes the self.next_eval function""" self.train_count = 0 - - class DataloaderIterable: - """A helper class for dataloader iterables. This class's __next__ function is determined by - the next() function passed into the __init__ function. It will assume the dataloader passed into - the __init__ function is the dataloader object we want to""" - - def __init__(self, dataloader: AbstractDataloaderV2, next: callable): - self.dataloader = dataloader - self.next = next - - def __next__(self): - return self.next(self.dataloader) - - return DataloaderIterable(self, self.next_eval) + return IterableWrapper(self, self.next_eval) @abstractmethod def setup_train(self): diff --git a/pyrad/data/structs.py b/pyrad/data/structs.py index f8cbb39ee..949c92248 100644 --- a/pyrad/data/structs.py +++ b/pyrad/data/structs.py @@ -117,8 +117,8 @@ class GenericDataContainer: data. Args: - rays: The rays for the image. - ground_truth_pixels: The ground truth pixels for the image. + rays (RayBundle): The rays for the image. + ground_truth_pixels (TensorType["num_pixels", 3]): The ground truth pixels for the image. """ rays: RayBundle From f5a354fdb05fca54f60090be3d65099b29fccc2a Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 22:48:46 -0700 Subject: [PATCH 04/13] Patching up some mistakes, linting --- pyrad/data/dataloader.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index ebf310378..50f97171e 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -86,23 +86,23 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl class IterableWrapper: - """A helper that will allow a class to return multiple kinds of iterables. + """A helper that will allow an instance of a class to return multiple kinds of iterables bound to different functions of that class. - To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in the - class method that you want to be the __next__() method of the iterable. The resulting instantiated object will + To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in a + method belonging to that class that you want to be the __next__() method of the iterable. The resulting instantiated object will be an iterable that will use the passed in class method as the __next__() method.""" - def __init__(self, instance: object, next: callable): + def __init__(self, instance: object, new_next: callable): """ Args: - instance (type): instance class we are wrapping - next (callable): function that will be called instead as the __next__() + instance (object): instance class we are wrapping + new_next (callable): function that will be called instead as the __next__() """ self.instance = instance - self.next = next + self.new_next = new_next def __next__(self): - return self.next(self.instance) + return self.new_next(self.instance) class AbstractDataloaderV2(nn.Module): @@ -171,7 +171,7 @@ class AbstractDataloaderV2(nn.Module): def iter_eval(self) -> IterableWrapper: """Returns an iterator that executes the self.next_eval function""" - self.train_count = 0 + self.eval_count = 0 return IterableWrapper(self, self.next_eval) @abstractmethod From 667de0b7583795dadb2993a9cae27acce121b6ff Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 23:01:42 -0700 Subject: [PATCH 05/13] Subclassed abstract cached dataloader, for things like generic NeRFs where data fits in memory --- pyrad/data/dataloader.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 50f97171e..1b6489b10 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -20,6 +20,7 @@ from abc import abstractmethod import random from typing import Dict, List, Tuple, Union from omegaconf import ListConfig +import torch from torchtyping import TensorType @@ -191,6 +192,13 @@ class AbstractDataloaderV2(nn.Module): """Returns the next batch of data from the eval dataloader""" +class AbstractCachedDataloaderV2(AbstractDataloaderV2): + """Subclass of the new V2 dataloader that is used for when things fit in memory""" + + camera_to_world: torch.Tensor + intrinsics: torch.Tensor + + class TrainDataloader: """Training dataloader base class.""" From 0422afc9135ae0f61218d24b998354f91d4e8cc1 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 17 Jul 2022 23:05:06 -0700 Subject: [PATCH 06/13] adding docstring for abstractcacheddataloaderv2 --- pyrad/data/dataloader.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 1b6489b10..186b51eae 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -193,7 +193,12 @@ class AbstractDataloaderV2(nn.Module): class AbstractCachedDataloaderV2(AbstractDataloaderV2): - """Subclass of the new V2 dataloader that is used for when things fit in memory""" + """Subclass of the new V2 dataloader that is used for when things fit in memory + + Attributes: + camera_to_world (torch.Tensor): camera to world transformation + intrinsics (torch.Tensor): intrinsics matrix + """ camera_to_world: torch.Tensor intrinsics: torch.Tensor From 482f7c9eeaefc8667d649cffc47c2e4ef4bc6e7d Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Mon, 18 Jul 2022 17:26:34 -0700 Subject: [PATCH 07/13] Fixing documentation, moving IterableWrapper to pyrad/utils/misc, sorting imports --- pyrad/data/dataloader.py | 39 +++++++++++++-------------------------- pyrad/utils/misc.py | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 186b51eae..90404bf12 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -16,15 +16,14 @@ Data loader. """ -from abc import abstractmethod import random +from abc import abstractmethod from typing import Dict, List, Tuple, Union -from omegaconf import ListConfig + import torch - -from torchtyping import TensorType - +from omegaconf import ListConfig from torch import nn +from torchtyping import TensorType from pyrad.cameras.cameras import Camera, get_camera from pyrad.cameras.rays import RayBundle @@ -36,7 +35,7 @@ from pyrad.data.utils import get_dataset_inputs_from_dataset_config from pyrad.graphs.modules.ray_generator import RayGenerator from pyrad.utils import profiler from pyrad.utils.config import DataConfig -from pyrad.utils.misc import get_dict_to_torch, instantiate_from_dict_config +from pyrad.utils.misc import IterableWrapper, get_dict_to_torch, instantiate_from_dict_config @profiler.time_function @@ -86,26 +85,6 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl return dataset_inputs_eval, dataloader_eval -class IterableWrapper: - """A helper that will allow an instance of a class to return multiple kinds of iterables bound to different functions of that class. - - To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in a - method belonging to that class that you want to be the __next__() method of the iterable. The resulting instantiated object will - be an iterable that will use the passed in class method as the __next__() method.""" - - def __init__(self, instance: object, new_next: callable): - """ - Args: - instance (object): instance class we are wrapping - new_next (callable): function that will be called instead as the __next__() - """ - self.instance = instance - self.new_next = new_next - - def __next__(self): - return self.new_next(self.instance) - - class AbstractDataloaderV2(nn.Module): """Second version of the dataloader class @@ -113,6 +92,14 @@ class AbstractDataloaderV2(nn.Module): this may contain learnable parameters which need to be shared across the train and test dataloaders. The idea is that we have setup methods for train and eval separatley and this can be a combined train/eval if you want. + The default should be for the train and eval dataloaders to be the same, but this can be overridden. This is + needed when there are learned parameters either in your data itself or in the way some of the data (that we will + pass to the renderer / Field) was generated. In these cases, we want these parameters to be accessible by + both the train and eval dataloaders, hence why you would want them to be in the same dataloader. + + An instance where you may want to have only the eval dataloader is if you are doing evaluation and + don't have the dataset used to train the model. + Train Methods: setup_train: sets up for being used as train diff --git a/pyrad/utils/misc.py b/pyrad/utils/misc.py index bf68cba22..2600431e5 100644 --- a/pyrad/utils/misc.py +++ b/pyrad/utils/misc.py @@ -90,3 +90,28 @@ def get_hash_str_from_dict(dictionary: Dict[str, Any]) -> str: encoded = json.dumps(dictionary, sort_keys=True).encode() dhash.update(encoded) return dhash.hexdigest() + + +class IterableWrapper: + """A helper that will allow an instance of a class to return multiple kinds of iterables bound to different functions of that class. + + To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in a + method belonging to that class that you want to be the __next__() method of the iterable. The resulting instantiated object will + be an iterable that will use the passed in class method as the __next__() method. + + Args: + instance (object): instance class we are wrapping + new_next (callable): function that will be called instead as the __next__() + + + Attributes: + instance (object): instance class we are wrapping + new_next (callable): function that will be called instead as the __next__() + """ + + def __init__(self, instance: object, new_next: callable): + self.instance = instance + self.new_next = new_next + + def __next__(self): + return self.new_next(self.instance) From 3a78a9cb2eca93abace6d61eadbaa86b54fe4840 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Wed, 20 Jul 2022 16:42:47 -0700 Subject: [PATCH 08/13] passing linting tests and fixed documentation --- pyrad/data/dataloader.py | 37 ++++++++++++++++++++++++++++--------- pyrad/data/structs.py | 3 ++- pyrad/utils/misc.py | 12 +++++++----- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 90404bf12..2c644d5b0 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -88,17 +88,19 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl class AbstractDataloaderV2(nn.Module): """Second version of the dataloader class - This version of the dataloader is designed to subsume both the train and eval dataloaders, especially since - this may contain learnable parameters which need to be shared across the train and test dataloaders. The idea - is that we have setup methods for train and eval separatley and this can be a combined train/eval if you want. + This version of the dataloader is designed to subsume both the train and eval dataloaders, + especially since this may contain learnable parameters which need to be shared across the train + and test dataloaders. The idea is that we have setup methods for train and eval separatley and + this can be a combined train/eval if you want. - The default should be for the train and eval dataloaders to be the same, but this can be overridden. This is - needed when there are learned parameters either in your data itself or in the way some of the data (that we will - pass to the renderer / Field) was generated. In these cases, we want these parameters to be accessible by - both the train and eval dataloaders, hence why you would want them to be in the same dataloader. + The default should be for the train and eval dataloaders to be the same, but this can be + overridden. This is needed when there are learned parameters either in your data itself or in + the way some of the data (that we will pass to the renderer / Field) was generated. In these + cases, we want these parameters to be accessible by both the train and eval dataloaders, hence + why you would want them to be in the same dataloader. - An instance where you may want to have only the eval dataloader is if you are doing evaluation and - don't have the dataset used to train the model. + An instance where you may want to have only the eval dataloader is if you are doing evaluation + and don't have the dataset used to train the model. Train Methods: @@ -190,6 +192,23 @@ class AbstractCachedDataloaderV2(AbstractDataloaderV2): camera_to_world: torch.Tensor intrinsics: torch.Tensor + # These abstract methods are only copied over to appease the linter + @abstractmethod + def setup_train(self): + """Sets up the dataloader for training""" + + @abstractmethod + def setup_eval(self): + """Sets up the dataloader for evaluation""" + + @abstractmethod + def next_train(self) -> GenericDataContainer: + """Returns the next batch of data from the train dataloader""" + + @abstractmethod + def next_eval(self) -> GenericDataContainer: + """Returns the next batch of data from the eval dataloader""" + class TrainDataloader: """Training dataloader base class.""" diff --git a/pyrad/data/structs.py b/pyrad/data/structs.py index 949c92248..7e2fdb755 100644 --- a/pyrad/data/structs.py +++ b/pyrad/data/structs.py @@ -20,9 +20,10 @@ from dataclasses import dataclass from typing import List, Optional import torch -from pyrad.cameras.rays import RayBundle from torchtyping import TensorType +from pyrad.cameras.rays import RayBundle + @dataclass class PointCloud: diff --git a/pyrad/utils/misc.py b/pyrad/utils/misc.py index 2600431e5..51539320e 100644 --- a/pyrad/utils/misc.py +++ b/pyrad/utils/misc.py @@ -92,12 +92,14 @@ def get_hash_str_from_dict(dictionary: Dict[str, Any]) -> str: return dhash.hexdigest() -class IterableWrapper: - """A helper that will allow an instance of a class to return multiple kinds of iterables bound to different functions of that class. +class IterableWrapper: # pylint: disable=too-few-public-methods + """A helper that will allow an instance of a class to return multiple kinds of iterables bound + to different functions of that class. - To use this, pass in the instance of the class you want to have multiple kinds of iterables for, and pass in a - method belonging to that class that you want to be the __next__() method of the iterable. The resulting instantiated object will - be an iterable that will use the passed in class method as the __next__() method. + To use this, pass in the instance of the class you want to have multiple kinds of iterables for, + and pass in a method belonging to that class that you want to be the __next__() method of the + iterable. The resulting instantiated object will be an iterable that will use the passed in + class method as the __next__() method. Args: instance (object): instance class we are wrapping From 2fc2fe3817b724883d69c0592dd5deb92df64ddd Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 24 Jul 2022 16:49:19 -0700 Subject: [PATCH 09/13] Making some updates to notation, documentation --- pyrad/data/dataloader.py | 27 ++++++++++++++------------- pyrad/data/structs.py | 7 ++++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 2c644d5b0..5312c50e1 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -85,8 +85,8 @@ def setup_dataset_eval(config: DataConfig, test_mode: bool, device: str) -> Tupl return dataset_inputs_eval, dataloader_eval -class AbstractDataloaderV2(nn.Module): - """Second version of the dataloader class +class AbstractDataloader(nn.Module): + """Second version of the dataloader class (V2) This version of the dataloader is designed to subsume both the train and eval dataloaders, especially since this may contain learnable parameters which need to be shared across the train @@ -118,8 +118,8 @@ class AbstractDataloaderV2(nn.Module): image_sampler (ImageSampler): image sampler pixel_sampler (PixelSampler): pixel sampler ray_generator (RayGenerator): ray generator - is_train (bool): whether this is being used for training - is_eval (bool): whether this is being used for evaluation + use_train (bool): whether this is being used for training + use_eval (bool): whether this is being used for evaluation @@ -136,22 +136,22 @@ class AbstractDataloaderV2(nn.Module): image_sampler: ImageSampler, pixel_sampler: PixelSampler, ray_generator: RayGenerator, - is_train: bool, - is_eval: bool, + use_train: bool, + use_eval: bool, ): super().__init__() self.image_sampler = image_sampler self.pixel_sampler = pixel_sampler self.iter_image_sampler = iter(self.image_sampler) self.ray_generator = ray_generator - self.is_train = is_train - self.is_eval = is_eval + self.use_train = use_train + self.use_eval = use_eval self.train_count = 0 self.eval_count = 0 - assert is_train or is_eval - if is_train: + assert use_train or use_eval + if use_train: self.setup_train() - if is_eval: + if use_eval: self.setup_eval() def iter_train(self) -> IterableWrapper: @@ -181,8 +181,9 @@ class AbstractDataloaderV2(nn.Module): """Returns the next batch of data from the eval dataloader""" -class AbstractCachedDataloaderV2(AbstractDataloaderV2): - """Subclass of the new V2 dataloader that is used for when things fit in memory +class AbstractCachedDataloaderV2(AbstractDataloader): + """Subclass of the new V2 dataloader that is used for when things fit in memory, + and will be cached in the dataloader itself. Attributes: camera_to_world (torch.Tensor): camera to world transformation diff --git a/pyrad/data/structs.py b/pyrad/data/structs.py index 7e2fdb755..089772b49 100644 --- a/pyrad/data/structs.py +++ b/pyrad/data/structs.py @@ -111,7 +111,7 @@ class DatasetInputs: @dataclass -class GenericDataContainer: +class BaseDataContainer: """A container for data that is not specific to any dataset. It should be everything needed by the renderer and loss calculation. Different datasets and models will probably need to subclass from this differently, since different Field modules will require different @@ -122,5 +122,6 @@ class GenericDataContainer: ground_truth_pixels (TensorType["num_pixels", 3]): The ground truth pixels for the image. """ - rays: RayBundle - ground_truth_pixels: TensorType["num_pixels", 3] = None + rays: RayBundle # Raybundle and the cameras will be merged into one thing in a later PR + cameras: torch.tensor + ground_truth_pixels: Optional[TensorType["num_pixels", 3]] = None From 3e7ca2976284d5805b41fb0ced93e929de016831 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 24 Jul 2022 16:50:02 -0700 Subject: [PATCH 10/13] Forgot to save --- pyrad/utils/misc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrad/utils/misc.py b/pyrad/utils/misc.py index 51539320e..80323b77a 100644 --- a/pyrad/utils/misc.py +++ b/pyrad/utils/misc.py @@ -19,7 +19,7 @@ Miscellaneous helper code. import hashlib import json from pydoc import locate -from typing import Any, Dict +from typing import Any, Callable, Dict import torch from omegaconf import DictConfig @@ -111,7 +111,7 @@ class IterableWrapper: # pylint: disable=too-few-public-methods new_next (callable): function that will be called instead as the __next__() """ - def __init__(self, instance: object, new_next: callable): + def __init__(self, instance: object, new_next: Callable): self.instance = instance self.new_next = new_next From 5e9f1eb1a316dbd8af9abd4c60cdbb638c11b80f Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 24 Jul 2022 17:43:40 -0700 Subject: [PATCH 11/13] Updating names again --- pyrad/data/dataloader.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index 36bd35687..d20458bb9 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -31,7 +31,7 @@ from pyrad.cameras.rays import RayBundle from pyrad.data.image_dataset import ImageDataset from pyrad.data.image_sampler import ImageSampler from pyrad.data.pixel_sampler import PixelSampler -from pyrad.data.structs import DatasetInputs, GenericDataContainer +from pyrad.data.structs import DatasetInputs, BaseDataContainer from pyrad.data.utils import get_dataset_inputs_from_dataset_config from pyrad.graphs.modules.ray_generator import RayGenerator from pyrad.utils import profiler @@ -174,17 +174,17 @@ class AbstractDataloader(nn.Module): """Sets up the dataloader for evaluation""" @abstractmethod - def next_train(self) -> GenericDataContainer: + def next_train(self) -> BaseDataContainer: """Returns the next batch of data from the train dataloader""" @abstractmethod - def next_eval(self) -> GenericDataContainer: + def next_eval(self) -> BaseDataContainer: """Returns the next batch of data from the eval dataloader""" -class AbstractCachedDataloaderV2(AbstractDataloader): +class AbstractStoredDataloader(AbstractDataloader): """Subclass of the new V2 dataloader that is used for when things fit in memory, - and will be cached in the dataloader itself. + and will be stored in the dataloader itself. Attributes: camera_to_world (torch.Tensor): camera to world transformation @@ -204,11 +204,11 @@ class AbstractCachedDataloaderV2(AbstractDataloader): """Sets up the dataloader for evaluation""" @abstractmethod - def next_train(self) -> GenericDataContainer: + def next_train(self) -> BaseDataContainer: """Returns the next batch of data from the train dataloader""" @abstractmethod - def next_eval(self) -> GenericDataContainer: + def next_eval(self) -> BaseDataContainer: """Returns the next batch of data from the eval dataloader""" From 280bf1bec37d1844b7ee4aaef11819c48604cffe Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Sun, 24 Jul 2022 17:49:42 -0700 Subject: [PATCH 12/13] Appeasing the linter --- pyrad/data/dataloader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyrad/data/dataloader.py b/pyrad/data/dataloader.py index d20458bb9..7e0e6e00c 100644 --- a/pyrad/data/dataloader.py +++ b/pyrad/data/dataloader.py @@ -22,7 +22,6 @@ from typing import Dict, List, Optional, Tuple, Union from omegaconf import ListConfig import torch -from omegaconf import ListConfig from torch import nn from torchtyping import TensorType From c168565cc02aa87fad79368b42785eaa44853142 Mon Sep 17 00:00:00 2001 From: Jake Austin Date: Mon, 25 Jul 2022 17:21:14 -0700 Subject: [PATCH 13/13] Fixing nerfactory name change import error --- nerfactory/data/structs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nerfactory/data/structs.py b/nerfactory/data/structs.py index 089772b49..437d656cd 100644 --- a/nerfactory/data/structs.py +++ b/nerfactory/data/structs.py @@ -22,7 +22,7 @@ from typing import List, Optional import torch from torchtyping import TensorType -from pyrad.cameras.rays import RayBundle +from nerfactory.cameras.rays import RayBundle @dataclass