En effet je n'incrémente i que quand il trouve une ligne "intéressante" et pas à chaque ligne qu'il parcours.
Version imprimable
writer.writerow attend une séquence pas un tas d'arguments positionnels: writer.writerow(tp[j:j+6]) devrait fonctionner.
Vous incrémentez i à chaque ajout dans temp et vous ne regardez que les 6 derniers items ajoutés: il y a certainement des simplifications à faire et aussi des tests d'intégrité sur les informations récupérées puisque l'unité d'information est une suite de 6 lignes.
- W
bon , j'ai enfin compris (un peu mieux) puisque trouvé le format de l'entrée
Depuis ce fichier (dcm.txt) trouvé, j'ai pu réécrire mon code qui doit maintenant être plus proche de ton besoin
note: déclencheur autre car pas présent et par conséquent certainement pas les bonnes valeurs dans csv
pour "buffer", utiliser plutôt deque que list ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 declencheur = "(0040, 0244)" buffer = [] # sauve des valeurs with open("dcm.txt", "r") as f_in, open("sortie.csv", "w") as f_out: f_out.write("code DICOM paramètre, Nom paramètre, Code DICOM mesure, Valeur mesurée, Mesure, Unité mesure\n") for line in f_in: line = line.lstrip() # uniquement pour mon fichier trouvé if line[:12] not in ("(0008, 0104)", "(0008, 0100)", declencheur): # on sauve que ces clés, autres sont ignorés continue if line[:12] != declencheur: # tu ne désire pas cette valeur dans csv il me semble valeur = line.split("'")[1] buffer.append(valeur) # les 2 normalement sur une ligne ;) else: # ici on ne garde que les 6 dernières valeurs, déclencheur non comprises! #TODO test si len(buffer) < 6 ? valeurs = buffer[-6:] print(*valeurs, sep="\n") # pour debug for i, valeur in enumerate(valeurs): if valeur in ('121410', 'User chosen value', 'no units'): valeurs[i] = "" print("->", ", ".join(valeurs)) # pour info f_out.write(", ".join(valeurs)+ "\n") print() buffer.clear()
Merci Papajoker,
En effet le déclencheur ne peut pas fonctionner car tu as pris un dicom storage (une image) en fait. Donc forcément vu que moi j'essaie tant bien que mal de récupérer les mesures. C'est pas la même chose.
Mais je te remercie grandement d'avoir passé autant de temps pour moi.
Qui plus est il existe de nombreuses mesures taguées en Private Tag donc sans le champ dicom habituels, mais vu que je bosses chez un des fabricants et que j'essaie de créer un outil pour s'assurer que notre système envoie bien les données j'ai accès a ces private tags
le déclencheur pour ce qui est le Dicom SR (Structured Report) devrait être:
TID 5100 Vascular Ultrasound Report et a pour service tag : (0040,DB00)
du coup je dois pouvoir récupérer uniquement les valeurs qui m’intéressent depuis le dataset original viamais le tag n'est pas présent dans le fichier via pydicomCode:di[(0x0040, 0xDB00)]
dict_keys([(0008, 0016), (0008, 0018), (0008, 0020), (0008, 0023), (0008, 0030), (0008, 0033), (0008, 0050), (0008, 0060), (0008, 0070), (0008, 0080), (0008, 0090), (0008, 1010), (0008, 1040), (0008, 1070), (0008, 1090), (0008, 1111), (0010, 0010), (0010, 0020), (0010, 0030), (0010, 0032), (0010, 0040), (0010, 1010), (0010, 1020), (0010, 1030), (0018, 1020), (0020, 000d), (0020, 000e), (0020, 0010), (0020, 0011), (0020, 0013), (0040, a040), (0040, a043), (0040, a050), (0040, a078), (0040, a370), (0040, a372), (0040, a375), (0040, a491), (0040, a493), (0040, a504), (0040, a730), (6005, 0010), (6005, 1010)])Code:print(di.keys())
mais je le trouve bien par un autre moyen
(0040,DB00) CS TemplateIdentifier 5100
d'où ma tentative de tatonner pour trouver un truc qui roule a peu près
Bon là j'ai entrainement de Bad donc je vous dis à demain j'aurai le temps de regarder votre script plus en détail
MErci encore une fois
Papajoker :
légère modif de votre code pour qu'il matche mieux avec mes désidérata
Bémol vous virez le déclencheur alors que j'en avais besoin (tkt je l'ai récupéré)
et j'ai un 1 qui se promène alors que je ne sais pas d'où il vient
surement de cette ligne là :mais uniquement quand il y a 'no units', pour les autres valeurs 'user chosen value' et '121410', il met bien rienCode:if valeur in ('121410', 'User chosen value', 'no units'):
et dernier point il faut intervertir la mesure et les unités, là on les rentre dans l'ordre donné
mais dans l'absolu il m'aurait fallu
en lieu et place deCode:valeurs=(buffer[:4],buffer[6],buffer[5])
pas encore trouvé la bonne syntaxe, je cherche encore le '1' qui m'embêteCode:valeurs = (buffer[-6:])
Dans tous les cas un grand merci à toi
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 from pydicom import dcmread from tkinter import filedialog from pathlib import Path path = Path(filedialog.askopenfilename(initialdir="c:\\", title="Select a File")) new_path = path.with_suffix('.csv') # utilise la lib pydicom pour lire et enregistrer le dcm dans un fichier txt di = dcmread(path) f_in = str(di).split('\n') declencheur = "(0040, a30a)" buffer = [] # sauve des valeurs with open(new_path, "w") as f_out: f_out.write("code DICOM paramètre, Nom paramètre, Code DICOM mesure, Valeur mesurée, Mesure, Unité mesure\n") for line in f_in: line = line.lstrip() # uniquement pour mon fichier trouvé if line[:12] not in ("(0008, 0104)", "(0008, 0100)", declencheur): # on sauve que ces clés, autres sont ignorés continue if line[:12] != declencheur: # tu ne désire pas cette valeur dans csv il me semble valeur = line.split("'")[1] buffer.append(valeur) # les 2 normalement sur une ligne ;) else: # remplacer par un elif len(buffer)=6 à voir avec d'autres fichiers mesure # comme le déclencheur contient la valeur mesurée je le rajoute # et je supprime le dernière valeur qui est en doublon del (buffer[-1]) valeur = line.split("'")[1] buffer.append(valeur) valeurs = (buffer[-6:]) print(*valeurs, sep="\n") # pour debug for i, valeur in enumerate(valeurs): if valeur in ('121410', 'User chosen value', 'no units'): valeurs[i] = "" print("->", ", ".join(valeurs)) # pour info f_out.write(", ".join(valeurs) + "\n") print() buffer = []
f_in=str(dcmread(path)).split("\n")...
Ah, tu n'as pas aimé le for line in map(str.lstrip, f_in). Bon effectivement je l'avais mis parce que j'aime le map() mais suis presque sûr que ça ne change rien.
Rhôôô !!!:?
buffer[-1]=line.split("'")[1] !!!
? pas sûr de ta demande…
Il est plus simple de travailler sur "valeurs" que "buffer" surtout lorsque l'on ne comprend pas les listes (et ici, tu récupères les premières valeurs et non les dernières !)
si tu cherches à intervertir uniquement les 2 derniers : valeurs[4], valeurs[5] = valeurs[5], valeurs[4] (ou utiliser -1 et -2)
Note: si il avait une note sur deque, c'est que justement, c'est normalement ce que tu devrais utiliser (mais il faut lire la doc et ce n'est pas obligatoire et ne change rien au code sinon une ligne en moins et sans doute moins de ram utilisée)
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 from pydicom import dcmread from tkinter import filedialog from pathlib import Path path = Path(filedialog.askopenfilename(initialdir="c:\\", title="Select a File")) new_path = path.with_suffix('.csv') # utilise la lib pydicom pour lire et enregistrer le dcm dans un fichier txt di = dcmread(path) f_in = str(dcmread(path)).split('\n') declencheur = "(0040, a30a)" buffer = [] # sauve des valeurs modifie = [] # pour intervertir buffer 4 et 5 with open(new_path, "w") as f_out: f_out.write("code DICOM paramètre, Nom paramètre, Code DICOM mesure, Valeur mesurée, Mesure, Unité mesure\n") for line in map(str.lstrip, f_in): # uniquement pour mon fichier trouvé if line[:12] not in ("(0008, 0104)", "(0008, 0100)", declencheur): # on sauve que ces clés, autres sont ignorés continue if line[:12] != declencheur: valeur = line.split("'")[1] buffer.append(valeur) # les 2 normalement sur une ligne ;) else: # remplacer par un elif len(buffer)=6 à voir avec d'autres fichiers mesure # comme le déclencheur contient la valeur mesurée je le rajoute # et je supprime le dernière valeur qui est en doublon buffer[-1] = line.split("'")[1] valeurs = (buffer[-6:]) for j in range(4): modifie.append(valeurs[j]) modifie.append(valeurs[5]) modifie.append(valeurs[4]) if valeurs[4] != '1' else modifie.append("") print(*modifie, sep="\n") for i, valeur in enumerate(modifie): if valeur in ('121410', 'User chosen value', 'no units'): modifie[i] = "" # print("->", ", ".join(modifie)) # pour info f_out.write(", ".join(modifie) + "\n") print() buffer = [] modifie = []
Code:
1
2 if line[:12] != declencheur: buffer.append(line.split("'")[1])
créer une nouvelle variable "modifié" est oui une solution, mais après, il ne faut pas que tu comptes tes lignes de codes :lol:
Quelle est cette très mauvaise manie de mettre des (...) un peu partout dans ce sujet ?Code:valeurs = (buffer[-6:])
ça c'est sûr, et je te rassure (ou pas) toujours pas :
La ligne du haut ne fonctionne pas et celle du bas oui
Donc oui je dois bien l'avouer je ne comprends pas ou en toutvcas ce que je comprends ne fonctionne pasCode:
1
2 # tp.append(temp[i-6]) if temp[i-6] != '121410' else '' tp.append(temp[i-6]) if temp[i-6] != '121410' else tp.append('')
modifie.extend(valeurs[:5])...
si je boucle jusqu’à 4 il prend de 0 à 3 et comme ça je peux inverser la 4 et la 5
D'ailleurs la ligne else if rapide fonctionneCode:
1
2
3 for j in range(4): modifie.append(valeurs[j]) modifie.append(valeurs[5]) modifie.append(valeurs[4]) if valeurs[4] != '1' else ""
Alors la première ligne a une erreur de parenthèse. Je l'ai mise en rouge car elle doit se trouver à la fin de la ligne.
L'expression de base c'est valeurA if condition else valeurB. Elle vaut "valeurA" si la condition est vraie sinon vaut valeurB. Mais bien entendu, en tant que telle elle ne sert à rien. C'est une instruction qui exprime un résultat mais si ce résultat n'est pas récupéré d'une manière ou d'une autre ça ne sert à rien.
Donc ce résultat peut se récupérer
- dans une variable =>variable=(valeurA if condition else valeurB) (je mets des parenthèses pour illustrer le fait que c'est pareil que variable=valeur sauf que la valeur est prise à partir d'une expression)
- dans une fonction =>fonction(valeurA if condition else valeurB) qui est sur le même principe que fonction(valeur_simple)
- dans toute écriture qui attend une valeur
Ecrire tp.append(valeurA) if condition else tp.append(valeurB) fonctionne aussi mais fait perdre le bénéfice de l'écriture. Cela revient à créer une expression qui vaut quelque chose (ie le retour de tp.append()) mais la valeur n'est pas utilisée. Dans ce cas, autant rester sur un if...else classique.
Alors attention à l'écriture. Si tu n'as qu'une instruction X dans le for tu peux écrire
ou bien for ... instructionX sur une ligne. C'est autorisé.Code:
1
2for ... instructionX
Mais si tu en as deux X et Y, tu dois absolument écrire
Tu ne peux absolument pas écrireCode:
1
2
3for ... instructionX instructionY
C'est carrément illisible. On ne sait plus si Y est dans ou hors du forCode:
1
2for ... instructionX instructionY
De fait, dans le code que j'ai cité, les instructions sont à la même verticale sans tabulation (lignes 30 et 31) donc le modif.append(valeur[5]) se fait après le for et non dans le for...
La bonne syntaxe est celle de Sve@r, c'est simple !
tes 2 comparaisons sont une mauvaise pratique et en plus tu ne vois même pas que tu compares 2 lignes complètement différentes :
ligne 1, tu as une seule commande append()
ligne 2, tu as 2 commandes append()
La ligne 1 n'a bien sûr aucun sens : faire action si condition, sinon faire un truc inutile/sans conséquence histoire de meubler mon code
ligne 2 : faire action1 si condition sinon faire action2
Ce qui nous amène donc à la fin et surtout grace à vos remarques
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 from pydicom import dcmread from tkinter import filedialog from pathlib import Path path = Path(filedialog.askopenfilename(initialdir="c:\\", title="Select a File")) new_path = path.with_suffix('.csv') f_in = str(dcmread(path)).split('\n') declencheur = "(0040, a30a)" buffer = [] with open(new_path, "w") as f_out: f_out.write("code DICOM paramètre, Nom paramètre, Code DICOM mesure, Valeur mesurée, Mesure, Unité mesure\n") for line in map(str.lstrip, f_in): if line[:12] not in ("(0008, 0104)", "(0008, 0100)", declencheur): continue if line[:12] != declencheur: buffer.append(line.split("'")[1]) else: buffer[-1] = line.split("'")[1] valeurs = buffer[-6:] valeurs[4], valeurs[5] = valeurs[5], valeurs[4] if valeurs[5] == '1': valeurs[5] = '' for i, valeur in enumerate(valeurs): if valeur in ('121410', 'User chosen value', 'no units'): valeurs[i] = "" f_out.write(", ".join(valeurs) + "\n") buffer = []
Oui, j'avais proposé ça au pif c'est un vrai coup de chance. :wow:
print(", ".join(valeurs), file=f_out) et le "\n" sera mis automatiquement
Après il y a ces différents line.split("'")[1] qui me turlupinent. Est-ce que tu veux vraiment récupérer le second élément du découpage, ou bien tu veux récupérer le dernier d'une info n'en contenant que 2
Si c'est vraiment le second ok pas de souci. Mais si c'est le dernier, alors tu peux essayer line.split("'")[-1]. Ainsi si demain la ligne évolue et que des trucs viennent s'intercaler, le programme fonctionnera toujours.
les lignes que je traite, sont toujours sous ce format là
(0008, 0100) Code Value SH: 'cm/s'
j'ai besoin du premier (0008, 0100) dicom tag qui permet de connaitre ce que contient la ligne
et le dernier champs entre '', qui est la valeur texte que contient la ligne
Donc en théorie j'aurais toujours besoin du dernier paramètre et du premier
le premier fait toujours 12 caractères d'où le
line[:12].
Et donc oui j'aurais toujours besoin du dernier.
buffer.append(line.split("'")[-2]).
Merci