Text boxes in xmgrace (preferably with GracePlot.py) - python

I am currently plotting figures with xmgrace from python using GracePlot.py and I would like to make text annotations in the graph and place them inside a box, in order to make the reading easy when the grid is on.
Does anybody know how to do it with GracePlot.py? Or from xmgrace GUI?
The code I use is similar to the following:
import GracePlot as xg
import math
from numpy import arange
x=arange(0,10,0.1)
y=[math.exp(-q) for q in x]
grace=xg.GracePlot()
graph=grace[0]
data=xg.Data(x=x,y=y)
graph.plot(data)
graph.text('This should be placed inside a box',5,0.5)

I had a quick look through the latest GracePlot module source code. It seems that the author has not yet implemented the capability to make boxes.
Normally, the "Box" tool can be found under "Drawing Objects" when using the Grace/xmgrace GUI. Create a box and save the project, then view it in a text editor as the file is saved in an ASCII format. The following section can be found:
#with box
# box on
# box loctype view
# box 0.340196078431, 0.691176470588, 0.619607843137, 0.513725490196
# box linestyle 1
# box linewidth 1.0
# box color 1
# box fill color 1
# box fill pattern 0
#box def
As you can see by comparing similar chunks for text creation etc. with the source code, the GracePlot module is just printing similar commands for each of the things it is generating. It would be quite easy to add the capability to make boxes. Perhaps you have time yourself? :)
The capability for text has been implemented:
from GracePlot import *
p = GracePlot()
[....]
p.text('Hello, world!', 0.5, 0.4, color=violet, charsize=1.2)
will place some violet-colored text at (0.5, 0.4) with 1.2 character size.
Boxes in Grace do not have their own text, so in order to solve your question you can simply place a text object over the box you created.

Related

How to check Altair chart 's Zoom in/out functionality in a programatic way each time when i Zoom in/out in the front end

I have written a streamlit code where I am using altair to display a chart in the front end. The made that chart to have zoom in/out functionality. I used ".interactive()" to get this done like below.
chart = alt.Chart(embd_1).mark_circle(size=30).encode(
x = 'dimention1:Q',
y = 'dimention2:Q',
tooltip=['col1'] ,
color=color).properties(width=600,height=600).add_selection(selected).interactive()
But, I am facing a problem when I do zoom in/out in my app. It's taking lot of time to get updated. once i start scrolling the mouse, it takes literally more than 10 secs to update the zoomed chart in the front end.
I was just wondering this may be because streamlit is running all the code which is beneath the altairs code as i don't know how to skip or avoid a certain code when i use zoom in/out functionality.
So, The question is how to programatically define whether the user is zooming in/out ?
like below :
if CheckZoom_SomeThingIDnotKnowYet == True:
logic to execute code1
else:
logic to execute code2
Additional Info On data and Altair Code used:
def altair_graph(embd_1):
selected = alt.selection_single(on="click", empty="none")
dom = ['Other IPs', 'Slected IP','Sel Dims']
rng_clr = ['lightgrey', 'red','blue']
color_point=alt.Color('color', scale=alt.Scale(domain=dom, range=rng_clr))
color = alt.condition(selected, alt.value('red'), color_point,legend=None)
chart = alt.Chart(embd_1).mark_circle(size=30).encode(
x = 'dimention1:Q',
y = 'dimention2:Q',
tooltip=['dimention1','dimention2'] ,
color=color
).properties(width=600,height=600).add_selection(selected).interactive()
return chart
And Sample for the above function Can be created like below:
dimention1=np.random.rand(1,100000).squeeze()
dimention2=np.random.rand(1,100000).squeeze()
colr_values = ['Other Ids', 'Slected Id','Sel Dims']
color = np.random.choice(colr_values, 100000, p=[0.9, 0.05, 0.05])
sample = pd.DataFrame({'dimention1':dimention1,'dimention2':dimention2,'color':color})
altair_graph(sample)
As shown in the example, My real time data is more than 150k data points.
Even When I have executed the above code outside streamlit, This is taking significant time to zoom in/out. Could ssomeone please provide a workaround for this problem.
Altair/VegaLite is a the moment not very performant with that many data points (I think it slows down around 20-40k somewhere). You can try alt.data_transformers.enable('data_server') for potential minor improvements and see my answer here for some more details and discussion in the comments https://stackoverflow.com/a/67349827/2166823.

Is there a way to dynamically change the font color in Jupyter markdown?

I am using Jupyter to create a report file of an analysis I'm doing. At the end of each analysis I'll provide a summary of how many errors/irregularities the analysis has found. I was wondering if there is a way to dynamically change the font color based on the results. e.g. let's say we have a variable called "font_color" and we have a if statement that sets the variable to "Red" if there are errors and "Black" if there is none, now in Jupyter markdown set the color as:
In code cell:
font_color = *IF statement to define color*
In markdown cell:
<font color={{font_color}}>
- Testing
I'm open to suggestions and if there is a better way to dynamically change font colors.
Yes, in Jupyter notebooks you can use code to output markdown as well the standout and stderr channels. And also in Jupyter notebooks you can use HTML within the markdown to color code parts of text. Combining those, you could customize something like this for your report generation:
from IPython.display import Markdown, display
a = "Good"
if a == "Good":
font_color="green"
else:
font_color="red"
def printmd(string):
display(Markdown(string))
printmd("Summary:")
printmd(f'**<font color={font_color}>Status for a.</font>**')
Also see here and here.

My Folium does not output anything, just a blank image

