Label Offset function in R Mapview do not alter the position of the text - r-mapview

I have been trying to adjust the position of labels in Mapview. However, the functions that I have seen discussed won't work for me. The one that comes closest so far is addStaticLabels.
library(mapview)
mapview(breweries) %>% addStaticLabels(label = breweries$zipcode,
direction = 'left',
offset = c(12,-15),
textsize = "10px")
No matter what offset I give it doesn't change where the text is. This makes it really hard to see the text and the point.

Related

Moviepy - Place textclips at relative position

How do I place a textclip, right below the other? I require to place an image at the left of the video and two lines of text to the right of image, that are placed one below the other.
Something like this:
I tried to use set_position, but doesn't scale well for different videos (of different resolutions). By adjusting the arguments of set_position, I am able to place the textclips one below the other without gap in one resolution, but when I go to a higher resolution video, it shows a gap (I understand why the gap comes, but not sure how to prevent it)
txt_clip1 = TextClip("This is line 1 of text", fontsize = 12, color = 'white', bg_color='black')
txt_clip1 = txt_clip1.set_duration(7).set_start(0).set_end(7)
txt_clip1 = txt_clip1.set_position((0.1,0.90), relative=True).set_opacity(0.6)
txt_clip2 = TextClip("This is line 2 of the text, smaller font", fontsize = 8, color = 'white', bg_color='black')
txt_clip2 = txt_clip2.set_duration(7).set_start(0).set_end(7)
txt_clip2 = txt_clip2.set_position((0.1,0.93), relative=True).set_opacity(0.6)
I tried to insert a new line character in the text, but that doesn't suit me because the second line of text has different font properties.
Hopefully this will help you
txt_clip1 = TextClip(
"Cool effect 2nd line", color="black", bg_color="red", font="Amiri-Bold", kerning=5, fontsize=20
)
cvc = CompositeVideoClip([txt_clip1.set_position("East")], size=screensize)
txt_clip1 = txt_clip1.set_position((5,35))
.set_position mother take to arguments 1st is the position from the left screen and second is the position from the top
so your code is like something
txt_clip1 = txt_clip1.set_position((5,500))
txt_clip2 = txt_clip2.set_position((5,535))
It will place the text in the position you want.
Hopefully, this will help.
Happy coding

PIL: Imageobject.save() after drawing completely corrupts images and smurfs the ouput

I have these two functions in my program:
def depict_ph_increase(x,y,color, imobject):
program_print(color)
draw = PIL.ImageDraw.Draw(imobject)
draw.text((x, y),color,(255,255,255))
imobject.save('tmp-out.gif')
im_temp = PIL.Image.open("tmp-out.gif")#.convert2byte()
im_temp = im_temp.resize((930, 340), PIL.Image.ANTIALIAS)
MAP_temp = ImageTk.PhotoImage(im_temp)
map_display_temp = Label(main, image=MAP_temp)
map_display_temp.image = MAP_temp # keep a reference!
map_display_temp.grid(row=4,column=2, columnspan=3)
def read_temp_pixels(temperature_file, rngup, rngdown):
temp_image_object = PIL.Image.open(temperature_file)
(length, width) = get_image_size(temp_image_object)
(rngxleft, rngxright) = rngup
(rngyup,rngydown) = rngdown
print 'the length and width is'
print length, width
hotspots = 5;
for hotspot in range(0,hotspots):
color = "#ffffff"
while color == "#ffffff" or color == "#000000" or color == "#505050" or color == "#969696":
yc = random.randint(rngxleft, rngxright)
xc = random.randint(rngyup,rngydown)
color = convert_RGB_HEX(get_pixel_color(temp_image_object, xc, yc))
depict_ph_increase(xc,yc,color, temp_image_object)
The bottom one calls the top one. Their job is to read in this image:
It then randomly selects a few pixels, grabs their colors, and writes the hex values of the colors on top. But, when it redisplays the image, it gives me this garbage:
Those white numbers up near the upper right corner are the hex values its drawing. Its somehow reading the values from the corrupted image, despite the fact that I don't collect the values until AFTER I actually call the ImageDraw() method. Can someone explain to me why it is corrupting the image?
Some background--the get_pixel_color() function is used several other times in the program and is highly accurate, its just reading the pixel data from the newly corrupted image somehow. Furthermore, I do similar image reading (but not writing) at other points in my code.
If there is anything I can clarify, or any other part of my code you want to see, please let me know. You can also view the program in its entirety at my github here: https://github.com/jrfarah/coral/blob/master/src/realtime.py It should be commit #29.
Other SO questions I have examined, to no avail: Corrupted image is being saved with PIL
Any help would be greatly appreciated!
I fixed the problem by editing this line:
temp_image_object = PIL.Image.open(temperature_file)
to be
temp_image_object = PIL.Image.open(temperature_file).convert('RGB')

D3 expanding rectangle's text is not adjusted

I have a rectangle and a text created through D3 which are grouped together like below.
<g>
<rect></rect>
<text></text>
</g>
In a javascript function I'm expanding this rectangle's width to allow the the value of text to be displayed in one go. (If the value is too long as the text value is set dynamically). This is working fine. However even though the rectangle width is expanding depending on the text value size , D3 text element is not showing the complete text value that is added, eventually the text is moved to left and the first bit of it can't be seen.
Do I need to increase the text element's width too or what would be the solution for this?
[UPDATE]
Following is the current code.
var elms = d3.selectAll("[id=s]"); // has the rectangle and text elements
var s = d3.selectAll("[id=s]").selectAll("text"); // just the text elements
var minimumValue = 100;
// updating rectangle width
elms.attr('width', function() { return dynamic < minimumValue ? minimumValue : dynamic;});
Now I need a way to update the position of the text element when the rectangle is expanded. Hope this is more clear. I just tried manually updating 'x' property of text element that works. But can I derive this value dynamically to set it within this function?
In case someone is looking for this, was able to get the text new 'x' value by x of rectangle + half of rectangle's width (and similar for y but with the height).
Got the answer from this link (How to place and center text in an SVG rectangle)

