Two or more crops for a single image

Hey! Thank you for the great work.
Is it possible to apply the same pipeline multiple times to the same image? From what I checked, this is currently not possible as it seems that the images are loaded and cropped within a single operation. Is there any way to go around this, loading the image only once and applying the augmentations pipelines multiple times?

Hello,
Can you clarify exactly what you are trying to do ? I'm sure we can find a way to work it out.
The reason they are currently fused is because we are working with batches so all images have to have the same size as they exit the first operation of the pipeline

For self-supervised learning you usually need 2 or more crops of the same image. With torchvision this is pretty easy as you can do something like wrapping the transformations with a custom class that calls the underlying transformations multiple times. For example
class TwoCropsTransform:
    def __init__(self, base_transform):
        self.base_transform = base_transform
    def __call__(self, x):
        q = self.base_transform(x)
        k = self.base_transform(x)
        return [q, k]

where base_transform is something like this
augmentation = transforms.Compose(
    [
        transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
        transforms.RandomApply(
            [transforms.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8  # not strengthened
        ),
        transforms.RandomGrayscale(p=0.2),
        transforms.RandomApply([moco.loader.GaussianBlur([0.1, 2.0])], p=0.5),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        normalize,
    ]
)

Can the same be accomplished with ffcv?

I see, that's a very good point. We actually got a similar request. The
idea would be to have multiple pipelines use the same field name as source.
That would work for this use case right ?
On Fri, Jan 21, 2022, 7:24 AM Victor Turrisi @.***>
wrote:

For self-supervised learning you usually need 2 or more crops of the same
image. With torchvision this is pretty easy as you can do something like
wrapping the transformations with a custom class that calls the underlying
transformations multiple times. For example
class TwoCropsTransform:
def init(self, base_transform):
self.base_transform = base_transform
def call(self, x):
q = self.base_transform(x)
k = self.base_transform(x)
return [q, k]
where base_transform is something like this
augmentation = transforms.Compose(
[
transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
transforms.RandomApply(
[transforms.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8  # not strengthened
),
transforms.RandomGrayscale(p=0.2),
transforms.RandomApply([moco.loader.GaussianBlur([0.1, 2.0])], p=0.5),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,
]
)
Can the same be accomplished with ffcv?
—
Reply to this email directly, view it on GitHub
https://github.com/libffcv/ffcv/issues/77#issuecomment-1018460832, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAPMOG36TWKQE4MDEED5PADUXFF6NANCNFSM5MPK6CLQ
.
Triage notifications on the go with GitHub Mobile for iOS
https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
or Android
https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you commented.Message ID:
@.***>

Exactly, I think so.

As a temporary solution you could extend the original decoder and have it
output images with double the height and have the two crop stiched
together. In your loop you could split them.
On Fri, Jan 21, 2022, 7:29 AM Guillaume Leclerc <
@.***> wrote:

I see, that's a very good point. We actually got a similar request. The
idea would be to have multiple pipelines use the same field name as source.
That would work for this use case right ?
On Fri, Jan 21, 2022, 7:24 AM Victor Turrisi @.***>
wrote:

For self-supervised learning you usually need 2 or more crops of the same
image. With torchvision this is pretty easy as you can do something like
wrapping the transformations with a custom class that calls the underlying
transformations multiple times. For example
class TwoCropsTransform:
def init(self, base_transform):
self.base_transform = base_transform
def call(self, x):
q = self.base_transform(x)
k = self.base_transform(x)
return [q, k]
where base_transform is something like this
augmentation = transforms.Compose(
[
transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
transforms.RandomApply(
[transforms.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8  # not strengthened
),
transforms.RandomGrayscale(p=0.2),
transforms.RandomApply([moco.loader.GaussianBlur([0.1, 2.0])], p=0.5),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,
]
)
Can the same be accomplished with ffcv?
—
Reply to this email directly, view it on GitHub
https://github.com/libffcv/ffcv/issues/77#issuecomment-1018460832, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAPMOG36TWKQE4MDEED5PADUXFF6NANCNFSM5MPK6CLQ
.
Triage notifications on the go with GitHub Mobile for iOS
https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
or Android
https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you commented.Message ID:
@.***>

I see, but I still think this wouldn't solve it since the random parameters for the other augmentations are generated twice (one for each crop). If there's anything that I could help let me know. Looking forward to using ffcv :)

Hi @vturrisi ! One thing that might work for now is to just create two Loader objects, point them at the same dataset file, initialize them with the same seed (the seed is just for batch ordering so it won't mess with the augmentations), and then zip them together---I can make a minimal example if it helps!

Hey @andrewilyas, yeah, what you suggested will for sure work. However, wouldn't this be too slow since the images are loaded once for each crop?

Yeah this will be a little slower but I think it could still be fast enough to saturate most GPUs, especially if it's a simple 2-crop algorithm. Data on how it scales with # crops would be very much appreciated!! We'll keep you updated as we figure out how to support feeding the same field through multiple pipelines!

There will also be an impact on ram usage right? I'll get to you tomorrow with some data regarding how it scales in time and memory.

Definitely no impact with is caching

I'm going to close this issue in favor of #82 which is about implementing the actual clean solution to what is faced by this issue. If you want to discuss the temporary solution we can reopen this one

Had the same issue this afternoon; this is how I solved it:
(thought I would post it as others seem to need something similar so they can come and build from this)
Make CIFAR10 return the same image twice:
class DoubleCifar10Dataset(Dataset):
    def __init__(self, root='data', train=True, download=True):
        self.cifar10_dataset = torchvision.datasets.CIFAR10(root=root, train=train, download=download)

    def __len__(self):
        return len(self.cifar10_dataset)

    def __getitem__(self, idx):
        return self.cifar10_dataset[idx][0], self.cifar10_dataset[idx][0]

Create the dataset
train_data = utils.DoubleCifar10Dataset(root='data', train=True, download=True)

train_writer = DatasetWriter(f'tmp/cifar10_train_data.beton', {
    'image1': RGBImageField(),
    'image2': RGBImageField(),
})
train_writer.from_indexed_dataset(train_data)

Create train loader:
train_loader = Loader(f'./tmp/cifar10_train_data.beton',
                    batch_size=batch_size,
                    num_workers=10,
                    order=OrderOption.RANDOM,
                    os_cache=True,
                    drop_last=False,
                    pipelines={
                        'image1': utils.Cifar10TransformFFCV.train_pipeline(gpu),
                        'image2': utils.Cifar10TransformFFCV.train_pipeline(gpu)
                    },
                    distributed=False)

Now you get two augmentations of the same image!

@davidrzs thanks for sharing. I'm going the route of creating multiple loaders and wrapping them. I'll share once it's working 100%.

Hello,
I am trying to have 4 images out of pipeline. I saved them like :-
writer = DatasetWriter(write_path, {         # Roughly 25% of the images will be stored in raw and the other in jpeg         'image': RGBImageField(             write_mode='jpg', # Randomly compress             jpeg_quality=60  # Use 50% quality when compressing an image using JPG         ),         'image_high': RGBImageField(             write_mode='jpg', # Randomly compress             jpeg_quality=60  # Use 50% quality when compressing an image using JPG         ),         'image_teacher': RGBImageField(             write_mode='jpg', # Randomly compress             jpeg_quality=60  # Use 50% quality when compressing an image using JPG         ),         'image_high_teacher': RGBImageField(             write_mode='jpg', # Randomly compress             jpeg_quality=60  # Use 50% quality when compressing an image using JPG         )     }, num_workers=2 )
Then I am reading that like this :-
`        image_pipeline: List[Operation] = [
# ffcv.fields.decoders.RandomResizedCropRGBImageDecoder((input_image_size, input_image_size)),
ffcv.fields.decoders.SimpleRGBImageDecoder(),
# ffcv.transforms.RandomHorizontalFlip(),
ffcv.transforms.ToTensor(),
ffcv.transforms.ToDevice('cuda:'+str(args.gpu), non_blocking=True),
ffcv.transforms.ToTorchImage(),
ffcv.transforms.Convert(torch.float16),
# torchvision.transforms.RandomApply([color_jitter], p=0.8),
# torchvision.transforms.RandomGrayscale(p=0.2),
# torchvision.transforms.RandomApply([Gaussian_Blur], p=0.5)
# torchvision.transforms.Normalize(0.2, 0.2), # Normalize using image statistics
]
    image_pipeline_high: List[Operation] = [
        # ffcv.fields.decoders.RandomResizedCropRGBImageDecoder((input_image_size*args.magnification, input_image_size*args.magnification)),
        ffcv.fields.decoders.SimpleRGBImageDecoder(),
        # ffcv.transforms.RandomHorizontalFlip(),
        ffcv.transforms.ToTensor(),
        ffcv.transforms.ToDevice('cuda:'+str(args.gpu), non_blocking=True),
        ffcv.transforms.ToTorchImage(),
        ffcv.transforms.Convert(torch.float16),
        # torchvision.transforms.RandomApply([color_jitter], p=0.8),
        # torchvision.transforms.RandomGrayscale(p=0.2),
        # torchvision.transforms.RandomApply([Gaussian_Blur], p=0.5)
        # torchvision.transforms.Normalize(0.2, 0.2), # Normalize using image statistics
    ]

    data_loader = Loader(args.data_path,
                    batch_size = args.batch_size_per_gpu,
                    num_workers = args.num_workers,
                    os_cache = True,
                    distributed = True,
                    batches_ahead = 1,
                    order = OrderOption.RANDOM,
                    pipelines = {
              'image': image_pipeline,
              'image_high': image_pipeline_high,
              'image_teacher': image_pipeline,
              'image_high_teacher': image_pipeline_high
                    })`

But the output is coming as :-
cuda:0 tensor(174., device='cuda:0', dtype=torch.float16) torch.Size([80, 3, 224, 224])
cuda:0 tensor(209., device='cuda:0', dtype=torch.float16) torch.Size([80, 3, 896, 896])
cuda:0 tensor(174., device='cuda:0', dtype=torch.float16) torch.Size([80, 3, 224, 224])
cpu tensor(209, dtype=torch.uint8) torch.Size([80, 896, 896, 3])
It seems the pipeline is not able to go beyond 3rd image for augmentation. Can you please let me know how to fix this? It is a bit urgent as I need to get my experiments running.
Thanks a lot!

@saarthak02 Can you create new issue ?

Hi @davidrzs
I tried your solution in contrastive learning with the below transforms.
ffcv_trns.RandomResizedCrop(scale=(0.08, 1.0), ratio=np.array((3. / 4., 4. / 3.)), size=size),
ffcv_trns.RandomHorizontalFlip(),
ffcv_trns.ToTensor(),
ffcv_trns.Convert(torch.float32),
ffcv_trns.ToTorchImage(),
ffcv_trns.ToDevice(device, non_blocking=True),

But I found that the data loading is much slower than using a single image with one pipeline. Even worse. The loading is much slower than using PyTorch standard loader with more complicated transforms:
transforms.RandomResizedCrop(size=size),
transforms.RandomHorizontalFlip(),
transforms.RandomApply([color_jitter], p=0.8),
transforms.RandomGrayscale(p=0.2),
GaussianBlur(kernel_size=int(0.1 * size)),
transforms.ToTensor()

Do you have the same issue?

Yeah it's completely expected. You are using pytorch augmentations. They are written in python, which means a single one can run at a given time per process.
Pytorch spawns sub-processes which means they can run them in parallel, but it's also very inefficient because processes can't share memory and have to communicate with IPC instead of shared
FFCV supports Pytorch augmentations just to experiment and see if an augmentation actually helps your model. You should never use them in situations where you care about performance. If you actually want speed you have to get rid of them.
Two solutions:

Implement your own augmentations using the FFCV API. It's really easy if you know numpy
Move your augmentations on the GPU. Because GPU code runs in the background you will be able to run multiple in parallel so you should have reasonable performance (not as good as FFCV augmentations because you will steal GPU compute power from your neural network)

(I created an issue #127 to issue a warning in this situation so that users don't expect good performance in this case)

Thanks for your reply.
When I use only FFCV augmentations, the two pipeline implementation with FFCV loading is still slower (though comparable) than the PyTorch loading with two-view transforms.
I suppose the problem is because loading two images is slower than loading one image (even by PyTorch).
train_loader = Loader(ffcv_cache_path,
                      batch_size=train_batch_size,
                      num_workers=num_workers,
                      order=OrderOption.RANDOM,
                      drop_last=True,
                      pipelines={'image0': image_pipeline,
                                 'image1': image_pipeline1,
                                 'attribute': label_pipeline})

Yeah it's completely expected. You are using pytorch augmentations. They are written in python, which means a single one can run at a given time per process.
Pytorch spawns sub-processes which means they can run them in parallel, but it's also very inefficient because processes can't share memory and have to communicate with IPC instead of shared
FFCV supports Pytorch augmentations just to experiment and see if an augmentation actually helps your model. You should never use them in situations where you care about performance. If you actually want speed you have to get rid of them. If you look at our examples we never use any Pytorch augmentation on the CPU.
Two solutions:

Implement your own augmentations using the FFCV API. It's really easy if you know numpy
Move your augmentations on the GPU. Because GPU code runs in the background you will be able to run multiple in parallel so you should have reasonable performance (not as good as FFCV augmentations because you will steal GPU compute power from your neural network)

Can I see your image_pipeline, image_pipeline1, and label_pipeline.
How is your CPU usage ?
(I haven't yet sen a situation where FFCV is not at least 10x faster than Pytorch, so I still strongly suspect there is a misconfiguration somewhere in your code)

(also @andrewilyas was suggesting zip any reason why you are not using this instead of saving your images twice ?)

zip is a good idea. I will try it and come back to you later.
Here is my imagepipeline (the same for imagepipeline1),
SimpleRGBImageDecoder()
ffcv_trns.RandomResizedCrop(scale=(0.08, 1.0), ratio=np.array((3. / 4., 4. / 3.)),
                            size=size),
ffcv_trns.RandomHorizontalFlip(),
ffcv_trns.ToTensor(),
ffcv_trns.Convert(torch.float32),
ffcv_trns.ToTorchImage(),
ffcv_trns.ToDevice(device, non_blocking=True),

and label_pipeline: List[Operation] = [NDArrayDecoder(), trns.ToTensor(), Squeeze()].
My CPU use

Other information. It takes me 2min 2secs to finish one epoch with FFCV (as I described above). In comparison, it takes me  2min 4secs to finish one epoch without FFCV (I additionally add more PyTorch transforms). So the time complexity is barely different.
For comparison, the pure PyTorch transforms w/o FFCV is
transforms.RandomResizedCrop(size=size),
transforms.RandomHorizontalFlip(),
transforms.RandomApply([color_jitter], p=0.8),
transforms.RandomGrayscale(p=0.2),
GaussianBlur(kernel_size=int(0.1 * size)),
transforms.ToTensor()

How are you storing your two images in your dataset ? Are you using RAW or JPEG ?

Also:
I see a lot of red on your htop (kernel time) so it seems that you have a lot of overhead (probably scheduling overhead). How many workers are you using?

Also you seem to be CPU bottleneck. Why not having the Convert after the ToDevice instead of doing it on the CPU (and also transmitting more data over the PCI bus) ?

I store the images by using the default fields. The images are from CelebA dataset of size (178, 218), stored in 'raw' format. attribute is a 40-dimensional vector per sample.
writer = DatasetWriter(ffcv_cache_path, {
            'image0': RGBImageField(),
            'image1': RGBImageField(),
            'attribute': NDArrayField(full_train_set.attr.dtype, (full_train_set.attr.shape[1],)),
        })

I used 8 workers.
Following your advice, here is some methods that works

Move images to GPU as early as possible. Improve by 10 seconds.

Some methods that do not work

Use jpeg instead of raw on writing images.
zip two duplicated loaders which load from the same file.

I you have an hyper-threaded processor. I would recommend using as many workers as you have physical cores on your processor (usually what htop shows / 2). And divide by 2 again when you use zip since you have two loaders.
I don't think the attribute is causing any slowdown. I think the main bottleneck right now is image resizing and right now with your pipeline you are doing it twice. I'm currently working hard on the next release that will make the pipelines much more flexible this is how it will look like in your case:
decoder =   ffcv_trns.RandomResizedCrop(scale=(0.08, 1.0), ratio=np.array((3. / 4., 4. / 3.)), size=size)

pipeline_1 = [
  ffcv_trns.RandomHorizontalFlip(),
  ffcv_trns.ToTensor(),
  ffcv_trns.Convert(torch.float32),
  ffcv_trns.ToTorchImage(),
  ffcv_trns.ToDevice(device, non_blocking=True),
]

pipeline_2 = [
  ffcv_trns.RandomHorizontalFlip(),
  ffcv_trns.ToTensor(),
  ffcv_trns.Convert(torch.float32),
  ffcv_trns.ToTorchImage(),
  ffcv_trns.ToDevice(device, non_blocking=True),
]

train_loader = Loader(ffcv_cache_path,
                      batch_size=train_batch_size,
                      num_workers=num_workers,
                      order=OrderOption.RANDOM,
                      drop_last=True,
                      pipelines={'image': [decoder],
                                       'image1': PipelineSpec(source=decoder, transforms=pipeline_1),
                                       'image2': PipelineSpec(source=decoder, transforms=pipeline_1),
                                       'attribute': label_pipeline})

And you would have a single image field in your FFCV dataset

Hi @davidrzs I tried your solution in contrastive learning with the below transforms.
ffcv_trns.RandomResizedCrop(scale=(0.08, 1.0), ratio=np.array((3. / 4., 4. / 3.)), size=size),
ffcv_trns.RandomHorizontalFlip(),
ffcv_trns.ToTensor(),
ffcv_trns.Convert(torch.float32),
ffcv_trns.ToTorchImage(),
ffcv_trns.ToDevice(device, non_blocking=True),

But I found that the data loading is much slower than using a single image with one pipeline. Even worse. The loading is much slower than using PyTorch standard loader with more complicated transforms:
transforms.RandomResizedCrop(size=size),
transforms.RandomHorizontalFlip(),
transforms.RandomApply([color_jitter], p=0.8),
transforms.RandomGrayscale(p=0.2),
GaussianBlur(kernel_size=int(0.1 * size)),
transforms.ToTensor()

Do you have the same issue?

Yeah, I had to do this trick to get performance parity with the old pipeline https://github.com/libffcv/ffcv/issues/64#issuecomment-1019346083 . Though it is hacky! I have reverted to the old standard PyTorch pipeline as the speed was already decent enough, so I cannot give you more information.

Hi there, I would also like to use ffcv with SimCLR training. @GuillaumeLeclerc what is the current state of #82? I saw others commenting on going back to standard Pytorch due to speed issues. Have these been resolved, i.e. is SimCLR training with ffcv viable?

@GuillaumeLeclerc it seems that the PipelineSpec is still not already yet? Is there any beta version supporting it? Given the fact that all the workarounds mentioned here have different limitations, it would be sweet to do two crops by just one image via PipelineSpec


Fourier-Hankel implementation for direct and inverse Abel transforms

Probably won't be too hard to implement at some point, if somebody is interested.  See FHA cycle
The only thing that need to be cheked is whether the Hankel transform can be done exclusively with numpy, scipy (don't know if scipy.linalg.hankel is related) or whether we would need to use a separate package  hankel.
In which case it can be added as an optional dependency, and this implementation should raise an error if hankel module is not installed (trying to keep the number of additional dependencies low). Or any other way you prefer to handle this.

Yes, it would be fun to include the FH version of the transform for comparison purposes!
The scipy.linalg.hankel says that it constructs a "Hankel Matrix". Wikipedia says that the Hankel Transform is "Not to be confused with the determinant of the Hankel matrix of a sequence."
So, I think that we may need to use that package that you suggest, or figure something else out.

This should be pretty easy to implement, but, when I looked around the literature, I could not find a clear equation for the Fourier-Hankel transform, despite it being mentioned frequently. @stggh, do you know of a paper that gives the equation/algorithm for the FH transform?

Python code for the Hankel transform is available at this github.
The HankelTransform function requires a function (image) input rather than (grid) data. At the moment I am confused by the evaluation of the Hankel transform in radial (1D) space, and how to return the 2D image, although, the (slightly buggy) examples appear to cover this case.
Thoughts, suggestions?

Oh, that is pretty cool that you found code for the Hankel transform. It looks like that code is just for the 1D case, right? We would just need to loop over all rows (or, hopefully, vectorize somehow).
It looks like that package was developed reasonably recently, so the author might be able to help us wrangle it into a Fourier-Hankel transform function.

@DanHickstein my apologies for the delay in my response. My coding time is limited at the moment, due to an upcoming teaching semester. @steven-murray author of the hankel is very helpful. I just have not had time to work through the 2D implementation, but will do so, once I have some free time.

Hi there,
Would love to figure out how to get hankel to do what you need it to do. It currently just does the 1D Hankel transform -- which covers any n-dimensional radially symmetric Fourier transform.
Having briefly read through this thread -- it seems like you need a 2D image. My code will of course do this fine if the image is radially symmetric. I have never considered a case where there is not radial symmetry (radial symmetry is usually the reason you'd use a hankel transform in the context of a FT). Just let me know what you need and I should be able to help out pretty easily.
Cheers.

Velocity-map images are (at least) "radially" symmetric in 1-d, about axis=0, along each image row.
e.g. O-2 photoelectron image:

It would be preferable not to have to iterate row-by-row.

Hmmm, so is a 2D FT required, or a 1D FT over each row?

@steven-murray, Thanks for being willing to help us out!
Everything happens in 1D. And, conceptually, each row can be treated separately.
When @stggh says that we want to avoid iterating "row-by-row", he is pointing that, to achieve the highest efficiency, we need to avoid for loops in Python, and instead vectorize our calculations using 2D numpy arrays. (So, there are still for loops, but they are just getting done by the c-code in numpy).
Anyway, for a proof-of-principle demonstration, it's totally fine to iterate over the rows in Python, as far as I am concerned. We can figure out how to speed things up after we get reasonable results.
Big picture: the "Fourier-Hankel" transform is mentioned in many papers about Abel transform as something of the "1980's gold standard" that has now been improved upon. We always thought that PyAbel should include it, because everyone talks about it so much, but we never really knew a good implementation of the Hankel transform, and I'm not sure that I ever really found a paper that explains how this "Fourier-Hankel" transform should be completed.
This thesis seems to say that we just need to take an inverse Hankel transform of the FT of our data:

http://trace.tennessee.edu/cgi/viewcontent.cgi?article=4324&context=utk_gradthes
I am curious to see how the FH transform compares with the other methods. It may offer a different efficiency scaling with the image size, and may be able to handle larger images. And it may offer an advantage in that it doesn't need to pre-computer and basis-sets like many of the other transform methods.

I agree our main aim is to implement the F-H transform (and if possible improve the execution speed), and Eq. (2.7) appears correct, according to @rth's FHA cycle top comment:
FA = H, hence A-1 F-1=  H-1, and therefore A-1 = H-1F
As @DanHickstein  states, we process each row, Fourier transform and then inverse Hankel transform.

Okay cool. Well, hankel doesn't do a discrete transform as its primary  goal (not in the same way that say a DFT is a discrete transform which can be written as a matrix equation). It's main purpose is to perform an accurate Hankel integral, which provides for an accurate transform for a given k. It can vectorize this operation for a vector of k, but this won't be quite as fast as a simple discrete transform (or any of the more efficient versions introduced in that thesis).
This is why hankel is written to accept a callable function f(x) to integrate/transform.
I'm wondering if there's a reason you don't want to use the basic "Direct HT" given in Eq. 2.12 of the thesis you shared? It would be easy to implement, easy to vectorize, and probably faster than hankel for your problem.
I'm assuming that you start the problem only with a discrete 2D array, not an analytic function?

hankel doesn't do a discrete transform

Bummer! Sorry, that I did not realise this.

use the basic "Direct HT" given in Eq. 2.12

Path of least pain ;-)    Eq. 2.12 requires a little thought.

I have been thinking about implementing some discrete HT functions in hankel, so they might appear soon.
I should clarify my last comment -- hankel will do a discrete transform if you force it to, it's just not built to do it. The way to do it is to use a spline on your array. The biggest problem is that it uses the same underlying array for each k, which has N elements (N is a parameter to hankel, not the length of the input function). Due to the way it's built, this array underlying the transform has to be good enough to get the integral right for all k in the vector you pass, which basically means the worst one sets the performance level. If you have a big dynamic range, this can be a killer. If not, then you're ok, and hankel will perform alright (similar to a direct HT, except more accurate).
Here's a small implementation of the DHT that I just wrote (it seems to work on a simple Gaussian function):
from scipy.special import jn
import numpy as np
from numpy.fft import fft, hfft, fftfreq, fftshift

def construct_dht_matrix(N, nu  = 0, b = 1):
    m = np.arange(0,N).astype('float')
    n = np.arange(0,N).astype('float')
    return b * jn(nu, np.outer(b*m, n/N))

def dht(X, d = 1, nu = 0, axis=-1, b = 1):
    N = X.shape[axis]

    prefac = d**2
    m = np.arange(0,N)
    freq = m/(float(d)*N)

    F = construct_dht_matrix(N,nu,b)*m
    return prefac * np.tensordot(F,X, axes=([1],[axis])), freq

This works for arbitrary dimension matrix X. Setting b sets the frequency normalisation (the thesis uses b=2pi). It's pretty quick as well.
I tried also writing the Abell transform, as specified by Eq. 2.13 in the thesis. I'm getting something slightly wrong (probably the frequency normalisation), but the code I have thus far is
def hankel_fourier_transform(X, d=1, nu = 0):
    N = X.shape[-1] # Assuming we're doing transform on second axis (X is 2D here)

    # Assumes X is 2D and has symmetry about 0
    G = np.real(fftshift(fft(X, axis=-1))[:,N/2:]*d) # Just get non-negative frequencies

    # Now the DHT
    eps = dht(G, d=1/(N*d), nu=nu, b=np.pi)[0] * 2  #b=pi to account for N/2, then *2 to get 2pi out front

    return eps, d*np.arange(0,N/2)

Feel free to play around with these. Doing this has sparked some ideas for things to implement in hankel, so it might get an update soon ;-)

@steven-murray fantastic - great work!
I can confirm the Gaussian discrete Hankel transform, although I am also not sure about the normalization.

code here
For the inverse Abel transform we pass 1/2 image row (right-side), a 1d-numpy array. This may then duplicated for the (r)fft  np.append(X[::-1], X), followed by the dht on G. Repeat for each row.
Testing this for inverse Abel transform

Some progress, but the profile is overcorrected.

very poor coding here

I reckon it could be vectorized -- the call to rfft() admits an axis parameter, so all rows can be done in one call. Otherwise, it's all looking very good.
Just a thought -- the transform you've done is the forward Abell transform, right? To do the inverse you need to do the Hankel then the Fourier?
Is there a reference plot to see what the output should look like?

Tks @steven-murray, order noted. NB once this code is running correctly you may provide the PR (with the fourier_hankel.py file that we finish with).
A 1D-Gaussian function looks ok, apart from a y (or intensity) offset. 3 plots in image, original Gaussian function, fourier_hankel inverse Abel transform, and PyAbel 3pt inverse Abel transform:

Code gist here.
The offset may be 'fixed' by adding the y[-1] offset.  However, this may be a symptom of another issue. I will give the 2D transform next (once checked, as it is not working correctly, for my usual mistakes).

2D has issues, looks like rows are flipped, but it is more complex. Some more investigation required.

Code, inset in place of __main__ in the gist above, or use with my fourier_hankel PyAbel branch:
import numpy as np
import abel
import matplotlib.pyplot as plt

IM = np.loadtxt("O2-ANU1024.txt.bz2")

quad = abel.tools.symmetry.get_image_quadrants(IM)
rows, cols = quad[0].shape

fhIM = abel.fourier_hankel.fourier_hankel_transform(quad[0])
tpIM = abel.dasch.three_point_transform(quad[0])

fhr, fhsp = abel.tools.vmi.angular_integration(fhIM, origin=(0,0))
tpr, tpsp = abel.tools.vmi.angular_integration(tpIM, origin=(0,0))

fig, ax = plt.subplots(2, 2)
ax[0, 0].imshow(quad[0], vmin=0, extent=[-512, 512, -512, 512])
ax[1, 0].set_title('F-H')
ax[1, 0].imshow(fhIM, vmin=0, vmax=1, extent=[-512, 512, -512, 512])
ax[0, 1].set_title('3pt')
ax[0, 1].imshow(tpIM, vmin=0, vmax=1, extent=[-512, 512, -512, 512])

# speed profiles
ax[1, 1].set_title('speed')
ax[1, 1].plot(fhr, fhsp, label='Fourier_Hankel')
ax[1, 1].plot(tpr, tpsp/10, label=r'3pt $/10$')
ax[1, 1].legend()

plt.savefig("Fourier-Hankel2D.png", dpi=75)
plt.show()

Here is a 2D cylindrical Gaussian. Ok, except for the offset:

Code:
import numpy as np
import abel
import matplotlib.pyplot as plt

def gauss(r, r0, sigma):
    return np.exp(-(r-r0)**2/sigma**2)

n = 501
image_shape=(n, n)
rows, cols = image_shape
r2 = rows//2
c2 = cols//2
r4 = rows//4
c4 = cols//4
sigma = 20*n/100

x = np.linspace(-c2, c2, cols)
y = np.linspace(-r2, r2, rows)

X, Y = np.meshgrid(x, y)

IM = gauss(X, 0, sigma) # cylindrical Gaussian located at pixel R=0
Q0 = IM[:r2, c2:] # quadrant, top-right
Q0c = Q0.copy()

tpQ0 = abel.dasch.three_point_transform(Q0)
fhQ0 = abel.fourier_hankel.fourier_hankel_transform(Q0c)

# plot results
fig, ax = plt.subplots(2, 2)
ax[0, 0].set_title('3pt')
ax[0, 0].set_ylabel('pixels')
ax[0, 0].imshow(tpQ0, vmin=0, extent=[-r4, r4, -c4, c4])

ax[1, 0].set_title('Fourier-Hankel')
ax[1, 0].imshow(fhQ0, vmin=0, extent=[-r4, r4, -c4, c4])

ax[0, 1].set_title('inverse Abel transform')
ax[0, 1].plot(tpQ0[r4], label='3pt')
ax[0, 1].plot(Q0[r4]/np.sqrt(np.pi)/sigma, '--', label='orig.')
ax[0, 1].plot(fhQ0[r4], label='fh')
ax[0, 1].set_xlabel('radius (pixels)')
ax[0, 1].legend()

ax[1, 1].axis('off')

plt.suptitle("cylindrical Gaussian")
plt.subplots_adjust(hspace=0.3, wspace=0.3)
plt.savefig("FHcylgauss.png", dpi=75)
plt.show()

Nice... well I tinkered around with the code and made it much faster (see this gist). It is now vectorized and this means the most intense part of the calculation (the bessel function matrix) needs only be done once (on my system, this gets a 257x257 image down from ~6 sec to 25 ms).
It also fixes a very small issue where the central value of the array was being duplicated when it was flipped and appended. However, this doesn't fix the offset issue. It seems to be an additive offset, not a multiplicative one, which severely decreases the places where things could be going wrong. But I couldn't find the problem!

@steven-murray great work, much faster, @PyAbel/developers love speed!
I am not sure about the need to remove the last array element, fft prefers an even number of points, PyAbel uses an odd-number of points(*), which when doubled (flip) is even. For the Gaussian example, the maximum is at r=0, pixel 0. However, this aspect should not have a major effect on the new fourier_hankel method.
Another known 1D-analytical inverse Abel transform is curve A in Hansen and Law

code gist
BTW,  direction='inverse' is legacy PyAbel, although inverse=True is neater, and perhaps, should be considered for PyAbel (@DanHickstein ?), along with a version change.
(*) except for onion_bordas.

It looks like you guys are making progress! Very exiting.
Regarding the direction='inverse' versus inverse=True, I think that I prefer the  direction='inverse', since it places the two directions on even footing, and makes the user consider which transform they are really looking for instead of just blindly setting the kwargs to True since it sounds nice. Is there a compelling reason to change? I'd suggest that we open a new issue about that if we want to continue the discussion.

Regarding the direction='inverse' versus inverse=True, I think that I prefer the direction='inverse', since it places the two directions on even footing, and makes the user consider which transform they are really looking for instead of just blindly setting the kwargs to True since it sounds nice.

Clearly, you guys are free to use whichever way suits you best -- especially if it's already implemented a certain way throughout PyAbel.  I always ask myself the question. I like the idea that they're placed on equal footing, but I usually go for the bool for simplicity. Usually one direction is more common than another, which means that the "equal footing" thing is not so important. Using logical values also increases speed (very slightly, negligible compared to the rest of the calculations in this case), and to me is just easier. If someone sees inverse=True and knows they don't want an inverse, then it is obvious what to do. If they see direction='inverse', it is not immediately obvious, without looking up the docs, what to put for the alternative case. And then you also have to deal with capitalisation etc. (all the ambiguities of a string).
Concerning the removal of the last element -- you're right in that it won't make much of a difference, however I would think for completeness you'd want to get it exactly right (not duplicating the zero-term). If you want to enforce an even-sized array, you could drop the last element after appending?
The analytic example is a bit alarming... not sure what to make of that! It's probably easier to work with that example though, because the differences are bigger.

With the "Curve A", we could attempt to determine the solution to the Fourier transform and then the Hankel transform (analytically) to see where things are going astray.

For Curve A, is the curve zero beyond r=1? If so, the solution is (I think):

Neat! Amazing sympy? ;-)
How do we evaluate the last term F2(...)?

Concerning the removal of the last element -- you're right in that it won't make much of a difference, however I would think for completeness you'd want to get it exactly right (not duplicating the zero-term).

Ahh! I now get this. X[0] should not be duplicated (for the Fourier transform input). Good point.

Regarding the direction='inverse' versus inverse=True

I will open a separate issue on this, once we have fourier_hankel operational. @steven-murray you do make a compelling argument.

discrete Hankel transform
This 2015 paper Baddour and Chaouinard JOSAA 32, 611 examines the discrete Hankel transform in terms of a transformation matrix (Y or T):

where T is given by:

The orthornomality test for the T-matrix Eq. (28):
import numpy as np
from scipy.special import jn, jn_zeros

def construct_dht_matrix(N, nu=0, b=1):
    m = np.arange(N)
    k = np.arange(N)

    jz = jn_zeros(nu, N+1)  # spherical Bessel zeros

    """
    # Murray
    b * jn(nu, np.outer(b*m, n/N))

    # Baddour Eq. (19)
    b = 2/(jz[N] * jn(nu, jz[k])**2)
    Y = jn(nu, np.outer(jz[m], jz[k] / jz[N]))
    Y = b * Y
    """

    # Baddour Eq. (25)
    b = 2/(jn(nu+1, jz[m]) * jn(nu+1, jz[k]) * jz[N])
    T = b * jn(nu, np.outer(jz[m], jz[k] / jz[N]))

    return T

# main -----
N = 5

T = construct_dht_matrix(N)

print((np.dot(T, T)+0.1).astype('int'))

correctly gives:
[[1 0 0 0 0]
 [0 1 0 0 0]
 [0 0 1 0 0]
 [0 0 0 1 0]
 [0 0 0 0 1]]

more later ...

Hankel transform pairs
This code gist attempts to compare an inverse Hankel transform with its pair. I am not sure of the relationship between r and k (frequency), or the correct amplitude scalings. Consider the code as some form of starting point for discussion.

Thanks @stggh , this looks promising -- certainly using the zeros of the Bessel function is more akin to the way that hankel works. Making this a proper DHT will be very useful.
I don't have much time this week as I am away for a conference, but will plug away at it when I can.

Neat! Amazing sympy? ;-)

Actually, this time I just used Wolfram|Alpha on each term separately :-)

The "secret" is to sample the function correctly:

This then yields Fig 1.(a), (c), for the Gaussian trial function 'forward' Hankel transform:

poor quality code gist for the above figure

The "trick" for the Hankel transform is that the source function is evaluated at the spherical Bessel function zeros. A radial range r = 0, ..., n-1 becomes jz*(n-1)/jz[N] where jz = scipy.special.jn_zeros(nu, N+1) and N is chosen so that jz[N] ~ n-1. jz then selects the sample points.
More later, at this moment I am also time poor.

This code gist appears to correctly (forward, inverse) transform the Baddour analytical exponential transform pairs. This image shows the numerical transform with its analytical function:

The only issue appears to be the need to sample our PyAbel images on to the Bessel grid

Improved version of the transformation_matrix:
def transformation_matrix(jz, nu=0):
    # Baddour transformation matrix Eq. (25) JOSA A32, 611-622 (2015)
    b = 2/(jn(nu+1, jz) * jn(nu+1, jz) * jz[-1])

    return b * jn(nu, np.outer(jz, jz / jz[-1]))

Updated code gist

This all looks really good. It is frustrating that a re-sampling has to be performed, It would be nice to be able to directly use an input discrete array.
I'm trying to think of a way around this, but can't at this point (my own hankel code also uses the Bessel zeros as nodes of the integration, so this seems to be a common theme amongst discrete Hankel transform methods).
We could perhaps build a reasonably robust case-by-case system in which an input array is interpolated onto the correct grid. It would be hard to vectorize well though, and interpolation always turns up problems for bad functions.
I might give it a shot this afternoon, and add a few tests in as well.

I find the sample space selection confusing. I think the required sampling condition is in fact the product space x frequency = jn_zeros(nu, N+1) i.e. choose N so that  r_max x ρ_max ~jz[N].
This gist is the Baddour sinc function test, Eq.s (84, 85). The above condition gives N=286, similar to the selected 256 in Baddour's paper:

@steven-murray thanks for keeping a tag on this. I am sure you understand much more about these transform sample spaces that I do. I agree, interpolation of each image row intensity will be necessary, but perhaps there is some clever @DanHickstein map_coordinates() function that may be applied to the image.

Image interpolation is not a good idea because of the measurement noise. We may as well return to the discrete version of the basic definition:

and @steven-murray original code above, which, I think(?), is the a fast version of Whittaker C-code Imaging in Chemical Dynamics, that I converted to Python (below). This Hankel transform operates on each image row, without requiring interpolation.
def Hankel(F, nu=0):
    """
    Whitaker "Image reconstruction: the Abel transform" Ch 5

    Parameters
    ----------
    F : numpy 1D array
       image row

    Returns
    -------
    f : numpy 1D array
       Hankel transform
    """

    n = F.size

    Nyquist = 1/(2*n)

    f = np.zeros_like(F)
    for i in range(n):
       for j in range(n):
           q = Nyquist*j
           f[i] += q*F[j]*jn(nu, 2*np.pi*q*i)

    return f

I will play some more. Sorry, for the diversion into the Baddour algorithm, which appears more suitable for analytical functions.

Vectorized Whitaker code:
    n = F.size

    Nyquist = 1/(2*n)

    f = np.zeros_like(F)
    i = np.arange(n)

    for j in range(n):
       q = Nyquist*j
       f[:] += q*F[j]*jn(nu, 2*np.pi*q*i[:])

    return f

code gist
Not sure about frequency axis or amplitude scaling.  @steven-murray I have not reconciled your original code. Out of free time at this moment.

Here is the sinc function transform pair:

code gist

The @steven-murray version of the Hankel transform is good, equivalent to, but faster than, Whitaker's and they both pass the Baddour analytical function (Gaussian, Sinc) transform pair test.  The issue of the Fourier-Hankel transform of curve A (above) remains.

discrete Fourier transform
Sorry for the (testing noise). I think we are getting close.
A check of the dft function for a square pulse, which should give a sinc function, shows that every second rfft element is zero. Hence, only the even elements of the rfft array must be selected, but his means that the return array is only 1/2 size. I am missing a detail?

code gist

It looks like @stggh is very close to a working FH transform. So, probably this isn't especially relevant, but, for the record, I found a matlab implementation of the FH transform hiding in the original BASEX matlab code: https://github.com/PyAbel/PyAbelLegacy/blob/master/BASEX/Matlab/fourier_hankel.m

A good resource with many references on the FHT (or the FFP) is chapter 4 Wavenumber Integration Techniques in Computational Ocean Acoustics (usually available through university accounts). E.g.: chapter 4.5.6.

Danhickstein writes on februar 19, 2018 18:00:

Hi @gauteh, thanks for pointing this out!
When you write FHT, I originally thought that you were referring to the "Fourier Hankel Transform", but now that I have looked up the book chapter, I see that FHT = "Fast Hankel Transform".
I believe that @stggh and @steven-murray have some numerical version of the Hankel transform working already. But, probably the references in that book contain more efficient algorithms for the Hankel Transform, which could speed things up.

Worth checking out at least! I have not looked in detail on the
difference with the implementations here. Both the Fast Field
Approximation and Fast Hankel Transform as described in this reference
use the asymptotic versions of the Hankel functions. But the version of
the Fast Hankel Transform (which does not seem to uniquely refer to one
method) can use the full Bessel functions for lower wavenumbers*ranges
as well as the negative spectrum as well.


Can this lib support creating hyper-v containers?

What did you expect to happen?:
Go through CreateContainerParameters and seems it doesn't support hyper-v. Hyper-v container is with more and more usage with taking security into consideration. Is it possbile to support creating hyper-v container with this lib?

It's configurable via Docker.DotNet.Models.HostConfig.Isolation


Add a Gitter chat badge to README.md

chen-keinan/mesh-kridik now has a Chat Room on Gitter
@chen-keinan has just created a chat room. You can visit it here: https://gitter.im/beacon-sec/mesh-kridik.
This pull-request adds this badge to your README.md:

If my aim is a little off, please let me know.
Happy chatting.
PS: Click here if you would prefer not to receive automatic pull-requests from Gitter in future.

I'll be happy to merge , please resolve conflict 1st


Revert "[SPARK-31765][WEBUI] Upgrade HtmlUnit >= 2.37.0"

This reverts commit 92877c4ef2ad113c156b7d9c359f396187c78fa3.

See the discussion in https://github.com/apache/spark/pull/28585#issuecomment-632386519

Since this is the latest commit, I am going to merge it now.
cc @sarutak

Test build #122948 has started for PR 28602 at commit 4a72dff.

Test build #122948 has finished for PR 28602 at commit 4a72dff.

This patch fails Spark unit tests.
This patch merges cleanly.
This patch adds no public classes.

Merged build finished. Test FAILed.

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/122948/
Test FAILed.


Can't login to Rancher server after upgrade from 1.6.5 to 1.6.6-rc2 with AD TLS authentication enabled using IP instead of hostname

Rancher versions:
rancher/server: v1.6.5
Steps to Reproduce:

Start rancher server v1.6.5
Enable AD with TLS authentication using IP and not hostname
Upgrade rancher server to v1.6.6-rc2
try to login

Results:
Can't login to rancher server, and getting this error Error Response from Auth service
Rancher server logs:
time="2017-07-25T00:04:22Z" level=error msg="GetToken failed with error: Error Error LDAP Result Code 200 \"\": x509: cannot validate certificate for <IP_ADDRESS> because it doesn't contain any IP SANs creating ssl connection creating connection"
2017-07-25 00:04:22,581 ERROR [:] [] [] [] [tp1020391880-14] [.a.a.i.e.ExternalServiceAuthProvider] Got error from Auth service. statusCode: 500
time="2017-07-25T00:04:28Z" level=info msg="Now generating Ldap token"
time="2017-07-25T00:04:28Z" level=error msg="GetToken failed with error: Error Error LDAP Result Code 200 \"\": x509: cannot validate certificate for <IP_ADDRESS> because it doesn't contain any IP SANs creating ssl connection creating connection"
2017-07-25 00:04:28,901 ERROR [:] [] [] [] [tp1020391880-15] [.a.a.i.e.ExternalServiceAuthProvider] Got error from Auth service. statusCode: 500
time="2017-07-25T00:04:34Z" level=info msg="Now generating Ldap token"
time="2017-07-25T00:04:34Z" level=error msg="GetToken failed with error: Error Error LDAP Result Code 200 \"\": x509: cannot validate certificate for <IP_ADDRESS> because it doesn't contain any IP SANs creating ssl connection creating connection"
2017-07-25 00:04:34,713 ERROR [:] [] [] [] [tp1020391880-62] [.a.a.i.e.ExternalServiceAuthProvider] Got error from Auth service. statusCode: 500

This should have never worked in the first place and is being fixed to correctly fail now.  Encryption is essentially worthless if you don't verify the identity of the other side of the line...  The hostname you're connecting to needs to match the certificate.

As a workaround, i disabled the authentication from the DB, and then renabled using hostname:
mysql> select * from setting where id=23;
+----+----------------------+-------+
| id | name                 | value |
+----+----------------------+-------+
| 23 | api.security.enabled | true  |
+----+----------------------+-------+

mysql> update setting set value="false" where id=23;

This verification is handled by golang tls package.
Should we document this workaround?

As this is a security issue, we will be providing workarounds on how to fix your setup before upgrade or if you have upgraded, how to fix it afterwards. @galal-hussein will be providing these details

For users who are authenticated with AD using TLS and have configured Access Control using an IP that doesn't match the hostname of their certificate, please follow the following workarounds:
Prior to Upgrading to v1.6.6+
Through the settings in the  v2-beta endpoint (<SERVER_IP:PORT>/v2-beta/settings/), which can be found under API -> Keys, update the value of api.auth.ldap.server from the IP to the hostname that matches the certificate.  After upgrading to v1.6.6, you should face no issues with your authentication.
Upgrading after v1.6.6+
If you have already upgraded to v1.6.6, you will not be able to log in. An admin who has access to the Rancher DB will need to disable access control through the DB. After access control has been disabled, you will need to re-enable with access control with the correct hostname and not the IP.

Note: When disabling and re-enabling your access control, your site access will be reset. You will need to adjust this back to your previous settings.


Eliminate dependency on const_cstr

https://rustsec.org/advisories/RUSTSEC-2023-0020

Let's not merge this until the capsicum crate is ready.  If that takes > 12 weeks, I may need to build a release without this change.

Superseded by #29 .


build: add workflow preferring TypeScript files

SUMMARY
Adds a Github workflow to check if any .js or .jsx files were added in a PR, and adds a comment to the PR asking to change the files to use TypeScript. This check always passes and will never prevent merge.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Comments when a .js file is added:

Skips the comment step when no js files are added:

TEST PLAN
Add a .js file to this PR and see the message appear. See the comment step skip when no js is added. Also test the jq command locally to ensure it works will all file extensions
ADDITIONAL INFORMATION

[ ] Has associated issue:
[ ] Changes UI
[ ] Requires DB Migration.
[ ] Confirm DB Migration upgrade and downgrade tested.
[ ] Introduces new feature or API
[ ] Removes existing feature or API

to: @ktmud @john-bodley @kristw @nytai @graceguo-supercat

Codecov Report

Merging #9901 into master will decrease coverage by 11.84%.
The diff coverage is n/a.

@@             Coverage Diff             @@
##           master    #9901       +/-   ##
===========================================
- Coverage   71.22%   59.38%   -11.85%
===========================================
  Files         585      401      -184
  Lines       30828    12736    -18092
  Branches     3237     3237
===========================================
- Hits        21957     7563    -14394
+ Misses       8762     4994     -3768
- Partials      109      179       +70

Flag
Coverage Δ

#cypress
?

#javascript
59.38% <ø> (ø)

#python
?

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9edfc8f...820d9d2. Read the comment docs.

This is a great idea!

ping @ktmud for rereview


Add more docs / tests for DiGraph reachableFrom method

Type of Improvement: Documentation & testing
API Impact: None
Backend Code Generation Impact: None

Lol @ that response time.


UrlLauncher should give examples of opening a mail or dialer

https://docs.flutter.io/flutter/services/UrlLauncher-class.html
I get asked "how to open a web browser" or "how to make a phone call" or "how to send an email" from Flutter a lot, and UrlLauncher is typically the answer folks are asking for.
But looking at the docs today they're pretty sparse.  We should probably give an example of the above.

Would it be better to send an email as a "Share" action? Or, how do I know when to trigger an email from a share or from a UrlLauncher ?

For email, there is yet Share or other fancier APIs (like https://developer.apple.com/reference/messageui) and those are probably best, but mailto: urls do work if needed. :)

Ah, so, when simply initiating a new email to an email address, use mailto:. When emailing an item/thing, use Share.

I have to point out this class rather frequently to customers, I suspect it would be a good bang-for-buck to document it.

@amirh I notice this old request from 2017. Is this still relevant?

Hi, how can we open email inbox on click ?

We have examples now, including an example of how to do mailto correctly which is the most common pain point. Given that, closing.


Invalid operation name under python 3.6.0

Hello, I tried a very simple snippet and I get this:
>>> from bytecode import Bytecode
>>> Bytecode.from_code((lambda: x).__code__)
Traceback (most recent call last):
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/instr.py", line 199, in _set
    opcode = _opcode.opmap[name]
KeyError: '<0>'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/bytecode.py", line 117, in from_code
    concrete = _bytecode.ConcreteBytecode.from_code(code)
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/concrete.py", line 143, in from_code
    instr = ConcreteInstr.disassemble(lineno, code.co_code, offset)
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/concrete.py", line 91, in disassemble
    return cls(name, arg, lineno=lineno)
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/concrete.py", line 36, in __init__
    self._set(name, arg, lineno)
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/concrete.py", line 49, in _set
    super()._set(name, arg, lineno)
  File "/home/alancristhian/py360/lib/python3.6/site-packages/bytecode/instr.py", line 201, in _set
    raise ValueError("invalid operation name")
ValueError: invalid operation name

I cannot reproduce on master what version are you running ?

Oh right, bytecode 0.4 doesn't support Python 3.6.
I just released bytecode 0.5 which adds Python 3.6 support, enjoy ;-)

Thanks! :)


Check for previous/existing GitHub issues/module proposals

[X] I have checked for previous/existing GitHub issues/module proposals.

Check this module doesn't already exist in the module indexes

[X] I have checked for that this module doesn't already exist in the module indexes; or I'm proposing the module to be migrated from CARML/TFVM.

Bicep or Terraform?
Bicep
Module Classification?
Resource Module
Module Name
avm/res/network/vpn-site
Module Details
Migrate from CARML to AVM
Do you want to be the owner of this module?
Yes
Module Owner's GitHub Username (handle)
fabmas
(Optional) Secondary Module Owner's GitHub Username (handle)
No response

Hi @fabmas,
Thanks for requesting/proposing to be an AVM module owner!
We just want to confirm you agree to the below pages that define what module ownership means:

Team Definitions & RACI
Shared Specification (Bicep & Terraform)
Module Support

Any questions or clarifications needed, let us know!
If you agree, please just reply to this issue with the exact sentence below (as this helps with our automation 👍):
"I CONFIRM I WISH TO OWN THIS AVM MODULE AND UNDERSTAND THE REQUIREMENTS AND DEFINITION OF A MODULE OWNER"
Thanks,
The AVM Core Team
#RR

I CONFIRM I WISH TO OWN THIS AVM MODULE AND UNDERSTAND THE REQUIREMENTS AND DEFINITION OF A MODULE OWNER

Hi @fabma,
Thanks for confirming that you wish to own this AVM module and understand the related requirements and responsibilities!
Before starting development, please ensure ALL the following requirements are met.
Please use the following values explicitly as provided in the module index page:

For your module:

ModuleName - for naming your module
TelemetryIdPrefix - for your module's telemetry

For your module's repository:

Repo name and folder path are defined in RepoURL
Create GitHub teams for module owners and contributors and grant them permissions as outlined here.
Grant permissions for the AVM core team and PG teams on your GitHub repo as described here.

Check if this module exists in the other IaC language. If so, collaborate with the other owner for consistency. 👍
You can now start the development of this module! ✅ Happy coding! 🎉
Please respond to this comment and request a review from the AVM core team once your module is ready to be published! Please include a link pointing to your PR, once available. 🙏
Any further questions or clarifications needed, let us know!
Thanks,
The AVM Core Team

Hi @fabmas,
Thanks for confirming that you wish to own this AVM module and understand the related requirements and responsibilities!
Before starting development, please ensure ALL the following requirements are met.
Please use the following values explicitly as provided in the module index page:

For your module:

ModuleName - for naming your module
TelemetryIdPrefix - for your module's telemetry

For your module's repository:

Repo name and folder path are defined in RepoURL
Create GitHub teams for module owners and contributors and grant them permissions as outlined here.
Grant permissions for the AVM core team and PG teams on your GitHub repo as described here.

Check if this module exists in the other IaC language. If so, collaborate with the other owner for consistency. 👍
You can now start the development of this module! ✅ Happy coding! 🎉
Please respond to this comment and request a review from the AVM core team once your module is ready to be published! Please include a link pointing to your PR, once available. 🙏
Any further questions or clarifications needed, let us know!
Thanks,
The AVM Core Team

[x] PR merged; Module published. PR: https://github.com/Azure/bicep-registry-modules/pull/751
[x] GitHub teams are available and assigned to their parents.
[x] CODEOWNERS file updated.

Thank you for your work @fabmas! I'm closing this issue now.


Support extending validator

It would be nice to be able to extend an existing validator to apply it on the root of the current validated object, in order to use a validator created for a super type (or just to create a hierarchy of validator)
For example, let's say I have two classes like these :
public class Person {
    private String name;

    public static final validator = ValidatorBuilder.of(Person.class)
                            .constraint(Person::getName, "name", Constraint::NotNull)
                            .build();

    // Etc...
}

public class Employee extends Person {
    private String serviceId;

    public static final validator = ValidatorBuilder.of(Employee.class)
                            // Apply the validator Person.validator here
                            .constraint(Employee::getServiceId, "service", Constraint::NotNull)
                            .build();

    // Etc ...
}

In this case, the work around I have come out with is .nest(Person.class::cast, "person", Person.validator) but it's not super readable. and I end up with a prefix "person.Xxx" which doesn't really mean anything.
Something like .extends(Person.validator) would be perfect

@jolangloys Thanks for your feedback. That's what I didn't come up with.
Introduction extends might cause complex situations like multiple inheritance.
I'm thinking to add delegate or copyOf to support your case.

@jolangloys
I've added ValidatorBuilder.cast method so that you can share Person 's validator with Employee. This should be simpler than extending validator.
Please take a look at a test case.
https://github.com/making/yavi/commit/3c56a4c054b089a78c048421cca0891215f7560c

Sorry I'll revert https://github.com/making/yavi/commit/3c56a4c054b089a78c048421cca0891215f7560c
This implementation mutates ValidatorBuilder ...

also added clone method.
See https://github.com/making/yavi/commit/82c6990f76ab4011560389a1fa978415af4186db

Thank you for your answer and work.
But the problem here is that we usually don't retain instance of ValidatorBuilder but we build them directly into Validator so the clone() and cast() methods won't help in this case.
I don't really think multiple inheritance of validator should be a problem. However, I can see the problem extracting internal attributes from the Validator class.
I can suggest you a compromise : create a method in the Validator class ValidatorBuilder<S extends T> extend(Class<T> clazz) (or whatever the name) in order to obtain a ValidatorBuilder on a sub class of an existing validator.

@jolangloys I also considered to add mutate method to Validator. The usage looks like
Person.validator.mutate() // returns ValidatorBuilder
               .cast(Employee.class)
               .constraint(Employee::getServiceId, "service", Constraint::NotNull)
               .build();

pretty close to your suggestion.
The problem here is the cross reference between Validator <-> ValidatorBuilder I've ever resolved in #7 .
If you have any more idea that doesn't have the cross reference, suggestion or PR is welcome.

Hello,
It's up to you, but I don't think that having a class and its own builder tight coupled with circular dependency is a problem. If you change one, you'll always need to change the other. To be honest, I have been surprise to find them in different package.
However, If you want to keep the pure unidirectional relationship, my first  suggestion will be better then. For me, You'll then have two way of accomplishing this:

Extract the attributes of the Validator. For example use package private methods to and an intermediate class
Add an attributes to Validator & ValidatorBuilder like includedValidator which will be another Validator or a Set of Validator which will be called at validation time.


doc(dialog-basics): add webpack notes

Added some notes related to #298.
@jods4 could you check if there is something I need to correct/rephrase/add?

I proposed tiny precisions to your changed. Other than that, looked fine to me!

@jods4 I didn't see any info on PLATFORM.moduleName in the Webpack section of the hub and why it is important. So I hope you don't mind I took one of your comments as is.

The hub still describes the v1.x plugins.
In the meantime, there's a lot of info about the new v2.x plugins in aurelia-webpack-plugin wiki, though.
Webpack traces a precise graph of each module's dependencies.
moduleName is important because it teaches webpack about aurelia-loader dynamic dependencies.
If your project is not with Webpack you don't have to use it.
If you build a library or share code with others, then you should. It doesn't hurt to have it in the code as aurelia-pal implementation is just a no-op.

@jods4 If you are OK with the current changes I'll merge it.
About PLATFORM.moduleName, I just wanted to point to more info about it(or add in the dialog docs, as I did), so that we're not just saying that it must be used but and why.

Looks ok to me, but I just noted that the first addition is quite nasty.
It's the kind of things that should "just" work out of the box :(
As far as explaining why the best I can offer is to point users to this documentation: https://github.com/aurelia/webpack-plugin/wiki

@jods4 You are right about the nasty part. The reason I mentioned the Hub was I wanted to link to it, not the wiki, but it'll be probably better.
Thanks for the help 😄

@jods4 So I tracked why that nasty part was added - https://github.com/aurelia/dialog/issues/233#issuecomment-260755619, I'll see how to properly address it.

If I might: I don't like advice without explanation as it tends to turn into cargo cult.
Instead of just saying that it might get dismissed, could you say under which conditions? "when your app is the  tag, any dialog opened by the first page loaded in the application before attached and not properly awaited will be dismissed"

'the body tag


500 obtaining layer infowindow data of some vis

Fixes #3091

@rafatower CR please

Frontend tests were OK :+1: (details)

retest this please

Frontend tests were OK :+1: (details)

Looks good to me though you have something weird thing in the tests (they look unrelated)

retest this please

Frontend tests were OK :+1: (details)


Mouse scrolling background glitch

it fixes by keyboard scrolling.

How do you reproduce this effect? And what's the colorscheme you are using?

On Ubuntu 14.04, with default scheme (on screenshot) and with molokai (but background is gray instead black).
Just launch and scroll with mouse wheel.

I cannot reproduce this on Mac, and unfortunately I don't have a Ubuntu to test.
Hope that some one will be able to diagnose this issue.

I can reproduce this on Ubuntu 14.04 x64. It may be a random bug.
Reproduce steps(only 1):

neovim.as open a file.

Pics:

I can reproduce this on OS X, I see it when moving around in the file without the mouse too (just holding <j>)

Looks like (for me at least), the color that's getting filled is the background color of the bottom-right block (in my case my airline status line). When the scroll event comes in, it looks like it's setting the background of the new area to match that instead of the actual background color. I'll have a PR up shortly that should fix it

Thank you, It works really well now. :cat:


Documentation Simplification

Fixes #127
Incorporated most feedback from #132.
I'll leave the other comments up to you to decide.
Basically all the legacy is out and I think new docs should be provided, if applicable.
I'm not sure if the NEWFEATURES.md is even still relevant or if it should be removed as well since we have GH issues now.

:white_check_mark: Build ServiceBusExplorer 4.0.98-PullRequest0133.27.build.261 completed (commit https://github.com/paolosalvatori/ServiceBusExplorer/commit/f60d6d1e7d by @tomkerkhove)

Good work guys, Please remove Cerebrata from the list of alternative tools, and restore the link to ServiceBus360. For the management portal, please add a link to https://ms.portal.azure.com. :) Thanks!!! :)

We need to change the list of links at the end of the History of Azure Service Bus. I suggest we take the definition of Azure Service Bus from the documentation and replace the title from History of... to simply Azure Service Bus.

Please remove Cerebrata from the list of alternative tools

Any specific reason?

Contact me offline :)

Ok.
I'm flying to Italy 😃

@paolosalvatori To what do you want to change the links?

:white_check_mark: Build ServiceBusExplorer 4.0.98-PullRequest0133.28.build.262 completed (commit https://github.com/paolosalvatori/ServiceBusExplorer/commit/eb04258416 by @tomkerkhove)

Changed the Azure Service Bus section, let me know what you think. I've removed the links at the bottom now that it points to the official docs.

:white_check_mark: Build ServiceBusExplorer 4.0.98-PullRequest0133.29.build.263 completed (commit https://github.com/paolosalvatori/ServiceBusExplorer/commit/bc64f891dd by @tomkerkhove)

Almost there :) @tomkerkhove can you please:

Add a paragraph called Service Bus Explorer before Installation and use the following wording
"The Service Bus Explorer allows users to connect to a Service Bus namespace and administer messaging entities in an easy manner. The tool provides advanced features like import/export functionality or the ability to test topic, queues, subscriptions, relay services, notification hubs and events hubs."
Immediately below, please reuse the picture to the tool that you removed.
That's it :)

Please wait with merging until #134 is completed.

#134 is done, no longer blocking.

I'll change the rest this evening!

:white_check_mark: Build ServiceBusExplorer 4.0.99-PullRequest0133.31.build.265 completed (commit https://github.com/paolosalvatori/ServiceBusExplorer/commit/482cd09c54 by @tomkerkhove)

Almost there :) Two more changes guys:
Replace the following section
Important Note
The zip file contains:
•The source code for the Service Bus Explorer 3.0.4. This version of the tool uses the Microsoft.ServiceBus.dll 3.0.4 that is compatible with the current version of the Azure Service Bus, but not with the Service Bus 1.1, that is, the current version of the on-premises version of the Service Bus.
•The Service Bus Explorer <IP_ADDRESS>. This version can be used with the Service Bus 1.1. The Service Bus Explorer 2.1 uses the Microsoft.ServiceBus.dll client library which is compatible with the Service Bus for Windows Server 1.1 RTM version. You can download the source code of the Service Bus Explorer v2.X here.
with
Service Bus Explorer for Windows Server
The Service Bus Explorer <IP_ADDRESS> can be used with the Service Bus 1.1. The Service Bus Explorer 2.1 uses the Microsoft.ServiceBus.dll client library which is compatible with the Service Bus for Windows Server 1.1 RTM version. You can download the source code of the Service Bus Explorer v2.X here.
Can you please create a file containing the update log? I mean the section that in the current version of the readme file starts with the title Service Bus Explorer. When you created that file, please add a link to the readme file under a section called Tool Documentation.
Tool Documentation
Here you can find the tool documentation and a log of the features implemented over time.

@paolosalvatori Sure I'll add the server stuff later today.
About the release notes, I started converting that but it was more than 2 years old, is it worth keeping that around? If so, I think it's not worth converting it since it will not be updated anymore.
Thoughts on this?

Release notes should be under releases in GH.
Listing then seriously now as good as listing your daily childhood events 20 years later 🙂

Well, regarding release notes, I'd remove the parts where I mention fixes and keep those parts where I explain features. I'm aware that fixing this stuff needs time. We can just add a section at the end that says:
Release Notes
You can find release notes here.
Then, only if you have spare time and not necessarily now, you can fix the document and just remove dates and fixes and keep only those parts that explain features.

I added the section as-is in a dedicated file. I left the release notes out since that is tied per release, is that correct @SeanFeldman?

Just call this section Documentation for now... History of Service Bus Explorer is too verbose :) Then we can ship it in my opinion. Last change, promised :) Also please change the wording of the Service Bus Explorer for Windows Server section to:
The Service Bus Explorer 2.1.3 can be used with the Service Bus for Windows Server 1.1. The Service Bus Explorer 2.1.3 uses a version of the Microsoft.ServiceBus.dll client library which is compatible with the Service Bus for Windows Server 1.1 RTM version. You can download the source code of the Service Bus Explorer 2.1.3 here.

History of Service Bus Explorer is too verbose

Looks like @paolosalvatori wants to keep that for his memoir 🙂

@paolosalvatori I updated it but I think we should change the mentioned version to 2.1.0 since that is the released legacy version. What do you think?

@tomkerkhove I just made the same comment. Criminal minds think alike.

Took the liberty to align it with the released version, can still change it back to v2.1.3 if you want @paolosalvatori

I reviewed the latest version of the readme file and... let's ship it :)

Thanks!

:tada:


Update prototype token with the appropriate vision mode when darkvision or other special vision traits are set on the character sheet

The prototype token should be updated with the appropriate vision mode when a feature is added to the character.
The example below is specific to darkvision, but a fix should apply to all special vision modes added to the character sheet.
Character sheet vision options:

Prototype Token (current):

Prototype Token (desired):

This should be listed as a bug, not a feature request.

Fair enough, in that case I have a bug to submit separately.


Add support for async methods

Add an async version of the Execute method that will return a task from the method that was executed (or Task.CompletedTask).

Implemented in 0.9.10: the generated code now calls .Wait() on any methods that return a task.


[MFA Demo issue] adding fullstops and question marks

Add fullstop to the end of description when resetting recovery codes:

Add Question mark to the end description when removing methods:

Closed by #300


Loading a bitmap object

Hi, I was wondering If I can load a bitmap object (basically load an image without a URI), since in the features it is mentioned that I can load Bitmaps, Resources and URI, however I only saw the URI option.

It is available if you use CropImageView, see:
https://github.com/ArthurHub/Android-Image-Cropper/wiki/Using-CropImageView-in-own-Activity.
Passing bitmaps between activities is problematic, so I couldn't provide
this option for the built in activity.
On Tue, May 10, 2016, 22:12 Tony<EMAIL_ADDRESS>wrote:

Hi, I was wondering If I can load a bitmap object (basically load an image
without a URI), since in the features it is mentioned that I can load
Bitmaps, Resources and URI, however I only saw the URI option.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/ArthurHub/Android-Image-Cropper/issues/66

Alright, Thanks for the quick reply.


0 results found in 0ms

Description
I am getting 0 results found in 0ms.
details:
facet_counts: []
found: 0
hits: []
page: 1
request_params: {per_page: 10, q: "about"}
search_time_ms: 0

I am using Typesense Cloud as a server, and using this plugin on the gatsby project, follows this tutorial
This is not a simple test project, we are using Algolia, but I would like to use Typesense.
Correctly how to fix this issue?
Steps to reproduce
I added this code each pages:

About Us

test test description

      about

When gatsby build, I getting these warnning:
No HTMLelements had the data-typesense-field attribute, skipping page
No HTMLelements had the data-typesense-field attribute, skipping page
No HTMLelements had the data-typesense-field attribute, skipping page
No HTMLelements had the data-typesense-field attribute, skipping page
...

Expected Behavior
it seems this plugin doesn't index each page
Actual Behavior
Correctly, how to check the index each page in dev environment?
Metadata
Typsense Version: Typesense v0.17.0
OS: Typesense Cloud

@FullStackTiger That warning message seems strange. What this plugin essentially does, is it scans the public directory post build for any HTML files and looks for elements with the data-typesense-field attribute.
When you run gatsby build, may I know the structure of your public directory that gets generated? If you're able to zip the whole public dir and share it with me (jason at typesense d0t org), that would help a lot.
Btw, here's an example of a minimal Gatsby application that shows the plugin in action along with react-instantsearch: https://github.com/typesense/gatsby-plugin-typesense/tree/83adc28ff315f5a52800ef0658515799df8d6146/test/support/testground

Closing this for now, feel free to re-open with more info.


search sort

when I use /api/search?type=&q=  ,How to sort ?

http://docs.ponzu-cms.org/HTTP-APIs/Search/
If there is no specific documentation in Ponzu or in Bleve (linked from that URL), then you will have to sort the results in memory.

Thank you !


The version is development if you install kubeconform by running the go install command.

Reproduce
go install<EMAIL_ADDRESS>kubeconform -v # "development"

root cause: https://github.com/yannh/kubeconform/blob/v0.6.7/cmd/kubeconform/main.go#L18

If I download the binary from the release page (https://github.com/yannh/kubeconform/releases/tag/v0.6.7), the version is v0.6.7.

That would be working as expected. Builds on a specific tag in our CI pass  -X main.version={{.Tag}}    to set the version correctly - if you check out and build at a specific tag you should be able to pass this as well. I hope this works for you!

I'm hoping this worked! :+1:


CB-11237: linking cordova-fetch

See CB-11237. I have not tested this code, because I do not have a buildbot dev environment set up.

@rakatyal @stevengill please review

LGTM.

LGTM too! Sorry I forgot about medic :(

@stevengill no worries! Thanks for taking a look!


update ADAM feature package

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/mango-prb/305/
Test PASSed.


Updated solaris 10 environment toolchain

New PR since I goofed up the rebase on #85

@scotthain Modulo that last small comment things look :+1:!


Allowing periodic jobs to be schedules for less then 60 seconds

Currently setPeriodic call in JobRequest checks if argument is in range, this is if the scheduled periodic job is less then 60 seconds interval. This should be either configurable or not enforced.
Is there any reason of having a periodic job that can not be less then 60 seconds ?

That requirement is enforced by the AlarmManager and since this library is a wrapper for all of them I made this a global constraint. An explanation can be found here: https://code.google.com/p/android/issues/detail?id=161244
The GCM API has a minimum of 30 seconds: https://github.com/google/gcm/issues/58


Integrate with travis and coveralls

Changes Unknown when pulling<PHONE_NUMBER>f323813e2c96b8048a65313aa0700b on travis into ** on master**.

Changes Unknown when pulling<PHONE_NUMBER>f323813e2c96b8048a65313aa0700b on travis into ** on master**.

Changes Unknown when pulling 951a3d81c3300c2e749237c7a0e52c758d038e03 on travis into ** on master**.

Changes Unknown when pulling 951a3d81c3300c2e749237c7a0e52c758d038e03 on travis into ** on master**.


Reword --emit=asm advice

While it's true that codegen-units=1 will usually improve code generation, that's often application-specific and will slow down the compilation even more. It's a compromise, and it's unfair to tell users to always do that. It would have been the default if that was true.
In any case, --emit=asm isn't really good advice.

Thank you @lnicola , I will pull this when I get some time.

Thank you again @lnicola , and I apologize for the extreme delay pulling in this change.  I moved countries, got a new job, and was dealing with some medical issues, so I was preoccupied and unable to spend any time on this.  I am hoping to have a more stable life going forward.
Best Regards!

No worries, I doubt anyone missed that clarification. I hope everything works out fine for you. Good luck and stay healthy!


Update french translation

I'm still not done with it, but this is my first version.

Ok, how about the "è" character?

Seems like it would be $8A.

Any luck on finishing this out?

It is done :D
Merry Christmas btw ;)
Le ven. 24 déc. 2021 à 23:20, Matt Waltz @.***> a
écrit :

Any luck on finishing this out?
—
Reply to this email directly, view it on GitHub
https://github.com/mateoconlechuga/cesium/pull/203#issuecomment-1000940505,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AUJIUSUI6AEUS4IZJA7XVUTUSTW4HANCNFSM5J3OLCNQ
.
Triage notifications on the go with GitHub Mobile for iOS
https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
or Android
https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you authored the thread.Message ID:
@.***>

Great thank you! Merry Christmas to you too :)


DeepSpeed resume fails for multiple nodes

** Environment **

An environment with 2 nodes, each node has 1 GPU, shared file system.
deepspeed==0.8.3
mosaicml==0.14.1
** To reproduce
Steps to reproduce the behavior:

Launch the job in node0
CUDA_VISIBLE_DEVICES=0 composer --world_size 2 --node_rank 0 --master_addr node0
and in node1
CUDA_VISIBLE_DEVICES=0 composer --world_size 2 --node_rank 1 --master_addr node0
Once checkpoints saved, stop the job.
There should be latest-rank0.pt.tar and latest-rank1.pt.tar in the save_folder
Specify load_path to save_folder/f'latest-rank{composer.utils.dist.get_global_rank()}.pt.tar' in Trainer
Launch the resumed job  in node0
CUDA_VISIBLE_DEVICES=0 composer --world_size 2 --node_rank 0 --master_addr node0
and in node1
CUDA_VISIBLE_DEVICES=0 composer --world_size 2 --node_rank 1 --master_addr node0

Then there will be error in node1:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmp3o00dg6a/checkpoint/composer_states.pt'
Expected behavior

The resume should work without errors.
Proposed fix

The reason is because only (global) rank 0 saves composer_states.pt.
https://github.com/mosaicml/composer/blob/7da93f819c4d5f52ce5ccfef0f39a7f836cb0d08/composer/utils/checkpoint.py#L530-L535
So only latest-rank0.pt.tar has composer_states.pt.
In order for the other (global) ranks to access composer_states.pt, all (global) ranks should share the same node_checkpoint_folder as in
https://github.com/mosaicml/composer/blob/7da93f819c4d5f52ce5ccfef0f39a7f836cb0d08/composer/utils/checkpoint.py#L204-L205
However, _get_local_rank_zero_path(tempdir) as in
https://github.com/mosaicml/composer/blob/7da93f819c4d5f52ce5ccfef0f39a7f836cb0d08/composer/utils/checkpoint.py#L237-L243
cannot make every (global) rank share the same node_checkpoint_folder.
Instead, only local ranks on the same node share the same node_checkpoint_folder.
The correct way should be use _get_global_rank_zero_path(tempdir):
def _get_global_rank_zero_path(path: Optional[str]) -> str:
    """Broadcasts the ``path`` from the (GLOBAL) rank zero to all (GLOBAL) ranks."""
    paths = dist.all_gather_object(path)
    rank_zero_path = paths[0]
    assert rank_zero_path is not None, 'rank zero provides the path'
    return rank_zero_path

In summary, only (global) rank 0 saves composer_states.pt.
However, the code assumes every local rank 0 saves composer_states.pt.

Hey @sonodasong is it possible to download the checkpoint on node1 as well?
Alternatively, for composer, we've more typically used FSDP. Is there a requirement to use deepspeed?

Hey @sonodasong is it possible to download the checkpoint on node1 as well?

There is no problem for download on node1.

Alternatively, for composer, we've more typically used FSDP. Is there a requirement to use deepspeed?

We are exploring ways to pretrain transformers faster, and open to techniques that can help to achieve this.
Thanks.

@sonodasong hm... If it's possible to download the model on node0 and node1 then does resumption work?
Makes sense, at mosiac we have open sourced a repository for LLM-pretraining:
https://github.com/mosaicml/llm-foundry/
Typically, for this repo, we use FSDP as the distributed backend. We're able to achieve 50-60% MFU (https://github.com/mosaicml/llm-foundry/tree/7abae0d079e8c99a8f1eb73861b65e6766e45018/scripts/train/benchmarking). Let me know if you have any questions.
I'm going to close the issue for now, but feel free to re-open if the above doesn't satisfy your questions.

@sonodasong hm... If it's possible to download the model on node0 and node1 then does resumption work?

No, because node0 and node1 download to different extracted_checkpoint_folder.


Non existant classes

When I am running:
setup:di:compile
I am getting this:
Class Cloudinary\Api does not exist
And in Admin if I try to save config I am getting that Cloudinary class is not defined, and it is used in:
/app/code/Cloudinary/Cloudinary/Core/Security/CloudinaryEnvironmentVariable.php
Am I missing some library or what is it?
I am having Magento2 Commerce Cloud solution.

Hi @iva-fullers
The error might mean that Magento has not loaded the Cloudinary PHP library that the Cloudinary Magento module uses.
To install it manually run the composer require command from your Magento installation root directory:
Composer require cloudinary/cloudinary_php:1.8.0


how to compose 2 trees

hi!
how can I nest trees made with the editor?
for example like explained here:
http://aigamedev.com/open/tutorial/design-consistent-behaviors/#ASimpleMethodology
sleep bt uses move bt
how can that be implemented with behaviour3js
e.g. An action node that gets a tree instance from a factory?
I have no Idea where to start.

This kind of works but feels strange.
My goal is that I can define a Tree that uses Parameterized Trees as explained here:
http://aigamedev.com/open/tutorial/design-consistent-behaviors/#ASimpleMethodology
Can this be done with behaviour3js ?

My Current Solution:
Actions.BT = NodeFactory("Action", {
  name: "BT",
  initialize: function(settings) {
    this.tree = settings.tree
  },
  tick: function tick (tick) {
    var status = TreePool[this.tree].tick(tick.target, tick.blackboard)
    return status
  }
})

As of Editor version 0.2.0 it is possible to add subtrees.
I needed to make a small change in b3.js 0.2.0 to make it work though.


Currently supporting TCP protocol, add the corresponding checks

…e relevant process.
What type of PR is this?

What this PR does / why we need it:
Which issue(s) this PR fixes:
Fixes #
Currently supporting TCP protocol, add the corresponding checks
Special notes for your reviewer:
Does this PR introduce a user-facing change?:

/cherry-pick release-0.3


[cookbook] multi llm consistency update

[cookbook] multi llm consistency update
Fixes #374

update aiconfig json, repulled it from the LastMile workbook linked in the readme

update notebook with run with dependencies

use PaLM api key

Rebase, Updated readme colab link, synchronized the aiconfig file names across workbook, notebook impl, and colab


Identify & Reach out to Potential Partners

[ ] - Research institutions, government bodies, and private sector companies that CLENT Africa can partner with.
[ ] - Create a database of potential partners, including contact information and areas of interest.
[ ] -  Reach out to partners on behalf of CLENT Africa.

Hi @clentafrica/wg-partnerships is anyone available to work on this? Do we need an initial template for this so that we have a similar view across the various regions?

Hi @clentafrica/wg-partnerships is anyone available to work on this? Do we need an initial template for this so that we have a similar view across the various regions?

@yigakpoa I can start to work on it and yes we need a initial template.

HI @AxelleDongni please find a template here: https://docs.google.com/spreadsheets/d/1hcG4CI7s825DXltz4cj2QGl8eV0K8okt4aOsLqOTBtQ/edit


Resampling at arbitrary time steps

🚀 The feature
Currently, torchaudio.functional.resample can only resample at regular time points and the period is determined by orig_freq and new_freq.
Is it possible to resample at arbitrary time steps?
So rather than specifying a resampling ratio, we specify a array of time steps.
Motivation, pitch
I would like to be able to model jitter in an ADC which can be modelled by a slightly varying sample rate. If you integrate a sample rate curve (which isn't constant), you get irregular time steps. A function such as the one suggested above would allow me to resample using these time steps and model a jittery ADC.
Alternatives
I've rolled out my own function but it's not super efficient. Some experts might do a better job.
Additional context
No response

Does your jitter effect change the sample rate periodically?
If so, I think it's possible to reuse part of the resampling algorithm we have.
resample finds the lcm of orig_freq and new_freq to pre-compute the since filters and apply them periodically.
You can apply the same logic to get the needed since filters between the orig_freq and your modulation frequency (let's name it mod_freq).
If you want something that's more general, like np.interp, unfortunately, we don't have a similar function so far.

Does your jitter effect change the sample rate periodically? If so, I think it's possible to reuse part of the resampling algorithm we have. resample finds the lcm of orig_freq and new_freq to pre-compute the since filters and apply them periodically. You can apply the same logic to get the needed since filters between the orig_freq and your modulation frequency (let's name it mod_freq).
If you want something that's more general, like np.interp, unfortunately, we don't have a similar function so far.

The jitter is gaussian random and so the sample rate is slightly different at every sample. You can think model jitter (I think) as a sample rate that's undergoing a very small gaussian random walk between a minimum and upper bound. You can then calculate the time points by integrating the sample rate over time. Then I need to resample using those time points. So yes, something like np.interp but using a user defined filter, such as kaiser - sinc filter would be appropriate. Currently i'm using a polyphase filter. This works but I think we could do better.

@pfeatherstone You can use https://github.com/aliutkus/torchinterp1d for that purpose. In fact it's exactly what I used it for, implementing differentiable time warping.

Nice. Except you can't set the filter...


Add support for device.connection_list API call

Coverage increased (+0.01%) to 97.99% when pulling b83028ab4811a7970a5d6d6cbadf2b4936cad8cd on mgagne:device_connection_list into eff530eb34ccfa05b1fdb57588e72ee408a073d0 on jasonkeene:master.


Update LSP.md

Instruction is not related on neovim.

Hello!
How should Neovim users configure things then?
And is prabirshrestha/vim-lsp now integrated into Vim itself?


Simplify get started very condenced

https://mlem-ai-simplify-get-st-gq4xqx.herokuapp.com/doc/get-started
This is a draft for a draft.
Basically I got rid of some texts that tried to explain what is going on

One thing I noticed with toggles and tabs - if you have the same name for tabs in different toggles, you are switching all of them. Because tabs can have different length, you'll get jumpy content (try cli/api toggle for serving)

This needs a merge from main, actually 🙂

@jorgeorpinel  - I'm going to use this to grab some ideas and put on top of the current get-started iterations. Not sure which ones yet, but I plan to then make a more "review ready" PR and will ping you there, let's keep this here just for me to use as a reference (sorry about the confusion this may cause).
BTW there are some things here that I disagree or would like to tweak and not take as is exactly.
I think that, among other things, @mike0sv @aguschin and myself (and maybe you as well) have a slightly different mental model of the HL workflow, and we need to reconcile that conceptually.

This one def. looks stale. Probably safe to close (can always be reopened).


Contributing code to read felled-tree requests for Haifa

readpdf.zip

This is code to read the list of tree-felling permits for Haifa:
https://www.haifa.muni.il/development-and-construction/engineering-administration/uprooting-trees/
I am contributing it to the Meirim project, no strings attached

Closed due to implemented, thank you


Antibiotic Resistance Gene Search error

When I go to the antibiotic gene search from the data landing page, get errors.
https://www.patricbrc.org/portal/portal/patric/AntibioticResistanceGeneSearch

this is a problem of link. As error message says, we should have context params when we call the search page. The search itself has not broken. I will update wordpress to fix the link.

fixed and available on production.


Webkit: Add any newly required Linux deps to our docker images for running Webkit browser

Add anything required and documented in https://github.com/cypress-io/cypress-documentation/issues/4060

I think we should wait until WebKit is in stable to add this. WebKit adds like 500MB of dependencies to our current image, and maintaining a separate image series for it seems like more effort than it's worth when users can run npx playwright install-deps webkit for now.

@jennifer-shehane @flotwig is there any simple way to add missing required dependencies besides what npx playwright install-deps webkit installs for the cypress docker containers?
I am trying to build a docker image FROM cypress/browsers:node18.12.0-chrome107 and added npx playwright install-deps webkit to the dockerfile to install the missing dependencies to be able to also run webkit tests with it. But when trying to execute tests using webkit browser with cypress, the following error is emitted:
There was an error launching `playwright-webkit`:
Error:
╔══════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ Missing libraries:                                   ║
║     libvpx.so.7                                      ║
║     libicui18n.so.70                                 ║
║     libicuuc.so.70                                   ║
║     libjpeg.so.8                                     ║
║     libwebp.so.7                                     ║
║     libffi.so.8                                      ║
╚══════════════════════════════════════════════════════╝ Failed to launch browser.

I know the used cypress image derives from debian:bullseye-slim. I tried to find and install the missing packages using apt-get ... but with no luck so far... What I've tried was to do the following additional install besides npx playwright install-deps webkit:
apt-get install -y libvpx6 libvpx-dev libicu-dev libjpeg-dev libwebp-dev libffi-dev


fix: allow WikiPage.#revisionAuthor to be undefined

Possibly fixes #108
💸 TL;DR
Allows WikiPage.#revisionAuthor to be undefined, as that is a possibility for some wiki pages.
📜 Details
Removes assertNonNull(data.revisionBy?.data, 'Wiki page author details are missing'); from the WikiPage constructor and sets #revisionAuthor to be of type User | undefined depending on whether data.revisionBy exists. Updates get revisionAuthor() and toJSON() to reflect the type change.
It's worth noting that revisionBy is already marked as potentially undefined in the WikiPage interface from @devvit/protos. revisionId and revisionDate are not marked that way, but would also be returned as null by the Data API in this same edge case of a wiki page with no revision history.

🧪 Testing Steps / Validation
Untested, as I am unable to set up the environment to produce a successful build even with no changes. TypeScript language server doesn't show any new errors though. Additionally, there are no existing tests for WikiPage found in /packages/public-api/src/apis/reddit/tests.
✅ Checks

[❌] CI tests (if present) are passing
Unable to test, see above.
[❌] Adheres to code style for repo
Prettier doesn't even pass on an unmodified WikiPage.ts file.
[✅] Contributor License Agreement (CLA) completed if not a Reddit employee

Made the requested change now that I was finally able to compile and notice the issue with the undefined check.
And I agree that the README could use better instructions for compiling specific packages like the public-api one.
I ended up clearing everything except that package, changing out several of its dependencies for valid @next versions (packages like the matching @devvit/shared-types and @devvit/protos are not included with this repo), and copying the src/devvit/internals/semanticColors.ts and src/types/icons.js files from an already published version because generating them requires dependencies that aren't public (@reddit/faceplate-ui).


Karate does not work with Java 22 (?) => OK with Java 21

Hello,
I'm new to Karate and I tried the simple the standalone JAR with the very simple test : httpbin.feature
I've lost few hours fighting against Java 22 (from https://www.oracle.com/fr/java/technologies/downloads/#java22)
Nothing happens, except this:
java.exe -jar karate.jar httpbin.feature
10:00:42.716 [main]  INFO  com.intuit.karate - Karate version: 1.4.1

(none report, except karate.log)
But everything is OK with the previous version : Java 21
(From Windows 10 and Powershell)
Regards

tagging as help wanted for now. would @ecidou be interested in contributing a PR

@a11970 thanks for this - I think I'll prioritize this, will take a look and revert

this is fixed but we are unable to make a maven release which happens occasionally when the server is under high load. we can try again next week
the problem was graal was not compatible with java 22 and had to be upgraded. we also set our "compatibility" build to use Java 23 (early access) so we are in a better place that way
meanwhile you can build from source: https://github.com/karatelabs/karate/wiki/Developer-Guide

I can confirm that a locally build from the source with graal upgraded fixed the problem. So now I'm just waiting for a new release from you.
Thank you for your help.

@ecidou @a11970 @edwardsph 1.5.0.RC4 is now available https://central.sonatype.com/artifact/io.karatelabs/karate-core

1.5.0 released


Allow tweaking the default output directory for documentation generation

In #112, we set the output directory to target, but when using a Gradle project, this doesn't line up with the .gitignore'd directory build, and doesn't follow where it would generally be expected to be.

I agree, we should expose configuration API to tweak the output folder for documentation generation.

I've tweaked the general default to build/moduliths-docs in case we detect a Gradle project (lacking a pom.xml in the project root). I also introduced the option on Documenter to customize the output folder entirely, too.


[SPARK-46719][PS][TESTS] Rebalance pyspark_pandas and pyspark_pandas_slow

What changes were proposed in this pull request?
Rebalance pyspark_pandas and pyspark_pandas_slow
Why are the changes needed?
before:
pyspark_pandas: Tests passed in 1849 seconds
pyspark_pandas-slow: Tests passed in 3538 seconds
after:
pyspark_pandas: Tests passed in 2733 seconds
pyspark_pandas-slow: Tests passed in 2804 seconds
Does this PR introduce any user-facing change?
no
How was this patch tested?
ci, https://github.com/zhengruifeng/spark/actions/runs/7524159324/job/20478674209
Was this patch authored or co-authored using generative AI tooling?
no

thanks @HyukjinKwon ,
merged to master