In the first image, I have a map when I enter a certain range of numbers. As you can see on the second map, it maps out blank. I tried out different range and some of them crashes and outputs a blank map. For example, 300th address does not work even if I put the range from 299 to 301 and 450 does not work either. There are certain addresses block me from mapping it out. I already set the data limit to max through terminal as well.
I've found the answer to my own question. As for the popup, I added parse_html=True on popup which fixed my problem. Also I have just put the popup and icon function separately for clarity
map2 = folium.Map(location=[43.7, -79.4], tiles='cartodbpositron',
zoom_start=11) # set default location on the map
marker_cluster = folium.plugins.MarkerCluster().add_to(map2) # add the
location to the marker cluster
for point in range(len(locationlist)): # loop through the plots
# include popup
popup1 = folium.Popup(df['Condo Address'][point], parse_html=True)
# include icon
icon1 = folium.Icon(color=df['color'][point])
# mark every addresses in the map from the data
folium.Marker(locationlist[point],popup=popup1,icon =
icon1).add_to(marker_cluster)

How can I accurately set the new cursor positions after text replacements have been made

I am trying to adapt a plugin for automated text replacement in a Sublime Text 3 Plugin. What I want it to do is paste in text from the clipboard and make some automatic text substitutions
import sublime
import sublime_plugin
import re
class PasteAndEscapeCommand(sublime_plugin.TextCommand):
def run(self, edit):
# Position of cursor for all selections
before_selections = [sel for sel in self.view.sel()]
# Paste from clipboard
self.view.run_command('paste')
# Postion of cursor for all selections after paste
after_selections = [sel for sel in self.view.sel()]
# Define a new region based on pre and post paste cursor positions
new_selections = list()
delta = 0
for before, after in zip(before_selections, after_selections):
new = sublime.Region(before.begin() + delta, after.end())
delta = after.end() - before.end()
new_selections.append(new)
# Clear any existing selections
self.view.sel().clear()
# Select the saved region
self.view.sel().add_all(new_selections)
# Replace text accordingly
for region in self.view.sel():
# Get the text from the selected region
text = self.view.substr(region)
# Make the required edits on the text
text = text.replace("\\","\\\\")
text = text.replace("_","\\_")
text = text.replace("*","\\*")
# Paste the text back to the saved region
self.view.replace(edit, region, text)
# Clear selections and set cursor position
self.view.sel().clear()
self.view.sel().add_all(after_selections)
This works for the most part except I need to get the new region for the edited text. The cursor will be placed to the location of the end of the pasted text. However since I am making replacements which always make the text larger the final position will be inaccurate.
I know very little about Python for Sublime and like most others this is my first plugin.
How do I set the cursor position to account for the size changes in the text. I know I need to do something with the after_selections list as I am not sure how to create new regions as they were created from selections which are cleared in an earlier step.
I feel that I am getting close with
# Add the updated region to the selection
self.view.sel().subtract(region)
self.view.sel().add(sublime.Region(region.begin()+len(text)))
This, for some yet unknown to me reason, places the cursor at the beginning and end of the replaced text. A guess would be that I am removing the regions one by one but forgetting some "initial" region that also exists.
Note
I am pretty sure the double loop in the code in the question here is redundant. but that is outside the scope of the question.
I think your own answer to your question is a good one and probably the way I would go if I was to do something like this in this manner.
In particular, since the plugin is modifying the text on the fly and making it longer, the first way that immediately presents itself as a solution other than what your own answer is doing would be to track the length change of the text after the replacements so you can adjust the selections accordingly.
Since I can't really provide a better answer to your question than the one you already came up with, here's an alternative solution to this instead:
import sublime
import sublime_plugin
class PasteAndEscapeCommand(sublime_plugin.TextCommand):
def run(self, edit):
org_text = sublime.get_clipboard()
text = org_text.replace("\\","\\\\")
text = text.replace("_","\\_")
text = text.replace("*","\\*")
sublime.set_clipboard(text)
self.view.run_command("paste")
sublime.set_clipboard(org_text)
This modifies the text on the clipboard to be quoted the way you want it to be quoted so that it can just use the built in paste command to perform the paste.
The last part puts the original clipboard text back on the clipboard, which for your purposes may or may not be needed.
So, one approach for this would be to make new regions as the replaced text is created using their respective lengths as starting positions. Then once the loop is complete clear all existing selections and set the new one we created in the replacement loop.
# Replace text accordingly
new_replacedselections = list()
for region in self.view.sel():
# Get the text from the selected region
text = self.view.substr(region)
# Make the required edits on the text
text = text.replace("\\","\\\\") # Double up slashes
text = text.replace("*","\\*") # Escape *
text = text.replace("_","\\_") # Escape _
# Paste the text back to the saved region
self.view.replace(edit, region, text)
# Add the updated region to the collection
new_replacedselections.append(sublime.Region(region.begin()+len(text)))
# Set the selection positions after the new insertions.
self.view.sel().clear()
self.view.sel().add_all(new_replacedselections)

replace downloaded youtube video content with a bold centered text

I have zero experience with python, but it is clear enough (for most of the code).
There is this code:
from moviepy.editor import *
video = VideoFileClip("myHolidays.mp4").subclip(50,60)
# Make the text. Many more options are available.
txt_clip = ( TextClip("My Holidays 2013",fontsize=70,color='white')
.set_position('center')
.set_duration(10) )
result = CompositeVideoClip([video, txt_clip]) # Overlay text on video
result.write_videofile("myHolidays_edited.webm",fps=25) # Many options...
What I want to do:
replace my whole video with a text centered and bold (maybe with some little effects) and some solid color background
How do I do that?
A* if I delete the "subclip(50,60)" part, will that select the whole clip?
B* And if I delete ".set_duration(10)", will the rest of the code work?
C* how do I delete the whole (previous) video content?
D* please suggest a simple pro effect (for text)
If you are trying to create a video of just the text the same length as the original video just find the length of the whole video, set the length of the text clip to the same and then txt_clip.write(...

Categories