NVD3.js multiChart x-axis labels is aligned to lines, but not bars

I am using NVD3.js multiChart to show multiple lines and bars in the chart. All is working fine, but the x-axis labels is aligned only to the line points, not bars. I want to correctly align labels directly below the bars as it should. But I get this:
With red lines I marked where the labels should be.
I made jsFiddle: http://jsfiddle.net/n2hfN/
Thanks!
As #Miichi mentioned, this is a bug in nvd3...
I'm surprised that they have a TODO to "figure out why the value appears to be shifted" because it's pretty obvious... The bars use an ordinal scale with .rangeBands() and the line uses a linear scale, and the two scales are never made to relate to one another, except in that they share the same endpoints.
One solution would be to take the ordinal scale from the bars, and simply adjust it by half of the bar width to make the line's x-scale. That would put the line points in the center of the bars. I imagine that something similar is done in the nv.models.linePlusBarChart that #LarsKotthoff mentioned.
Basically, your line's x-scale would look something like this:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
...where xScaleBars is the x-scale used for the bar portion of the chart.
By combing through the source code for nvd3, it seems that this scale is accessible as chart.bars1.scale().
Maybe someday the authors of nvd3 will decide that their kludge of a library deserves some documentation. For now, I can show you the kind of thing that would solve the problem, by making a custom chart, and showing how the two scales would relate.
First, I'll use your data, but separate the line and bar data into two arrays:
var barData = [
{"x":0,"y":6500},
{"x":1,"y":8600},
{"x":2,"y":17200},
{"x":3,"y":15597},
{"x":4,"y":8600},
{"x":5,"y":814}
];
var lineData = [
{"x":0,"y":2},
{"x":1,"y":2},
{"x":2,"y":4},
{"x":3,"y":6},
{"x":4,"y":2},
{"x":5,"y":5}
];
Then set up the scales for the bars. For the x-scale, I'll use an ordinal scale and rangeRoundBands with the default group spacing for nvd3's multiBar which is 0.1. For the y-scale I'll use a regular linear scale, using .nice() so that the scale doesn't end on an awkward value as it does by default in nvd3. Having some space above the largest value gives you some context, which is "nice" to have when trying to interpret a chart.
var xScaleBars = d3.scale.ordinal()
.domain(d3.range(barData.length))
.rangeRoundBands([0, w], 0.1);
var yScaleBars = d3.scale.linear()
.domain([0, d3.max(barData, function(d) {return d.y;})])
.range([h, 0])
.nice(10);
Now here's the important part. For the line's x-scale, don't make a separate scale, but just make it a function of the bars' x-scale:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
Here's the complete example as a JSBin. I've tried to document the major sections with comments so it's easy to follow the overall logic of it. If you can figure out from the nvd3 source code exactly what each of the elements of the multiChart are called and how to set the individual scales of the constituent parts, then you might be able to just plug in the new scale.
My feeling on it is that you need to have a pretty good handle on how d3 works to do anything useful with nvd3, and if you want to customize it, you're probably better off just rolling your own chart. That way you have complete knowledge and control of what the element classes and variable names of the parts of your chart are, and can do whatever you want with them. If nvd3 ever gets proper documentation, maybe this will become a simple fix. Good luck, and I hope this at least helps you get started.

d3 autospace overlapping tick labels

Is there a way in d3 to not draw overlapping tick labels? For example, if I have a bar chart, but the bars are only 5 pixels wide and the labels are 10 pixels wide, I end up with a cluttered mess. I'm currently working on an implementation to only draw the labels when they do not overlap. I can't find any existing way to do that, but wasn't sure if anyone else had dealt with this problem.
There is no way of doing this automatically in D3. You can set the number of ticks or the tick values explicitly (see the documentation), but you'll have to figure out the respective numbers/values yourself. Another option would be to rotate the labels such that there is less chance of them overlapping.
Alternatively, like suggested in the other answer, you could try using a force layout to place the labels. To clarify, you would use the force layout on the labels only -- this is completely independent of the type of chart. I have done this in this example, which is slightly more relevant than the one linked in the other answer.
Note that if you go with the force layout solution, you don't have to animate the position of the labels. You could simply compute the force layout until it converges and then plot the labels.
I've had a similar problem with multiple (sub-)axis, where the last tick overlaps my vertical axis in some situations (depending on the screen width), so I've just wrote a little function that compares the position of the end of the text label with the position of the next axis. This code is very specific to my use case, but could adapted easily to your needs:
var $svg = $('#svg');
// get the last tick of each of my sub-axis
$('.tick-axis').find('.tick:last-of-type').each(function() {
// get position of the end of this text field
var endOfTextField = $(this).offset().left + $(this).find('text').width();
// get the next vertical axis
var $nextAxis = $('line[data-axis="' + $(this).closest('.tick-axis').attr('data-axis') + '"]');
// there is no axis on the very right, so just use the svg width
var positionOfAxis = ($nextAxis.length > 0) ? $nextAxis.offset().left : $svg.offset().left + $svg.width();
// hide the ugly ones!
if (endOfTextField > positionOfAxis) {
$(this).attr('class', 'tick hide');
}
});
The ticks with color: aqua are the hidden ones:

Resources