Jupyter Notebook indispensable au développement de logiciels

Bonjour. Je suis un ingénieur logiciel qui réalise diverses choses telles que l'intégration, les jeux, les applications Web, les applications iOS et les systèmes de contrôle de la signalisation. Il y a environ deux ans et demi, en tant que langage de script à usage général, je pensais qu'il fallait écrire en Python qu'il était difficile de se rendre compte avec seulement le shell, et j'essayais d'apprendre Python en souffrant. Je ne l'utilise qu'occasionnellement, alors j'oublie à chaque fois comment écrire des boucles if et for.

Cependant, il y a environ un an et demi, j'ai appris qu'il existe une REPL appelée Jupyter Notebook dans un livre sur l'apprentissage automatique et la science des données, et lorsque j'ai essayé de l'utiliser comme essai, cela ne se limitait pas à l'apprentissage automatique et à la science des données. , J'ai trouvé qu'il était pratique pour toutes les tâches qui nécessitent des essais et des erreurs quotidiens, et j'écris cet article pour le diffuser.

Jupyter Notebook a une image forte de l'analyse de données.

Cependant, vous n'avez pas besoin de caractéristiques en temps réel, comme envoyer un peu un paquet, l'utiliser comme une calculatrice qui peut faire des choses compliquées, convertir divers formats de fichiers, copier des fichiers compliqués, etc., vous ne pouvez le faire qu'une seule fois. C'est très approprié pour faire des choses diverses comme, bien que cela puisse être, mais il peut y avoir plus d'une fois. Vous pouvez écrire un script en l'essayant phrase par phrase et en vérifiant si le résultat est comme prévu ou faux, comme l'exécution par étapes, afin de pouvoir écrire rapidement du code avec une grande fiabilité.

De plus, lors de l'écriture d'un programme dans un langage dynamique, il y a un inconvénient que vous avez tendance à écrire du code dans un état où la complétion ne fonctionne pas tellement, mais dans le cas de Jupyter Notebook, tout en enquêtant directement sur l'instance matérialisée Comme vous pouvez compléter des méthodes et des champs, la complétion fonctionne aussi bien que les langages de type statique, et vous pouvez gagner beaucoup de temps pour lire la référence.

Cette fois,

--Cas utilisé pour l'analyse --Cas utilisé comme calculatrice

Je vais expliquer les quatre genres de.

Cas utilisé pour l'analyse

Lors de la création d'un logiciel, il existe de nombreuses situations dans lesquelles vous devez effectuer une analyse de comportement à une échelle qui ne peut pas être suivie par un débogueur, ou vous devez faire des recherches qui ne peuvent pas être effectuées avec des outils existants. Les périphériques qui devraient pouvoir être contrôlés par TCP ou UDP sont parfois invités à enquêter parce qu'ils ne peuvent pas être contrôlés, ou je veux vérifier avec désinvolture la valeur renvoyée par les données du capteur sans regarder les spécifications. , Certains caractères peuvent être affichés dans une police spécifique et certains ne le peuvent pas. On m'a donc demandé de décider de la plage de caractères pouvant être utilisée dans le système.

Fondamentalement, vous devez analyser le journal ou lire les métadonnées et faire quelque chose à ce sujet, mais avec Jupyter, il est confortable de procéder tout en vérifiant avec ad hoc.

Analyse des paquets capturés par Wireshark

Nous avons reçu une demande pour enquêter sur le problème selon lequel le périphérique contrôlé par TCP / UDP ne pouvait parfois pas être contrôlé, et avons examiné si la cause était du côté du logiciel de contrôle, du réseau ou du côté du périphérique. Il y avait quelque chose que je devais faire. Pour le moment, je pensais qu'il serait possible de gérer en regardant la communication, alors je lui ai demandé de préparer un hub de commutation capable de mettre en miroir des ports, et de collecter des paquets de plusieurs Go de niveau par jour avec tshark, qui est un outil en ligne de commande de Wireshark. Convertissez le fichier de capture et le fichier .pcap obtenus en Pandas DataFrame avec le code suivant.

