svg path fill animation dasharray dashoffset - svg

I've created a bunch of cubic bezier curves in 1 svg path and now trying to fill the path from top to bottom with dasharray and offset, but the animation keeps starting at every cubic bezier curve start point, so at every C in the path. how can I combine the lines, so the animation goes from the very top to the very bottom?
Here's my svg animation:
https://codepen.io/mj2023/pen/wvEMwyB
<style>
svg {
width: 600px;
overflow:visible;
}
#lined-svg path {
stroke-dasharray: 7867.43;
stroke-dashoffset: 7867.43;
animation: dash 5s linear alternate infinite;
}
#keyframes dash {
from {
stroke-dashoffset: 7867.43;
}
to {
stroke-dashoffset: 0;
}
}
</style>
<svg id="lined-svg" viewBox="0 0 600 4088">
<path stroke="red" fill="none" stroke-width="6" d="M 300, 0 C 300, 114, 600, 76, 600, 190 C 600, 304, 300, 266, 300, 380 M 300, 380, C 300, 542.6, 600, 488.4, 600, 651 C 600, 813.6, 300, 759.4, 300, 922 M 300, 922, C 300, 1003.6, 600, 976.4, 600, 1058 C 600, 1139.6, 300, 1112.4, 300, 1194 M 300, 1194, C 300, 1308, 600, 1270, 600, 1384 C 600, 1498, 300, 1460, 300, 1574 M 300, 1574, C 300, 1655.6, 600, 1628.4, 600, 1710 C 600, 1791.6, 300, 1764.4, 300, 1846 M 300, 1846, C 300, 2008.6, 600, 1954.4, 600, 2117 C 600, 2279.6, 300, 2225.4, 300, 2388 M 300, 2388, C 300, 2604.6, 600, 2532.4, 600, 2749 C 600, 2965.6, 300, 2893.4, 300, 3110 M 300, 3110, C 300, 3224, 600, 3186, 600, 3300 C 600, 3414, 300, 3376, 300, 3490 M 300, 3490, C 300, 3555.4, 600, 3533.6, 600, 3599 C 600, 3664.4, 300, 3642.6, 300, 3708 M 300, 3708, C 300, 3822, 600, 3784, 600, 3898 C 600, 4012, 300, 3974, 300, 4088"></path>
</svg>

Related

How to compare all values of numpy ndarray and a particular column of data frame to extract corresponding values of another column of that data frame