def makeDfFromPcap(filename):
    p = dpkt.pcapng.Reader(open(filename, 'rb'))

    dDict = {'t':[], 'src':[], 'dst':[], 'type':[], 'srcport':[], 'dstport':[], 'length':[]}
    count = 0
    for ti,buf in p:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
        except dpkt.NeedData:
            pass
        if type(eth.data) == dpkt.ip.IP:
            ip = eth.data
            src = ip.src
            dst = ip.dst
            src_a = socket.inet_ntoa(src)
            dst_a = socket.inet_ntoa(dst)
            t = 'IP'
            srcPort = 0
            dstPort = 0
            if type(ip.data) == dpkt.udp.UDP:
                srcPort = ip.data.sport
                dstPort = ip.data.dport
                t = 'UDP'
            elif type(ip.data) == dpkt.tcp.TCP:
                srcPort = ip.data.sport
                dstPort = ip.data.dport
                t = 'TCP'
            dDict['t'].append(ti)
            dDict['src'].append(src_a)
            dDict['dst'].append(dst_a)
            dDict['type'].append(t)
            dDict['srcport'].append(srcPort)
            dDict['dstport'].append(dstPort)
            dDict['length'].append(ip.len)
            count += 1
            if count % 10000 == 0:
                print(count)

    df = pd.DataFrame(dDict, columns=['t','src','dst','type','srcport','dstport','length'])
    
    return df
df = makeDfFromPcap('cap_00001_20191216.pcap')
df
スクリーンショット 2019-12-18 10.55.24.png

Après cela, vous pouvez vérifier le niveau de communication entre l'adresse IP source et l'adresse IP de destination en regroupant avec DataFrame et en totalisant.

pd.DataFrame(df.groupby(['src','dst'])['length'].sum().sort_values(ascending=False) * 8 / (df.t.max() - df.t.min()))
#Bande utilisée(unité: bps)
スクリーンショット 2019-12-18 10.56.49.png
pd.DataFrame(df.groupby(['src','dst']).size().sort_values(ascending=False) / (df.t.max() - df.t.min()))
#Nombre de paquets par unité de temps(unité: tps)
スクリーンショット 2019-12-18 10.56.58.png

Dans ce cas, il semble que la communication entre 10.100.45.26 et 10.100.45.39 se produit fréquemment, donc juste au cas où, ayez un concentrateur qui ne connecte que 10.100.45.26 et 10.100.45.39 qui sont en cascade depuis le concentrateur principal, et le problème est J'ai regardé la transition pour voir si

Bien sûr, je pense qu'il existe de nombreux outils qui peuvent être utilisés pour agréger des paquets de ce niveau, mais le grand mérite est que si vous connaissez Pandas, vous n'avez pas à apprendre à utiliser des outils spéciaux.

Visualisation des données des capteurs des appareils IoT acquises auprès de TeraTerm

Je pense qu'il existe de nombreux cas où vous souhaitez avoir une idée de ce que les données du capteur de l'appareil retournent, puis passer à une mise en œuvre à grande échelle. Il était nécessaire de savoir rapidement comment les valeurs du capteur géomagnétique 3 axes attaché à l'appareil IoT sont liées à la rotation de l'appareil et quel type de traitement de données doit être effectué lorsque vous souhaitez extraire l'orientation. .. Heureusement, il y avait un exemple de code du capteur géomagnétique, qui vidait les données du capteur via série, j'ai donc décidé de sauvegarder le journal de texte avec TeraTerm et de le visualiser.

スクリーンショット 2019-12-18 10.58.59.png

Parce que ce sont des données de journal comme celle-ci

def parse_mag_str(line):
    try:
        splitted = line[5:].replace(' ', '').split(',')
        return [float(n) for n in splitted]
    except:
        return None

Créons une fonction de perspective appropriée telle que.

スクリーンショット 2019-12-18 11.00.05.png

Le comportement semble être correct, alors

mags = [parse_mag_str(l) for l in log[2:]][0:-1]

Faisons un tableau 3D flottant.

Après cela, si vous placez les données dans une bibliothèque de visualisation 3D interactive telle que ipyvolume, vous pouvez facilement convertir les données en un graphique 3D en utilisant la souris. Tu peux vérifier.

import ipyvolume as ipv

start = 250
end = 8000
t = np.array(range(start,end))
x = np.array([m[0] for m in mags[start:end]])
y = np.array([m[1] for m in mags[start:end]])
z = np.array([m[2] for m in mags[start:end]])
x_n = np.array([m[0] for m in mags[start+10:end+10]])
y_n = np.array([m[1] for m in mags[start+10:end+10]])
z_n = np.array([m[2] for m in mags[start+10:end+10]])
u = x_n - x
v = y_n - y
w = z_n - z


ipv.figure()
quiver = ipv.quiver(x, y, z, u, v, w, size=3, size_selected=20)
ipv.show()

ipyvolume.gif

Dans ce cas, j'ai trouvé que pour obtenir l'orientation, il me fallait juste atan2 les valeurs de coordonnées du plan xy. Puisque la série chronologique des données est également connue par la direction du cône, le signe peut être ajusté correctement.

De nombreux packages commençant par ipy sont utiles car ils améliorent la visibilité et l'interactivité de Jupyter. Il existe des ipyleaflet qui peuvent afficher des données sur une carte interactive, des ipywidgets qui peuvent créer une interface utilisateur avec des boutons, etc.

Résumé de l'analyse

Si vous devez vérifier le journal de manière exhaustive et visualiser / exprimer le résultat du traitement des données, il semble que l'écriture d'un outil de traitement semble être gênante jusqu'à présent (seulement quand c'est vraiment nécessaire). (Je l'ai écrit en utilisant openFrameworks), mais je me suis trompé avec une vérification sans grand chose, mais dans le domaine de l'analyse et de la visualisation de données, qui est le point principal de Jupyter Notebook, la plupart des choses peuvent être faites en douceur, et mon esprit est nerveux. Vous pouvez faire un pas en avant dans la résolution du problème sans l'utiliser, et comme le résultat des essais et des erreurs reste comme un cahier sans autorisation, il faut très peu de temps et d'efforts lorsque vous devez revérifier avec d'autres données plus tard. J'en suis venu à aimer la journalisation et l'extraction de métadonnées à des fins d'enquête. Juste en écrivant le code dans une atmosphère, je peux créer un rapport d'enquête qui dépasse la vérification manuelle que j'avais hésité à faire avec une précision et une quantité écrasantes, et je ressens un sentiment d'accomplissement.

Cas que j'ai essayé d'utiliser comme calculatrice

Avez-vous déjà mis en œuvre la conception de l'interface utilisateur et avez-vous connu la même multiplication et la même addition plusieurs fois en fonction de la taille de l'écran basée sur le dessin de conception? Aussi, si vous faites du traitement d'image et que vous voulez faire un petit calcul matriciel (matrice inverse, diagonalisation, etc.), vous voulez créer une matrice de rotation dans votre ordre de rotation préféré, une matrice inverse un peu compliquée est algébrique Souhaitez-vous demander quelque chose?

Calcul matriciel simple

Calcul numérique

Il est nécessaire de reproduire la vision des couleurs d'une personne avec une anomalie de la vision des couleurs, et lorsque l'espace colorimétrique RVB est converti en espace colorimétrique LMS (il s'agit d'une conversion linéaire), le calcul de la matrice est effectué dans l'espace colorimétrique LMS, puis il est renvoyé dans l'espace RVB. En conséquence, nous avons dû déterminer quel type de conversion linéaire devait être effectué dans l'espace colorimétrique RVB. La formule est la suivante.

\begin{eqnarray}
\mathbf{c^{'}}_\mathrm{RGB} & = & \mathbf{M}_\mathrm{LMStoRGB} \cdot \mathbf{M}_\mathrm{protanopia} \cdot \mathbf{M}_\mathrm{RGBtoLMS} \cdot \mathbf{c}_\mathrm{RGB} \\
 & = & ( \mathbf{M}^{-1}_\mathrm{RGBtoLMS} \cdot \mathbf{M}_\mathrm{protanopia} \cdot \mathbf{M}_\mathrm{RGBtoLMS}) \cdot \mathbf{c}_\mathrm{RGB}
\end{eqnarray}

Vous n'avez qu'à calculer la partie de la matrice entre parenthèses sur le côté droit, alors mettez-la dans Numpy presque telle quelle, et elle est complétée par le code suivant.

import numpy as np

rgb2lms = np.array([0.31399022, 0.63951294,
            0.04649755, 0.15537241, 0.75789446, 0.08670142, 0.01775239,
            0.10944209, 0.87256922]).reshape((3,3))

lms2rgb = np.linalg.inv(rgb2lms)
スクリーンショット 2019-12-18 11.08.26.png

Tout en vérifiant si rgb2lms et lms2rgb sont faits correctement (je ne savais pas si Numpy est Column Major ou Row Major, j'ai donc procédé en vérifiant sur Jupyter) La matrice résultante pourrait être calculée ci-dessous.

protanopia = np.array([0.0, 1.05118294,-0.05116099, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]).reshape((3,3))

lms2rgb.dot(protanopia).dot(rgb2lms)
スクリーンショット 2019-12-18 11.09.08.png

Calcul algébrique

Je pense que la matrice de rotation dans l'espace 3D est souvent utilisée pour créer des jeux, manipuler des coordonnées avec 3DCG et toucher le capteur de mouvement d'un smartphone. Il existe 6 modèles de matrices de rotation selon l'ordre dans lequel les axes X, Y et Z sont tournés. Jusqu'à présent, j'ai fait beaucoup de gaspillage en cherchant sur Wikipédia un par un et en disant que celui que j'ai choisi est faux et ne fonctionne pas. Cependant, il est en fait le plus fiable et le plus rapide à multiplier de la gauche un par un tout en saisissant fermement comment le vecteur est converti du système de coordonnées local au système de coordonnées global. C'est pourquoi je calcule moi-même la matrice de rotation. Juste en Python, il existe une bibliothèque appelée Sympy qui effectue des calculs algébriques.

from sympy import *
#rotation de l'axe x
theta = Symbol('theta')
Rx = Matrix([[1, 0, 0], [0, cos(theta), -sin(theta)], [0, sin(theta), cos(theta)]])

#Rotation dans la direction de l'axe y
yaw = Symbol('yaw')
Ry = Matrix([[cos(yaw), 0, sin(yaw)], [0, 1, 0], [-sin(yaw), 0, cos(yaw)]])

#Rotation de l'axe Z
phi = Symbol('phi')
Rz = Matrix([[cos(phi), -sin(phi), 0], [sin(phi), cos(phi), 0], [0, 0, 1]])

R = Ry * Rx * Rz
R
スクリーンショット 2019-12-18 11.10.41.png

Le résultat est également affiché dans une belle forme rendue avec TeX, il est donc facile à vérifier, et comme je construis moi-même la matrice de rotation, même si quelque chose ne va pas, essayez de changer l'ordre ou de réduire la matrice de rotation de un. Vous pouvez facilement le faire.

Calcul de matrice inverse compliqué

J'ai reçu une demande d'affichage d'une image sur un appareil IoT par conversion de projection sans aucune bibliothèque. C'était. Le processus de dérivation n'est pas le sujet principal, je vais donc l'omettre (bien que le format soit légèrement différent, il s'agit essentiellement de homographie - Shogo Computing Laboratory Le même calcul devrait être fait), mais en conséquence, lorsque la matrice inverse de la matrice 9 par 9 suivante a été résolue et multipliée par le vecteur, chaque élément de la matrice de transformation de projection 3 par 3 est devenu un vecteur à 9 dimensions. Vous pouvez trouver la chose X.

from sympy import *

# x0 = Symbol('x0')Substitution comme x0- x3, y0 -Faire pour y3
for i in range(4):
    for c in "xy":
        globals().update({c + str(i): Symbol(c + str(i))})

u0 = 640
v0 = 0
u1 = 640
v1 = 480
u2 = 0
v2 = 480
u3 = 0
v3 = 0

A = Matrix([
            [ x0, y0, 1, 0, 0, 0, -x0*u0, -y0*u0, 0 ],
            [ 0, 0, 0, x0, y0, 1, -x0*v0, -y0*v0, 0 ],
            [ x1, y1, 1, 0, 0, 0, -x1*u1, -y1*u1, 0 ],
            [ 0, 0, 0, x1, y1, 1, -x1*v1, -y1*v1, 0 ],
            [ x2, y2, 1, 0, 0, 0, -x2*u2, -y2*u2, 0 ],
            [ 0, 0, 0, x2, y2, 1, -x2*v2, -y2*v2, 0 ],
            [ x3, y3, 1, 0, 0, 0, -x3*u3, -y3*u3, 0 ],
            [ 0, 0, 0, x3, y3, 1, -x3*v3, -y3*v3, 0 ],
            [ 0, 0, 0,  0,  0, 0,      0,      0, 1 ],
            ])
A
スクリーンショット 2019-12-18 11.12.04.png
B = Matrix([u0, v0, u1, v1, u2, v2, u3, v3, 1])
B
スクリーンショット 2019-12-18 11.12.24.png
X = A.inv() * B
スクリーンショット 2019-12-18 11.13.27.png

Il semble qu'il puisse être calculé en 5 secondes environ. Cependant, il semble que chaque élément de X a beaucoup de termes, et si vous essayez de l'afficher, il faudra beaucoup de temps pour compiler TeX, donc je vais l'extraire sous forme de chaîne de caractères.

X_strs = [str(simplify(X[i])) for i in range(9)]
スクリーンショット 2019-12-18 11.14.29.png

Cela a pris presque 2 minutes, probablement parce qu'il a fallu beaucoup de temps pour simplifier. Je veux le convertir en code C tel quel, alors je renomme le terme x0 ** 2 en x0p2.

list(zip([v + str(i) + '**2' for v in 'xy' for i in range(4)],[v + str(i) + 'p2' for v in 'xy' for i in range(4)]))
スクリーンショット 2019-12-18 11.14.41.png

Il semble que nous pouvons le renommer ainsi, nous allons donc le remplacer par réduire immédiatement.

X_strs2 = [functools.reduce(lambda s, t: s.replace(*t), list(zip([v + str(j) + '**2' for v in 'xy' for j in range(4)],[v + str(j) + 'p2' for v in 'xy' for j in range(4)])), X_strs[i]) for i in range(9)]

La conversion finale en code C se fait avec un code comme celui-ci:

for v in 'xy':
    for i in range(4):
        print('float %s%dp2 = %s%d * %s%d;\n' % (v, i, v, i, v, i))

for i in range(9):
    print('float X%d = ' % i + X_strs2[i] + ';\n')
スクリーンショット 2019-12-18 11.25.03.png スクリーンショット 2019-12-18 11.24.04.png

Désormais, la fonction de conversion de projection avec des paramètres arbitraires est conçue pour les périphériques embarqués sous une forme qui ne dépend d'aucune bibliothèque. Il y avait une omission de conversion à un endroit, mais lorsque je l'ai corrigée, cela a fonctionné comme prévu.

J'ai également trouvé l'inverse de cette matrice de transformation de projection avec un sentiment similaire.

スクリーンショット 2019-12-18 11.26.08.png

C'est facile car si vous écrivez la formule presque telle quelle, elle sera complétée.

Calculatrice simple

Il est également utilisé pour calculer la taille des éléments de l'interface utilisateur conçus avec différentes tailles d'écran. Ce n'est pas vraiment un gros problème, mais je suis heureux que ce soit facile à voir et à réparer.

l.png

Un cas où je l'ai utilisé pour créer des données binaires et émettre un paquet

Expérience de contrôle de périphérique en émettant des paquets UDP

Je crée un système de contrôle de signalisation et un certain dispositif de contrôle de puissance devrait fonctionner avec des paquets binaires UDP, alors j'ai essayé de créer un paquet selon les spécifications et de l'envoyer par UDP.

Commencez par créer un paquet.

switches = [True, False, True, True, False]

model_id = 3 # LA-5R
unit_id = 0b00001111 ^ 0

def make_send_bytes(model_id, unit_id, switches):
    return bytes([0xf0 | unit_id, switches[4] << 4 | switches[3] << 3 | switches[2] << 2 | switches[1] << 1 | switches[0]])

send_bytes = make_send_bytes(model_id, unit_id, switches)
[format(send_bytes[i], '02x') for i in [0, 1]]
スクリーンショット 2019-12-18 16.31.39.png

Il semble que le paquet a été créé, je vais donc l'envoyer.

switches = [random.random() < 0.5 for i in range(0, 5)]

send_bytes = make_send_bytes(model_id, unit_id, switches)
[format(send_bytes[i], '02x') for i in [0, 1]]

s.sendto(send_bytes, (HOST, PORT))

Je ne peux pas préparer de captures d'écran, mais j'ai pu confirmer que cela fonctionne lorsque j'envoie un paquet.

Ensuite, vérifiez si l'interrupteur ON / OFF de tous les modèles 5 canaux et 32 modèles peut être contrôlé.

sl = 0.08
l = 0.08 / sl
for j in range(0, int(l)):
    for i in range(0, 32):
        switches = [c == '1' for c in format(i, '05b')]
        send_bytes = make_send_bytes(model_id, unit_id, switches)
        [format(send_bytes[i], '02x') for i in [0, 1]]
        s.sendto(send_bytes, (HOST, PORT))
        time.sleep(sl)
スクリーンショット 2019-12-18 16.32.07.png

En regardant uniquement le résultat de l'écriture, c'est presque la même chose que l'écriture en C, mais sans être habitué à l'arithmétique des bits, aux essais et aux erreurs, que le paquet soit fait correctement ou non, en l'envoyant et en essayant de fonctionner Il s'avère que la boucle rapide de est très importante pour l'efficacité de la mise en œuvre.

En même temps, j'ai également vérifié le contrôle avec la connexion TCP, mais si vous ajoutez une table au notebook, il ne sera pas dans un état plein de commentaires mystérieux, vous pouvez donc trier les parties qui peuvent être détournées entre TCP et UDP et les parties qui ne peuvent pas être détournées. , Vous pouvez revenir plus tard et rendre le code plus facile à utiliser.

Cas de conversion de format

Cela peut être le cas le plus typique. En tant qu'ingénieur logiciel, il existe de nombreux cas où vous souhaitez écrire un script simple et résoudre diverses conversions de format afin d'obtenir les données sur les matières premières et d'en faire la forme finale. Même dans un tel cas, le point fort de Jupyter Notebook est que vous pouvez essayer de faire des erreurs en le regardant est très utile.

Convertissez le JSON exporté d'AfterEffects pour créer un code de création d'objet qui peut être exécuté par Unity's Immediate

Pendant le développement du jeu, j'ai parfois voulu porter des images placées à l'aide de la fonction de calque 3D dans After Effects vers Unity. Bien sûr, cela peut être réalisé en créant un objet Unity Quad tout en regardant les valeurs numériques une couche à la fois, mais je ne veux pas faire une tâche aussi simple même s'il y a environ 50 couches. Donc, tout d'abord, j'ai écrit chaque information du calque After Effects dans JSON à l'aide d'ESTK, puis je l'ai traitée dans Jupyter Notebook.

Tout d'abord, vérifiez quelle valeur est incluse,

import json
import codecs
from operator import itemgetter

with codecs.open('transforms.json', 'r', encoding='shift-jis') as f:
    root = json.load(f)

root
スクリーンショット 2019-12-18 11.29.15.png

Sortez une couche,

layer = root['9']
layer
スクリーンショット 2019-12-18 11.29.32.png

La position, le point d'ancrage, la largeur, la hauteur, l'échelle, etc. sont résumés pour chaque élément de X et Y,

list(zip(layer['position'],layer['Point d'ancrage'],[layer['width'], layer['height']], [layer['échelle'][0], layer['échelle'][1]]))
スクリーンショット 2019-12-18 11.29.38.png

Nous utiliserons la spécification de position et l'agrandissement / réduction qui sont les critères du point d'ancrage comme référence centrale.

[ps[0] - ps[1] * ps[3] + ps[2] * ps[3] / 2 for ps in zip(
    layer['position'],
    layer['Point d'ancrage'],
    [layer['width'], layer['height'], 0], 
    [layer['échelle'][0] / 100, layer['échelle'][1] / 100, 1])]
スクリーンショット 2019-12-18 11.29.47.png

Maintenant que nous savons comment gérer une couche, appliquons-la à toutes les couches. La raison de l'inversion est que l'ordre de chevauchement est inversé entre After Effects et Unity.

t_list = [([ps[0] - ps[1] * ps[3] + ps[2] * ps[3] / 2 for ps in zip(layer['position'],layer['Point d'ancrage'],[layer['width'], layer['height'], 0], [layer['échelle'][0], layer['échelle'][1], 1])], 
 [layer['width'] * layer['échelle'][0] / 100, layer['height'] * layer['échelle'][1] / 100], layer['name']) for layer in root.values()]
t_list.reverse()
t_list
スクリーンショット 2019-12-18 11.30.16.png

Maintenant que nous connaissons les coordonnées, la largeur et la hauteur de tous les calques, nous allons taper dans le volet Immédiat de Unity Editor et générer le code C # pour créer les objets sur la scène.

cs_str = '''{GameObject q = GameObject.CreatePrimitive(PrimitiveType.Quad);
q.name = "%s";
q.transform.position = new Vector3(%ff, %ff, %ff);
q.transform.localScale = new Vector3(%ff, %ff, 1.0f);
var m = (q.GetComponent<Renderer>().material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/Textures/Background/_Materials/%s.mat"));
if (m != null) m.renderQueue = %d;
}'''
sss = '\n'.join([cs_str % (t[2].replace('.psd', ''),
                           t[0][0] / 1000, -t[0][1] / 1000, t[0][2] / 1000, 
                           t[1][0] / 1000, t[1][1] / 1000, t[2].replace('.psd', ''),
                           3000 + i + start) for i, t in 
                 enumerate(sorted(t_list, key=lambda t: int(t[0][2]), reverse=True)[start:start + lll])])
print(sss)
スクリーンショット 2019-12-18 11.30.56.png

En fait, la saisie du code dans le volet Exécution a recréé la scène After Effects. Il semble que cela ait pris autant de temps que de taper 50 fois, mais même si le concepteur joue avec la scène After Effects, cela peut être géré mécaniquement, donc cela se sent beaucoup plus facile dès la deuxième fois. Malheureusement, le concepteur a déclaré: "Je ne veux plus jouer avec des fichiers AE aussi compliqués et difficiles à utiliser."

Générer des parties HTML

Parfois, je code aussi du HTML, mais parfois je dois écrire à la main une partie telle qu'une liste d'articles sur un blog où la chaîne de caractères du titre, etc. apparaît plusieurs fois presque à plusieurs reprises. On dit que vous pouvez insérer un CMS et l'utiliser avec un générateur de site Web statique, mais dans la plupart des cas, vous devez donner la priorité à la publication, et s'il n'y a que quelques parties répétitives, après tous les éditeurs HTML tels que Brackets Je pense qu'il est plus rapide d'écrire directement (même si c'est aussi une grande raison pour laquelle j'ai peu d'expérience avec HTML / CSS). Même dans un tel cas, il est fastidieux et gênant de copier la même chaîne de caractères à plusieurs endroits, et c'est angoissant, donc le programmeur pense qu'il veut l'ignorer. Donc, une fois que je l'ai écrit dans Brackets et qu'il est bien affiché, je vais créer un modèle et le remplacer.

news_template='''                <article class="news-box">
                  <div class="news-photo-box"><img src="assets/image/news/###image_name###"></div>
                  <div class="news-date">###date_str###</div>
                  <div class="news-title">###title_str###</div>
                  <button class="news-more" alt="MORE"></button>
                  <div class="news-description news-description-hidden">
                    <button class="close-button"></button>
                    <button class="news-prev-button"></button>
                    <button class="news-next-button"></button>
                    <div class="news-description-inner">
                      <div class="news-description-pdt-box">
                        <div class="news-description-photo-box"><img src="assets/image/news/###image_name###"></div>
                        <div class="news-description-dt-box">
                          <div class="news-description-date">###date_str###</div>
                          <div class="news-description-title">###title_str###</div>
                        </div>
                      </div>
                      <div class="news-description-body">
                        ###body_str###
                      </div>
                    </div>
                  </div>
                </article>
'''

def make_news(date_str, title_str, body_str, image_name='default.png'):
    return news_template \
        .replace('###date_str###', date_str) \
        .replace('###title_str###', title_str) \
        .replace('###body_str###', body_str) \
        .replace('###image_name###', image_name)
スクリーンショット 2019-12-18 16.14.49.png

Maintenant, vous pouvez certainement créer du HTML simplement en remplissant les éléments requis. C'est formidable de pouvoir le faire sans aucun coût d'apprentissage. Aussi, quand on me demande d'ajouter des nouvelles dans le futur, je pense qu'ouvrir ce cahier me rappellera tout, ce qui est un bon point en ce sens qu'il ne laissera pas de dette dans le futur même si ce n'est pas clairement documenté. pense.

Autre

Par ailleurs,

Et ainsi de suite, la lecture et la conversion se font principalement avec Jupyter Notebook, sauf si cela peut être fait avec une seule commande.

Je pense que vous pouvez faire beaucoup de choses avec les outils de ligne de commande traditionnels, mais il est difficile de savoir comment utiliser les outils et de penser à transmettre des données entre les outils, et il est presque certain que les enregistrements resteront et que vous devrez recommencer. Je n'ai pas à m'en soucier, je continue donc à utiliser Jupyter Notebook au lieu de shells.

Pensez que vous avez été dupé et essayez d'utiliser le Jupyter Notebook. Je pense que c'est très approprié pour les personnes qui ont beaucoup de travail non standard sur une base de projet par projet.

Recommended Posts

Jupyter Notebook indispensable au développement de logiciels
Paramètres d'extrait de code pour le notebook jupyter python
[MEMO] [Construction de l'environnement de développement] Jupyter Notebook
Extension Jupyter Notebook, paramètres nbextensions pour moi-même
Mémo Jupyter Notebook
Présentation de Jupyter Notebook
Puissant ordinateur portable Jupyter
Mot de passe du notebook Jupyter
Mémo Jupyter Notebook
Analyse des données pour améliorer POG 2 ~ Analyse avec le notebook jupyter ~
[Pour la science des données] Aide-mémoire Oreore Jupyter [Jupyter Notebook / Lab]
Démarrer Jupyter Notebook
Essayez les opérations de base sur Pandas DataFrame sur Jupyter Notebook
Application Mac pour ouvrir Jupyter Notebook (* .ipynb) en double-cliquant
3 astuces du notebook Jupyter (Python)
À côté d'Excel, le notebook Jupyter pour le moment
[Cloud103] # 3 Jupyter Notebook à nouveau
Recommandation de Jupyter Notebook, un environnement de codage pour les data scientists
<Python> Construisez un serveur dédié pour l'analyse des données Jupyter Notebook
[Développement Remotte] Fonctionnalités pour les développeurs
Introduction de Jupyter Notebook dans CentOS7
Afficher le HTML dans le notebook Jupyter
Environnement de développement adapté à ArcPy
Utiliser pip avec Jupyter Notebook
Erreur de multitraitement dans Jupyter Notebook
Sept tendances du développement logiciel en 2020
Essayez d'utiliser Jupyter Notebook de manière dynamique
[Super Basics] À propos de Jupyter Notebook
Graphiques élevés dans le notebook Jupyter
Afficher le PDF sur Jupyter Notebook
Utiliser Cython avec Jupyter Notebook
homebrew, pyenv, anaconda, Jupyter Notebook
Jouer avec Jupyter Notebook (IPython Notebook)
[Édition complète] Raccourci vers le bloc-notes Jupyter
[Pour organiser] Environnement de développement Python
Exécutez Jupyter Notebook sous Windows
Comment utiliser Jupyter Notebook
notebook jupyter dans l'environnement venv python3.8