import requests
import pandas as pd
import numpy
def get_token(instrument):
response = requests.get("https://api.kite.trade/instruments")
var1 = response.content.decode('ISO-8859-1')
df = pd.DataFrame([x.split(',') for x in var1.split('\n')])
df =df.rename(columns=df.iloc[0]).drop(df.index[0])
mask = df['segment'].isin(['NFO-FUT', 'NFO-OPT'])
df_filtered = df[mask]
if (instrument.lower() == "future"):
df = df_filtered.loc[df_filtered['segment'] == 'NFO-FUT']
else:
df = df_filtered.loc[df_filtered['segment'] == 'NFO-OPT']
df = df.drop(['tick_size', 'last_price'], axis = 1)
return df.replace('"','', regex=True)
df = get_token("Option")
# print(df)
def get_bhavcopy(date):
date = date.replace("-","")
try:
payload=pd.read_csv("https://archives.nseindia.com/products/content/sec_bhavdata_full_"+date+".csv", skipinitialspace = True)
except Exception as e:
print(e)
return payload
pd.set_option('max_column', None)
price_data= get_bhavcopy("25-06-2021")
mask = price_data['SERIES'].isin(['EQ'])
price_data = price_data[mask]
df_np = df['name'].unique()
data = pd.DataFrame(columns=['name','close'])
I am trying to get the ATM strike, and 5 strike above and below ATM.
What I am doing here is
getting the price of each symbol from NSE
getting the strike lists of all F&O
and intend to find ATM strike by getting the strike price closest to the last close price for each symbol.
Therefore I need to compare the each value in df_np (a np array) and "SYMBOL" column in price_data (dataFrame) to get the last price so that I can use it to find the ATM strike from df
I am not sure how to do that!! or if there's any better way to achieve my goal of finding 10 strike above and below of ATM price for a symbol on a particular day.
Get symbol, last price, and strikes together
First, let's get a proper dataframe with the last price (close) for each symbol: turn df_np into its own dataframe, then merge with price_data and extract the relevant columns:
last_px = pd.merge(pd.DataFrame({'SYMBOL': df_np}), price_data)[['SYMBOL', 'LAST_PRICE']]
On the df dataframe, we group strike prices by name, and aggregate by listing, so that we can build a dataframe where each name is associated to a list of strike prices. Also, change 'name' to 'SYMBOL' in preparation for another merge:
strikes = pd.DataFrame(df.groupby('name')['strike'].agg(list)).reset_index()
strikes.columns = ['SYMBOL', 'strike']
Now merge last price and strikes together:
df3 = pd.merge(last_px, strikes)
Now we have the following dataframe:
In [26]: df3
Out[26]:
SYMBOL LAST_PRICE strike
0 AARTIIND 862.10 [1000, 1000, 1010, 1010, 1020, 1020, 1030, 103...
1 ABFRL 222.80 [165, 165, 170, 170, 175, 175, 180, 180, 185, ...
2 ACC 2044.90 [1160, 1160, 1180, 1180, 1200, 1200, 1220, 122...
3 ADANIENT 1516.00 [1000, 1000, 1020, 1020, 1040, 1040, 1060, 106...
4 ADANIPORTS 711.00 [1000, 1000, 1010, 1010, 1020, 1020, 1030, 103...
.. ... ... ...
155 UPL 803.55 [410, 410, 420, 420, 430, 430, 440, 440, 450, ...
156 VEDL 262.55 [165, 165, 170, 170, 175, 175, 180, 180, 185, ...
157 VOLTAS 1030.00 [1000, 1000, 1020, 1020, 1040, 1040, 1060, 106...
158 WIPRO 546.90 [320, 320, 325, 325, 330, 330, 335, 335, 340, ...
159 ZEEL 218.00 [130, 130, 135, 135, 140, 140, 145, 145, 150, ...
[160 rows x 3 columns]
Find the strikes around the ATM price
Now we're going to apply a function on each row, using the last price and strikes list to determine the ATM price and the 5 strikes above and below. The function turns the strikes list into its own dataframe (with float values), then adds a column that computes the difference with the last price, and the idxmin function will tell us where that difference is minimal, i.e. where are we closer to the ATM price. Using iloc (and because we reset the index) it's easy to find +/- 5 indices, so we return those values as a list.
Here's the function definition:
def around_atm(last_prc, strike_list):
xdf = pd.DataFrame({'strikes': strike_list}).reset_index(drop=True)
xdf['strikes'] = xdf['strikes'].astype(float)
xdf['abs_delta'] = abs(last_prc - xdf['strikes'])
imin = xdf['abs_delta'].idxmin()
return xdf.iloc[imin-5:imin+5]['strikes'].tolist()
Finally, let's apply this function, putting the results in a new column:
df3['above_below'] = df3.apply(lambda x: around_atm(x['LAST_PRICE'], x['strike']), axis=1)
The above_below column now holds the 5 strike above and below the ATM price:
In [30]: df3
Out[30]:
SYMBOL LAST_PRICE \
0 AARTIIND 862.10
1 ABFRL 222.80
2 ACC 2044.90
3 ADANIENT 1516.00
4 ADANIPORTS 711.00
.. ... ...
155 UPL 803.55
156 VEDL 262.55
157 VOLTAS 1030.00
158 WIPRO 546.90
159 ZEEL 218.00
strike \
0 [1000, 1000, 1010, 1010, 1020, 1020, 1030, 103...
1 [165, 165, 170, 170, 175, 175, 180, 180, 185, ...
2 [1160, 1160, 1180, 1180, 1200, 1200, 1220, 122...
3 [1000, 1000, 1020, 1020, 1040, 1040, 1060, 106...
4 [1000, 1000, 1010, 1010, 1020, 1020, 1030, 103...
.. ...
155 [410, 410, 420, 420, 430, 430, 440, 440, 450, ...
156 [165, 165, 170, 170, 175, 175, 180, 180, 185, ...
157 [1000, 1000, 1020, 1020, 1040, 1040, 1060, 106...
158 [320, 320, 325, 325, 330, 330, 335, 335, 340, ...
159 [130, 130, 135, 135, 140, 140, 145, 145, 150, ...
above_below
0 [830.0, 840.0, 840.0, 850.0, 850.0, 860.0, 860...
1 [210.0, 215.0, 215.0, 220.0, 220.0, 225.0, 225...
2 [1980.0, 2000.0, 2000.0, 2020.0, 2020.0, 2040....
3 [1460.0, 1480.0, 1480.0, 1500.0, 1500.0, 1520....
4 [680.0, 690.0, 690.0, 700.0, 700.0, 710.0, 710...
.. ...
155 [770.0, 780.0, 780.0, 790.0, 790.0, 800.0, 800...
156 [250.0, 255.0, 255.0, 260.0, 260.0, 265.0, 265...
157 []
158 [530.0, 535.0, 535.0, 540.0, 540.0, 545.0, 545...
159 [205.0, 210.0, 210.0, 215.0, 215.0, 220.0, 220...
[160 rows x 4 columns]

Draw a shadow border on ModalView with kivy Vertex Instruction?

I am trying to draw a shadow for a ModalView using the Canvas Line vertex instructions. I.e. the ModalView bottom and left sides should have a slight shadowy overlay when open. I have tried calling the ModalView property overlay_color with no effect and Canvas Line vertex instructions do not create the right effect. But I cannot seem to only draw a bottom and left border that gives the shadowy effect.
<PopScrollModal>
on_open: app.root._is_modal_open = True
on_dismiss: app.root._is_modal_open = False
id: popscroll
auto_dismiss: True
orientation: 'vertical'
size_hint: (0.94, 0.41)
border: [50, 50, 16, 16]
overlay_color: [0.1, 0.1, 0.1, 0.4]
pos_hint: {'top': 0.72}
background_normal: ''
background_color: (1, 1, 1, 0)
background: 'white.png'
canvas:
Color:
rgba: app.theme_cls.bg_dark
RoundedRectangle:
size: self.size
pos: self.pos
radius: [7,]
canvas.after:
Color:
rgba: (0.2, 0.2, 0.2, 0.4)
Line:
width: 1.
rounded_rectangle: (self.x, self.y, self.width, self.height, 7)
RecycleView:
id: view_popscroll
viewclass: 'PopScrollBut'
pos_hint: {'top': 1}
size_hint: [1, 0.99]
do_scroll_y: True
RecycleGridLayout:
cols: 1
spacing: 1
default_size: None, 70
default_size_hint: 1, None
size_hint: 1, None
size: self.minimum_size
This line instruction draws on the bottom but does not adhere to the radius of the canvas:
canvas.after:
Color:
rgba: (0.2, 0.2, 0.2, 0.4)
Line:
width: 1.
close: False
points: self.pos[0], self.pos[1], self.pos[0] + self.size[0], self.pos[1]]
The Line instruction only draws a line around the ModalView.
Can somebody help to understand how to set the Points so they only appear left and bottom or set the overlay_color in the same way?
You can do that using BorderImage. It is not well documented and difficult to understand how it is actually intended to work. But here is an example that mostly does what you want:
class MyPop(Popup):
pass
kv = '''
<MyPop>:
canvas.before:
BorderImage:
source: 'shadow32.png'
border: 30, 0, 0, 30
pos: self.x - 30, self.y - 30
size: self.width + 60, self.height + 60
'''
And here is the shadow32.png that is used above:

Bug with finite sympy segments

I am intersecting a plane with 12 segments which represent the edges of a cube. The problem I have is that all the intersections produce one point, even if the point should not be part of the segment, because they should be finite, right?
Code:
from sympy import Point3D, Plane, intersection, Segment3D
# Cube's vertices
v = (Point3D(500, 500, 500), Point3D(-500, 500, 500), Point3D(-500, -500, 500),
Point3D(500, -500, 500), Point3D(500, 500, -500), Point3D(-500, 500, -500),
Point3D(-500, -500, -500), Point3D(500, -500, -500))
# CubeĀ“s edges
a = (Segment3D(v[0], v[1]), Segment3D(v[1], v[2]),
Segment3D(v[2], v[3]), Segment3D(v[3], v[0]),
Segment3D(v[0], v[4]), Segment3D(v[1], v[5]),
Segment3D(v[2], v[6]), Segment3D(v[3], v[7]),
Segment3D(v[4], v[5]), Segment3D(v[5], v[6]),
Segment3D(v[6], v[7]), Segment3D(v[7], v[4]))
# Example plane which should generate 3 points
plano = Plane(Point3D(450, 400, 400), Point3D(400, 450, 400), Point3D(400, 400, 450))
bad = []
good = []
for i in range(12):
inter = intersection(plano, a[i])
# This should be executed when the intersection generates anything, but is always executed:
if inter:
bad.append(inter[0])
# This comparation should not be necessary, checks if point is in range desired
if abs(inter[0][0]) <= 500 and abs(inter[0][1]) <= 500 and abs(inter[0][2]) <= 500:
good.append(inter[0])
print(len(bad), bad)
print(len(good), good)
Output:
12 [Point3D(250, 500, 500), Point3D(-500, 1250, 500), Point3D(1250, -500, 500), Point3D(500, 250, 500), Point3D(500, 500, 250), Point3D(-500, 500, 1250), Point3D(-500, -500, 2250), Point3D(500, -500, 1250), Point3D(1250, 500, -500), Point3D(-500, 2250, -500), Point3D(2250, -500, -500), Point3D(500, 1250, -500)]
3 [Point3D(250, 500, 500), Point3D(500, 250, 500), Point3D(500, 500, 250)]
9 of the 12 points are not part of any segment
This is fixed on SymPy master but the fix is not yet in a released version. On master I get:
3 [Point3D(250, 500, 500), Point3D(500, 250, 500), Point3D(500, 500, 250)]
3 [Point3D(250, 500, 500), Point3D(500, 250, 500), Point3D(500, 500, 250)]
(which I assume is what you expect)
This is currently a bug (In sympy 1.4 or early) and will be fixed at 1.5 release.
https://github.com/sympy/sympy/pull/16637

Array swapping in python

I want to swap elements between two array starting from a particular array index value keeping other values prior to the array index intact.
import numpy as np
r = np.array([10, 20, 30, 40, 50, 60])
p = np.array([70, 80, 90, 100, 110, 120])
t = []
for i in range(len(r)):
for j in range(len(p)):
if i >= 3 and j >= 3:
t.append(p[j])
p[j] = r[i]
for k in t:
r[i] = k
The above code does the task but the values are in reverse order.
The value that I want in array p after swapping is:
[70, 80, 90, 40, 50, 60]
and the value that i want in array r after swapping is:
[10, 20, 30, 100, 110, 120]
But in array p I am getting:
[70, 80, 90, 60, 50, 40]
and in array r I am getting:
[10, 20, 30, 120, 110, 100]
I don't know what is wrong with the code.
import numpy as np
r = np.array([10, 20, 30, 40, 50, 60])
p = np.array([70, 80, 90, 100, 110, 120])
for i in range(len(r)):
if (i>=3):
p[i],r[i] = r[i],p[i]
Above code will do the work for you. You don't need to run two for loop and t array if I understand your problem right. All you want is to swap at some indexes. You can just swap at those indexes as above no need of a temporary array t.
You can achieve the same without looping:
r = np.array([10, 20, 30, 40, 50, 60])
p = np.array([70, 80, 90, 100, 110, 120])
i = 3
temp = p[i:].copy()
p[i:] = r[i:]
r[i:] = temp
Now:
>>> p
array([70, 80, 90, 40, 50, 60])
>>> r
array([ 10, 20, 30, 100, 110, 120])
You can copy a slice of one array on to the other:
In [113]: r = np.array([10, 20, 30, 40, 50, 60])
...: p = np.array([70, 80, 90, 100, 110, 120])
...:
In [114]: t = p.copy()
In [115]: t[3:]=r[3:]
In [116]: t
Out[116]: array([70, 80, 90, 40, 50, 60])
You could also join slices:
In [117]: np.concatenate((p[:3], r[3:]))
Out[117]: array([70, 80, 90, 40, 50, 60])
Those answers create a new array. I think that's clearer than doing an inplace swap. But here's how I'd do the swap
In [128]: temp = r[3:].copy()
In [129]: r[3:]=p[3:]
In [130]: p[3:]=temp
In [131]: r
Out[131]: array([ 10, 20, 30, 100, 110, 120])
In [132]: p
Out[132]: array([70, 80, 90, 40, 50, 60])
I use copy in temp because otherwise a slice produces a view, which will get modified in the next copy. That issue has come up recently when swapping rows of a 2d array.
With lists the swapping is easier - because r[3:] makes a copy.
In [139]: r=r.tolist()
In [140]: p=p.tolist()
In [141]: temp = r[3:]
In [142]: r[3:], p[3:] = p[3:], r[3:]
In [143]: r
Out[143]: [10, 20, 30, 100, 110, 120]
In [144]: p
Out[144]: [70, 80, 90, 40, 50, 60]

Drawing path with FabricJS

First:
var canvas = new fabric.StaticCanvas('c');
var path = new fabric.Path('M 0 0 L 50 0 M 0 0 L 4 -3 M 0 0 L 4 3 z', {
left: 100,
top: 100,
stroke: 'red',
strokeWidth: 1,
fill: false
});
canvas.add(path);
result:
So how can I rotate this arrow by 45 degree whose center point is the head of the arrow like this:
I tried to set 'originX' and 'originY', but the problem is I cannot set the origin to the head of the arrow by setting these two parameters. As shown below:
var canvas = new fabric.StaticCanvas('c');
var path = new fabric.Path('M 0 0 L 50 0 M 0 0 L 4 -3 M 0 0 L 4 3 z', {
left: 100,
top: 100,
stroke: 'red',
strokeWidth: 1,
fill: false,
**originX: 'left',**
**originY: 'top'**
});
canvas.add(path);
var canvas = new fabric.StaticCanvas('c');
var path = new fabric.Path('M 0 0 L 50 0 M 0 0 L 4 -3 M 0 0 L 4 3 z', {
left: 100,
top: 100,
stroke: 'red',
strokeWidth: 1,
fill: false,
originX: 'left',
originY: 'top',
**angle: 45**
});
canvas.add(path);
This should do it:
var canvas = new fabric.StaticCanvas('c');
var path = new fabric.Path('M 0 0 L 50 0 M 0 0 L 4 -3 M 0 0 L 4 3 z', {
stroke: 'red',
strokeWidth: 1,
fill: false,
originX: 'left',
originY: 'top'
});
path.setAngle(45).set({ left: 100, top: 100 });
canvas.add(path);

Resources